IIC设备驱动实例

本文详细介绍了如何在Linux系统中使用C语言编写IIC设备驱动程序,涵盖了IIC总线协议的基本概念,以及具体实现步骤,包括初始化、数据传输等关键环节,为开发者提供实际操作指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   前面转载了很多关于i2c的文章,做完一个项目了,也该自己写点i2c心得了,我这个可是纯应用角度的,想看原理的,去看转载的文章,人家写的好多了!
   对于一个i2c设备来说,其设备文件是最简单也是最复杂的,说它简单是因为很设备厂商会提供linux下的代码,这样就简单了;但是也有很多厂商它不提供或不完整提供linux下的代码,这样的话当然就复杂了。那么这个我现在这里就不说了,下面说说做了几个I2C设备(以ISA1200为例)后发现,不管设备文件如何总是要自己来做的一些事情,这大概就是所谓的移植吧。
   当然这个工作都是在板文件中进行的。以mach-s5pv210.c为例来说一下:
   先说下用板子自己带的I2C实现驱动加载:
首先在板文件中建立ISA1200的信息:
static int isa1200_power(int on)
{    
       if(on){
              gpio_direction_output(S5PV210_GPJ3(1), 1);
              gpio_direction_output(S5PV210_GPJ3(0), 1);
       }else{
              gpio_direction_output(S5PV210_GPJ3(1), 0);
              gpio_direction_output(S5PV210_GPJ3(0), 0);
       }
       return 0;
}

static struct isa1200_platform_data isa1200_1_pdata = {
       .name = "isa1200",
       .power_on = isa1200_power,
       .pwm_ch_id = 1,
       .hap_en_gpio = S5PV210_GPH3(1),
       .max_timeout = 60000,
};

static void isa1200_init(void)
{
       gpio_direction_output(S5PV210_GPJ3(7), 1);
       gpio_direction_output(S5PV210_GPJ3(1), 1);
       gpio_direction_output(S5PV210_GPJ3(0), 1);

       /*i2c_register_board_info(3, isa1200_board_info,
              ARRAY_SIZE(isa1200_board_info));*/
       return;
}
以及i2c_board_info结构体:
       {
              I2C_BOARD_INFO("isa1200_1", 0x90>>1),/*这个是I2C设备的从机地址*/
              .platform_data = &isa1200_1_pdata,
       },

然后在以下三个I2C总线中找到一条如i2c_devs1[]
/* I2C0 */
static struct i2c_board_info i2c_devs0[] __initdata = {
       
### 关于Linux I2C设备驱动开发 #### 三、I2C设备驱动基础概念 在Linux环境中,I2C设备通过特定的数据结构`i2c_client`表示。当解析设备树中的I2C子节点时,不仅会创建对应的客户端实例,还会处理其中定义的中断信息。具体来说,一个I2C设备被转换成`i2c_client`结构体,在这个过程中,如果存在关联的中断配置,则该中断号会被存储到`i2c_client`对象的`irq`字段中[^4]。 #### 四、编写简单的I2C设备驱动程序 为了实现基本功能,通常需要完成如下几个主要步骤: 1. **注册适配器**:首先应当确保目标硬件上的I2C控制器已被正确识别并初始化为系统内的一个适配器(adapter)。这一步骤一般由板级支持包(BSP)自动完成。 2. **匹配算法**:为了让内核能够找到合适的驱动来操作具体的物理器件,开发者需提供一种机制让新入系统的I2C设备能与其相匹配。最常见的方式是在模块载期间向核心层传递一组预设的名字列表或是地址范围作为过滤条件。 3. **探测函数**:一旦发现有新的I2C设备接入并且满足上述匹配规则之后,就会调用预先设定好的探测回调方法来进行进一步验证以及资源分配工作。此阶段可以读取芯片ID寄存器确认型号无误后再继续后续流程;反之则放弃连接尝试。 4. **数据交换接口**:成功建立联系后便可通过标准API执行命令发送/接收动作。这些API允许应用程序或其它上层组件方便快捷地访问底层硬件特性而无需关心实际通信细节。 下面给出一段简化版代码片段用于说明如何构建这样一个简易驱动框架: ```c #include <linux/i2c.h> #include <linux/module.h> static int my_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id){ printk(KERN_INFO "Device %s found at address 0x%02X\n", id->name, client->addr); // 这里可以根据实际情况添更多初始化逻辑 return 0; } static void my_i2c_remove(struct i2c_client *client){ printk(KERN_INFO "Removing device from system...\n"); } // 定义兼容表项以便与DTS描述符对接 static const struct of_device_id my_match_table[] = { { .compatible = "example,i2c-device"}, {}, }; MODULE_DEVICE_TABLE(of, my_match_table); static struct i2c_driver my_i2c_driver = { .probe = my_i2c_probe, .remove = my_i2c_remove, .driver = { .name = "my-i2c-driver", .of_match_table = my_match_table, }, }; module_i2c_driver(my_i2c_driver); ``` 这段示例展示了怎样基于OF(Device Tree)方式去检测指定类型的外设并与之交互的过程。值得注意的是,这里仅实现了最基本的功能框架,真实项目往往还需要考虑错误恢复策略、电源管理等方面的要求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值