新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > I2C總線時序模擬(二)-加深理解總線協(xié)議

I2C總線時序模擬(二)-加深理解總線協(xié)議

作者: 時間:2016-11-22 來源:網(wǎng)絡(luò) 收藏
[cpp]view plaincopy
print?
  1. /********************************************************************
  2. 此程序是I2C操作平臺(主方式的軟件平臺)的底層的C子程序,如發(fā)送數(shù)據(jù)
  3. 及接收數(shù)據(jù),應(yīng)答位發(fā)送,并提供了幾個直接面對器件的操作函數(shù),它很方便的
  4. 與用戶程序連接并擴展.....
  5. 注意:函數(shù)是采用軟件延時的方法產(chǎn)生SCL脈沖,固對高晶振頻率要作
  6. 一定的修改....(本例是1us機器周期,即晶振頻率要小于12MHZ)
  7. ********************************************************************/
  8. #include/*頭文件的包含*/
  9. #include
  10. #defineucharunsignedchar/*宏定義*/
  11. #defineuintunsignedint
  12. #define_Nop()_nop_()/*定義空指令*/
  13. /*常,變量定義區(qū)*/
  14. /*端口位定義*/
  15. sbitSDA=P1^3;/*模擬I2C數(shù)據(jù)傳送位*/
  16. sbitSCL=P1^2;/*模擬I2C時鐘控制位*/
  17. /*狀態(tài)標(biāo)志*/
  18. bitack;/*應(yīng)答標(biāo)志位*/
  19. /*******************************************************************
  20. 起動總線函數(shù)
  21. 函數(shù)原型:voidStart_I2c();
  22. 功能:啟動I2C總線,即發(fā)送I2C起始條件.
  23. ********************************************************************/
  24. voidStart_I2c()
  25. {
  26. SDA=1;/*發(fā)送起始條件的數(shù)據(jù)信號*/
  27. _Nop();
  28. SCL=1;
  29. _Nop();/*起始條件建立時間大于4.7us,延時*/
  30. _Nop();
  31. _Nop();
  32. _Nop();
  33. _Nop();
  34. SDA=0;/*發(fā)送起始信號*/
  35. _Nop();/*起始條件鎖定時間大于4μs*/
  36. _Nop();
  37. _Nop();
  38. _Nop();
  39. _Nop();
  40. SCL=0;/*鉗住I2C總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù)*/
  41. _Nop();
  42. _Nop();
  43. }
  44. /*******************************************************************
  45. 結(jié)束總線函數(shù)
  46. 函數(shù)原型:voidStop_I2c();
  47. 功能:結(jié)束I2C總線,即發(fā)送I2C結(jié)束條件.
  48. ********************************************************************/
  49. voidStop_I2c()
  50. {
  51. SDA=0;/*發(fā)送結(jié)束條件的數(shù)據(jù)信號*/
  52. _Nop();/*發(fā)送結(jié)束條件的時鐘信號*/
  53. SCL=1;/*結(jié)束條件建立時間大于4μs*/
  54. _Nop();
  55. _Nop();
  56. _Nop();
  57. _Nop();
  58. _Nop();
  59. SDA=1;/*發(fā)送I2C總線結(jié)束信號*/
  60. _Nop();
  61. _Nop();
  62. _Nop();
  63. _Nop();
  64. }
  65. /*******************************************************************
  66. 字節(jié)數(shù)據(jù)傳送函數(shù)
  67. 函數(shù)原型:voidSendByte(ucharc);
  68. 功能:將數(shù)據(jù)c發(fā)送出去,可以是地址,也可以是數(shù)據(jù),發(fā)完后等待應(yīng)答,并對
  69. 此狀態(tài)位進行操作.(不應(yīng)答或非應(yīng)答都使ack=0假)
  70. 發(fā)送數(shù)據(jù)正常,ack=1;ack=0表示被控器無應(yīng)答或損壞。
  71. ********************************************************************/
  72. voidSendByte(ucharc)
  73. {
  74. ucharBitCnt;
  75. for(BitCnt=0;BitCnt<8;BitCnt++)/*要傳送的數(shù)據(jù)長度為8位*/
  76. {
  77. if((c<
  78. ;/*判斷發(fā)送位*/
  79. elseSDA=0;
  80. _Nop();
  81. SCL=1;/*置時鐘線為高,通知被控器開始接收數(shù)據(jù)位*/
  82. _Nop();
  83. _Nop();/*保證時鐘高電平周期大于4μs*/
  84. _Nop();
  85. _Nop();
  86. _Nop();
  87. SCL=0;
  88. }
  89. _Nop();
  90. _Nop();
  91. SDA=1;/*8位發(fā)送完后釋放數(shù)據(jù)線,準(zhǔn)備接收應(yīng)答位*/
  92. _Nop();
  93. _Nop();
  94. SCL=1;
  95. _Nop();
  96. _Nop();
  97. _Nop();
  98. if(SDA==1)ack=0;
  99. elseack=1;/*判斷是否接收到應(yīng)答信號*/
  100. SCL=0;
  101. _Nop();
  102. _Nop();
  103. }
  104. /*******************************************************************
  105. 字節(jié)數(shù)據(jù)傳送函數(shù)
  106. 函數(shù)原型:ucharRcvByte();
  107. 功能:用來接收從器件傳來的數(shù)據(jù),并判斷總線錯誤(不發(fā)應(yīng)答信號),
  108. 發(fā)完后請用應(yīng)答函數(shù)。
  109. ********************************************************************/
  110. ucharRcvByte()
  111. {
  112. ucharretc;
  113. ucharBitCnt;
  114. retc=0;
  115. SDA=1;/*置數(shù)據(jù)線為輸入方式*/
  116. for(BitCnt=0;BitCnt<8;BitCnt++)
  117. {
  118. _Nop();
  119. SCL=0;/*置時鐘線為低,準(zhǔn)備接收數(shù)據(jù)位*/
  120. _Nop();
  121. _Nop();/*時鐘低電平周期大于4.7μs*/
  122. _Nop();
  123. _Nop();
  124. _Nop();
  125. SCL=1;/*置時鐘線為高使數(shù)據(jù)線上數(shù)據(jù)有效*/
  126. _Nop();
  127. _Nop();
  128. retc=retc<<1;
  129. if(SDA==1)retc=retc+1;/*讀數(shù)據(jù)位,接收的數(shù)據(jù)位放入retc中*/
  130. _Nop();
  131. _Nop();
  132. }
  133. SCL=0;
  134. _Nop();
  135. _Nop();
  136. return(retc);
  137. }
  138. /********************************************************************
  139. 應(yīng)答子函數(shù)
  140. 原型:voidAck_I2c(bita);
  141. 功能:主控器進行應(yīng)答信號,(可以是應(yīng)答或非應(yīng)答信號)
  142. ********************************************************************/
  143. voidAck_I2c(bita)
  144. {
  145. if(a==0)SDA=0;/*在此發(fā)出應(yīng)答或非應(yīng)答信號*/
  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總線以便繼續(xù)接收*/
  157. _Nop();
  158. _Nop();
  159. }
  160. /*******************************************************************
  161. 向無子地址器件發(fā)送字節(jié)數(shù)據(jù)函數(shù)
  162. 函數(shù)原型:bitISendByte(ucharsla,ucahrc);
  163. 功能:從啟動總線到發(fā)送地址,數(shù)據(jù),結(jié)束總線的全過程,從器件地址sla.
  164. 如果返回1表示操作成功,否則操作有誤。
  165. 注意:使用前必須已結(jié)束總線。
  166. ********************************************************************/
  167. bitISendByte(ucharsla,ucharc)
  168. {
  169. Start_I2c();/*啟動總線*/
  170. SendByte(sla);/*發(fā)送器件地址*/
  171. if(ack==0)return(0);
  172. SendByte(c);/*發(fā)送數(shù)據(jù)*/
  173. if(ack==0)return(0);
  174. Stop_I2c();/*結(jié)束總線*/
  175. return(1);
  176. }
  177. /*******************************************************************
  178. 向有子地址器件發(fā)送多字節(jié)數(shù)據(jù)函數(shù)
  179. 函數(shù)原型:bitISendStr(ucharsla,ucharsuba,ucahr*s,ucharno);
  180. 功能:從啟動總線到發(fā)送地址,子地址,數(shù)據(jù),結(jié)束總線的全過程,從器件
  181. 地址sla,子地址suba,發(fā)送內(nèi)容是s指向的內(nèi)容,發(fā)送no個字節(jié)。
  182. 如果返回1表示操作成功,否則操作有誤。
  183. 注意:使用前必須已結(jié)束總線。
  184. ********************************************************************/
  185. bitISendStr(ucharsla,ucharsuba,uchar*s,ucharno)
  186. {
  187. uchari;
  188. Start_I2c();/*啟動總線*/
  189. SendByte(sla);/*發(fā)送器件地址*/
  190. if(ack==0)return(0);
  191. SendByte(suba);/*發(fā)送器件子地址*/
  192. if(ack==0)return(0);
  193. for(i=0;i
  194. {
  195. SendByte(*s);/*發(fā)送數(shù)據(jù)*/
  196. if(ack==0)return(0);
  197. s++;
  198. }
  199. Stop_I2c();/*結(jié)束總線*/
  200. return(1);
  201. }
  202. /*******************************************************************
  203. 向無子地址器件讀字節(jié)數(shù)據(jù)函數(shù)
  204. 函數(shù)原型:bitIRcvByte(ucharsla,ucahr*c);
  205. 功能:從啟動總線到發(fā)送地址,讀數(shù)據(jù),結(jié)束總線的全過程,從器件地
  206. 址sla,返回值在c.
  207. 如果返回1表示操作成功,否則操作有誤。
  208. 注意:使用前必須已結(jié)束總線。
  209. ********************************************************************/
  210. bitIRcvByte(ucharsla,uchar*c)
  211. {
  212. Start_I2c();/*啟動總線*/
  213. SendByte(sla+1);/*發(fā)送器件地址*/
  214. if(ack==0)return(0);
  215. *c=RcvByte();/*讀取數(shù)據(jù)*/
  216. Ack_I2c(1);/*發(fā)送非就答位*/
  217. Stop_I2c();/*結(jié)束總線*/
  218. return(1);
  219. }
  220. /*******************************************************************
  221. 向有子地址器件讀取多字節(jié)數(shù)據(jù)函數(shù)
  222. 函數(shù)原型:bitISendStr(ucharsla,ucharsuba,ucahr*s,ucharno);
  223. 功能:從啟動總線到發(fā)送地址,子地址,讀數(shù)據(jù),結(jié)束總線的全過程,從器件
  224. 地址sla,子地址suba,讀出的內(nèi)容放入s指向的存儲區(qū),讀no個字節(jié)。
  225. 如果返回1表示操作成功,否則操作有誤。
  226. 注意:使用前必須已結(jié)束總線。
  227. ********************************************************************/
  228. bitIRcvStr(ucharsla,ucharsuba,uchar*s,ucharno)
  229. {
  230. uchari;
  231. Start_I2c();/*啟動總線*/
  232. SendByte(sla);/*發(fā)送器件地址*/
  233. if(ack==0)return(0);
  234. SendByte(suba);/*發(fā)送器件子地址*/
  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();/*發(fā)送數(shù)據(jù)*/
  242. Ack_I2c(0);/*發(fā)送就答位*/
  243. s++;
  244. }
  245. *s=RcvByte();
  246. Ack_I2c(1);/*發(fā)送非應(yīng)位*/
  247. Stop_I2c();/*結(jié)束總線*/
  248. return(1);
  249. }
  250. /*完畢*/


評論


技術(shù)專區(qū)

關(guān)閉