编写设备驱动之i2c_driver -9

参考资料:

  • Linux内核文档:

    • Documentation\i2c\instantiating-devices.rst

    • Documentation\i2c\writing-clients.rst

  • Linux内核驱动程序示例:

    • drivers/eeprom/at24.c

  • 本节代码:GIT仓库中

    • 框架:

      • IMX6ULL\source\04_I2C\02_i2c_driver_example

      • STM32MP157\source\A7\04_I2C\02_i2c_driver_example

    • AP3216C

      • IMX6ULL\source\04_I2C\03_ap3216c

      • STM32MP157\source\A7\04_I2C\03_ap3216c

1. 套路

1.1 I2C总线-设备-驱动模型

 

1.2 示例

分配、设置、注册一个i2c_driver结构体,类似drivers/eeprom/at24.c

 

在probe_new函数中,分配、设置、注册file_operations结构体。 在file_operations的函数中,使用i2c_transfer等函数发起I2C传输。

 

2. 编写i2c_driver

2.1 先写一个框架

2.2 在为AP3216C编写代码

百问网的开发板上有光感芯片AP3216C:

 

AP3216C是红外、光强、距离三合一的传感器,以读出光强、距离值为例,步骤如下:

  • 复位:往寄存器0写入0x4

  • 使能:往寄存器0写入0x3

  • 读红外:读寄存器0xA、0xB得到2字节的红外数据

  • 读光强:读寄存器0xC、0xD得到2字节的光强

  • 读距离:读寄存器0xE、0xF得到2字节的距离值

AP3216C的设备地址是0x1E。

 

static ssize_t ap3216c_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
int err;
char kernel_buf[6];
int val;

if (size != 6)
return -EINVAL;

val = i2c_smbus_read_word_data(ap3216c_client, 0xA); /* read IR */
kernel_buf[0] = val & 0xff;
kernel_buf[1] = (val>>8) & 0xff;

val = i2c_smbus_read_word_data(ap3216c_client, 0xC); /* read 光强 */
kernel_buf[2] = val & 0xff;
kernel_buf[3] = (val>>8) & 0xff;

val = i2c_smbus_read_word_data(ap3216c_client, 0xE); /* read 距离 */
kernel_buf[4] = val & 0xff;
kernel_buf[5] = (val>>8) & 0xff;

err = copy_to_user(buf, kernel_buf, size);
return size;
}


static int ap3216c_open (struct inode *node, struct file *file)
{
i2c_smbus_write_byte_data(ap3216c_client, 0, 0x4);
/* delay for reset */
mdelay(20);
i2c_smbus_write_byte_data(ap3216c_client, 0, 0x3);
return 0;
}

3. 构造i2c_client

下节视频。

posted on 2023-07-30 19:18  拉风摊主  阅读(15)  评论(0编辑  收藏  举报

导航