您的位置 首页 设计

I2C总线时序模拟(二)-加深了解总线协议

[cpp]viewplaincopyprint?********************************************************************此程序是I2C操

[cpp]view plaincopy

print?

  1. /********************************************************************
  2. 此程序是I2C操作渠道(主办法的软件渠道)的底层的C子程序,如发送数据
  3. 及接纳数据,应对位发送,并供给了几个直接面临器材的操作函数,它很便利的
  4. 与用户程序衔接并扩展…..
  5. 留意:函数是选用软件延时的办法发生SCL脉冲,固对高晶振频率要作
  6. 必定的修正….(本例是1us机器周期,即晶振频率要小于12MHZ)
  7. ********************************************************************/
  8. #include/*头文件的包括*/
  9. #include
  10. #defineucharunsignedchar/*宏界说*/
  11. #defineuintunsignedint
  12. #define_Nop()_nop_()/*界说空指令*/
  13. /*常,变量界说区*/
  14. /*端口位界说*/
  15. sbitSDA=P1^3;/*模仿I2C数据传送位*/
  16. sbitSCL=P1^2;/*模仿I2C时钟操控位*/
  17. /*状况标志*/
  18. bitack;/*应对标志位*/
  19. /*******************************************************************
  20. 起动总线函数
  21. 函数原型:voidStart_I2c();
  22. 功用:发动I2C总线,即发送I2C开端条件.
  23. ********************************************************************/
  24. voidStart_I2c()
  25. {
  26. SDA=1;/*发送开端条件的数据信号*/
  27. _Nop();
  28. SCL=1;
  29. _Nop();/*开端条件树立时刻大于4.7us,延时*/
  30. _Nop();
  31. _Nop();
  32. _Nop();
  33. _Nop();
  34. SDA=0;/*发送开端信号*/
  35. _Nop();/*开端条件确定时刻大于4μs*/
  36. _Nop();
  37. _Nop();
  38. _Nop();
  39. _Nop();
  40. SCL=0;/*钳住I2C总线,预备发送或接纳数据*/
  41. _Nop();
  42. _Nop();
  43. }
  44. /*******************************************************************
  45. 结束总线函数
  46. 函数原型:voidStop_I2c();
  47. 功用:结束I2C总线,即发送I2C结束条件.
  48. ********************************************************************/
  49. voidStop_I2c()
  50. {
  51. SDA=0;/*发送结束条件的数据信号*/
  52. _Nop();/*发送结束条件的时钟信号*/
  53. SCL=1;/*结束条件树立时刻大于4μs*/
  54. _Nop();
  55. _Nop();
  56. _Nop();
  57. _Nop();
  58. _Nop();
  59. SDA=1;/*发送I2C总线结束信号*/
  60. _Nop();
  61. _Nop();
  62. _Nop();
  63. _Nop();
  64. }
  65. /*******************************************************************
  66. 字节数据传送函数
  67. 函数原型:voidSendByte(ucharc);
  68. 功用:将数据c发送出去,可所以地址,也可所以数据,发完后等候应对,并对
  69. 此状况位进行操作.(不应对或非应对都使ack=0假)
  70. 发送数据正常,ack=1;ack=0表明被控器无应对或损坏。
  71. ********************************************************************/
  72. voidSendByte(ucharc)
  73. {
  74. ucharBitCnt;
  75. for(BitCnt=0;BitCnt<8;BitCnt++)/*要传送的数据长度为8位*/
  76. {
  77. if((c<
  78. ;/*判别发送位*/
  79. elseSDA=0;
  80. _Nop();
  81. SCL=1;/*置时钟线为高,告诉被控器开端接纳数据位*/
  82. _Nop();
  83. _Nop();/*确保时钟高电平周期大于4μs*/
  84. _Nop();
  85. _Nop();
  86. _Nop();
  87. SCL=0;
  88. }
  89. _Nop();
  90. _Nop();
  91. SDA=1;/*8位发送完后开释数据线,预备接纳应对位*/
  92. _Nop();
  93. _Nop();
  94. SCL=1;
  95. _Nop();
  96. _Nop();
  97. _Nop();
  98. if(SDA==1)ack=0;
  99. elseack=1;/*判别是否接纳到应对信号*/
  100. SCL=0;
  101. _Nop();
  102. _Nop();
  103. }
  104. /*******************************************************************
  105. 字节数据传送函数
  106. 函数原型:ucharRcvByte();
  107. 功用:用来接纳从器材传来的数据,并判别总线过错(不发应对信号),
  108. 发完后请用应对函数。
  109. ********************************************************************/
  110. ucharRcvByte()
  111. {
  112. ucharretc;
  113. ucharBitCnt;
  114. retc=0;
  115. SDA=1;/*置数据线为输入办法*/
  116. for(BitCnt=0;BitCnt<8;BitCnt++)
  117. {
  118. _Nop();
  119. SCL=0;/*置时钟线为低,预备接纳数据位*/
  120. _Nop();
  121. _Nop();/*时钟低电平周期大于4.7μs*/
  122. _Nop();
  123. _Nop();
  124. _Nop();
  125. SCL=1;/*置时钟线为高使数据线上数据有用*/
  126. _Nop();
  127. _Nop();
  128. retc=retc<<1;
  129. if(SDA==1)retc=retc+1;/*读数据位,接纳的数据位放入retc中*/
  130. _Nop();
  131. _Nop();
  132. }
  133. SCL=0;
  134. _Nop();
  135. _Nop();
  136. return(retc);
  137. }
  138. /********************************************************************
  139. 应对子函数
  140. 原型:voidAck_I2c(bita);
  141. 功用:主控器进行应对信号,(可所以应对或非应对信号)
  142. ********************************************************************/
  143. voidAck_I2c(bita)
  144. {
  145. if(a==0)SDA=0;/*在此宣布应对或非应对信号*/
  146. elseSDA=1;
  147. _Nop();
  148. _Nop();
  149. _Nop();
  150. SCL=1;
  151. _Nop();
  152. _Nop();/*时钟低电平周期大于4μs*/
  153. _Nop();
  154. _Nop();
  155. _Nop();
  156. SCL=0;/*清时钟线,钳住I2C总线以便持续接纳*/
  157. _Nop();
  158. _Nop();
  159. }
  160. /*******************************************************************
  161. 向无子地址器材发送字节数据函数
  162. 函数原型:bitISendByte(ucharsla,ucahrc);
  163. 功用:从发动总线到发送地址,数据,结束总线的全过程,从器材地址sla.
  164. 假如回来1表明操作成功,不然操作有误。
  165. 留意:运用前有必要已结束总线。
  166. ********************************************************************/
  167. bitISendByte(ucharsla,ucharc)
  168. {
  169. Start_I2c();/*发动总线*/
  170. SendByte(sla);/*发送器材地址*/
  171. if(ack==0)return(0);
  172. SendByte(c);/*发送数据*/
  173. if(ack==0)return(0);
  174. Stop_I2c();/*结束总线*/
  175. return(1);
  176. }
  177. /*******************************************************************
  178. 向有子地址器材发送多字节数据函数
  179. 函数原型:bitISendStr(ucharsla,ucharsuba,ucahr*s,ucharno);
  180. 功用:从发动总线到发送地址,子地址,数据,结束总线的全过程,从器材
  181. 地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
  182. 假如回来1表明操作成功,不然操作有误。
  183. 留意:运用前有必要已结束总线。
  184. ********************************************************************/
  185. bitISendStr(ucharsla,ucharsuba,uchar*s,ucharno)
  186. {
  187. uchari;
  188. Start_I2c();/*发动总线*/
  189. SendByte(sla);/*发送器材地址*/
  190. if(ack==0)return(0);
  191. SendByte(suba);/*发送器材子地址*/
  192. if(ack==0)return(0);
  193. for(i=0;i
  194. {
  195. SendByte(*s);/*发送数据*/
  196. if(ack==0)return(0);
  197. s++;
  198. }
  199. Stop_I2c();/*结束总线*/
  200. return(1);
  201. }
  202. /*******************************************************************
  203. 向无子地址器材读字节数据函数
  204. 函数原型:bitIRcvByte(ucharsla,ucahr*c);
  205. 功用:从发动总线到发送地址,读数据,结束总线的全过程,从器材地
  206. 址sla,回来值在c.
  207. 假如回来1表明操作成功,不然操作有误。
  208. 留意:运用前有必要已结束总线。
  209. ********************************************************************/
  210. bitIRcvByte(ucharsla,uchar*c)
  211. {
  212. Start_I2c();/*发动总线*/
  213. SendByte(sla+1);/*发送器材地址*/
  214. if(ack==0)return(0);
  215. *c=RcvByte();/*读取数据*/
  216. Ack_I2c(1);/*发送非就答位*/
  217. Stop_I2c();/*结束总线*/
  218. return(1);
  219. }
  220. /*******************************************************************
  221. 向有子地址器材读取多字节数据函数
  222. 函数原型:bitISendStr(ucharsla,ucharsuba,ucahr*s,ucharno);
  223. 功用:从发动总线到发送地址,子地址,读数据,结束总线的全过程,从器材
  224. 地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
  225. 假如回来1表明操作成功,不然操作有误。
  226. 留意:运用前有必要已结束总线。
  227. ********************************************************************/
  228. bitIRcvStr(ucharsla,ucharsuba,uchar*s,ucharno)
  229. {
  230. uchari;
  231. Start_I2c();/*发动总线*/
  232. SendByte(sla);/*发送器材地址*/
  233. if(ack==0)return(0);
  234. SendByte(suba);/*发送器材子地址*/
  235. if(ack==0)return(0);
  236. Start_I2c();
  237. SendByte(sla+1);
  238. if(ack==0)return(0);
  239. for(i=0;i
  240. {
  241. *s=RcvByte();/*发送数据*/
  242. Ack_I2c(0);/*发送就答位*/
  243. s++;
  244. }
  245. *s=RcvByte();
  246. Ack_I2c(1);/*发送非应位*/
  247. Stop_I2c();/*结束总线*/
  248. return(1);
  249. }
  250. /*结束*/

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ziliao/sheji/262429.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部