MLX90640_SWI2C_Driver.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /**
  2. * @copyright (C) 2017 Melexis N.V.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. /**
  18. * As the timings depend heavily on the MCU in use, it is recommended
  19. * to make sure that the proper timings are achieved. For that purpose
  20. * an oscilloscope might be needed to strobe the SCL and SDA signals.
  21. * The Wait(int) function could be modified in order to better
  22. * trim the frequency. For coarse setting of the frequency or
  23. * dynamic frequency change using the default function implementation,
  24. * ‘freqCnt’ argument should be changed – lower value results in
  25. * higher frequency.
  26. */
  27. #include "MLX90640_I2C_Driver.h"
  28. #include "main.h"
  29. #define SCL_HIGH HAL_GPIO_WritePin(GPIOA,IIC_SCL_Pin,GPIO_PIN_SET)
  30. #define SCL_LOW HAL_GPIO_WritePin(GPIOA,IIC_SCL_Pin,GPIO_PIN_RESET)
  31. #define SDA_HIGH HAL_GPIO_WritePin(GPIOA,IIC_SDA_Pin,GPIO_PIN_SET)
  32. #define SDA_LOW HAL_GPIO_WritePin(GPIOA,IIC_SDA_Pin,GPIO_PIN_RESET)
  33. // 将 SDA 配置为输入模式
  34. #define SDA_IN { \
  35. GPIO_InitTypeDef GPIO_InitStruct = {0}; \
  36. GPIO_InitStruct.Pin = IIC_SDA_Pin; \
  37. GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \
  38. GPIO_InitStruct.Pull = GPIO_NOPULL; \
  39. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); \
  40. }
  41. // 将 SDA 配置为输出模式
  42. #define SDA_OUT { \
  43. GPIO_InitTypeDef GPIO_InitStruct = {0}; \
  44. GPIO_InitStruct.Pin = IIC_SDA_Pin; \
  45. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; \
  46. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; \
  47. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); \
  48. }
  49. #define sda HAL_GPIO_ReadPin(GPIOA,IIC_SDA_Pin)
  50. char i2cData[1664] = {0}; // MLX90640_I2CRead
  51. int I2CSendByte(int8_t);
  52. void I2CReadBytes(int, char *);
  53. void I2CStart(void);
  54. void I2CStop(void);
  55. void I2CRepeatedStart(void);
  56. void I2CSendACK(void);
  57. void I2CSendNack(void);
  58. int I2CReceiveAck(void);
  59. void Wait(int);
  60. static int freqCnt = 5;
  61. void MLX90640_I2CInit()
  62. {
  63. GPIO_InitTypeDef GPIO_InitStruct = {0};
  64. __HAL_RCC_GPIOA_CLK_ENABLE();
  65. /*Configure GPIO pins : PA9 SCL */
  66. GPIO_InitStruct.Pin = IIC_SCL_Pin;
  67. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  68. GPIO_InitStruct.Pull = GPIO_NOPULL;
  69. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  70. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  71. /*Configure GPIO pins : PA10 SDA*/
  72. GPIO_InitStruct.Pin = IIC_SDA_Pin;
  73. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  74. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  75. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  76. HAL_GPIO_WritePin(GPIOA, IIC_SDA_Pin, GPIO_PIN_SET);
  77. HAL_GPIO_WritePin(GPIOA, IIC_SCL_Pin, GPIO_PIN_SET);
  78. I2CStop();
  79. }
  80. int MLX90640_I2CRead(uint8_t slaveAddr, uint16_t startAddress,uint16_t nMemAddressRead, uint16_t *data)
  81. {
  82. uint8_t sa;
  83. int ack = 0;
  84. int cnt = 0;
  85. int i = 0;
  86. char cmd[2] = {0,0};
  87. // char i2cData[1664] = {0};
  88. uint16_t *p;
  89. p = data;
  90. sa = (slaveAddr << 1);
  91. cmd[0] = startAddress >> 8;
  92. cmd[1] = startAddress & 0x00FF;
  93. I2CStop();
  94. Wait(freqCnt);
  95. I2CStart();
  96. Wait(freqCnt);
  97. ack = I2CSendByte(sa);
  98. if(ack != 0)
  99. {
  100. return -1;
  101. }
  102. ack = I2CSendByte(cmd[0]);
  103. if(ack != 0)
  104. {
  105. return -1;
  106. }
  107. ack = I2CSendByte(cmd[1]);
  108. if(ack != 0)
  109. {
  110. return -1;
  111. }
  112. I2CRepeatedStart();
  113. sa = sa | 0x01;
  114. ack = I2CSendByte(sa);
  115. if(ack != 0)
  116. {
  117. return -1;
  118. }
  119. I2CReadBytes((nMemAddressRead << 1), i2cData);
  120. I2CStop();
  121. for(cnt=0; cnt < nMemAddressRead; cnt++)
  122. {
  123. i = cnt << 1;
  124. *p++ = ((int16_t)i2cData[i]<<8 )|(int16_t)i2cData[i+1];
  125. // *p++ = (int)i2cData[i]*256 + (int)i2cData[i+1];
  126. }
  127. return 0;
  128. }
  129. void MLX90640_I2CFreqSet(int freq)
  130. {
  131. freqCnt = freq>>1;
  132. }
  133. int MLX90640_I2CWrite(uint8_t slaveAddr, uint16_t writeAddress, uint16_t data)
  134. {
  135. uint8_t sa;
  136. int ack = 0;
  137. char cmd[4] = {0,0,0,0};
  138. static uint16_t dataCheck;
  139. sa = (slaveAddr << 1);
  140. cmd[0] = writeAddress >> 8;
  141. cmd[1] = writeAddress & 0x00FF;
  142. cmd[2] = data >> 8;
  143. cmd[3] = data & 0x00FF;
  144. I2CStop();
  145. Wait(freqCnt);
  146. I2CStart();
  147. ack = I2CSendByte(sa);
  148. if (ack != 0x00)
  149. {
  150. return 1;
  151. }
  152. for(int i = 0; i<4; i++)
  153. {
  154. ack = I2CSendByte(cmd[i]);
  155. if (ack != 0x00)
  156. {
  157. return -1;
  158. }
  159. }
  160. I2CStop();
  161. MLX90640_I2CRead(slaveAddr,writeAddress,1, &dataCheck);
  162. if ( dataCheck != data)
  163. {
  164. return -2;
  165. }
  166. return 0;
  167. }
  168. int I2CSendByte(int8_t data)
  169. {
  170. int ack = 1;
  171. int8_t byte = data;
  172. // SDA_OUT;
  173. for(int i=0;i<8;i++)
  174. {
  175. Wait(freqCnt);
  176. if(byte & 0x80)
  177. {
  178. SDA_HIGH;
  179. }
  180. else
  181. {
  182. SDA_LOW;
  183. }
  184. Wait(freqCnt);
  185. SCL_HIGH;
  186. Wait(freqCnt);
  187. Wait(freqCnt);
  188. SCL_LOW;
  189. byte = byte<<1;
  190. }
  191. Wait(freqCnt);
  192. ack = I2CReceiveAck();
  193. return ack;
  194. }
  195. void I2CReadBytes(int nBytes, char *dataP)
  196. {
  197. char data;
  198. for(int j=0;j<nBytes;j++)
  199. {
  200. Wait(freqCnt);
  201. // SDA_IN;
  202. data = 0;
  203. for(int i=0;i<8;i++){
  204. Wait(freqCnt);
  205. SCL_HIGH;
  206. Wait(freqCnt);
  207. data = data<<1;
  208. if(sda == 1){
  209. data = data+1;
  210. }
  211. Wait(freqCnt);
  212. SCL_LOW;
  213. Wait(freqCnt);
  214. }
  215. if(j == (nBytes-1))
  216. {
  217. I2CSendNack();
  218. }
  219. else
  220. {
  221. I2CSendACK();
  222. }
  223. *(dataP+j) = data;
  224. }
  225. }
  226. void Wait(int freqCnt)
  227. {
  228. int cnt;
  229. // for(int i = 0;i<freqCnt;i++)
  230. // {
  231. // cnt = cnt++;
  232. // }
  233. while(freqCnt--)
  234. for(cnt=7;cnt>0;cnt--);
  235. }
  236. void I2CStart(void)
  237. {
  238. // SDA_OUT;
  239. SDA_HIGH;
  240. SCL_HIGH;
  241. Wait(freqCnt);
  242. Wait(freqCnt);
  243. SDA_LOW;
  244. Wait(freqCnt);
  245. SCL_LOW;
  246. Wait(freqCnt);
  247. }
  248. void I2CStop(void)
  249. {
  250. // SDA_OUT;
  251. SCL_LOW;
  252. SDA_LOW;
  253. Wait(freqCnt);
  254. SCL_HIGH;
  255. Wait(freqCnt);
  256. SDA_HIGH;
  257. Wait(freqCnt);
  258. }
  259. void I2CRepeatedStart(void)
  260. {
  261. // SDA_OUT;
  262. SCL_LOW;
  263. Wait(freqCnt);
  264. SDA_HIGH;
  265. Wait(freqCnt);
  266. SCL_HIGH;
  267. Wait(freqCnt);
  268. SDA_LOW;
  269. Wait(freqCnt);
  270. SCL_LOW;
  271. }
  272. void I2CSendACK(void)
  273. {
  274. // SDA_OUT;
  275. SDA_LOW;
  276. Wait(freqCnt);
  277. SCL_HIGH;
  278. Wait(freqCnt);
  279. Wait(freqCnt);
  280. SCL_LOW;
  281. Wait(freqCnt);
  282. SDA_HIGH;
  283. }
  284. void I2CSendNack(void)
  285. {
  286. // SDA_OUT;
  287. SDA_HIGH;
  288. Wait(freqCnt);
  289. SCL_HIGH;
  290. Wait(freqCnt);
  291. Wait(freqCnt);
  292. SCL_LOW;
  293. Wait(freqCnt);
  294. SDA_HIGH;
  295. }
  296. int I2CReceiveAck(void)
  297. {
  298. int ack;
  299. // SDA_IN;
  300. Wait(freqCnt);
  301. SCL_HIGH;
  302. Wait(freqCnt);
  303. if(sda == 0)
  304. {
  305. ack = 0;
  306. }
  307. else
  308. {
  309. ack = 1;
  310. }
  311. Wait(freqCnt);
  312. SCL_LOW;
  313. SDA_LOW;
  314. return ack;
  315. }