IIC.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #include "IIC.h"
  2. #define GPIO_PORT_I2C GPIOB /* GPIO端口 */
  3. #define RCC_I2C_PORT RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
  4. #define I2C_SCL_PIN GPIO_Pin_1 /* 连接到SCL时钟线的GPIO */
  5. #define I2C_SDA_PIN GPIO_Pin_0 /* 连接到SDA数据线的GPIO */
  6. /* 定义读写SCL和SDA的宏,已增加代码的可移植性和可阅读性 */
  7. #if 0 /* 条件编译: 1 选择GPIO的库函数实现IO读写 */
  8. #define I2C_SCL_1() GPIO_SetBits(GPIO_PORT_I2C, I2C_SCL_PIN) /* SCL = 1 */
  9. #define I2C_SCL_0() GPIO_ResetBits(GPIO_PORT_I2C, I2C_SCL_PIN) /* SCL = 0 */
  10. #define I2C_SDA_1() GPIO_SetBits(GPIO_PORT_I2C, I2C_SDA_PIN) /* SDA = 1 */
  11. #define I2C_SDA_0() GPIO_ResetBits(GPIO_PORT_I2C, I2C_SDA_PIN) /* SDA = 0 */
  12. #define I2C_SDA_READ() GPIO_ReadInputDataBit(GPIO_PORT_I2C, I2C_SDA_PIN) /* 读SDA口线状态 */
  13. #else /* 这个分支选择直接寄存器操作实现IO读写 */
  14. /* 注意:如下写法,在IAR最高级别优化时,会被编译器错误优化 */
  15. #define I2C_SCL_1() GPIO_PORT_I2C->BSRR = I2C_SCL_PIN /* SCL = 1 */
  16. #define I2C_SCL_0() GPIO_PORT_I2C->BRR = I2C_SCL_PIN /* SCL = 0 */
  17. #define I2C_SDA_1() GPIO_PORT_I2C->BSRR = I2C_SDA_PIN /* SDA = 1 */
  18. #define I2C_SDA_0() GPIO_PORT_I2C->BRR = I2C_SDA_PIN /* SDA = 0 */
  19. #define I2C_SDA_READ() ((GPIO_PORT_I2C->IDR & I2C_SDA_PIN) != 0) /* 读SDA口线状态 */
  20. #endif
  21. /*
  22. *********************************************************************************************************
  23. * 函 数 名: IIC_delay
  24. * 功能说明: I2C总线位延迟,最快400KHz
  25. * 形 参:无
  26. * 返 回 值: 无
  27. *********************************************************************************************************
  28. */
  29. static void IIC_delay(void)
  30. {
  31. uint8_t i;
  32. /* 
  33. 下面的时间是通过安富莱AX-Pro逻辑分析仪测试得到的。
  34. CPU主频72MHz时,在内部Flash运行, MDK工程不优化
  35. 循环次数为10时,SCL频率 = 205KHz
  36. 循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us
  37. 循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us
  38. IAR工程编译效率高,不能设置为7
  39. */
  40. for (i = 0; i < 10; i++);
  41. }
  42. /*
  43. *********************************************************************************************************
  44. * 函 数 名: IIC_start
  45. * 功能说明: CPU发起I2C总线启动信号
  46. * 形 参:无
  47. * 返 回 值: 无
  48. *********************************************************************************************************
  49. */
  50. void IIC_start(void)
  51. {
  52. /* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
  53. I2C_SDA_1();
  54. I2C_SCL_1();
  55. IIC_delay();
  56. I2C_SDA_0();
  57. IIC_delay();
  58. I2C_SCL_0();
  59. IIC_delay();
  60. }
  61. /*
  62. *********************************************************************************************************
  63. * 函 数 名: IIC_start
  64. * 功能说明: CPU发起I2C总线停止信号
  65. * 形 参:无
  66. * 返 回 值: 无
  67. *********************************************************************************************************
  68. */
  69. void IIC_stop(void)
  70. {
  71. /* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
  72. I2C_SDA_0();
  73. I2C_SCL_1();
  74. IIC_delay();
  75. I2C_SDA_1();
  76. }
  77. /*
  78. *********************************************************************************************************
  79. * 函 数 名: IIC_send_byte
  80. * 功能说明: CPU向I2C总线设备发送8bit数据
  81. * 形 参:_ucByte : 等待发送的字节
  82. * 返 回 值: 无
  83. *********************************************************************************************************
  84. */
  85. void IIC_send_byte(uint8_t _ucByte)
  86. {
  87. uint8_t i;
  88. /* 先发送字节的高位bit7 */
  89. for (i = 0; i < 8; i++)
  90. {
  91. if (_ucByte & 0x80)
  92. {
  93. I2C_SDA_1();
  94. }
  95. else
  96. {
  97. I2C_SDA_0();
  98. }
  99. IIC_delay();
  100. I2C_SCL_1();
  101. IIC_delay();
  102. I2C_SCL_0();
  103. if (i == 7)
  104. {
  105. I2C_SDA_1(); // 释放总线
  106. }
  107. _ucByte <<= 1; /* 左移一个bit */
  108. IIC_delay();
  109. }
  110. }
  111. /*
  112. *********************************************************************************************************
  113. * 函 数 名: IIC_read_byte
  114. * 功能说明: CPU从I2C总线设备读取8bit数据
  115. * 形 参:无
  116. * 返 回 值: 读到的数据
  117. *********************************************************************************************************
  118. */
  119. uint8_t IIC_read_byte(u8 ack)
  120. {
  121. uint8_t i;
  122. uint8_t value;
  123. /* 读到第1个bit为数据的bit7 */
  124. value = 0;
  125. for (i = 0; i < 8; i++)
  126. {
  127. value <<= 1;
  128. I2C_SCL_1();
  129. IIC_delay();
  130. if (I2C_SDA_READ())
  131. {
  132. value++;
  133. }
  134. I2C_SCL_0();
  135. IIC_delay();
  136. }
  137. if(ack==0)
  138. IIC_nack();
  139. else
  140. IIC_ack();
  141. return value;
  142. }
  143. /*
  144. *********************************************************************************************************
  145. * 函 数 名: IIC_wait_ack
  146. * 功能说明: CPU产生一个时钟,并读取器件的ACK应答信号
  147. * 形 参:无
  148. * 返 回 值: 返回0表示正确应答,1表示无器件响应
  149. *********************************************************************************************************
  150. */
  151. uint8_t IIC_wait_ack(void)
  152. {
  153. uint8_t re;
  154. I2C_SDA_1(); /* CPU释放SDA总线 */
  155. IIC_delay();
  156. I2C_SCL_1(); /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
  157. IIC_delay();
  158. if (I2C_SDA_READ()) /* CPU读取SDA口线状态 */
  159. {
  160. re = 1;
  161. }
  162. else
  163. {
  164. re = 0;
  165. }
  166. I2C_SCL_0();
  167. IIC_delay();
  168. return re;
  169. }
  170. /*
  171. *********************************************************************************************************
  172. * 函 数 名: IIC_ack
  173. * 功能说明: CPU产生一个ACK信号
  174. * 形 参:无
  175. * 返 回 值: 无
  176. *********************************************************************************************************
  177. */
  178. void IIC_ack(void)
  179. {
  180. I2C_SDA_0(); /* CPU驱动SDA = 0 */
  181. IIC_delay();
  182. I2C_SCL_1(); /* CPU产生1个时钟 */
  183. IIC_delay();
  184. I2C_SCL_0();
  185. IIC_delay();
  186. I2C_SDA_1(); /* CPU释放SDA总线 */
  187. }
  188. /*
  189. *********************************************************************************************************
  190. * 函 数 名: IIC_nack
  191. * 功能说明: CPU产生1个NACK信号
  192. * 形 参:无
  193. * 返 回 值: 无
  194. *********************************************************************************************************
  195. */
  196. void IIC_nack(void)
  197. {
  198. I2C_SDA_1(); /* CPU驱动SDA = 1 */
  199. IIC_delay();
  200. I2C_SCL_1(); /* CPU产生1个时钟 */
  201. IIC_delay();
  202. I2C_SCL_0();
  203. IIC_delay();
  204. }
  205. /*
  206. *********************************************************************************************************
  207. * 函 数 名: i2c_GPIO_Config
  208. * 功能说明: 配置I2C总线的GPIO,采用模拟IO的方式实现
  209. * 形 参:无
  210. * 返 回 值: 无
  211. *********************************************************************************************************
  212. */
  213. void IIC_init(void)
  214. {
  215. GPIO_InitTypeDef GPIO_InitStructure;
  216. RCC_APB2PeriphClockCmd(RCC_I2C_PORT, ENABLE); /* 打开GPIO时钟 */
  217. GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
  218. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  219. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; /* 开漏输出 */
  220. GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);
  221. /* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */
  222. IIC_stop();
  223. }