[经验分享] 【GD32F350开发分享七】GPIO模拟I2C驱动

Justice_Gao   2018-10-9 19:58 楼主
我的作品没有用到I2C,有空的时候改了一下,仅供大家才考一下
  1. #include "I2C.h"
  2. #define SCL_HIGH gpio_bit_set(GPIOC, GPIO_PIN_10)
  3. #define SCL_LOW gpio_bit_reset(GPIOC, GPIO_PIN_10)
  4. #define RESET_HIGH gpio_bit_set(GPIOC, GPIO_PIN_11)
  5. #define RESET_LOW gpio_bit_reset(GPIOC, GPIO_PIN_11)
  6. #define POWERDOWN_HIGH gpio_bit_set(GPIOC, GPIO_PIN_12)
  7. #define POWERDOWN_LOW gpio_bit_reset(GPIOC, GPIO_PIN_12)
  8. #define SDA_HIGH gpio_bit_set(GPIOC, GPIO_PIN_13)
  9. #define SDA_LOW gpio_bit_reset(GPIOC, GPIO_PIN_13)
  10. #define SDA_READ gpio_input_bit_get(GPIOC, GPIO_PIN_13)
  11. void I2C_delay(void)
  12. {
  13. uint32_t t=300*13.5;
  14. while(t--);
  15. }
  16. void nops1ms(void) //1ms
  17. {
  18. uint32_t t=8000*13.5;
  19. while(t--);
  20. }
  21. void delay_50ms(void) //50ms
  22. {
  23. uint t=50;
  24. for(t=0;t<50;t++)
  25. nops1ms();
  26. }
  27. void Delay(void)
  28. {
  29. nops1ms();
  30. nops1ms();
  31. }
  32. int I2C_Start(void)
  33. {
  34. SDA_HIGH;
  35. SCL_HIGH;//高电平有效
  36. I2C_delay();//延时
  37. if(!SDA_READ)
  38. {
  39. return DISABLE;//SDA总线忙,退出
  40. }
  41. SDA_LOW;
  42. I2C_delay();
  43. //查看此时SDA已经变为低电平
  44. if(SDA_READ)
  45. return DISABLE;//SDA总线忙,退出
  46. }
  47. SCL_LOW;
  48. return ENABLE;
  49. }
  50. void I2C_Stop(void)
  51. {
  52. SCL_LOW;
  53. //制造一个上升沿,上升沿是结束的标志
  54. SDA_LOW;
  55. SCL_HIGH;//高电平有效
  56. I2C_delay();//延时
  57. SDA_HIGH;
  58. I2C_delay();
  59. }
  60. void I2C_Ack()
  61. {
  62. SCL_LOW;
  63. SDA_LOW;//置低
  64. I2C_delay(); //注意延时时间应该大于4微秒,其他位置也是如此
  65. SCL_HIGH;
  66. I2C_delay();
  67. SCL_LOW;
  68. }
  69. void I2C_NoAck()
  70. {
  71. SCL_LOW;
  72. I2C_delay();
  73. SDA_HIGH;//置高
  74. I2C_delay();
  75. SCL_HIGH;
  76. I2C_delay();
  77. SCL_LOW;
  78. }
  79. uint8_t I2C_GetAck(void)
  80. {
  81. uint8_t time = 0;
  82. SDA_HIGH;
  83. I2C_delay();
  84. SCL_HIGH;
  85. I2C_delay();
  86. while(SDA_READ)
  87. {
  88. time++;
  89. if(time > 250)
  90. {
  91. SCL_LOW;
  92. return DISABLE;
  93. }
  94. }
  95. SCL_LOW;
  96. return ENABLE;
  97. }
  98. //I2C写一个字节
  99. void I2C_SendByte(uint8_t Data)
  100. {
  101. uint8_t cnt;
  102. for(cnt=0; cnt<8; cnt++)
  103. {
  104. SCL_LOW; //SCL低(SCL低时,变化SDA)
  105. I2C_delay();
  106. if(Data & 0x80)
  107. {
  108. SDA_HIGH; //SDA高,从最低位开始写起
  109. }
  110. else
  111. {
  112. SDA_LOW; //SDA低
  113. }
  114. Data <<= 1;
  115. SCL_HIGH; //SCL高(发送数据)
  116. I2C_delay();
  117. }
  118. SCL_LOW; //SCL低(等待应答信号)
  119. I2C_delay();
  120. }
  121. //I2C读取一个字节
  122. uint8_t I2C_ReadByte(uint8_t ack)
  123. {
  124. uint8_t cnt;
  125. uint8_t data;
  126. for(cnt=0; cnt<8; cnt++)
  127. {
  128. SCL_LOW; //SCL低
  129. I2C_delay();
  130. SCL_HIGH; //SCL高(读取数据)
  131. data <<= 1;
  132. if(SDA_READ)
  133. {
  134. data |= 0x01; //SDA高(数据有效)
  135. }
  136. I2C_delay();
  137. }
  138. //发送应答信号,为低代表应答,高代表非应答
  139. if(ack == 1)
  140. {
  141. I2C_NoAck();
  142. }
  143. else
  144. {
  145. I2C_Ack();
  146. }
  147. return data; //返回数据
  148. }
本帖最后由 Justice_Gao 于 2018-10-9 20:07 编辑

回复评论 (3)

开始的宏定义值得借鉴,谢谢楼主!
点赞  2018-10-10 10:24
引用: hujj 发表于 2018-10-10 10:24
开始的宏定义值得借鉴,谢谢楼主!

不客气
点赞  2018-10-10 12:28
多谢分享!
点赞  2018-10-10 18:33
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复