MLX90614.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. #include "MLX90614.h"
  2. #define ACK 0
  3. #define NACK 1
  4. #define SA 0x00
  5. #define RAM_ACCESS 0x00
  6. #define EEPROM_ACCESS 0x20
  7. #define RAM_TOBJ1 0x07
  8. #define SMBUS_PORT GPIOB
  9. #define SMBUS_SCK GPIO_Pin_7
  10. #define SMBUS_SDA GPIO_Pin_6
  11. #define RCC_APB2Periph_SMBUS_PORT RCC_APB2Periph_GPIOB
  12. #define SMBUS_SCK_H() SMBUS_PORT->BSRR = SMBUS_SCK
  13. #define SMBUS_SCK_L() SMBUS_PORT->BRR = SMBUS_SCK
  14. #define SMBUS_SDA_H() SMBUS_PORT->BSRR = SMBUS_SDA
  15. #define SMBUS_SDA_L() SMBUS_PORT->BRR = SMBUS_SDA
  16. #define SMBUS_SDA_PIN() SMBUS_PORT->IDR & SMBUS_SDA
  17. void SMBus_StartBit(void)
  18. {
  19. SMBUS_SDA_H(); // Set SDA line
  20. SMBus_Delay(8); // Wait a few microseconds
  21. SMBUS_SCK_H(); // Set SCL line
  22. SMBus_Delay(8); // Generate bus free time between Stop
  23. SMBUS_SDA_L(); // Clear SDA line
  24. SMBus_Delay(8); // Hold time after (Repeated) Start
  25. // Condition. After this period, the first clock is generated.
  26. //(Thd:sta=4.0us min)
  27. SMBUS_SCK_L(); // Clear SCL line
  28. SMBus_Delay(8); // Wait a few microseconds
  29. }
  30. void SMBus_StopBit(void)
  31. {
  32. SMBUS_SCK_L(); // Clear SCL line
  33. SMBus_Delay(8); // Wait a few microseconds
  34. SMBUS_SDA_L(); // Clear SDA line
  35. SMBus_Delay(8); // Wait a few microseconds
  36. SMBUS_SCK_H(); // Set SCL line
  37. SMBus_Delay(8); // Stop condition setup time(Tsu:sto=4.0us min)
  38. SMBUS_SDA_H(); // Set SDA line
  39. }
  40. u8 SMBus_SendByte(u8 Tx_buffer)
  41. {
  42. u8 Bit_counter;
  43. u8 Ack_bit;
  44. u8 bit_out;
  45. for(Bit_counter=8; Bit_counter; Bit_counter--)
  46. {
  47. if (Tx_buffer&0x80)
  48. {
  49. bit_out=1; // If the current bit of Tx_buffer is 1 set bit_out
  50. }
  51. else
  52. {
  53. bit_out=0; // else clear bit_out
  54. }
  55. SMBus_SendBit(bit_out); // Send the current bit on SDA
  56. Tx_buffer<<=1; // Get next bit for checking
  57. }
  58. Ack_bit=SMBus_ReceiveBit(); // Get acknowledgment bit
  59. return Ack_bit;
  60. }
  61. void SMBus_SendBit(u8 bit_out)
  62. {
  63. if(bit_out==0)
  64. {
  65. SMBUS_SDA_L();
  66. }
  67. else
  68. {
  69. SMBUS_SDA_H();
  70. }
  71. SMBus_Delay(6); // Tsu:dat = 250ns minimum
  72. SMBUS_SCK_H(); // Set SCL line
  73. SMBus_Delay(8); // High Level of Clock Pulse
  74. SMBUS_SCK_L(); // Clear SCL line
  75. SMBus_Delay(8); // Low Level of Clock Pulse
  76. return;
  77. }
  78. u8 SMBus_ReceiveBit(void)
  79. {
  80. u8 Ack_bit;
  81. SMBUS_SDA_H();
  82. SMBus_Delay(6); // High Level of Clock Pulse
  83. SMBUS_SCK_H(); // Set SCL line
  84. SMBus_Delay(8); // High Level of Clock Pulse
  85. if (SMBUS_SDA_PIN())
  86. {
  87. Ack_bit=1;
  88. }
  89. else
  90. {
  91. Ack_bit=0;
  92. }
  93. SMBUS_SCK_L(); // Clear SCL line
  94. SMBus_Delay(8); // Low Level of Clock Pulse
  95. return Ack_bit;
  96. }
  97. u8 SMBus_ReceiveByte(u8 ack_nack)
  98. {
  99. u8 RX_buffer;
  100. u8 Bit_Counter;
  101. for(Bit_Counter=8; Bit_Counter; Bit_Counter--)
  102. {
  103. if(SMBus_ReceiveBit()) // Get a bit from the SDA line
  104. {
  105. RX_buffer <<= 1; // If the bit is HIGH save 1 in RX_buffer
  106. RX_buffer |=0x01;
  107. }
  108. else
  109. {
  110. RX_buffer <<= 1; // If the bit is LOW save 0 in RX_buffer
  111. RX_buffer &=0xfe;
  112. }
  113. }
  114. SMBus_SendBit(ack_nack); // Sends acknowledgment bit
  115. return RX_buffer;
  116. }
  117. void SMBus_Delay(u16 time)
  118. {
  119. u16 i, j;
  120. for (i=0; i<5; i++)
  121. {
  122. for (j=0; j<time; j++);
  123. }
  124. }
  125. void SMBus_Init()
  126. {
  127. GPIO_InitTypeDef GPIO_InitStructure;
  128. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SMBUS_PORT, ENABLE);
  129. GPIO_InitStructure.GPIO_Pin = SMBUS_SCK | SMBUS_SDA;
  130. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
  131. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  132. GPIO_Init(SMBUS_PORT, &GPIO_InitStructure);
  133. SMBUS_SCK_H();
  134. SMBUS_SDA_H();
  135. }
  136. u16 SMBus_ReadMemory(u8 slaveAddress, u8 command)
  137. {
  138. u16 data; // Data storage (DataH:DataL)
  139. u8 Pec; // PEC byte storage
  140. u8 DataL=0; // Low data byte storage
  141. u8 DataH=0; // High data byte storage
  142. u8 arr[6]; // Buffer for the sent bytes
  143. u8 PecReg; // Calculated PEC byte storage
  144. u8 ErrorCounter; // Defines the number of the attempts for communication with MLX90614
  145. ErrorCounter=0x00; // Initialising of ErrorCounter
  146. slaveAddress <<= 1; //2-7???????
  147. do
  148. {
  149. repeat:
  150. SMBus_StopBit(); //If slave send NACK stop comunication
  151. --ErrorCounter; //Pre-decrement ErrorCounter
  152. if(!ErrorCounter) //ErrorCounter=0?
  153. {
  154. break; //Yes,go out from do-while{}
  155. }
  156. SMBus_StartBit(); //Start condition
  157. if(SMBus_SendByte(slaveAddress))//Send SlaveAddress ???Wr=0????????
  158. {
  159. goto repeat; //Repeat comunication again
  160. }
  161. if(SMBus_SendByte(command)) //Send command
  162. {
  163. goto repeat; //Repeat comunication again
  164. }
  165. SMBus_StartBit(); //Repeated Start condition
  166. if(SMBus_SendByte(slaveAddress+1)) //Send SlaveAddress ???Rd=1????????
  167. {
  168. goto repeat; //Repeat comunication again
  169. }
  170. DataL = SMBus_ReceiveByte(ACK); //Read low data,master must send ACK
  171. DataH = SMBus_ReceiveByte(ACK); //Read high data,master must send ACK
  172. Pec = SMBus_ReceiveByte(NACK); //Read PEC byte, master must send NACK
  173. SMBus_StopBit(); //Stop condition
  174. arr[5] = slaveAddress; //
  175. arr[4] = command; //
  176. arr[3] = slaveAddress+1; //Load array arr
  177. arr[2] = DataL; //
  178. arr[1] = DataH; //
  179. arr[0] = 0; //
  180. PecReg=PEC_Calculation(arr);//Calculate CRC
  181. }
  182. while(PecReg != Pec); //If received and calculated CRC are equal go out from do-while{}
  183. data = (DataH<<8) | DataL; //data=DataH:DataL
  184. return data;
  185. }
  186. u8 PEC_Calculation(u8 pec[])
  187. {
  188. u8 crc[6];
  189. u8 BitPosition=47;
  190. u8 shift;
  191. u8 i;
  192. u8 j;
  193. u8 temp;
  194. do
  195. {
  196. /*Load pattern value 0x000000000107*/
  197. crc[5]=0;
  198. crc[4]=0;
  199. crc[3]=0;
  200. crc[2]=0;
  201. crc[1]=0x01;
  202. crc[0]=0x07;
  203. /*Set maximum bit position at 47 ( six bytes byte5...byte0,MSbit=47)*/
  204. BitPosition=47;
  205. /*Set shift position at 0*/
  206. shift=0;
  207. /*Find first "1" in the transmited message beginning from the MSByte byte5*/
  208. i=5;
  209. j=0;
  210. while((pec[i]&(0x80>>j))==0 && i>0)
  211. {
  212. BitPosition--;
  213. if(j<7)
  214. {
  215. j++;
  216. }
  217. else
  218. {
  219. j=0x00;
  220. i--;
  221. }
  222. }/*End of while */
  223. /*Get shift value for pattern value*/
  224. shift=BitPosition-8;
  225. /*Shift pattern value */
  226. while(shift)
  227. {
  228. for(i=5; i<0xFF; i--)
  229. {
  230. if((crc[i-1]&0x80) && (i>0))
  231. {
  232. temp=1;
  233. }
  234. else
  235. {
  236. temp=0;
  237. }
  238. crc[i]<<=1;
  239. crc[i]+=temp;
  240. }/*End of for*/
  241. shift--;
  242. }/*End of while*/
  243. /*Exclusive OR between pec and crc*/
  244. for(i=0; i<=5; i++)
  245. {
  246. pec[i] ^=crc[i];
  247. }/*End of for*/
  248. }
  249. while(BitPosition>8); /*End of do-while*/
  250. return pec[0];
  251. }
  252. float SMBus_ReadTemp(void)
  253. {
  254. return (SMBus_ReadMemory(SA, RAM_ACCESS|RAM_TOBJ1)*0.02-273.15);
  255. }