Chinaunix首页 | 论坛 | 博客
  • 博客访问: 23441
  • 博文数量: 4
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 55
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-07 16:05
文章分类

全部博文(4)

文章存档

2016年(4)

我的朋友

分类: 嵌入式

2016-07-23 14:58:44

本人比较懒,每次遇见iic的时候,都是移植别人的驱动,底层能不管就不管。这次参加电赛,调试LDC1314的时候,没有现成的驱动可移植,没有办法,只有从iic看起走了,而且LDC1314的板子是我们在实验室做的,不清楚能否使用,必须自己保证程序运行没有问题,因此照着时序写了一份iic程序,历经千辛万苦终于能够使用,在这里分享出来,也防止以后忘记再到处找资料。

一、iic协议时序图
写时序:

1、起始信号:SCL高电平时,SDA下降沿,进入数据传输状态。
2、数据传输:不论是写还是读,iic规定在SCL被拉高之前,数据必须放在SDA上待读取,SCL一旦处于高电平,SDA上的数据必须稳定,如果有跳变就会成为起始信号和停止信号发生错误,这点在写程序时一定要注意。
3、读写位:高电平-读 低电平-写。
4、应答信号:总线上每传送完一个字节,被传送方都会在第9个时钟吧总线拉低,以示回应。
5、停止信号:SCL高电平时,SDA上升沿,结束此次传输。
整个传输过程就是:
主机发出起始信号->高7位写设备地址,低0位写0->等待回应->写设备内部寄存器地址->等待回应->写n个字节,并等待回应(n>=1)->主机发出停止信号

读时序:

1:读信号。
2:应答信号:和写入不同,应该由主机发出,读取一个字节发出一个应答信号。
3:无应答信号:第9个时钟不拉低SDA。注意,在一次读取多个字节的时候,最后一个字节应该不应答,直接stop,否则会出错,实测。
整个流程如下:
主机发出起始信号->写7位从机地址+1位写信号->等从机应答->写寄存器地址->等从机应答->主机发出起始信号->写7位从机地址+1位读信号->等从机应答->读字节->发出应答信号->...->读字节->无应答->主机发出停止信号

注意几点:
1、iic总线在硬件上,应该保证线与,即一条线上有一个为低,那么整条线就为低。解决办法就是挂载在总线上的设备io口设置为开漏模式,并挂一个上拉电阻。
2、在不需要使用SDA的时候,主机应该释放,保证从机能够传输电平信号,比如上图的ack by slave,如果主机不释放SDA,始终为低电平,根本无法判断是主机拉低的还是从机拉低的。
3、在进入传输状态的时候,如果没有传输数据,SCL应该为低电平,因为SCL如果为高电平,SDA有任何的电平抖动都会被识别为起始或是停止信号,导致此次传输失败。

二、c代码
OIIC.h

点击(此处)折叠或打开

  1. /***************************************************************
  2. portable iic driver
  3. author:logic
  4. date:2016-7-23
  5. ***************************************************************/

  6. #ifndef _OIIC_H
  7. #define _OIIC_H
  8. #include "MK60_port.h"
  9. #include "MK60_gpio.h"


  10. /*
  11. *public:
  12. */
  13. void OIIC_init();
  14. void OIIC_writeByte(unsigned char devAddr,unsigned char regAddr,unsigned char byte);
  15. void OIIC_writeWord(unsigned char devAddr,unsigned char regAddr,unsigned int word);
  16. void OIIC_writeBytes(unsigned char devAddr,unsigned char regAddr,unsigned char *bytes,int length);
  17. unsigned char OIIC_readByte(unsigned char devAddr,unsigned char regAddr);
  18. unsigned int OIIC_readWord(unsigned char devAddr,unsigned char regAddr);
  19. void OIIC_readBytes(unsigned char devAddr,unsigned char regAddr,unsigned char *bytes,int length);

  20. /*
  21. *private:
  22. */
  23. void OIIC_delay(int t);
  24. void OIIC_start();
  25. void OIIC_stop();
  26. void OIIC_waitForResponse();
  27. void OIIC_response();
  28. void OIIC_noResponse();
  29. void OIIC_putByteOnBus(unsigned char byte);
  30. unsigned char getByteOnBus();

  31. #define OSCL_H() (PTXn_T(PTE25,OUT)=1)
  32. #define OSCL_L() (PTXn_T(PTE25,OUT)=0)
  33. #define OSCL_V() PTXn_T(PTE25,IN)
  34. #define OSDA_H() (PTXn_T(PTE24,OUT)=1)
  35. #define OSDA_L() (PTXn_T(PTE24,OUT)=0)
  36. #define OSDA_V() PTXn_T(PTE24,IN)
  37. #define OSDA_OUT() (1==1)//ignore it when GPIO is openDrain and pullUp mode
  38. #define OSDA_IN() (1==1)




  39. #endif
OIIC.c

点击(此处)折叠或打开

  1. #include "OIIC.h"


  2. void OIIC_delay(int t)
  3. {
  4.     while(t>0)
  5.     {
  6.         t-=2;//adjustable
  7.     }
  8. }

  9. void OIIC_init()
  10. {
  11.     /*
  12.     initialize handware
  13.     */
  14.     gpio_init(PTE24,GPO,1);
  15.     gpio_init(PTE25,GPO,1);
  16.     port_init_NoALT(PTE24,ODO|PULLUP);//openDrain and pullUp
  17.     port_init_NoALT(PTE25,ODO|PULLUP);
  18.   
  19.     
  20.     OSCL_H();
  21.     OSDA_H();
  22. }

  23. void OIIC_start()
  24. {
  25.     OSCL_H();
  26.     OIIC_delay(1000);
  27.     OSDA_L();
  28.     OIIC_delay(1000);
  29.     OSCL_L();//wait for data
  30.     OIIC_delay(1000);
  31.     //OSDA_H();
  32.     //OIIC_delay(1000);
  33. }

  34. void OIIC_stop()
  35. {
  36.     OSDA_L();
  37.     OIIC_delay(1000);
  38.     OSCL_H();
  39.     OIIC_delay(1000);
  40.     OSDA_H();
  41.     OIIC_delay(1000);
  42. }
  43. void OIIC_waitForResponse()
  44. {
  45.     int i=0;
  46.     OSDA_H();
  47.     OIIC_delay(1000);
  48.     OSCL_H();
  49.     OSDA_IN();
  50.     while(OSDA_V()&&i<255){i+=1;}
  51.     OIIC_delay(1000);//can be removed
  52.     OSDA_OUT();
  53.     OSCL_L();
  54.     OIIC_delay(1000);

  55. }
  56. void OIIC_response()
  57. {
  58.     OSDA_L();
  59.     OIIC_delay(1000);
  60.     OSCL_H();
  61.     OIIC_delay(1000);
  62.     OSCL_L();
  63.     OIIC_delay(1000);
  64.     OSDA_H();
  65.     OIIC_delay(100);
  66. }
  67. void OIIC_noResponse()
  68. {
  69.     OSDA_H();//NACK
  70.     OIIC_delay(1000);
  71.     OSCL_H();
  72.     OIIC_delay(1000);
  73.     OSCL_L();
  74.     OIIC_delay(1000);
  75. }

  76. void OIIC_putByteOnBus(unsigned char byte)
  77. {
  78.     int i;
  79.     for(i=0;i<8;i+=1)
  80.     {
  81.         if(byte&(0x80>>i))
  82.             OSDA_H();
  83.         else
  84.             OSDA_L();
  85.         OIIC_delay(1000);
  86.         OSCL_H();//send data
  87.         OIIC_delay(1000);
  88.         OSCL_L();
  89.         OIIC_delay(1000);
  90.     }
  91.     OSDA_H();//release
  92.     OIIC_delay(1000);
  93. }
  94. unsigned char OIIC_getByteOnBus()
  95. {
  96.     unsigned char data=0;
  97.     int i;
  98.     OSDA_H();//release SDA to get data
  99.     OSDA_IN();
  100.     OIIC_delay(1000);
  101.     for(i=0;i<8;i+=1)
  102.     {
  103.         OSCL_H();//to get data
  104.         OIIC_delay(1000);
  105.         if(OSDA_V())
  106.             data=data|(0x80>>i);
  107.         OSCL_L();//to refresh data
  108.         OIIC_delay(1000);
  109.     }
  110.     OSDA_OUT();
  111.     return data;
  112. }
  113. void OIIC_writeByte(unsigned char devAddr,unsigned char regAddr,unsigned char byte)
  114. {
  115.     OIIC_start();
  116.     OIIC_putByteOnBus((devAddr<<1)|0x00);
  117.     OIIC_waitForResponse();
  118.     OIIC_putByteOnBus(regAddr);
  119.     OIIC_waitForResponse();
  120.     OIIC_putByteOnBus(byte);
  121.     OIIC_waitForResponse();
  122.     OIIC_stop();
  123. }
  124. void OIIC_writeWord(unsigned char devAddr,unsigned char regAddr,unsigned int word)
  125. {
  126.     OIIC_start();
  127.     OIIC_putByteOnBus((devAddr<<1)|0x00);
  128.     OIIC_waitForResponse();
  129.     OIIC_putByteOnBus(regAddr);
  130.     OIIC_waitForResponse();
  131.     OIIC_putByteOnBus((word>>8)&0xff);
  132.     OIIC_waitForResponse();
  133.     OIIC_putByteOnBus(word&0xff);
  134.     OIIC_waitForResponse();
  135.     OIIC_stop();
  136. }
  137. void OIIC_writeBytes(unsigned char devAddr,unsigned char regAddr,unsigned char *bytes,int length)
  138. {
  139.     int i;
  140.     OIIC_start();
  141.     OIIC_putByteOnBus((devAddr<<1)|0x00);
  142.     OIIC_waitForResponse();
  143.     OIIC_putByteOnBus(regAddr);
  144.     OIIC_waitForResponse();
  145.     for(i=0;i<length;i+=1)
  146.     {    
  147.         OIIC_putByteOnBus(bytes[i]);
  148.         OIIC_waitForResponse();
  149.     }
  150.     OIIC_stop();
  151. }
  152. unsigned char OIIC_readByte(unsigned char devAddr,unsigned char regAddr)
  153. {
  154.     unsigned char byte;
  155.     OIIC_start();
  156.     OIIC_putByteOnBus((devAddr<<1)|0x00);
  157.     OIIC_waitForResponse();
  158.     OIIC_putByteOnBus(regAddr);
  159.     OIIC_waitForResponse();
  160.     OIIC_start();
  161.     OIIC_putByteOnBus((devAddr<<1)|0x01);
  162.     OIIC_waitForResponse();
  163.     byte=OIIC_getByteOnBus();
  164.     OIIC_noResponse();
  165.     OIIC_stop();
  166.     return byte;
  167. }
  168. unsigned int OIIC_readWord(unsigned char devAddr,unsigned char regAddr)
  169. {
  170.     unsigned int word=0;
  171.     OIIC_start();
  172.     OIIC_putByteOnBus((devAddr<<1)|0x00);
  173.     OIIC_waitForResponse();
  174.     OIIC_putByteOnBus(regAddr);
  175.     OIIC_waitForResponse();
  176.     OIIC_start();
  177.     OIIC_putByteOnBus((devAddr<<1)|0x01);
  178.     OIIC_waitForResponse();
  179.     word=OIIC_getByteOnBus()<<8;
  180.     OIIC_response();
  181.     word|=OIIC_getByteOnBus();
  182.     OIIC_noResponse();
  183.     OIIC_stop();
  184.     return word;
  185. }
  186. void OIIC_readBytes(unsigned char devAddr,unsigned char regAddr,unsigned char *bytes,int length)
  187. {
  188.     int i;
  189.     OIIC_start();
  190.     OIIC_putByteOnBus((devAddr<<1)|0x00);
  191.     OIIC_waitForResponse();
  192.     OIIC_putByteOnBus(regAddr);
  193.     OIIC_waitForResponse();
  194.     OIIC_start();
  195.     OIIC_putByteOnBus((devAddr<<1)|0x01);
  196.     OIIC_waitForResponse();
  197.     for(i=0;i<length;i+=1)
  198.     {
  199.         bytes[i]=OIIC_getByteOnBus();
  200.         if(i==length-1)
  201.             OIIC_noResponse();
  202.         else
  203.             OIIC_response();
  204.     }
  205.     OIIC_stop();
  206. }

---------------------------------------------------------------------------------------------
注意:
以上代码已被我无情抛弃,因为没有采用面向对象的编程方式,导致无法实例化多个i2c设备,故重新实现了一套,命名为universal_i2c,可以跑在任何单片机上,欢迎使用,多多提issue。
github传送门:
阅读(6439) | 评论(4) | 转发(0) |
给主人留下些什么吧!~~

llz6315056092016-07-27 04:00:52

这个东西真的很有用啊~要是没有办法贴代码就上传到网盘里面共享一下吧~

logicwei2016-07-26 11:12:05

我歌月徘徊灬:好人,可以把你代码发给我看看么,被IIC给难住了

我的代码超过一百行,就无法贴出来。。。

回复 | 举报

我歌月徘徊灬2016-07-24 15:05:57

logicwei:哪位朋友可以告诉我,为什么代码过长就无法插入,是有什么限制吗,本人新手

好人,可以把你代码发给我看看么,被IIC给难住了

回复 | 举报

logicwei2016-07-23 15:11:04

哪位朋友可以告诉我,为什么代码过长就无法插入,是有什么限制吗,本人新手