2019独角兽企业重金招聘Python工程师标准>>>

以前一直在用I2C接口,因为总是有线程的例子就一直没有去深入的了解,今天分析了一下在linux下通用GPIO模拟I2C的程序。

I2C的驱动是用杂项设备实现的,这也是一种比较简单的实现方式。通过 misc_register(&mygpioi2c_dev);来注册自己的杂项设备,此函数中会自动创建设备节点,即设备文件。无需mknod指令创建设备文件。因为misc_register()会调用class_device_creat或者device_creat。主设备号也不用管,是最简单的一种驱动了。注册后通过miscdevice结构体关联的file_operations的操作来实现驱动程序的open,read,write接口。

[cpp]  view plain copy
  1. static struct file_operations gpioi2c_fops = {
  2. .owner      = THIS_MODULE,
  3. .ioctl      = gpioi2c_ioctl,
  4. .open       = gpioi2c_open,
  5. .release    = gpioi2c_close
  6. };
具体的操作在IOCTL中实现
[cpp]  view plain copy
  1. int gpioi2c_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  2. {
  3. unsigned int val;
  4. char device_addr, reg_addr;
  5. short reg_val;
  6. switch(cmd)
  7. {
  8. case GPIO_I2C_READ:
  9. val = *(unsigned int *)arg;
  10. device_addr = (val&0xff000000)>>24;//设备地址
  11. reg_addr = (val&0xff0000)>>16;//设备中读写寄存器地址。对于两字节的地址需要自己去定义数据传送的方法。
  12. reg_val = gpio_i2c_read(device_addr, reg_addr);
  13. *(unsigned int *)arg = (val&0xffff0000)|reg_val;
  14. break;
  15. case GPIO_I2C_WRITE:
  16. val = *(unsigned int *)arg;
  17. device_addr = (val&0xff000000)>>24;
  18. reg_addr = (val&0xff0000)>>16;
  19. reg_val = val&0xffff;
  20. gpio_i2c_write(device_addr, reg_addr, reg_val);
  21. break;
  22. default:
  23. return -1;
  24. }
  25. return 0;
  26. }
[cpp]  view plain copy
  1. 下面拿随即读取数据来举例。
[cpp]  view plain copy
  1. <pre name="code" class="cpp" style="font-family: 宋体, Arial; line-height: 1.5; ">unsigned char gpio_i2c_read(unsigned char devaddress, unsigned char address)
  2. {
  3. int mydata;
  4. i2c_start_bit();
  5. i2c_send_byte((unsigned char)(devaddress));
  6. i2c_receive_ack();
  7. i2c_send_byte(address);
  8. i2c_receive_ack();
  9. i2c_start_bit();
  10. i2c_send_byte((unsigned char)(devaddress) | 1);
  11. i2c_receive_ack();
  12. mydata = i2c_receive_byte();
  13. i2c_stop_bit();
  14. </pre><span style="font-family:宋体,Arial"><span style="line-height:1.5">}<br>
  15. 其中的规则就是I2C协议的规定.下面是开始信号的模拟</span></span>
  16. <pre style="font-family:宋体,Arial; line-height:1.5"></pre>
  17. <pre name="code" class="cpp" style="font-family: 宋体, Arial; line-height: 1.5; ">static void i2c_start_bit(void)
  18. {
  19. DELAY(1);//这里的时序需要自己模拟。用一个for循环就可以
  20. i2c_set(SDA | SCL);//sda.scl设为1
  21. DELAY(1);
  22. i2c_clr(SDA);//在SCL为1时拉低SDA,表示发送开始信号
  23. DELAY(2);
  24. }</pre>
  25. <pre></pre>

delay具体多久需要计算,感觉可以用定时器实现,之前就写过一个定时1ms的驱动,因为通过linux应用层单步操作时间间隔最好也是10ms,当时写过selest和一些别的方式做过测试,过几天把这部分整理出来。。回到这个驱动上来。。。。
在做模拟时,总结出了一些要点:
1.自己模拟时序时I2C的占空比并不是一定的,只要符合其数据在上升沿读取这一规律以及高电平不变数据就行
2.释放SDA就是把SDA拉高
3.应答位谁接受谁产生
4.数据是在上升沿锁存,所以在需要读数据前最好把模拟成CL的GPIO做一下拉低再拉高处理,不要直接拉高。
为什么随机读要产生两个开始信号呢,因为随机读需要CPU发送deviceaddress和regaddress,数据流向是cpu->e2prom 而确定了地址后需要改变数据流向。因此需要从新发送开始信号,为什么呢,因为I2C里面的deviceaddress里面包含有读写信息, 即如果写地址是deviceaddress, 则读地址是deviceaddress+1 因此可以这样讲一个开始信号确定当前是读还是写,要改变读写,对不起,只能重新开始。下面是IO口模拟写的时序
[cpp]  view plain copy
  1. void gpio_i2c_write(unsigned char devaddress, unsigned char address, unsigned char data)
  2. {
  3. i2c_start_bit();
  4. i2c_send_byte((unsigned char)(devaddress));
  5. i2c_receive_ack();
  6. i2c_send_byte(address);
  7. i2c_receive_ack();
  8. i2c_send_byte(data);
  9. i2c_stop_bit();
  10. }
可以看到这里只有一次起始,模拟的时候需要注意。以上就是linux模拟I2C驱动的一点心得。

转载于:https://my.oschina.net/u/164131/blog/132247

linux下IO口模拟I2C的一些总结相关推荐

  1. linux下I2C驱动发送IO时序,笔记四:linux下IO口模拟实现I2C协议

    一.i2c总线是什么? 1.i2c总线是一种物理总线及实实在在的总线,通过板子pcb等图能看到. 2.i2c总线是一种主从结构. 3.i2c总线是一种通信协议. 4.i2c总线是两线制半双工串行总线: ...

  2. uboot 周立功 mx6g2c imx6ul io口模拟i2c 调试at24c512

    关于 uboot 周立功 mx6g2c imx6ul io口模拟i2c 调试at24c512 cpu模块连接电路 uboot 使用i2c驱动 为如图 修改include/configs/mx6g2c. ...

  3. 串口发送程序linux,单片机IO口模拟串口程序(发送+接收

    前一阵一直在做单片机的程序,由于串口不够,需要用IO口来模拟出一个串口.经过若干曲折并参考了一些现有的资料,基本上完成了.现在将完整的测试程序,以及其中一些需要总结的部分贴出来. 程序硬件平台:11. ...

  4. Linux下使用GPIO模拟I2C IIC驱动(PCF8563)

    此代码实现LINUX下,创建/dev/algortc设备,但是没有实现rtc标准的读写接口,仅仅实现了IIC时序模拟,编译出.ko文件之后,使用insmod命令挂载,代码里面的线程就会循环读写PCF8 ...

  5. STM32V107VCT6,基于HAL库的用IO口模拟I2C的0.96寸OLED驱动

    前言 作为一个初学者,当然希望有比较好的范例可以学习,但在CSDN和众多家的单片机学习网站,没发现现成的I2C模拟接口的HAL库的0.96寸的OLED驱动,经过努力,把这个代码调试出来,为此,基于技术 ...

  6. 【STM32】IIC的基本原理(实例:普通IO口模拟IIC时序读取24C02)(转载)

    版权声明:本文为博主原创文章,允许转载,但希望标注转载来源. https://blog.csdn.net/qq_38410730/article/details/80312357 IIC的基本介绍 I ...

  7. linux源码gpio模拟i2c,linux内核gpio模拟i2c实例.doc

    linux内核gpio模拟i2c实例.doc linux内核GPIO模拟I2C实例2010-10-11作者:cvip302814来源:cvip302814的blog前言:在许多情况下,我们并没有足够的 ...

  8. 单片机IO口模拟串口程序(发送+接收

    单片机IO口模拟串口程序(发送+接收)[转] qcmc 发表于 - 2011-6-23 0:42:00 前一阵一直在做单片机的程序,由于串口不够,需要用IO口来模拟出一个串口.经过若干曲折并参考了一些 ...

  9. STM8学习笔记----普通IO口模拟串口功能

    串口在产品应用中很常见,但是单片机的默认带的串口往往比较少,有时候就会出现串口不够用,所以就想着能不能用普通IO口模拟串口来实现串口的功能. 要模拟串口首先要清楚串口数据传输过程中的原理. 常用的串口 ...

最新文章

  1. 使用PHP Excel类读取和生成excel文件
  2. Java 性能优化的五大技巧
  3. LeetCode算法题9:递归和回溯-N皇后问题
  4. linux读写文件实例,Linux在应用层读写寄存器的方法及实现实例
  5. selenium python 安装
  6. Angular html 页面里的井号 #
  7. java.net.SocketException:No buffer space avaliable(maximum connection reached?):JVM_Bind 解决办法...
  8. 上几个WebAPI就算微服务架构?Too Young!
  9. 专升本c语言网课听谁的好_都说塑钢泥比玻璃胶好,填缝永不变黑,师傅却说不好用,听谁的?...
  10. uva 437——The Tower of Babylon
  11. 用nginx做了一下反向代理,得到的ip地址都是127.0.0.1
  12. 2021年考计算机考研三战,2021考研的小伙伴有3条忠告一定要记得,这些都是历年实战经验...
  13. BZOJ4197: [Noi2015]寿司晚宴
  14. TCP为什么避免测量重传报文段SampleRTT;TCP为什么等到三个重复的ack后才快速重传
  15. Java小游戏的音乐播放
  16. 在vim中删除空白行
  17. 蓝桥杯练习题 Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。 当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。
  18. 高压柜无线测温装置-无线无源温度传感器-安科瑞 顾月
  19. 网页颜色搭配,网站设计,Google logo配色 Google官方配色表
  20. Protobuf报错CHECK failed: GeneratedDatabase()->Add(encoded_file_descriptor, size):

热门文章

  1. Waymo无人车高层动荡:CFO今日也走了,半年已失8名高管
  2. GPT-3开始探索付费使用:每月给个700块,写得比莎士比亚还多
  3. 夺冠!中国队国际奥数大赛再称雄,满分选手已保送清华姚班,“中国二队”并列第一...
  4. java-数组排序--冒泡排序、鸡尾酒排序、地精排序
  5. Python数据科学-技术详解与商业实践视频教程
  6. Python 人脸识别 OpenCV (haarcascades)
  7. mysql 默认读取位置
  8. clion register
  9. web框架flask(12)——国际化和本地化
  10. MATALO OPENCART 自适应主题模板 ABC-0679-02