树莓派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);
}

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

相关推荐
小龙报19 分钟前
【51单片机】串口通讯从入门到精通:原理拆解 + 参数详解 + 51 单片机实战指南
c语言·驱动开发·stm32·单片机·嵌入式硬件·物联网·51单片机
dlz083617 小时前
POE驱动开发流程
驱动开发
嵌入式-老费19 小时前
Linux camera驱动开发(DVP接口的camera sensor)
驱动开发
VernonJsn1 天前
visual studio 2022的windows驱动开发
ide·驱动开发·visual studio
嵌入式郑工2 天前
RK3566 LubanCat 开发板 USB Gadget 配置完整复盘
linux·驱动开发·ubuntu
雾削木3 天前
树莓派 ESPHome 固件编译与烧录全攻略(解决超时与串口识别问题)
驱动开发
春日见4 天前
win11 分屏设置
java·开发语言·驱动开发·docker·单例模式·计算机外设
cheniie4 天前
Nerves从Hello World到点亮LED
树莓派·elixir·nerves
DarkAthena4 天前
【GaussDB】手动编译不同python版本的psycopg2驱动以适配airflow
驱动开发·python·gaussdb
松涛和鸣4 天前
DAY66 SPI Driver for ADXL345 Accelerometer
linux·网络·arm开发·数据库·驱动开发