打印
[其他ST产品]

基于STM32非接触测温测温传感器经验分享

[复制链接]
558|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
两只袜子|  楼主 | 2023-6-12 13:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 两只袜子 于 2023-6-12 14:40 编辑

前言

本文是个人笔记,文章只讲基本流程,

最后所有的资料原理图和程序都会上传至资源。


一、硬件部分

单品传感器的硬件部分还是很简单的:

1、STM32L051 和 STM32F103 是 Pin to Pin 的;

2、测温传感器使用的是I2C接口,使用了软件I2C,因为 D6T 是5V供电,所以使用了电平转换电路;

3、整个传感器项目需求是 485 通讯的,因为实际环境要求,所以采用了周立功的 485 模块;


1.1 STM32部分

老样子,最小系统都是一样的:




1.2 传感器部分




在这里插入图片描述

1.3 485通讯部分








1.4 电源部分

使用特权

评论回复
沙发
两只袜子|  楼主 | 2023-6-12 14:40 | 只看该作者
二、☆软件部分☆

硬件部分是简单的,本项目的核心就在于软件的实现,有2个部分是核心:

1、I2C 通讯驱动;

2、485 通讯驱动;


2.1 传感器 I2C 通讯部分

这里上一下上层调用的函数,具体的驱动细节见下文说明:

  • void D6T_Measure()
  • {
  • u8 D6Tbuff[20];
  • u8 D6T_Data=0;
  •     // u16 tPEC;
  •    i2c_start();
  • i2c_send_byte(0X14); //地址,和读写指令
  • i2c_wait_ack();
  • delay_us(150);    //这里必须加
  • i2c_send_byte(0X4C);
  • i2c_wait_ack();
  • delay_us(150);
  • i2c_start();
  • i2c_send_byte(0X15); //地址,读指令
  • i2c_wait_ack();
  • delay_us(120);
  • // D6T44L_ReadLenByte(5);    //D6T-1A-02 只有5个数值
  • u8 t;
  •    D6T_Data=0;
  • for(t=0;t<(5-1);t++)
  • {
  •   D6Tbuff[D6T_Data++] = i2c_read_byte(1);
  •   delay_us(120);
  • }
  •   D6Tbuff[D6T_Data] = i2c_read_byte(0);
  • delay_us(120);
  • i2c_stop();
  • //  tPTAT = 256 * D6Tbuff[1] + D6Tbuff[0];
  • tP = 256 * D6Tbuff[3] + D6Tbuff[2];
  • }
  • unsigned char  calc_crc(unsigned char  data)
  • {
  •    int index;
  •    unsigned char temp;
  •    for(index=0;index<8;index++){
  •       temp = data;
  •       data <<= 1;
  •       if(temp & 0x80) data ^= 0x07;
  •    }
  •    return data;
  • }

复制代码



2.2 485 通讯部分

本传感器是作为 485 从机设备,所以需要写一下 ModbusRTU 协议驱动,这里就不墨迹,直接源码奉上:

  • #include "Modbus_rtu.h"
  • #include "stdio.h"
  • void Modbus_check()
  • {
  •     u16 crc;
  •     u16 receivecrc1;
  •     u16 receivecrc2;
  •     u8 sendbuff[5];
  •     /*
  •     收到了8个数据:01 03 00 10 00 01 D5 CA
  •     USART2_Data = 8;
  •     USART2_BUF[0] ~ USART2_BUF[7] ;
  •     要做校验的数为6个,所以是 USART2_Data - 2;
  •     校验需要计算的是 USART2_BUF[6], USART2_BUF[7]
  •     USART2_BUF[USART2_Data - 2] 和 USART2_BUF[USART2_Data - 1]
  •     */
  •     crc = Checksum_CRC16(USART2_BUF,USART2_Data - 2);
  •     // printf("crc is :0x%x\r\n",crc);
  •     /*No matter the high bits before or the low bits before*/
  •     receivecrc1 = (USART2_BUF[USART2_Data - 2]<<8) + USART2_BUF[USART2_Data - 1];
  •     receivecrc2 = (USART2_BUF[USART2_Data - 1]<<8) + USART2_BUF[USART2_Data - 2];
  •     // if((lrc == receivelrc2)||(lrc == receivelrc1)){
  •     //     if(USART2_BUF[0] == mymodbus_add){
  •     //这里说明一下,先判断地址,然后返回错误,如果先判断校验,如果出错了,那么总线上所有都同时返回就有问题了
  •     if(USART2_BUF[0] == mymodbus_add){
  •         if((crc == receivecrc2)||(crc == receivecrc1)){
  •             switch (USART2_BUF[1]){
  •             case 3:
  •                 Modbus_03_ack();
  •                 break;
  •             case 6:
  •                 Modbus_06_ack();
  •                 break;
  •             default:
  •                 // printf("An unsupported command!\r\n");//for test
  •                 sendbuff[0] = mymodbus_add;
  •                 sendbuff[1] = 0x80 | USART2_BUF[1];
  •                 sendbuff[2] = 2;
  •                 crc = Checksum_CRC16(sendbuff,3);
  •                 sendbuff[3] = (u8)(crc >> 8);
  •                 sendbuff[4] = (u8)crc;
  •                 Uart2_sendBuffer(sendbuff,5);
  •                 break;
  •             }
  •         }
  •         else{ //校验错误,返回异常
  •             sendbuff[0] = mymodbus_add;
  •             sendbuff[1] = 0x80 | USART2_BUF[1];
  •             sendbuff[2] = 0;
  •             crc = Checksum_CRC16(sendbuff,3);
  •             sendbuff[3] = (u8)(crc >> 8);
  •             sendbuff[4] = (u8)crc;
  •             Uart2_sendBuffer(sendbuff,5);
  •         }
  •     }
  • }
  • void Modbus_03_ack(){
  •   u16   Register_add;  // 2,3
  •   u16   Register_len;  // 4,5
  •   u16   crc;
  •   u8    i;
  •   u8    j;
  •   Register_add = (USART2_BUF[2]<<8) + USART2_BUF[3]; //get add;
  •   Register_len = (USART2_BUF[4]<<8) + USART2_BUF[5]; //get len;
  •   u8 sendbuff[Register_len*2 + 5];
  •   /*
  •   如果读取的地址写错了,或者读取长度超过规定的长度
  •   返回错误
  •   */
  •   if(( 0x0010 <= Register_add)&&( Register_add <= 0x0014 )&&(Register_len < 6)){
  •     i = 0;
  •     sendbuff[i++] = mymodbus_add;
  •     sendbuff[i++] = 0x03;
  •     sendbuff[i++] = Register_len<<1;
  •     switch(Register_add){
  •     case 0x0010:
  •         for(j=0;j<Register_len;j++){
  •             sendbuff[i++]= (u8)(Register_value[0+j]>>8);    //发送读取数据字节数的高位
  •             sendbuff[i++]= (u8)Register_value[0+j];   //发送读取数据字节数的低位
  •         }
  •         break;
  •     case 0x0011:
  •         for(j=0;j<Register_len;j++){
  •             sendbuff[i++]= (u8)(Register_value[1+j]>>8);
  •             sendbuff[i++]= (u8)Register_value[1+j];
  •         }
  •         break;
  •     case 0x0012:
  •         for(j=0;j<Register_len;j++){
  •             sendbuff[i++]= (u8)(Register_value[2+j]>>8);
  •             sendbuff[i++]= (u8)Register_value[2+j];
  •         }
  •         break;
  •     case 0x0013:
  •         for(j=0;j<Register_len;j++){
  •             sendbuff[i++]= (u8)(Register_value[3+j]>>8);
  •             sendbuff[i++]= (u8)Register_value[3+j];
  •         }
  •         break;
  •     case 0x0014:
  •         for(j=0;j<Register_len;j++){
  •             sendbuff[i++]= (u8)(Register_value[4+j]>>8);
  •             sendbuff[i++]= (u8)Register_value[4+j];
  •         }
  •         break;
  •     default:break;
  •     }
  •     crc = Checksum_CRC16(sendbuff,i);
  •     sendbuff[i++] = (u8)(crc >> 8);
  •     sendbuff[i++] = (u8)crc;
  •     Uart2_sendBuffer(sendbuff,i);
  •   }
  •   else{//地址不在规定返回或者长度太长,返回错误
  •     sendbuff[0] = mymodbus_add;
  •     sendbuff[1] = 0x80 | USART2_BUF[1];
  •     sendbuff[2] = 1;
  •     crc = Checksum_CRC16(sendbuff,3);
  •     sendbuff[3] = (u8)(crc >> 8);
  •     sendbuff[4] = (u8)crc;
  •     Uart2_sendBuffer(sendbuff,5);
  •   }
  • }
  • void Modbus_06_ack(){
  •   u16   Register_add;  //
  •   u16   val;  //
  •   u16   crc;
  •   u8    i;
  •   u8    sendbuff[8] = {0};
  •   if(USART2_Data < 9){
  •     Register_add = (USART2_BUF[2]<<8) + USART2_BUF[3]; //get add;
  •     val = (USART2_BUF[4]<<8) + USART2_BUF[5]; //
  •     if((val > 0)&&(val < 248)){
  •         if(Register_add == 0x0013){
  •             mymodbus_add = val;
  •             Register_value[3] = mymodbus_add;
  •             MY_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE,Modbus_ID_ADDR,mymodbus_add);
  •             i = 0;
  •             sendbuff[i++] = mymodbus_add;
  •             sendbuff[i++] = 0x06;
  •             sendbuff[i++] = (u8)(Register_add>>8);
  •             sendbuff[i++] = (u8)Register_add;
  •             sendbuff[i++] = (u8)(val>>8);
  •             sendbuff[i++] = (u8)val;
  •             crc = Checksum_CRC16(sendbuff,i);
  •             sendbuff[i++] = (u8)(crc >> 8);
  •             sendbuff[i++] = (u8)crc;
  •             Uart2_sendBuffer(sendbuff,i);
  •         }
  •         else{//写地址不在规定范围
  •             sendbuff[0] = mymodbus_add;
  •             sendbuff[1] = 0x80 | USART2_BUF[1];
  •             sendbuff[2] = 3;
  •             crc = Checksum_CRC16(sendbuff,3);
  •             sendbuff[3] = (u8)(crc >> 8);
  •             sendbuff[4] = (u8)crc;
  •             Uart2_sendBuffer(sendbuff,5);
  •         }
  •     }else{//写地址不在规定范围
  •         sendbuff[0] = mymodbus_add;
  •         sendbuff[1] = 0x80 | USART2_BUF[1];
  •         sendbuff[2] = 4;
  •         crc = Checksum_CRC16(sendbuff,3);
  •         sendbuff[3] = (u8)(crc >> 8);
  •         sendbuff[4] = (u8)crc;
  •         Uart2_sendBuffer(sendbuff,5);
  •     }
  •   }
  •   else{//写地址不在规定范围
  •     sendbuff[0] = mymodbus_add;
  •     sendbuff[1] = 0x80 | USART2_BUF[1];
  •     sendbuff[2] = 1;
  •     crc = Checksum_CRC16(sendbuff,3);
  •     sendbuff[3] = (u8)(crc >> 8);
  •     sendbuff[4] = (u8)crc;
  •     Uart2_sendBuffer(sendbuff,5);
  •   }
  • }


复制代码


2.3 其他代码说明

此项目的核心就是上面2个的驱动,其他部分,STM32和一些基本的按键驱动,LED等操作都和以往项目基本一样。

实际上当初我在 FreeRTOS 记录 实例的时候就是使用的这个项目作为说明的,所以从 0 开始的设计思路

当然额外说一句,这种 单品传感器 的简单的项目一般来说用不用 RTOS 实际使用上区别不大。


使用特权

评论回复
板凳
LLGTR| | 2023-6-12 15:20 | 只看该作者
测温传感器是什么型号的?

使用特权

评论回复
地板
朝生| | 2023-6-12 15:30 | 只看该作者
代码部分有点凌乱呀。

使用特权

评论回复
5
软核硬核| | 2023-6-12 15:31 | 只看该作者
可以分享一下工程文件嘛?

使用特权

评论回复
6
Henryko| | 2023-6-12 21:52 | 只看该作者
传感器用的mlx90614 吗?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2038

主题

7364

帖子

10

粉丝