树莓派3B+驱动开发(8)- i2c控制PCF8591

github主页:https://github.com/snqx-lqh

本项目github地址:https://github.com/snqx-lqh/RaspberryPiDriver

本项目硬件地址:https://oshwhub.com/from_zero/shu-mei-pai-kuo-zhan-ban

欢迎交流

笔记说明

这一节,主要是设备树有点不同,其他和正点原子的教程差不多。

主要参考的文章

正点原子《I.MX6U 嵌入式 Linux 驱动开发指南 V1.81》

本节源码路径02_Firmware/16_pcf8591_drv_i2c

设备树

这里为了减少篇幅,只是写了i2c相关的,完整的看项目源代码。

C 复制代码
// Definitions for gpio-key module
/dts-v1/;
/plugin/;

/ {
	compatible = "brcm,bcm2835";
    
	fragment@2 {
		// Configure the gpio pin controller
		target = <&i2c1>;
		__overlay__ {
			clock-frequency = <100000>;
			status = "okay";
			pinctrl-names = "default";
			pinctrl-0 = <&i2c1_pins>;
			
			pcf8591@48{
				compatible = "shb,pcf8591";
				reg = <0x48>;
			};
		};
	};

	fragment@3 {
		target = <&i2c1_pins>;
		pins1: __overlay__ {
			brcm,pins = <2 3>;
			brcm,function = <4>; /* alt 0 */
		};
	};
};

驱动代码

首先驱动出入口函数发生了变化,使用的是和i2c相关的注册和注销。

c 复制代码
/* 传统匹配方式ID列表 */
static const struct i2c_device_id pcf8591_id[] = {
	{"shb,pcf8591", 0},  
	{}
};

/* 设备树匹配列表 */
static const struct of_device_id pcf8591_of_match[] = {
	{ .compatible = "shb,pcf8591" },
	{ /* Sentinel */ }
};

/* i2c驱动结构体 */	
static struct i2c_driver pcf8591_driver = {
	.probe = pcf8591_probe,
	.remove = pcf8591_remove,
	.driver = {
			.owner = THIS_MODULE,
		   	.name = "pcf8591",
		   	.of_match_table = pcf8591_of_match, 
		   },
	.id_table = pcf8591_id,
};    

static int __init pcf8591_init(void)
{
	int ret = 0;
	ret = i2c_add_driver(&pcf8591_driver);
	return ret;
}

static void __exit pcf8591_exit(void)
{
	i2c_del_driver(&pcf8591_driver);
}

module_init(pcf8591_init);
module_exit(pcf8591_exit);

其他的差别不大

然后i2c的读写方式如下

c 复制代码
static int pcf8591_read_regs(pcf8591_dev_t *dev, u8 reg, void *val, int len)
{
	int ret;
	struct i2c_msg msg[2];
	struct i2c_client *client = (struct i2c_client *)dev->client;

	/* msg[0]为发送要读取的首地址 */
	msg[0].addr = client->addr;			/* pcf8591地址 */
	msg[0].flags = 0;					/* 标记为发送数据 */
	msg[0].buf = &reg;					/* 读取的首地址 */
	msg[0].len = 1;						/* reg长度*/

	/* msg[1]读取数据 */
	msg[1].addr = client->addr;			/* pcf8591地址 */
	msg[1].flags = I2C_M_RD;			/* 标记为读取数据*/
	msg[1].buf = val;					/* 读取数据缓冲区 */
	msg[1].len = len;					/* 要读取的数据长度*/

	ret = i2c_transfer(client->adapter, msg, 2);
	if(ret == 2) {
		ret = 0;
	} else {
		printk("i2c rd failed=%d reg=%06x len=%d\n",ret, reg, len);
		ret = -EREMOTEIO;
	}
	return ret;
}

static s32 pcf8591_write_regs(pcf8591_dev_t *dev, u8 reg, u8 *buf, u8 len)
{
	u8 b[10];
	struct i2c_msg msg;
	struct i2c_client *client = (struct i2c_client *)dev->client;
	
	b[0] = reg;					/* 寄存器首地址 */
	memcpy(&b[1],buf,len);		/* 将要写入的数据拷贝到数组b里面 */
		
	msg.addr = client->addr;	/* pcf8591地址 */
	msg.flags = 0;				/* 标记为写数据 */

	msg.buf = b;				/* 要写入的数据缓冲区 */
	msg.len = len + 1;			/* 要写入的数据长度 */

	return i2c_transfer(client->adapter, &msg, 1);
}

其他的就是正常的读写操作了。

相关推荐
AI模型调用笔记2 天前
Copilot Fusion:用 Python 跑通模型级联
人工智能·驱动开发·语言模型·copilot
mounter6253 天前
深入理解 gccrs:GCC 如何实现 Rust 编译器,以及编译 Linux 内核面临的挑战
linux·驱动开发·rust
硅基手札3 天前
CAN 技术系列 04 · CAN 帧格式
驱动开发·嵌入式开发·通信协议·can总线
万物智能信息科技4 天前
六轴传感器Motion驱动框架开发—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
驱动开发·华为·开源·harmonyos·鸿蒙
AMASENSYS艾马斯5 天前
变频器滤波器选型与EMC合规建议
驱动开发·单片机·其他·硬件工程·精益工程
沃普天科技5 天前
100W 氮化镓充电器充电头扩展坞一体化设计,实用性翻倍
驱动开发·计算机外设·音视频·硬件工程·pcb工艺
阿白43595 天前
自建 Bitwarden 差点让我丢了所有密码:一次真实的数据灾难与三天重建备份体系
树莓派
lisw056 天前
算法与软件的本质区别
驱动开发·算法·数学建模
泡海椒6 天前
JQuick-SQL “数据源 SPI”辨析:应用适配器与 Function SPI 的正确边界
数据库·驱动开发·sql
万物智能信息科技6 天前
Zigbee透传驱动开发—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
驱动开发·华为·开源·harmonyos·鸿蒙