你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
攻城狮Melo 发布时间:2023-6-11 13:13
前言

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

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


一、硬件部分

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

1、STM32L051 和 STM32F103 是 Pin to Pin 的;

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

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


1.1 STM32部分

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


微信图片_20230611131249.png


1.2 传感器部分

微信图片_20230611131245.png



在这里插入图片描述

1.3 485通讯部分


微信图片_20230611131240.png






1.4 电源部分

微信图片_20230611131237.png



二、☆软件部分☆

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

1、I2C 通讯驱动;

2、485 通讯驱动;


2.1 传感器 I2C 通讯部分

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

  1. void D6T_Measure()
  2. {
  3. u8 D6Tbuff[20];
  4. u8 D6T_Data=0;
  5.     // u16 tPEC;

  6.    i2c_start();
  7. i2c_send_byte(0X14); //地址,和读写指令
  8. i2c_wait_ack();
  9. delay_us(150);    //这里必须加

  10. i2c_send_byte(0X4C);
  11. i2c_wait_ack();

  12. delay_us(150);

  13. i2c_start();
  14. i2c_send_byte(0X15); //地址,读指令
  15. i2c_wait_ack();
  16. delay_us(120);

  17. // D6T44L_ReadLenByte(5);    //D6T-1A-02 只有5个数值
  18. u8 t;
  19.    D6T_Data=0;
  20. for(t=0;t<(5-1);t++)
  21. {
  22.   D6Tbuff[D6T_Data++] = i2c_read_byte(1);
  23.   delay_us(120);
  24. }
  25.   D6Tbuff[D6T_Data] = i2c_read_byte(0);
  26. delay_us(120);
  27. i2c_stop();

  28. //  tPTAT = 256 * D6Tbuff[1] + D6Tbuff[0];
  29. tP = 256 * D6Tbuff[3] + D6Tbuff[2];
  30. }


  31. unsigned char  calc_crc(unsigned char  data)
  32. {
  33.    int index;
  34.    unsigned char temp;
  35.    
  36.    for(index=0;index<8;index++){
  37.       temp = data;
  38.       data <<= 1;
  39.       if(temp & 0x80) data ^= 0x07;
  40.    }
  41.    return data;
  42. }
复制代码


2.2 485 通讯部分

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

  1. #include "Modbus_rtu.h"
  2. #include "stdio.h"

  3. void Modbus_check()
  4. {
  5.     u16 crc;
  6.     u16 receivecrc1;
  7.     u16 receivecrc2;
  8.     u8 sendbuff[5];
  9.     /*   
  10.     收到了8个数据:01 03 00 10 00 01 D5 CA
  11.     USART2_Data = 8;
  12.     USART2_BUF[0] ~ USART2_BUF[7] ;
  13.     要做校验的数为6个,所以是 USART2_Data - 2;
  14.     校验需要计算的是 USART2_BUF[6], USART2_BUF[7]
  15.     USART2_BUF[USART2_Data - 2] 和 USART2_BUF[USART2_Data - 1]
  16.     */
  17.     crc = Checksum_CRC16(USART2_BUF,USART2_Data - 2);
  18.     // printf("crc is :0x%x\r\n",crc);
  19.     /*No matter the high bits before or the low bits before*/
  20.     receivecrc1 = (USART2_BUF[USART2_Data - 2]<<8) + USART2_BUF[USART2_Data - 1];
  21.     receivecrc2 = (USART2_BUF[USART2_Data - 1]<<8) + USART2_BUF[USART2_Data - 2];
  22.     // if((lrc == receivelrc2)||(lrc == receivelrc1)){
  23.     //     if(USART2_BUF[0] == mymodbus_add){
  24.     //这里说明一下,先判断地址,然后返回错误,如果先判断校验,如果出错了,那么总线上所有都同时返回就有问题了
  25.     if(USART2_BUF[0] == mymodbus_add){        
  26.         if((crc == receivecrc2)||(crc == receivecrc1)){
  27.             switch (USART2_BUF[1]){
  28.             case 3:
  29.                 Modbus_03_ack();
  30.                 break;
  31.             case 6:
  32.                 Modbus_06_ack();
  33.                 break;           
  34.             default:
  35.                 // printf("An unsupported command!\r\n");//for test
  36.                 sendbuff[0] = mymodbus_add;
  37.                 sendbuff[1] = 0x80 | USART2_BUF[1];
  38.                 sendbuff[2] = 2;
  39.                 crc = Checksum_CRC16(sendbuff,3);
  40.                 sendbuff[3] = (u8)(crc >> 8);
  41.                 sendbuff[4] = (u8)crc;
  42.                 Uart2_sendBuffer(sendbuff,5);
  43.                 break;
  44.             }
  45.         }
  46.         else{ //校验错误,返回异常
  47.             sendbuff[0] = mymodbus_add;
  48.             sendbuff[1] = 0x80 | USART2_BUF[1];
  49.             sendbuff[2] = 0;
  50.             crc = Checksum_CRC16(sendbuff,3);
  51.             sendbuff[3] = (u8)(crc >> 8);
  52.             sendbuff[4] = (u8)crc;
  53.             Uart2_sendBuffer(sendbuff,5);
  54.         }
  55.     }   
  56. }

  57. void Modbus_03_ack(){
  58.   u16   Register_add;  // 2,3
  59.   u16   Register_len;  // 4,5
  60.   u16   crc;
  61.   u8    i;
  62.   u8    j;

  63.   Register_add = (USART2_BUF[2]<<8) + USART2_BUF[3]; //get add;
  64.   Register_len = (USART2_BUF[4]<<8) + USART2_BUF[5]; //get len;

  65.   u8 sendbuff[Register_len*2 + 5];
  66.   /*
  67.   如果读取的地址写错了,或者读取长度超过规定的长度
  68.   返回错误
  69.   */
  70.   if(( 0x0010 <= Register_add)&&( Register_add <= 0x0014 )&&(Register_len < 6)){  
  71.     i = 0;
  72.     sendbuff[i++] = mymodbus_add;
  73.     sendbuff[i++] = 0x03;
  74.     sendbuff[i++] = Register_len<<1;
  75.     switch(Register_add){
  76.     case 0x0010:
  77.         for(j=0;j<Register_len;j++){
  78.             sendbuff[i++]= (u8)(Register_value[0+j]>>8);    //发送读取数据字节数的高位
  79.             sendbuff[i++]= (u8)Register_value[0+j];   //发送读取数据字节数的低位
  80.         }
  81.         break;
  82.     case 0x0011:
  83.         for(j=0;j<Register_len;j++){
  84.             sendbuff[i++]= (u8)(Register_value[1+j]>>8);     
  85.             sendbuff[i++]= (u8)Register_value[1+j];   
  86.         }
  87.         break;           
  88.     case 0x0012:
  89.         for(j=0;j<Register_len;j++){
  90.             sendbuff[i++]= (u8)(Register_value[2+j]>>8);     
  91.             sendbuff[i++]= (u8)Register_value[2+j];        
  92.         }
  93.         break;
  94.     case 0x0013:
  95.         for(j=0;j<Register_len;j++){
  96.             sendbuff[i++]= (u8)(Register_value[3+j]>>8);   
  97.             sendbuff[i++]= (u8)Register_value[3+j];   
  98.         }
  99.         break;
  100.     case 0x0014:
  101.         for(j=0;j<Register_len;j++){
  102.             sendbuff[i++]= (u8)(Register_value[4+j]>>8);     
  103.             sendbuff[i++]= (u8)Register_value[4+j];        
  104.         }
  105.         break;
  106.     default:break;  
  107.     }
  108.     crc = Checksum_CRC16(sendbuff,i);
  109.     sendbuff[i++] = (u8)(crc >> 8);
  110.     sendbuff[i++] = (u8)crc;
  111.     Uart2_sendBuffer(sendbuff,i);
  112.   }
  113.   else{//地址不在规定返回或者长度太长,返回错误
  114.     sendbuff[0] = mymodbus_add;
  115.     sendbuff[1] = 0x80 | USART2_BUF[1];
  116.     sendbuff[2] = 1;
  117.     crc = Checksum_CRC16(sendbuff,3);
  118.     sendbuff[3] = (u8)(crc >> 8);
  119.     sendbuff[4] = (u8)crc;
  120.     Uart2_sendBuffer(sendbuff,5);
  121.   }
  122. }

  123. void Modbus_06_ack(){
  124.   u16   Register_add;  //
  125.   u16   val;  //
  126.   u16   crc;
  127.   u8    i;
  128.   u8    sendbuff[8] = {0};
  129.   if(USART2_Data < 9){     
  130.     Register_add = (USART2_BUF[2]<<8) + USART2_BUF[3]; //get add;
  131.     val = (USART2_BUF[4]<<8) + USART2_BUF[5]; //

  132.     if((val > 0)&&(val < 248)){
  133.         if(Register_add == 0x0013){
  134.             mymodbus_add = val;
  135.             Register_value[3] = mymodbus_add;
  136.             MY_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE,Modbus_ID_ADDR,mymodbus_add);
  137.             i = 0;
  138.             sendbuff[i++] = mymodbus_add;
  139.             sendbuff[i++] = 0x06;
  140.             sendbuff[i++] = (u8)(Register_add>>8);     
  141.             sendbuff[i++] = (u8)Register_add;
  142.             sendbuff[i++] = (u8)(val>>8);     
  143.             sendbuff[i++] = (u8)val;
  144.             crc = Checksum_CRC16(sendbuff,i);
  145.             sendbuff[i++] = (u8)(crc >> 8);
  146.             sendbuff[i++] = (u8)crc;
  147.             Uart2_sendBuffer(sendbuff,i);  
  148.         }
  149.         else{//写地址不在规定范围
  150.             sendbuff[0] = mymodbus_add;
  151.             sendbuff[1] = 0x80 | USART2_BUF[1];
  152.             sendbuff[2] = 3;
  153.             crc = Checksum_CRC16(sendbuff,3);
  154.             sendbuff[3] = (u8)(crc >> 8);
  155.             sendbuff[4] = (u8)crc;
  156.             Uart2_sendBuffer(sendbuff,5);
  157.         }
  158.     }else{//写地址不在规定范围
  159.         sendbuff[0] = mymodbus_add;
  160.         sendbuff[1] = 0x80 | USART2_BUF[1];
  161.         sendbuff[2] = 4;
  162.         crc = Checksum_CRC16(sendbuff,3);
  163.         sendbuff[3] = (u8)(crc >> 8);
  164.         sendbuff[4] = (u8)crc;
  165.         Uart2_sendBuffer(sendbuff,5);
  166.     }
  167.   }
  168.   else{//写地址不在规定范围
  169.     sendbuff[0] = mymodbus_add;
  170.     sendbuff[1] = 0x80 | USART2_BUF[1];
  171.     sendbuff[2] = 1;
  172.     crc = Checksum_CRC16(sendbuff,3);
  173.     sendbuff[3] = (u8)(crc >> 8);
  174.     sendbuff[4] = (u8)crc;
  175.     Uart2_sendBuffer(sendbuff,5);
  176.   }   
  177. }
复制代码

2.3 其他代码说明

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

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

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


如有侵权请联系删除

转载自: [color=var(--weui-FG-2)]矜辰所致




收藏 评论0 发布时间:2023-6-11 13:13

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版