I2C设备驱动

合集下载

51单片机的I2C底层驱动程序(IO口模拟)

51单片机的I2C底层驱动程序(IO口模拟)

51单片机的I2C底层驱动程序(IO口模拟)/*Title:I2C for 80C51Author:yuyouliang51单片机(本人使用STC89C52单片机,12T模式)的I2C驱动程序,使用逻辑分析仪对该协议进行分析,发现波形比较美观,SCL 的频率在70KHz左右(11.0592M晶振),低于标准的100K,可以适应大多数的I2C器件。

如果感觉速度过快或过慢,可以自行修改延时。

希望可以给读者一个参考,给读者一些帮助!*//*i2c.h文件 */#ifndef __I2C_H_#define __I2C_H_sbit SCL = P2^1;sbit SDA = P2^0;void start_i2c(); //启动I2C总线:SCL高电平期间,SDA由高变低void stop_i2c(); //停止I2C总线:SCL高电平期间,SDA由低变高void send_i2c(unsigned char c); //主机发送一个字节,先发送最高位unsigned char receive_i2c(); //主机接收一个字节,先接收最高位void master_ack(bit ack); //主机非应答信号(填参数0)或应答信号(填参数1)void slave_ack(); //等待从机应答信号#endif/* i2c.c文件 */#include#include#include#define nop() _nop_()void start_i2c() //启动I2C总线:SCL高电平期间,SDA由高变低{SDA=1;SCL=1;nop();nop();nop();nop();SDA=0;SCL=0;}void stop_i2c() //停止I2C总线,SCL高电平期间,SDA由低变高{SDA=0;SCL=1;nop();nop();nop();nop();SDA=1;}void slave_ack() //等待从机应答信号,如果从机迟迟没有应答,则结束总线。

Linux下I2C驱动介绍

Linux下I2C驱动介绍

1、I2C概述I2C是philips公司提供的外设总线,I2C有两条数据线,一条是串行数据线SDA、一条是时钟线SCL,使用SDA和SCL实现了数据的交换,便于布线。

I2C总线方便用在EEPROM、实时钟、小型LCD等与CPU外部的接口上。

2、Linux下的驱动思路Linux系统下编写I2c驱动主要有两种方法:一种是把I2C当做普通字符设备来使用;另一种利用Linux下驱动的体系结构来实现。

第一种方法:优点:思路比较直接,不用花费大量时间去了解Linux系统下I2C体系结构缺点:不仅对I2C设备操作要了解,还有了解I2C的适配器操作不仅对I2C设备器和设备操作需要了解,编写的驱动移植性差,内核提供的I2C设备器都没有用上。

第二种方法:第一种的优点就是第二种的缺点,第一种的缺点就是第二种的优点。

3、I2C框架概述Linux的I2C体系结构分为3部分:1)I2C核心I2C核心提供了I2C总线驱动和设备驱动的注册和注销的方法,I2C 通信方法(algorithm)上层,与具体适配器无关的代码,检测设备上层的代码等。

2)I2C总线驱动I2C总线驱动是对I2C硬件体系结构中适配器端的实现,适配器可以直接受CPU来控制。

3)I2C设备驱动I2C设备驱动是对I2C硬件体系结构中设备端的实现,设备端挂在受CPU控制的适配器上,通过I2C适配器与CPU交换数据。

Linux下的I2C体系结构:1)Linux下的I2C体系结构4、I2C设备驱动编写方法首先让我们明白适配器驱动的作用是让我们能够通过它发出标准的I2C时序,在linux内核源代码中driver/I2C/buss包含一些适配器的驱动,例如s3c2410的驱动I2C-s3c2410.c,适配器被加载到内核中,接下的任务就是实现设备驱动的编写。

编写设备驱动的方法主要分为两种方法:第一种:利用设备提供的I2C-dev.c来实现I2C适配器设备文件,然后通过上层应用程序来操作I2C设备器来控制I2C设备。

详细讲解RT-Thread I2C设备驱动框架及相关函数

详细讲解RT-Thread I2C设备驱动框架及相关函数

详细讲解RT-Thread I2C设备驱动框架及相关函数本应用笔记以驱动I2C接口的6轴传感器MPU6050为例,说明了如何使用I2C设备驱动接口开发应用程序,并详细讲解了RT-Thread I2C设备驱动框架及相关函数。

1 本文的目的和结构1.1 本文的目的和背景I2C(或写作i2c、IIC、iic)总线是由Philips公司开发的一种简单、双向二线制(时钟SCL、数据SDA)同步串行总线。

它只需要两根线即可在连接于总线上的器件之间传送信息,是半导体芯片使用最为广泛的通信接口之一。

RT-Thread中引入了I2C设备驱动框架,I2C 设备驱动框架提供了基于GPIO模拟和硬件控制器的2种底层硬件接口。

1.2 本文的结构本文首先描述了RT-Thread I2C设备驱动框架的基本情况,然后详细描述了I2C设备驱动接口,并使用I2C设备驱动接口编写MPU6050的驱动程序,并给出了在正点原子STM32F4探索者开发板上验证的代码示例。

2 I2C设备驱动框架简介在使用MCU进行项目开发的时候,往往需要用到I2C总线。

一般来说,MCU带有I2C 控制器(硬件I2C),也可以使用MCU的2个GPIO自行编写程序模拟I2C总线协议实现同样的功能。

RT-Thread提供了一套I/O设备管理框架,它把I/O设备分成了三层进行处理:应用层、I/O 设备管理层、底层驱动。

I/O设备管理框架给上层应用提供了统一的设备操作接口和I2C 设备驱动接口,给下层提供的是底层驱动接口。

应用程序通过I/O设备模块提供的标准接口访问底层设备,底层设备的变更不会对上层应用产生影响,这种方式使得应用程序具有很好的可移植性,应用程序可以很方便的从一个MCU移植到另外一个MCU。

本文以6轴惯性传感器MPU6050为例,使用RT-Thread I2C设备驱动框架提供的GPIO模拟I2C控制器的方式,阐述了应用程序如何使用I2C设备驱动接口访问I2C设备。

i2c_rtc_rx8025驱动总结

i2c_rtc_rx8025驱动总结

ARM : at91-sam9x5ekLinux内核:linux-2.6.39时钟芯片:rx8025 SA/NB第一种方法:Rx8025驱动程序在该linux内核中已经包含,路径为:drivers/rtc/rtc-rx8025.c所以在内核中增加驱动只需要配置即可:1.执行make ARCH=arm menuconfig 进入菜单选项,选择RTC配置,选中EPSONRX-8025SA/NB,同时一定要去掉cpu自带的时钟。

2.i2c support 需要选中I2C Hardware Bus support中GPIO-based bitbanging I2C,否则,即使rtc驱动正确,也不能使用,提示:drivers/rtc/hctosys.c: unable to open rtc device (rtc0)。

问题源自,驱动配置正确,I2C驱动没有加载正确,udevd不能创建rtc0设备节点3.在arch/arm/mach-at91/board-sam9x5ek.c中添加信息,注意此处的name名称要与驱动程序中id_table中的名称保持一致。

而在linux某些匹配机制中,设备名称是与驱动名称相一致。

如果名称不能正确匹配,系统是不会执行probe函数的。

另外需要注意的是i2c地址,手册上给出的地址一般都是带有读写位的,而程序中的地址需要把最后一位的读写位去掉,取前面的7位。

Rx8025的地址为0x64,相应的程序中的地址应该为0x32。

否则会提示对寄存器的操作失败。

4.驱动正确配置后,生成相应的文件/dev/i2c-0/dev/rtc0/sys/bus/i2c/drivers/rtc-rx8025/sys/bus/i2c/drivers/0-0032。

I2C设备与驱动的关联

I2C设备与驱动的关联

I2C设备与驱动的关联作者:leeoo 联系方式:neu_linuxer@在Linux操作系统中,驱动程序的加载分为两种:内核启动时自动加载和用户手动加载;硬件设备也可以采用两种方式添加到系统中:在系统启动前及系统运行时的热插拨。

下面,我们以arm体系结构下的at91处理器中的I2C控制器为例,介绍一下硬件设备及相关的驱动程序是如何绑定及松绑的。

1.平台驱动注册过程1.1 at91_i2c_init()函数在文件drivers/i2c/busses/i2c-at91.c中,定义了结构体struct platform_driver并进行了初始化,通过使用module_init()宏进行声明,当模块被加载到内核时会调用 at91_i2c_init()函数。

在此函数中,调用了platform_driver_register()函数来完成注册。

static struct platform_driver at91_i2c_driver = {.probe = at91_i2c_probe,.remove = __devexit_p(at91_i2c_remove),.suspend = at91_i2c_suspend,.resume = at91_i2c_resume,.driver = {.name = "at91_i2c",.owner = THIS_MODULE,},};static int __init at91_i2c_init(void){return platform_driver_register(&at91_i2c_driver);}1.2 platform_driver_register()函数在文件drivers/base/platform.c中,实现并导出了platform_driver_register()函数,以便使其他模块中的函数可以调用此函数。

i2c驱动传入probe的参数解释

i2c驱动传入probe的参数解释

I2C驱动传入probe的参数解释在进行I2C设备的驱动开发过程中,常常会涉及到I2C驱动的probe 函数。

probe函数是Linux内核驱动中的一种特殊函数,它在驱动被加载并且设备被检测到时被调用,用于初始化设备并注册设备驱动。

在编写I2C驱动的probe函数时,通常需要传入不同的参数进行配置和初始化。

本文将对I2C驱动传入probe的参数进行解释和说明,帮助读者更好地理解和使用I2C设备驱动。

1. struct i2c_client *client在I2C驱动的probe函数中,通常需要传入一个指向structi2c_client结构体的指针作为参数。

这个结构体是I2C设备在内核中的表示,包含了I2C设备的位置区域、总线信息、驱动信息等。

通过这个参数,我们可以获取I2C设备的各种信息,并进行相应的初始化和配置。

2. const struct i2c_device_id *id另一个常见的参数是一个指向const struct i2c_device_id结构体的指针,用于指定要注册的设备驱动的ID信息。

这个结构体中通常包含了设备的厂商ID、设备类型、设备名称等信息,用于匹配加载指定的设备驱动。

在probe函数中,我们可以使用这个参数来判断当前检测到的I2C设备是否匹配当前的驱动,从而进行相应的初始化和注册操作。

3. int (*probe)(struct i2c_client *client, const struct i2c_device_id *id)最后一个重要的参数是probe函数本身。

这个参数是一个函数指针,用于指定实际的probe函数的位置区域。

在probe函数中,我们可以根据传入的client和id参数,进行设备的初始化、资源的申请、注册设备驱动等操作。

通过这个函数指针参数,内核可以在加载驱动并检测到设备时正确地调用对应的probe函数。

I2C驱动传入probe的参数包括指向I2C设备结构体的指针、指向设备ID信息的指针以及probe函数的函数指针。

TI-I2C驱动

TI-I2C驱动

TI-I2C驱动一、与I2C驱动相关的文件分成两部分:1)应用层接口部分:程序在svn中的路径如下:在https://dareglob-971006/svn/eocOS/branches/eocOS_v4/branches/bsp/user/i2c目录下,i2ctest.c文件,提供了lm75a_temp_read()方法,用来读取LM75A设备温度寄存器中的温度信息的功能。

2)内核驱动部分:内核位于svn中的路径如下:https://dareglob-971006/svn/eocOS/branches/eocOS_v4/branches/bsp/kernel(1)总线驱动:i2c-davinci.c:在内核目录中driver/i2c/busses目录下,适用于TI的I2C总线驱动程序。

I2C总线驱动是对I2C硬件体系结构中适配器端的实现。

(2)I2C驱动代码核心:i2c-core.c:在内核目录中driver/i2c/目录下,是I2C代码的核心,用于沟通虚拟文件系统与底层实现。

该文件提供了I2C总线驱动和设备驱动的注册、注销方法,I2C通信方法上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。

(3)I2C设备驱动:lm75.c:在内核目录中driver/hwmon目录下,是针对LM75A以及其他能兼容的温度传感器的设备驱动。

I2C设备驱动是对I2C硬件体系结构中设备端的实现,设备一般挂接在受CPU控制的I2C适配器上,通过I2C适配器与CPU交换数据。

二、I2C简要工作流程1)在总线驱动初始化时候,当通过Linux内核源代码/driver/base/platform.c文件中定义platform_driver_register()函数注册platform_driver结构体时,其中probe指针指向的davinci_i2c_probe()函数将被调用,以初始化适配器硬件。

2)而davinci_i2c_remove()函数则完成与davinci_i2c_probe()相反的功能。

I2C设备驱动介绍

I2C设备驱动介绍

I2C设备驱动介绍I2C(Inter-Integrated Circuit)是一种串行通信协议,用于连接并使多个外部设备与主控制器进行通信。

在嵌入式系统中,I2C设备驱动起着至关重要的作用,负责将操作系统与I2C总线上的设备进行通信,促进数据的传输和交互。

1.初始化:驱动程序需要初始化I2C控制器,包括设置时钟频率、地址范围等。

2.设备注册:设备驱动需要在操作系统中注册I2C设备,以便操作系统能够识别和管理设备。

3.读写操作:驱动程序需要实现读写设备寄存器的功能,包括发送开始和停止信号、以及发送、接收数据等。

4.错误处理:驱动程序需要处理I2C通信过程中可能出现的错误,例如传输失败、设备无响应等情况。

5.中断处理:驱动程序需要支持I2C设备的中断机制,以便及时处理设备的状态变化或数据传输完成的中断信号。

6.电源管理:驱动程序需要支持设备的电源管理功能,包括设备的唤醒、睡眠等操作。

7.设备控制:驱动程序需要实现设备特定的控制功能,例如设置传感器的采样率、配置设备的工作模式等。

8. 虚拟文件系统接口:在Linux系统中,驱动程序通常通过虚拟文件系统接口(如/dev)与用户空间进行交互,提供读写设备寄存器的功能。

1.确定设备:首先,开发者应该确定需要驱动的I2C设备。

这可能包括传感器、EEPROM、显示器等。

2.确定硬件连接:确定I2C设备与主控制器之间的硬件连接和电气特性。

这包括设备的I2C地址、I2C总线上的物理接口等。

3.编写驱动程序:在操作系统中,开发者可以根据设备的文档或芯片厂商提供的驱动程序框架,编写自己的I2C设备驱动程序。

驱动程序需要实现上述提到的功能,并且根据设备的特点进行相应的适配和优化。

4.编译和测试:完成驱动程序的编写后,需要将其编译成与操作系统内核匹配的模块或静态链接库。

然后,通过加载驱动模块或重新编译内核来使驱动程序生效。

最后,进行测试,确保驱动程序在各种场景下的正常运行。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

I2C驱动框架—suspend
• • • • • • • • • • • • • • • • • • • • static int ak4187_resume(struct i2c_client *client) { struct ak4187 *ts = i2c_get_clientdata(client); int err; if (ts->power) { err = ts->power(1); if (err < 0) printk(KERN_ERR "ak4187_resume power on failed\n"); } err = ak4187_device_init(ts); if (err) { dev_err(&client->dev, "Initialize error = %d \n", err); return err; } ts->is_suspended = 0; enable_irq(client->irq); dev_info(&client->dev, "ak4187_resume\n"); return 0; }
总结
I2C适配器、设备、核心 • I2C适配器驱动—设备在总线上能够正常通信,实 现设备的数据传输 • I2C设备驱动—实现对应设备的驱动,提供用户程 序接口 • I2C核心—是一条纽带,将设备适配器和设备驱动 连接起来。 它以通用的、与平台无关的的接口实 现了I2C中设备驱动与适配器的沟通
I2C子系统
• 1. I2C核心、I2C适配器驱动和I2C设备驱 动的关系
• 2பைடு நூலகம் 编写I2C设备驱动的方法
第一部分-- I2C体系结构
(1)I2C适配器驱动
• 一个i2c适配器驱动通常需要两个模块来描 述,一个是i2c_adapter和一个 i2c_algorithm • 内部主要是通过i2c_algorithm结构体包含 master_xfer函数的操作来完成数据传输的 • I2c_msg
• }
• static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) • { • int ret = 0;int retry=0; • char test_data = 1; • const char irq_table[2] = {IRQ_TYPE_EDGE_FALLING,IRQ_TYPE _EDGE_RISING}; • struct goodix_ts_data *ts; • struct goodix_i2c_rmi_platform_data *pdata;
I2C适配器作用
• I2C适配器驱动—设备在总线上能够正常通 信,实现设备的数据传输
(2)I2C核心
• I2C核心主要是提供了API用于供I2C设备驱 动来调用以实现和总线的通信(从而进一 步实现和设备和CPU之间通信)。
I2C核心
I2C核心作用
• I2C核心—是一条纽带,将I2C设备适配器 和设备驱动连接起来。 它以通用的、与平 台无关的的接口实现了I2C中设备与适配器 的沟通
I2C驱动框架—探测及初始化
• • • • • • •
ts = kzalloc(sizeof(*ts), GFP_KERNEL); if (ts == NULL) { ret = -ENOMEM; goto err_alloc_data_failed; ……. Request_irq(); Init_timer();
I2C驱动框架—模块初始化
• static int __init ak4187_init(void) • { • ak4187_wq = create_singlethread_workqueue("ak4187_wq"); if (!ak4187_wq) • return -ENOMEM; • • return i2c_add_driver(&ak4187_driver); • } • static void __exit ak4187_exit(void) • { i2c_del_driver(&ak4187_driver); • if (ak4187_wq) • destroy_workqueue(ak4187_wq);
I2C驱动框架—suspend
• • • • • • • • • • • • • • • • • static int ak4187_suspend(struct i2c_client *client, pm_message_t mesg) { struct ak4187 *ts = i2c_get_clientdata(client); int err=0; ts->is_suspended = 1; disable_irq(client->irq); cancel_work_sync(&ts->work); err = i2c_smbus_write_byte_data(ts->client, AK4187_SETUP_ADDRESS, AK4187_SETUP_SLEEP0); if (err) { dev_err(&client->dev, "Suspend error = %d \n", err); } if (ts->power) { err = ts->power(0); if (err < 0) printk(KERN_ERR "ak4187_resume power off failed\n"); } return 0;
(3)I2C设备驱动
• I2C设备驱动—实现对应设备的驱动,完成设 备的特定动作,也提供用户程序接口 • 另外,I2c-dev.c针对适配器生成一个主设 备号位89的设备文件,实现设备驱动的文 件操作接口,针对字符设备使用。
I2C设备驱动
第二部分--编写I2C设备驱动
• i2c设备驱动一般在./kernel/driver/chips/文 件夹下,(因为大多设备也属于输入设备, 有的会放在输入设备下,如触摸屏驱动 在.kernel/driver/input/touchscreen/下)。 • 设备驱动是对设备端的实现,设备要挂载 到对应总线上才能和CPU通信.
• • • • • • • • • • • • •
static struct i2c_driver AK4187_driver = { .probe = goodix_ts_probe, .remove = goodix_ts_remove, #ifndef CONFIG_HAS_EARLYSUSPEND .suspend = goodix_ts_suspend, .resume = goodix_ts_resume, #endif .id_table = goodix_ts_id, .driver = { .name = GOODIX_I2C_NAME, .owner = THIS_MODULE, }, };
• struct ak4187 { • struct input_dev *input; • struct hrtimer timer; • struct timer_list ts_timer; • struct work_struct work; • struct ts_event tc; • u8 intervalData[AK4187_INTDATA_NUM]; • • • • • • • • • • struct i2c_client *client; struct early_suspend early_suspend; spinlock_t lock; int irq; int is_suspended; int AK4187_First_Pendown; //Junger@0803 void (*clear_penirq)(void); int (*power)(int on); }; static struct ak4187 *gl_ts;
I2C适配器驱动
适配器驱动主要完成: 1)适配器i2c_adapter的初始化(时钟初始化、 申请I2C的I/O地址和中断号) 2)驱动适配器从硬件上产生各种信号和处理 I2C中断
部分适配器代码
static int tcc_i2c_doxfer(struct tcc_i2c *i2c, struct i2c_msg *msgs, int num) • { • int ret, i; • for (i = 0; i < num; i++) { • spin_lock_irq(&i2c->lock); • i2c->msg = &msgs[i]; • i2c->msg->flags = msgs[i].flags; • i2c->msg_num = num; • i2c->msg_ptr = 0; • i2c->msg_idx = 0; • i2c->state = STATE_START; • spin_unlock_irq(&i2c->lock); • • • • • • • • • • • • if (i2c->msg->flags & I2C_M_RD) { ret = recv_i2c(i2c); if (ret != 1) printk("recv_i2c failed! - addr(0x%02X)\n", i2c->msg->addr); } else { ret = send_i2c(i2c); if (ret != 1) printk("send_i2c failed! - addr(0x%02X)\n", i2c->msg->addr); } } return ret; }
相关文档
最新文档