当前位置:   article > 正文

STM32实现MLX90614非接触测温串口显示(标准库与HAL库实现)_stm32非接触测温传感器项目全资料

stm32非接触测温传感器项目全资料

目录

模块选择

编程环境

 MLX90614基本原理

通信协议(SMBus通信,类IIC通信)

代码实现

STM32与模块之间接线表

1.标准库实现温度采集

2.HAL库实现温度采集


模块选择

        ·STM32F103C8T6

        ·MLX90614 非接触式红外测温传感器

编程环境

        ·KEIL5(μVision V5.30.0.0) 其它版本影响并不大

         ·STM32CubeMX,版本不限

         ·串口助手

 MLX90614基本原理

 引脚说明

编号名称功能
1VCC电源正,3-5V
2GND电源地
3SCL串行时钟输入
4SDA串行地址和数据输入/输出

MLX90614是一种红外温度计,用于非接触式温度测量。红外测温是根据被测物体的红外辐射能量来确定物体的温度,不与被测物体接触,具有不影响被测物体温度分布场,温度分辨率高、响应速度快、测温范围广、不受测温上限的限制、稳定性好等特点。适合于汽车空调、室内暖气、家用电器、手持设备以及医疗设备应用等。

MLX90614的出厂校准温度范围很广:环境温度为-40°C——125°C,目标温度为-70°C——380°C。测量值是传感器视场中所有物体的平均温度。在室温下,MLX90614的标准精确度为±0.5°C。

 MLX90614由MLX81101红外热电堆传感器和包括含有稳压电路、低噪声放大器、A/D转换器、DSP单元、脉宽调制电路及逻辑控制电路的MLX90302信号处理芯片构成。

其工作原理为:红外热电堆传感器输出的温度信号经过内部低噪声、低失调的运算放大器(OPA)放大后经过A/D转换器(ADC)转换为17位数字信号通过可编程FIR及IIR低通数字滤波器(即DSP)处理后输出,输出结果存储在其内部RAM存储单元中。
MLX90614 是由内部状态机控制物体温度和环境温度的测量和计算,进行温度后处理,并将结果通过 PWM 或是 SMBus 模式输出。 ASSP 支持两个 IR 传感器。 (MLX90614xAx 只有一个 IR 传感器) IR 传感器的输出通过增益可编程的低噪声低失 调电压放大器放大,经过 Sigma Delta 调制器转换为单一比特流并反馈给 DSP 做后续的处理。信号通过可编程的 (用 EEPROM 实现) FIR 和 IIR 低通滤波器以进一步减低输入信号的带宽从而达到所需的噪声特性和刷新率。IIR 滤波器的输出为测量结果并存于内部 RAM 中,其中三个单元可被用到:一个是片内温度传感器(片上 PTAT 或 PTC),其余两个为 IR 传感器。 基于以上测量结果,计算出对应的环境温度 Ta物体温度 To,两个温度分辨率都为 0.01 ˚C。Ta 和 To 可通过两种方式读取:通过两线接口读取 RAM 单元,(0.02°C 分辨率,固定范围) 或者通过 PWM 数字模式输出。 (10 位分辨率, 范围可配置) 测量周期的最后一步为:测量所得 Ta 和 To 被重新调节为 PWM 所需的输出分辨率,并且该数据存在 PWM 状态 机的寄存器中,状态机可以产生固定频率和一定占空比来表示测量的数据。

通信协议(SMBus通信,类IIC通信)

单片机与MLX90614红外测温模块之间通信的方式是“类IIC”通信,意思就是通信方式跟IIC通信方式很像但又不是IIC,它有另外一个名字叫做SMBus。SMBus (System Management Bus)是 1995 年由 intel 公司提出的一种高效同步串行总线,SMBus 只有两根信号线:双向数据线和时钟信号线,容许 CPU 与各种外围接口器件以串行方式进行通信、交换信息,既可以提高传输速度也可以减小器件的资源占用,另外即使在没有SMBus 接口的单片机上也可利用软件进行模拟。

代码实现

STM32与模块之间接线表
MLX90614STM32F103C8T6
VCCVCC
GNDGND
SCLPB8
SDAPB9
-PA9(USART1_ TX)
-PA10(USART1_RX)
1.标准库实现温度采集

主函数:

  1. int main(void)
  2. {
  3. float Temperature=10;
  4. char temStr[100] = "";
  5. int i = 0; // 循环变量
  6. delay_init(); // 延时函数初始化配置
  7. uart_init(115200);
  8. USART_SendData(USART1, 'A');
  9. Mlx96014_Configuration();
  10. /* Infinite loop */
  11. while (1)
  12. {
  13. Temperature=SMBus_ReadTemp();
  14. sprintf(temStr,"The Temperature is:%.2f\r\n",Temperature);
  15. for(i=0;i<strlen(temStr);i++)
  16. {
  17. USART_SendData(USART1, temStr[i]);
  18. delay_ms(1);
  19. }
  20. delay_ms(500);
  21. }
  22. }

mlx90614.c

  1. /*******************************************************************************
  2. * 文件名 : mlx90614.c
  3. * 作 者 :
  4. * 版 本 :
  5. * 日 期 : 2015-08-07
  6. * 描 述 : mlx90614函数
  7. *******************************************************************************/
  8. #include "stm32f10x.h"
  9. #include "mlx90614.h"
  10. /*******************************************************************************
  11. * Function Name : Mlx90614_Configuration
  12. * Description : Mlx90614_Configuration
  13. * Input : None
  14. * Output : None
  15. * Return : None
  16. *******************************************************************************/
  17. void Mlx96014_Configuration(void)
  18. {
  19. GPIO_InitTypeDef GPIO; //声明一个结构体变量
  20. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
  21. // 温度传感器引脚配置
  22. GPIO.GPIO_Pin = GPIO_Pin_9;//非接触温度传感器SDA 连接PB9
  23. GPIO.GPIO_Speed = GPIO_Speed_50MHz;//管脚频率为50MHZ
  24. GPIO.GPIO_Mode = GPIO_Mode_Out_OD;//输出模式为
  25. GPIO_Init(GPIOB,&GPIO);//初始化GPIOB寄存器
  26. GPIO.GPIO_Pin = GPIO_Pin_8;//非接触温度传感器SCL 连接PB8
  27. GPIO.GPIO_Speed = GPIO_Speed_50MHz;//管脚频率为50MHZ
  28. GPIO.GPIO_Mode = GPIO_Mode_Out_OD;//输出模式为
  29. GPIO_Init(GPIOB,&GPIO);//初始化GPIOB寄存器
  30. SDA_H;
  31. SCL_H; //因为SMBus是下降沿触发
  32. }
  33. /*******************************************************************************
  34. * Function Name : SMBus_StartBit
  35. * Description : Generate START condition on SMBus
  36. * Input : None
  37. * Output : None
  38. * Return : None
  39. *******************************************************************************/
  40. void SMBus_StartBit(void)
  41. {
  42. SDA_H; // Set SDA line
  43. SMBus_Delay(1); // Wait a few microseconds
  44. SCL_H; // Set SCK line
  45. SMBus_Delay(5); // Generate bus free time between Stop
  46. SDA_L; // Clear SDA line
  47. SMBus_Delay(10); // Hold time after (Repeated) Start
  48. // Condition. After this period, the first clock is generated.
  49. //(Thd:sta=4.0us min)
  50. SCL_L; // Clear SCK line
  51. SMBus_Delay(2); // Wait a few microseconds
  52. }
  53. /*******************************************************************************
  54. * Function Name : SMBus_StopBit
  55. * Description : Generate STOP condition on SMBus
  56. * Input : None
  57. * Output : None
  58. * Return : None
  59. *******************************************************************************/
  60. void SMBus_StopBit(void)
  61. {
  62. SCL_L; // Clear SCK line
  63. SMBus_Delay(5); // Wait a few microseconds
  64. SDA_L; // Clear SDA line
  65. SMBus_Delay(5); // Wait a few microseconds
  66. SCL_H; // Set SCK line
  67. SMBus_Delay(10); // Stop condition setup time(Tsu:sto=4.0us min)
  68. SDA_H; // Set SDA line
  69. }
  70. /*******************************************************************************
  71. * Function Name : SMBus_SendByte
  72. * Description : Send a byte on SMBus
  73. * Input : Tx_buffer
  74. * Output : None
  75. * Return : None
  76. *******************************************************************************/
  77. u8 SMBus_SendByte(u8 Tx_buffer)
  78. {
  79. u8 Bit_counter;
  80. u8 Ack_bit;
  81. u8 bit_out;
  82. for(Bit_counter=8; Bit_counter; Bit_counter--)
  83. {
  84. if (Tx_buffer&0x80)
  85. {
  86. bit_out=1; // If the current bit of Tx_buffer is 1 set bit_out
  87. }
  88. else
  89. {
  90. bit_out=0; // else clear bit_out
  91. }
  92. SMBus_SendBit(bit_out); // Send the current bit on SDA
  93. Tx_buffer<<=1; // Get next bit for checking
  94. }
  95. Ack_bit=SMBus_ReceiveBit(); // Get acknowledgment bit
  96. return Ack_bit;
  97. }
  98. /*******************************************************************************
  99. * Function Name : SMBus_SendBit
  100. * Description : Send a bit on SMBus
  101. * Input : bit_out
  102. * Output : None
  103. * Return : None
  104. *******************************************************************************/
  105. void SMBus_SendBit(u8 bit_out)
  106. {
  107. if(bit_out==0)
  108. {
  109. SDA_L;
  110. }
  111. else
  112. {
  113. SDA_H;
  114. }
  115. SMBus_Delay(2); // Tsu:dat = 250ns minimum
  116. SCL_H; // Set SCK line
  117. SMBus_Delay(10); // High Level of Clock Pulse
  118. SCL_L; // Clear SCK line
  119. SMBus_Delay(10); // Low Level of Clock Pulse
  120. // SMBUS_SDA_H(); // Master release SDA line ,
  121. return;
  122. }
  123. /*******************************************************************************
  124. * Function Name : SMBus_ReceiveBit
  125. * Description : Receive a bit on SMBus
  126. * Input : None
  127. * Output : None
  128. * Return : Ack_bit
  129. *******************************************************************************/
  130. u8 SMBus_ReceiveBit(void)
  131. {
  132. u8 Ack_bit;
  133. SDA_H; //引脚靠外部电阻上拉,当作输入
  134. SCL_H; // Set SCL line
  135. SMBus_Delay(2); // High Level of Clock Pulse
  136. if (SMBUS_SDA_PIN)
  137. {
  138. Ack_bit=1;
  139. }
  140. else
  141. {
  142. Ack_bit=0;
  143. }
  144. SCL_L; // Clear SCL line
  145. SMBus_Delay(4); // Low Level of Clock Pulse
  146. return Ack_bit;
  147. }
  148. /*******************************************************************************
  149. * Function Name : SMBus_ReceiveByte
  150. * Description : Receive a byte on SMBus
  151. * Input : ack_nack
  152. * Output : None
  153. * Return : RX_buffer
  154. *******************************************************************************/
  155. u8 SMBus_ReceiveByte(u8 ack_nack)
  156. {
  157. u8 RX_buffer;
  158. u8 Bit_Counter;
  159. for(Bit_Counter=8; Bit_Counter; Bit_Counter--)
  160. {
  161. if(SMBus_ReceiveBit()) // Get a bit from the SDA line
  162. {
  163. RX_buffer <<= 1; // If the bit is HIGH save 1 in RX_buffer
  164. RX_buffer |=0x01;
  165. }
  166. else
  167. {
  168. RX_buffer <<= 1; // If the bit is LOW save 0 in RX_buffer
  169. RX_buffer &=0xfe;
  170. }
  171. }
  172. SMBus_SendBit(ack_nack); // Sends acknowledgment bit
  173. return RX_buffer;
  174. }
  175. /*******************************************************************************
  176. * Function Name : SMBus_Delay
  177. * Description : 延时 一次循环约1us
  178. * Input : time
  179. * Output : None
  180. * Return : None
  181. *******************************************************************************/
  182. void SMBus_Delay(u16 time)
  183. {
  184. u16 i, j;
  185. for (i=0; i<4; i++)
  186. {
  187. for (j=0; j<time; j++);
  188. }
  189. }
  190. /*******************************************************************************
  191. * Function Name : SMBus_ReadMemory
  192. * Description : READ DATA FROM RAM/EEPROM
  193. * Input : slaveAddress, command
  194. * Output : None
  195. * Return : Data
  196. *******************************************************************************/
  197. u16 SMBus_ReadMemory(u8 slaveAddress, u8 command)
  198. {
  199. u16 data; // Data storage (DataH:DataL)
  200. u8 Pec; // PEC byte storage
  201. u8 DataL=0; // Low data byte storage
  202. u8 DataH=0; // High data byte storage
  203. u8 arr[6]; // Buffer for the sent bytes
  204. u8 PecReg; // Calculated PEC byte storage
  205. u8 ErrorCounter; // Defines the number of the attempts for communication with MLX90614
  206. ErrorCounter=0x00; // Initialising of ErrorCounter
  207. slaveAddress <<= 1; //2-7位表示从机地址
  208. do
  209. {
  210. repeat:
  211. SMBus_StopBit(); //If slave send NACK stop comunication
  212. --ErrorCounter; //Pre-decrement ErrorCounter
  213. if(!ErrorCounter) //ErrorCounter=0?
  214. {
  215. break; //Yes,go out from do-while{}
  216. }
  217. SMBus_StartBit(); //Start condition
  218. if(SMBus_SendByte(slaveAddress))//Send SlaveAddress 最低位Wr=0表示接下来写命令
  219. {
  220. goto repeat; //Repeat comunication again
  221. }
  222. if(SMBus_SendByte(command)) //Send command
  223. {
  224. goto repeat; //Repeat comunication again
  225. }
  226. SMBus_StartBit(); //Repeated Start condition
  227. if(SMBus_SendByte(slaveAddress+1)) //Send SlaveAddress 最低位Rd=1表示接下来读数据
  228. {
  229. goto repeat; //Repeat comunication again
  230. }
  231. DataL = SMBus_ReceiveByte(ACK); //Read low data,master must send ACK
  232. DataH = SMBus_ReceiveByte(ACK); //Read high data,master must send ACK
  233. Pec = SMBus_ReceiveByte(NACK); //Read PEC byte, master must send NACK
  234. SMBus_StopBit(); //Stop condition
  235. arr[5] = slaveAddress;
  236. arr[4] = command;
  237. arr[3] = slaveAddress+1; //Load array arr
  238. arr[2] = DataL;
  239. arr[1] = DataH;
  240. arr[0] = 0;
  241. PecReg=PEC_Calculation(arr); //Calculate CRC
  242. }
  243. while(PecReg != Pec); //If received and calculated CRC are equal go out from do-while{}
  244. data = (DataH<<8) | DataL; //data=DataH:DataL
  245. return data;
  246. }
  247. /*******************************************************************************
  248. * Function Name : PEC_calculation
  249. * Description : Calculates the PEC of received bytes
  250. * Input : pec[]
  251. * Output : None
  252. * Return : pec[0]-this byte contains calculated crc value
  253. *******************************************************************************/
  254. u8 PEC_Calculation(u8 pec[])
  255. {
  256. u8 crc[6];
  257. u8 BitPosition=47;
  258. u8 shift;
  259. u8 i;
  260. u8 j;
  261. u8 temp;
  262. do
  263. {
  264. /*Load pattern value 0x000000000107*/
  265. crc[5]=0;
  266. crc[4]=0;
  267. crc[3]=0;
  268. crc[2]=0;
  269. crc[1]=0x01;
  270. crc[0]=0x07;
  271. /*Set maximum bit position at 47 ( six bytes byte5...byte0,MSbit=47)*/
  272. BitPosition=47;
  273. /*Set shift position at 0*/
  274. shift=0;
  275. /*Find first "1" in the transmited message beginning from the MSByte byte5*/
  276. i=5;
  277. j=0;
  278. while((pec[i]&(0x80>>j))==0 && i>0)
  279. {
  280. BitPosition--;
  281. if(j<7)
  282. {
  283. j++;
  284. }
  285. else
  286. {
  287. j=0x00;
  288. i--;
  289. }
  290. }/*End of while */
  291. /*Get shift value for pattern value*/
  292. shift=BitPosition-8;
  293. /*Shift pattern value */
  294. while(shift)
  295. {
  296. for(i=5; i<0xFF; i--)
  297. {
  298. if((crc[i-1]&0x80) && (i>0))
  299. {
  300. temp=1;
  301. }
  302. else
  303. {
  304. temp=0;
  305. }
  306. crc[i]<<=1;
  307. crc[i]+=temp;
  308. }/*End of for*/
  309. shift--;
  310. }/*End of while*/
  311. /*Exclusive OR between pec and crc*/
  312. for(i=0; i<=5; i++)
  313. {
  314. pec[i] ^=crc[i];
  315. }/*End of for*/
  316. }
  317. while(BitPosition>8); /*End of do-while*/
  318. return pec[0];
  319. }
  320. /*******************************************************************************
  321. * Function Name : SMBus_ReadTemp
  322. * Description : Calculate and return the temperature
  323. * Input : None
  324. * Output : None
  325. * Return : SMBus_ReadMemory(0x00, 0x07)*0.02-273.15
  326. *******************************************************************************/
  327. float SMBus_ReadTemp(void)
  328. {
  329. return SMBus_ReadMemory(SA, RAM_ACCESS|RAM_Ta)*0.02-273.15;
  330. }
  331. /*********************************END OF FILE*********************************/

 注意:

  1. float SMBus_ReadTemp(void)
  2. {
  3. return SMBus_ReadMemory(SA, RAM_ACCESS|RAM_Ta)*0.02-273.15;
  4. }

测的是环境温度,如果需要测量物体表面温度。

  1. #define RAM_TOBJ1 0x07 //To1 address in the eeprom 表面温度
  2. #define RAM_Ta 0x06 //Ta address in the eeprom 环境温度

实现效果:

2.HAL库实现温度采集

 因为代码封装的较好,移植性较好,和标准库代码基本相似,只需要修改部分核心代码。

修改片段:

  1. #define SMBUS_SCK_H() HAL_GPIO_WritePin(GPIOB, SMBus_SCL_Pin, GPIO_PIN_SET)
  2. #define SMBUS_SCK_L() HAL_GPIO_WritePin(GPIOB, SMBus_SCL_Pin, GPIO_PIN_RESET)
  3. #define SMBUS_SDA_H() HAL_GPIO_WritePin(GPIOB, SMBus_SDA_Pin, GPIO_PIN_SET)
  4. #define SMBUS_SDA_L() HAL_GPIO_WritePin(GPIOB, SMBus_SDA_Pin, GPIO_PIN_RESET)
  5. #define SMBUS_SDA_PIN() HAL_GPIO_ReadPin(GPIOB,SMBus_SDA_Pin)

基本就可以实现数据采集了。

注意:

  1. float SMBus_ReadTemp(void)
  2. {
  3. return (SMBus_ReadMemory(SA, RAM_ACCESS|RAM_TaA)*0.02-273.15);
  4. }

例子中测试的是物体温度,物体表面温度修改:

  1. #define RAM_TOBJ1 0x07 // 物体表面温度
  2. #define RAM_TaA 0x06 // 环境温度

这里需要需要注意的地方,CubeMX生成的代码需要修改一下,不然不能实现采集功能。

推挽输出

GPIO_MODE_OUTPUT_PP

修改成 开漏输出模式

GPIO_MODE_OUTPUT_OD

实现效果:

 源码下载链接:

STM32实现MLX90614非接触测温串口显示(标准库与HAL库实现)资源-CSDN文库

吾芯电子工作室

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号