前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于红外传输的多点温度采集系统

基于红外传输的多点温度采集系统

作者头像
飞哥
发布2020-07-10 10:29:47
9560
发布2020-07-10 10:29:47
举报

今天分享的是基于红外通信的多点温度采集系统。先简单说一下要实现的功能:使用三个温度传感器采集三路温度信号,然后将采集的信号通过红外的方式发射出去,主机接收红外信号并解码,将温度信息在上位机上面显示出来。

今天我们主要讲解的是前面部分,也就是采集温度和红外传输,关于上位机的内容,需要单独花一篇来讲,将在下一篇里介绍。

本项目使用到的器件:ds18b20温度传感器,红外发射管和接收管,单片机(51和stm32都可以)。在本次实验中,因为单片机数量有限,所以采用了一个做主机,另外两个做从机,共三个单片机。Stm32采集两路温度信息,51采集第三路温度信息,然后在另一块51上面接收,当然,这个是比较随意的,只要搞清楚里面的核心原理,用什么单片机,采集几路信号,这些都不是问题。

好了,废话不多说,接下来我们逐一介绍几个部分。

一、温度采集部分

温度采集部分我们用的是常见的DS18B20芯片,DS18B20是常用的数字温度传感器,其输出的是数字信号,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。DS18B20数字温度传感器接线方便,封装成后可应用于多种场合,如管道式,螺纹式,磁铁吸附式,不锈钢封装式,型号多种多样,有LTM8877,LTM8874等等。

主要根据应用场合的不同而改变其外观。封装后的DS18B20可用于电缆沟测温,高炉水循环测温,锅炉测温,机房测温,农业大棚测温,洁净室测温,弹药库测温等各种非极限温度场合。耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。

关于这块芯片详细的工作原理什么的,这里就不多介绍了,我们只需要关心怎么使用,怎么通过它来获取温度就好了。DS18B20在出厂时以配置为12位,读取温度时共读取16位,前5个位为符号位,当前5位为1时,读取的温度为负数;当前5位为0时,读取的温度为正数。温度为正时读取方法为:将16进制数转换成10进制即可。温度为负时读取方法为:将16进制取反后加1,再转换成10进制即可。例:0550H = +85 度,FC90H = -55 度。

1、接线

这块芯片的接线很简单,一个VCC,一个GND,一个dat数据线,这个数据线可以连上单片机任意的一个IO口。

2、控制方法

控制方法主要涉及到传感器的初始化工作,如何读取寄存器,如何写入寄存器,其他的也就没什么了。

a)初始化工作

(1) 先将数据线置高电平“1”。

(2) 延时(该时间要求的不是很严格,但是尽可能的短一点)

(3) 数据线拉到低电平“0”。

(4) 延时750微秒(该时间的时间范围可以从480到960微秒)。

(5) 数据线拉到高电平“1”。

(6) 延时等待(如果初始化成功则在15到60微秒时间之内产生一个由DS18B20所返回的低电平“0”。据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然会使程序进入死循环,所以要进行超时控制)。

(7) 若CPU读到了数据线上的低电平“0”后,还要做延时,其延时的时间从发出的高电平算起(第(5)步的时间算起)最少要480微秒。

(8) 将数据线再次拉高到高电平“1”后结束。

图一:初始化(复位)时序

简单的说就是主机首先发出一个480us~960us的低电平脉冲,然后释放总线变为高电平,并在随后的480us时间内对总线进行检测,如果有低电平出现说明总线上有器件已做出应答。若无低电平出现一直都是高电平说明总线上无器件应答。

做为从器件的DS18B20在一上电后就一直在检测总线上是否有480-960us的低电平出现,如果有,在总线转为高电平后等待15-60us后将总线电平拉低60us~240us做出响应存在脉冲,告诉主机本器件已做好准备。若没有检测到就一直在检测等待。

b)写操作

(1) 数据线先置低电平“0”。

(2) 延时确定的时间为15微秒。

(3) 按从低位到高位的顺序发送字节(一次只发送一位)。

(4) 延时时间为45微秒。

(5) 将数据线拉到高电平。

(6) 重复上(1)到(6)的操作直到所有的字节全部发送完为止。

(7) 最后将数据线拉高。

图二:写时序

写时序包含了两种写时序:写0时序和写1时序。所有写时序至少需要60us,且每个写时序之间至少需要1us的恢复时间。

主机产生0时序:DQ line 拉低,延时60us,然后释放总线为高电平,延时2us。

主机产生1时序:DQ line 拉低,延时2us,然后释放总线为高电平,延时60us

做为从机的DS18B20则在检测到总线被拉底后等待15us然后从15us到60us开始对总线采样,在采样期内总线为高电平则为1,若采样期内总线为低电平则为0。

c)读操作

(1)将数据线拉高“1”。

(2)延时2微秒。

(3)将数据线拉低“0”。

(4)延时3微秒。

(5)将数据线拉高“1”。

(6)延时5微秒。

(7)读数据线的状态得到1个状态位,并进行数据处理。

(8)延时60微秒。

图三:读时序

单总线期间仅在主机发出读时序时,才向主机传输数据,所以,在主机发出读数据命令后,必须马上产生读时序,以便从机能够传输数据。

对于读数据时序也分为读0时序和读1时序。所有读时序至少需要60us才能完成,且2次独立的读时序之间至少需要1us的恢复时间。每个读时序都由主机发起,至少拉低总线1us。在读时序期间必须释放总线,并且在时序起始后的15us之内采样总线数据。典型的读时序过程为:主机输出低电平延时 2us,然后主机转入输入模式延时 12us,然后读取单总线当前的电平,然后延时 50us。

以上都是一些具体的操作,那么一个完整的操作流程是怎么样的呢?DS18B20的典型温度读取过程:

复位 → 发 SKIP ROM 命令(0XCC)→ 发开始转换命令(0X44) → 延时 → 复位 → 发送 SKIP ROM 命令(0XCC) → 发读存储器命令(0XBE)→ 连续读出两个字节数据(即温度) → 结束。

以上就是温度传感器的操作,总的来说,并不是很难,最重要的就是要注意它的时序问题,也就是说里面的延时必须是很准确的,如果延时不准确很可能导致芯片的初始化失败。其实红外也是对时间有比较严格的要求,所以,接下来我们就来介绍红外部分。

二、红外发射部分

红外分为发射和接收部分,这里先介绍一下红外发射。

通常红外发射为了提高抗干扰性能和降低电源消耗,红外遥控器常用载波的方式传送二进制编码,常用的载波频率为38kHz。也有一些遥控系统采用36kHz、40 kHz、56 kHz等,一般由发射端晶振的振荡频率来决定。所以,通常的红外遥控器是将遥控信号(二进制脉冲码)调制在38KHz的载波上,经缓冲放大后送至红外发光二极管,转化为红外信号发射出去的。

二进制脉冲码的形式有多种,其中最为常用的是NECProtocol 的 PWM码(脉冲宽度调制)和 Philips RC-5 Protocol 的 PPM码(脉冲位置调制码,脉冲串之间的时间间隔来实现信号调制)。如果要开发红外接收设备,一定要知道红外遥控器的编码方式和载波频率,我们才可以选取一体化红外接收头和制定解码方案。这里使用的是NEC协议。

NEC协议的特征如下:

1、 8 位地址和 8 位指令长度;

2、地址和命令 2 次传输(确保可靠性)

3、 PWM 脉冲位置调制,以发射红外载波的占空比代表“ 0”和“ 1”;

4、载波频率为 38Khz;

5、位时间为 1.125ms 或 2.25ms;

NEC码的位定义:

一个脉冲对应 560us 的连续载波,一个逻辑 1 传输需要 2.25ms( 560us脉冲+1680us低电平),一个逻辑 0 的传输需要 1.125ms(560us 脉冲+560us 低电平)。而红外接收头在收到脉冲的时候为低电平,在没有脉冲的时候为高电平,这样,我们在接收头端收到的信号为:逻辑 1 应该是 560us 低+1680us高,逻辑 0 应该是 560us 低+560us 高。所以可以通过计算高电平时间判断接收到的数据是0还是1。

NEC码位定义时序图如图

NEC遥控指令的数据格式为:引导码、地址码、地址反码、控制码、控制反码。引导码由一个 9ms 的低电平和一个 4.5ms 的高电平组成,地址码、地址反码、控制码、控制反码均是8 位数据格式。按照低位在前,高位在后的顺序发送。采用反码是为了增加传输的可靠性(可用于校验)。数据格式如下:

NEC码还规定了连发码(由9ms 低电平+2.5m 高电平+0.56ms低电平+97.94ms 高电平组成),如果在一帧数据发送完毕之后,红外遥控器按键仍然没有放开,则发射连发码,可以通过统计连发码的次数来标记按键按下的长短或次数。

以上是关于红外发射的具体说明,简单来说就是这样:

首先要发射一段引导码,这段引导码的作用就是告诉接收端这是一帧数据的开始,这段引导码在接收端看来是9ms的低电平加上4.5ms的高电平,然后再发射接下来的4个字节,这4个字节分别是地址码,地址反码,控制码,控制反码。地址码是用来区分不同的红外设备的,因为有可能会使用不同的红外设备来遥控,所以要有一个唯一的标志。控制码就是真正的数据部分,就是你想要发送什么数据,然后接收端收到这个数据之后就执行相应的操作。发送反码是为了增强可靠性,用于数据校验。

那么对于具体的发射来说,如果想要发射低电平,并不是直接输出低电平,而是输出一段脉冲,这段脉冲的频率是38khz,如果想要发射高电平,就直接输出高电平就好了,因为在接收端看来,收到脉冲就认为是低电平,否则就认为是高电平。最后就是要注意以下时间,不管是“1”还是“0”,低电平的时间都是一样的,靠高电平时间来区分0和1,不过这个是在接收时要重点考虑的。

那么,应该如何编写代码?

因为要产生一个固定频率的载波,所以采用定时器中断的方法,38khz频率对应的时间周期就是26us,半周期就是13us,也是就是说要设置一个定时器,每13us产生一次中断,然后在中断函数中翻转电平,产生脉冲,但因为有时候不是要产生脉冲,所以加上一个标志,用来控制是否产生脉冲。

首先是发射引导码,引导码由9ms的低电平加上4.5ms的高电平组成,所以,对于发射端来说,就是9ms的脉冲加上4.5ms高电平。定义一个变量,每次进入中断加1,然后在发射函数中使用while循环,将这个变量与另一个设置好的变量相比较,一直等到他们相等退出循环。代码如下:

中断服务函数:

代码语言:javascript
复制
void TIM4_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM4,TIM_IT_Update))
    {
        led2=!led2;
        count++;
        if (flag==1)
        {
            OP=~OP;
        }
        else
        {
            OP = 0;
        }
        IR_OUT = OP;
    }
    TIM_ClearITPendingBit(TIM4,TIM_IT_Update);  
}    

发射函数(截取部分):

代码语言:javascript
复制
void SendIRdata(char p_irdata)
{
  int i;
  char irdata=p_irdata;
  //发送9ms的起始码
  endcount=t9000;
  flag=1;
  count=0;
  do{}while(count<endcount);

对于其他的也是和发射引导码类似的操作,这里就不多说了。

它的关键就在于产生准确的延时,这样才能产生固定频率的脉冲,然后我们通过一个变量计数就可以来控制时间。

我们可以看一下使用逻辑分析仪捕捉到的波形:

前面那一段比较长的脉冲就是引导码中的低电平。

三、红外接收部分

这一部分就是在接收端对红外信号进行解码的操作了。解码无非就是从收到的波形里面读取出它到底是0还是1,或者说携带的信息是什么。

实际上,我们根据上面的逻辑分析仪的波形,甚至可以自己手动解码,当自己根据波形可以手动解码之后,就说明对原理比较清楚了,这时候就可以编写程序,让单片机来为我们高效的工作。

根据前面的分析,1是0.56ms的低电平加上1.68ms的高电平,0是0.56ms的低电平加上0.56ms的高电平,所以,区分0和1只和高电平时间有关。上面的波形跳过引导码之后,解码出来就是

1100 0000 , 0011 1111 , 1000 0100 , 0111 1011;

由于发射是从低位开始,所以左边是LSB,右边是MSB,所以第一个字节解码后其实是3,第二个字节是252,第三个字节是33,第四个字节是222。第三个字节才是用户的实际要发的有效数据,在这里是温度信息。

代码语言:javascript
复制
SendIRdata(temp,0x03,0xfc);

可以看到,解码后的数据就是原来发送的数据,说明我们数据传输是成功的。

上面是我们手动的依靠波形来解码,那么,如何编写程序来实现解码呢?

思路其实就是首先,要捕获引导码,因为引导码代表着一帧数据的开始,捕获完了引导码之后,就是正式的解码过程,无非就是判断是0还是1,而判断是0还是1的依据就是判断高电平的时间长度。

我们还是使用到了定时器资源,每隔一定时间进入中断。对于51单片机来说,可以用一个变量记录上一次管脚的电平状态,然后每次进入中断读取本次管脚的电平状态,如果上一次是1,这一次是0,就可以判断为产生了下降沿,反之就是上升沿。而对于stm32来说,带有输入捕获的功能,所以可以直接使用上升沿捕获计算时间长度。

因为要计算高电平的时间,所以采用捕获上升沿的方法,当捕获到上升沿的时候,开始计时,捕获到下降沿的时候,结束计时,根据计时的长度就知道是引导码,还是0,或者是1.

如果捕获到的第一个高电平的时间是4.5ms左右,则表示捕获到了引导码,接着判断下一次上升沿到来后的高电平时间,如果高电平时间太长或者太短,则表示接收的是干扰信号,应该舍弃这一帧数据。当捕获完了32位数据之后,告诉主程序已经捕获完了,这时主程序可以对数据进行判断或处理。

以下是接收时中断处理函数的流程图

至此,接收部分就完成了。

四、各模块间的整合

前面已经把温度采集,红外发射,红外接收做好了,现在就是要将这几部分整合在一起。

首先是要把温度采集得到的数据,提供给发射模块作为输入参数,然后在接收端观察数据的接收。

这里有一点是特别需要注意的,那就是在红外发射模块当中,使用到了一个定时器,这个定时器的定时时间是很短的,也就是说会频繁的进入中断,那么,将温度采集模块和红外发射模块结合的时候,就会因为频繁进入中断影响主程序的执行,使得温度传感器初始化失败,因为温度传感器对延时时间是有比较严格的要求的,本来是正常的延时时间,因为中断的打扰,延时时间明显加长,这就导致采集的温度是错误的。解决的方法就是在温度采集的时候,关闭定时器中断,等采集完温度之后再打开中断,这样就不会影响了。

整个项目最好使用模块化的编程思路,也就是每个模块都单独写一个.c文件,然后在头文件中声明,这样可以方便程序的移植。

我们可以暂时使用串口助手来观察接收的数据是否正常。

可以看到,接收端可以正常接收温度信息并显示。这里面有一个小细节,就是串口助手显示的是ASCII码值,也就是说,如果使用串口发送一个数字51,在串口助手上并不会显示51,而是显示3,具体的可以去查一下ASCII码表,因此,为了便于观察,应该先将要发送的数据进行转化和处理,这样才能在串口助手上正确显示要发送的信息。

五、总结

以上就是整个多点温度采集系统的讲解,另外,关于项目中的一些细节问题,在这里也一并总结一下:

1、温度传感器对时序要求还是挺严格的,所以要有比较准确的延时函数,对于stm32来说,可以使用SysTick定时器来产生延时,比较准确,而对于51来说,延时并不是那么好把控,有时候需要去实际测一下更好。

2、对于红外发射和接收来说,其实并没有那么多要求,上面所说的那些规则,只是大家约定的习惯而已,并没有一个标准,事实上,只要保证发射和接收相匹配,就能收到数据。而且对于接收端来说,在一个比较宽的频率范围内,收到的脉冲都将被认为是0,并没有要求一定是38khz,实测19khz也是正常接收。

3、巧妙的借助一些工具可以非常有利于我们对实验结果的分析。比如本次实验当中,逻辑分析仪就起了很重要的作用。刚开始的时候分析红外发射的时候,只需要借助keil软件里自带的逻辑分析仪就可以分析输出的管脚电平,当然这是理论计算得到的结果,与事实可能有一点点差别,但是差别不会太大。而在分析接收端的管脚电平的时候,就不得不使用真实的逻辑分析仪来观察了,这个没办法仿真。

4、将模块进行整合的时候,原本各个模块都能正常工作的,整合在一起却不能工作了,这时要分析它们之间是否有相互作用。比如在本次项目中的温度采集和发射模块,两个模块单独测量都是没有问题的,但是将温度采集后的数据送到发送端却出了问题,刚开始排查是否共用了什么资源,发现并没有,后来在经过大量实验之后发现这两部分确实都是正常的,那么只可能是一个对另一个产生了影响,后来终于发现原来是中断打扰了主程序的运行。

5、代码要养成及时备份的习惯,每写好一部分功能,就要保存起来,下次要修改或者添加功能的时候,先复制出一份出来,在复制的那一份上进行修改,这样可以防止把原来能用的程序修改坏了。

后台回复“温度采集系统”获取源码和资料!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-07-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 电子技术研习社 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档