IICs.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #include "IICs.h"
  2. #define IIC_SCL_OUT_1(port, pin) (port->BSRR = (uint32_t)pin) // 置1
  3. #define IIC_SCL_OUT_0(port, pin) (port->BRR = (uint32_t)pin)
  4. #define IIC_SDA_OUT_1(port, pin) (port->BSRR = (uint32_t)pin) // 置1
  5. #define IIC_SDA_OUT_0(port, pin) (port->BRR = (uint32_t)pin)
  6. #define IIC_SDA_IN(port, pin) ((port->IDR & pin) != 0)
  7. struct IIC_CONFIG {
  8. uint32_t IIC_SDA_CLK;
  9. GPIO_TypeDef* IIC_SDA_PORT;
  10. uint16_t IIC_SDA_PIN;
  11. uint32_t IIC_SCL_CLK;
  12. GPIO_TypeDef* IIC_SCL_PORT;
  13. uint16_t IIC_SCL_PIN;
  14. } iic_config[] = {
  15. {RCC_APB2Periph_GPIOB, GPIOB, GPIO_Pin_0, RCC_APB2Periph_GPIOB, GPIOB, GPIO_Pin_1},
  16. {RCC_APB2Periph_GPIOA, GPIOA, GPIO_Pin_6, RCC_APB2Periph_GPIOA, GPIOA, GPIO_Pin_7}
  17. };
  18. /**
  19. * @brief IIC延时
  20. * @param None
  21. * @retval None
  22. */
  23. static void IIC_Delay(uint8_t iicNo)
  24. {
  25. static uint16_t delayTime[] = {400, 400};
  26. uint16_t i;
  27. /* 
  28. 下面的时间是通过逻辑分析仪测试得到的。
  29. 工作条件:CPU主频72MHz ,MDK编译环境,1级优化
  30. 循环次数为10时,SCL频率 = 205KHz
  31. 循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us
  32. 循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us
  33. */
  34. for (i = 0; i < delayTime[iicNo]; i++);
  35. }
  36. /**
  37. * @brief SDA输出方向配置
  38. * @param None
  39. * @retval None
  40. */
  41. void Set_IIC_SDA_OUT(uint8_t iicNo)
  42. {
  43. GPIO_InitTypeDef GPIO_InitStructure;
  44. RCC_APB2PeriphClockCmd(iic_config[iicNo].IIC_SDA_CLK, ENABLE);
  45. GPIO_InitStructure.GPIO_Pin=iic_config[iicNo].IIC_SDA_PIN;
  46. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  47. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
  48. GPIO_Init(iic_config[iicNo].IIC_SDA_PORT,&GPIO_InitStructure);
  49. }
  50. /**
  51. * @brief SDA输入方向配置
  52. * @param None
  53. * @retval None
  54. */
  55. void Set_IIC_SDA_IN(uint8_t iicNo)
  56. {
  57. GPIO_InitTypeDef GPIO_InitStructure;
  58. RCC_APB2PeriphClockCmd(iic_config[iicNo].IIC_SDA_CLK, ENABLE);
  59. GPIO_InitStructure.GPIO_Pin=iic_config[iicNo].IIC_SDA_PIN;
  60. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
  61. GPIO_Init(iic_config[iicNo].IIC_SDA_PORT,&GPIO_InitStructure);
  62. }
  63. /**
  64. * @brief 模拟IIC初始化
  65. * @param None
  66. * @retval None
  67. */
  68. void IIC_init(uint8_t iicNo)
  69. {
  70. GPIO_InitTypeDef GPIO_InitStructure;
  71. RCC_APB2PeriphClockCmd(iic_config[iicNo].IIC_SDA_CLK | iic_config[iicNo].IIC_SCL_CLK, ENABLE);
  72. GPIO_InitStructure.GPIO_Pin = iic_config[iicNo].IIC_SDA_PIN;
  73. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
  74. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  75. GPIO_Init(iic_config[iicNo].IIC_SDA_PORT, &GPIO_InitStructure);
  76. GPIO_InitStructure.GPIO_Pin = iic_config[iicNo].IIC_SCL_PIN;
  77. GPIO_Init(iic_config[iicNo].IIC_SCL_PORT, &GPIO_InitStructure);
  78. IIC_stop(iicNo);
  79. }
  80. /**
  81. * @brief 模拟IIC起始信号
  82. * @param None
  83. * @retval None
  84. */
  85. void IIC_start(uint8_t iicNo)
  86. {
  87. Set_IIC_SDA_OUT(iicNo);
  88. IIC_SCL_OUT_1(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
  89. IIC_SDA_OUT_1(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
  90. IIC_Delay(iicNo);
  91. IIC_SDA_OUT_0(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
  92. IIC_Delay(iicNo);
  93. IIC_SCL_OUT_0(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
  94. IIC_Delay(iicNo);
  95. }
  96. /**
  97. * @brief 模拟IIC停止信号
  98. * @param None
  99. * @retval None
  100. */
  101. void IIC_stop(uint8_t iicNo)
  102. {
  103. Set_IIC_SDA_OUT(iicNo);
  104. IIC_SCL_OUT_1(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
  105. IIC_SDA_OUT_0(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
  106. IIC_Delay(iicNo);
  107. IIC_SDA_OUT_1(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
  108. }
  109. /**
  110. * @brief 模拟IIC主机应答
  111. * @param None
  112. * @retval None
  113. */
  114. void IIC_ack(uint8_t iicNo)
  115. {
  116. Set_IIC_SDA_OUT(iicNo);
  117. IIC_SDA_OUT_0(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
  118. IIC_Delay(iicNo);
  119. IIC_SCL_OUT_1(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
  120. IIC_Delay(iicNo);
  121. IIC_SCL_OUT_0(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
  122. IIC_Delay(iicNo);
  123. IIC_SDA_OUT_1(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
  124. }
  125. /**
  126. * @brief 模拟IIC主机不应答
  127. * @param None
  128. * @retval None
  129. */
  130. void IIC_noack(uint8_t iicNo)
  131. {
  132. Set_IIC_SDA_OUT(iicNo);
  133. IIC_SDA_OUT_1(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
  134. IIC_Delay(iicNo);
  135. IIC_SCL_OUT_1(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
  136. IIC_Delay(iicNo);
  137. IIC_SCL_OUT_0(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
  138. IIC_Delay(iicNo);
  139. }
  140. /**
  141. * @brief 模拟IIC等待从机应答
  142. * @param None
  143. * @retval 1: 接收应答失败 0: 接收应答成功
  144. */
  145. uint8_t IIC_wait_ack(uint8_t iicNo)
  146. {
  147. uint8_t rec = 0;
  148. Set_IIC_SDA_OUT(iicNo);
  149. IIC_SDA_OUT_1(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
  150. IIC_Delay(iicNo);
  151. Set_IIC_SDA_IN(iicNo);
  152. IIC_SCL_OUT_1(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
  153. IIC_Delay(iicNo);
  154. rec = IIC_SDA_IN(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
  155. IIC_SCL_OUT_0(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
  156. IIC_Delay(iicNo);
  157. return rec;
  158. }
  159. /**
  160. * @brief 模拟IIC发送一个字节
  161. * @param None
  162. * @retval None
  163. */
  164. void IIC_send_byte(uint8_t iicNo, uint8_t txd)
  165. {
  166. uint8_t i=0;
  167. Set_IIC_SDA_OUT(iicNo);
  168. for(i=0;i<8;i++)
  169. {
  170. if(txd&0x80) IIC_SDA_OUT_1(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
  171. else IIC_SDA_OUT_0(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
  172. IIC_Delay(iicNo);
  173. IIC_SCL_OUT_1(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
  174. IIC_Delay(iicNo); // 发送数据
  175. IIC_SCL_OUT_0(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
  176. if(i == 7) IIC_SDA_OUT_1(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN); // 最后一位数据发送完要释放SDA总线
  177. txd <<= 1;
  178. IIC_Delay(iicNo);
  179. }
  180. }
  181. /**
  182. * @brief 模拟IIC读取一个字节
  183. * @param ack: 0,读完不产生应答 1,读完产生应答
  184. * @retval 返回读取到的字节
  185. */
  186. uint8_t IIC_read_byte(uint8_t iicNo, uint8_t ack)
  187. {
  188. uint8_t i,receive=0;
  189. Set_IIC_SDA_IN(iicNo);
  190. for(i=0;i<8;i++)
  191. {
  192. receive <<= 1;
  193. IIC_SCL_OUT_1(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
  194. IIC_Delay(iicNo);
  195. if(IIC_SDA_IN(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN)) receive++; // 连续读取八位
  196. IIC_SCL_OUT_0(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
  197. IIC_Delay(iicNo);
  198. }
  199. if(!ack) IIC_noack(iicNo);
  200. else IIC_ack(iicNo);
  201. return receive; // 返回读取到的字节
  202. }