|
本作品部分灵感和启发来自以下贴子,在此表示感谢:
http://www.51hei.com/bbs/dpj-57255-1.html
本作品使用NTC热敏电阻和nRF24L01实现无线测温功能。使用前请仔细阅读说明文字。
【测量部分】
平台:STC15W408AS,频率:22.1184MHz
测量部分使用NTC-MF52-103/3435热敏电阻进行温度采集,通过读取单片机内部BandGap电压得到准确的电源电压和外部电压,进而使用查表方法得到对应的最靠近的温度值,处理并显示。无线部分采用2.4G载波的nRF24L01模块进行数据传输。
误差分析:
设此采集过程中,影响采集精度的唯一因素为ADC对电压的分辨率,若排除高精度分压电阻的误差,则在5V稳定电压供电条件下,可得到能识别的NTC电阻变化跨度为97.7517106549(十倍欧姆),由于NTC电阻阻值是随温度非线性变化的,则固定分辨率下,不同温度值附近精度不同,本次设计使用的单片机具有10位ADC,最小分辨率为4.8828mV,计算得到20℃定点温度下的理论跨度误差约为1.521190476%。
【接收显示部分】
平台:STM8S103F2P6,HSI:16MHz,CPUDIV:8
显示使用双数码管显示,分别使用一个595进行段选控制(别问我为什么用两个595,设计的时候没想太多...),位选使用一个138译码器解决。
可以显示正负温度,自动消零。
程序部分说明:
1.发送和接收部分的nRF24L01驱动函数均进行了精简,发送部分仅有发送相关函数,接收部分只有接收部分的函数,移植需要注意。
2.无线报文数据格式见数据采集的程序,一共有14个字节,都是数字的形式,接收到之后直接判断送显即可。
【实物图片】
数据采集部分
接收部分的实际效果1
接收部分的实际效果2
接收部分数码管段选电路连接
数据采集部分重点电路
接收显示部分单片机引脚定义(典型连接)
【程序概要】
测量部分
接收部分主函数
- #include"iostm8s103f2.h"
- #include"Init.c" //系统初始化函数
- #include"nRF24L01.C"//提供nRF24L01驱动
- //运行数组
- unsigned char Display[8]={10,10,10,10,10,10,10,10};//用于显示的每一位数值,对应段选数组中的相应位
- unsigned char duan[11]={0xeb,0x09,0xe5,0xad,0x0f,0xae,0xee,0x89,0xef,0xaf,0x04};//数码管段选数组 数字0~9和符号"-"
- /*
- 段码对应表,仅适用本电路
- 8 4 2 1 8 4 2 1
- 7 6 5 4 3 2 1 0
- A E D H C G F B
- 1 1 1 0 1 0 1 1 0
- 0 0 0 0 1 0 0 1 1
- 1 1 1 0 0 1 0 1 2
- 1 0 1 0 1 1 0 1 3
- 0 0 0 0 1 1 1 1 4
- 1 0 1 0 1 1 1 0 5
- 1 1 1 0 1 1 1 0 6
- 1 0 0 0 1 0 0 1 7
- 1 1 1 0 1 1 1 1 8
- 1 0 1 0 1 1 1 1 9
- 0 0 0 0 0 1 0 0 -
- */
- //运行变量
- unsigned char pointpositionA=3;//温度显示的小数点位置,从0到3
- unsigned char pointpositionB=4;//电压显示的小数点位置,从4到7
- //运行计数
- unsigned int TIM4_cnt=0;//TIM4定时器周期计数
- /************************************************************
- 名称:基于NTC热敏电阻和nRF24L01的无线温度计(接收显示部分)
- 平台:STM8S103F2P6,HSI:16MHz,CPUDIV:8
- 资源:Flash:4K RAM:1K
- 简介:测量部分使用NTC-MF52-103/3435热敏电阻进行温度采集,
- 通过读取单片机内部BandGap电压得到准确的电源电压和外部电压,
- 使用查表方法得到对应的最靠近的温度值,处理并显示。
- 无线部分采用2.4G载波的nRF24L01模块进行数据传输。
- 程序编写:凌净清河
- 硬件制作:凌净欣羽
- 文稿排版:凌净欣羽
- 日期:2019年2月25日
- 声明:制作参考龙顺宇《深入浅出STM8单片机入门、进阶与应用实例》
- 所属:新矿城学习基地#2019
- 编写中临时记录:
- 本程序欠缺段选数组,数码管显示函数
- 数码管计划使用138和双595级联的方式驱动2个4位数码管
- 一个显示温度,一个显示采集部分的供电电压
- 还有配套的数据处理语句待编写。
- ************************************************************/
- void delay(unsigned char i) //延时函数,调用此函数进行一段时间的非精准延时
- {
- while(i--);
- }
- void SPIsendB(unsigned char dat)//给级联的第一个595写字节
- {
- unsigned char a;
- unsigned int tmp=0;
- tmp=dat<<8;
- SN74HC595_SRCLK=0;
- SN74HC595_RCLK=0;
- for(a=0;a<16;a++)
- {
- if(tmp&0x8000)
- {
- SN74HC595_SER=1;
- }
- else
- {
- SN74HC595_SER=0;
- }
- tmp<<=1;
- SN74HC595_SRCLK=1;
- asm("nop");
- asm("nop");
- asm("nop");
- asm("nop");
- SN74HC595_SRCLK=0;
- }
- SN74HC595_RCLK=1;
- asm("nop");
- asm("nop");
- SN74HC595_RCLK=0;
- }
- void SPIsendA(unsigned char dat)//给级联的第二个595写字节
- {
- unsigned char a;
- unsigned int tmp=0;
- tmp=tmp|dat;
- SN74HC595_SRCLK=0;
- SN74HC595_RCLK=0;
- for(a=0;a<16;a++)
- {
- if(tmp&0x8000)
- {
- SN74HC595_SER=1;
- }
- else
- {
- SN74HC595_SER=0;
- }
- tmp<<=1;
- SN74HC595_SRCLK=1;
- asm("nop");
- asm("nop");
- asm("nop");
- asm("nop");
- SN74HC595_SRCLK=0;
- }
- SN74HC595_RCLK=1;
- asm("nop");
- asm("nop");
- SN74HC595_RCLK=0;
- }
- void smgNum(unsigned char num)//位选函数,配合显示函数使用,选择138译码输出的位
- {
- switch(num)
- {
- case 0:SN74HC138_S3=1;SN74HC138_S2=1;SN74HC138_S1=1;break;
- case 1:SN74HC138_S3=1;SN74HC138_S2=1;SN74HC138_S1=0;break;
- case 2:SN74HC138_S3=1;SN74HC138_S2=0;SN74HC138_S1=1;break;
- case 3:SN74HC138_S3=1;SN74HC138_S2=0;SN74HC138_S1=0;break;
- case 4:SN74HC138_S3=0;SN74HC138_S2=1;SN74HC138_S1=1;break;
- case 5:SN74HC138_S3=0;SN74HC138_S2=1;SN74HC138_S1=0;break;
- case 6:SN74HC138_S3=0;SN74HC138_S2=0;SN74HC138_S1=1;break;
- case 7:SN74HC138_S3=0;SN74HC138_S2=0;SN74HC138_S1=0;break;
- default:SN74HC138_S3=0;SN74HC138_S2=0;SN74HC138_S1=0;break;
- }
- }
- /*
- 编者按:
- 在设计连接时,用于显示温度的74HC595的SN74HC595_SER端
- 接在用于显示电压的595 Q7'端,两个74HC595级联,
- 我也不知道当时怎么想的,选择如此焊接,
- 但是既然电路这么做出来了,程序只好照着编了。
- */
- void smgdisplay()
- {
- unsigned char i;
- for(i=0;i<4;i++)//温度数据显示
- {
- if(pointpositionA==i)
- {
- SPIsendA((duan[Display[i]])|0x10);
- }
- else
- {
- SPIsendA(duan[Display[i]]);
- }
- smgNum(i);//选择相应位
- delay(100);
- SPIsendA(0x00);//消隐
- delay(50);
- }
- for(i=4;i<8;i++)//电压数据显示
- {
- if(pointpositionB==i)
- {
- SPIsendB((duan[Display[i]])|0x10);
- }
- else
- {
- SPIsendB(duan[Display[i]]);
- }
- smgNum(i);//选择相应位
- delay(100);
- SPIsendB(0x00);//消隐
- delay(50);
- }
- }
- void sys_init()//系统初始化
- {
- asm("sim");
- CLK_init(); //HSI初始化,更改分频系数为1
- TIM4_init(); //TIM4初始化,定时1ms
- asm("rim");
- SN74HC595_IO_Define(); //SN74HC595接线定义
- SN74HC138_IO_Define(); //SN74HC138接线定义
- nRF24L01_IO_Define(); //nRF24L01接线定义
- nRF24L01_IO_init(); //nRF24L01通信线初始化
- nRF24L01_SetMode_Rx(); //nRF24L01功能初始化:接收模式
- }
- void main(void)
- {
- sys_init(); //系统初始化
- while(1)
- {
- if(nRF24L01_ReceiveData()) //如果接收到数据
- {
- TIM4_cnt=0;
- if(Received_Buff[0])//温度为正
- {
- if(Received_Buff[1]==0)//如果百位为0
- {
- if(Received_Buff[2]==0)//如果十位为0
- {
- Display[0]=Received_Buff[3];
- Display[1]=Received_Buff[4];
- Display[2]=Received_Buff[5];
- Display[3]=Received_Buff[6];
- pointpositionA=0;
- }
- else
- {
- Display[0]=Received_Buff[2];
- Display[1]=Received_Buff[3];
- Display[2]=Received_Buff[4];
- Display[3]=Received_Buff[5];
- pointpositionA=1;
- }
- }
- else
- {
- Display[0]=Received_Buff[1];
- Display[1]=Received_Buff[2];
- Display[2]=Received_Buff[3];
- Display[3]=Received_Buff[4];
- pointpositionA=2;
- }
- }
- else
- {
- Display[0]=11;//负号
- if(Received_Buff[1]==0)//如果百位为0
- {
- if(Received_Buff[2]==0)//如果十位为0
- {
- Display[1]=Received_Buff[3];
- Display[2]=Received_Buff[4];
- Display[3]=Received_Buff[5];
- pointpositionA=1;
- }
- else
- {
- Display[1]=Received_Buff[2];
- Display[2]=Received_Buff[3];
- Display[3]=Received_Buff[4];
- pointpositionA=2;
- }
- }
- else
- {
- Display[1]=Received_Buff[1];
- Display[2]=Received_Buff[2];
- Display[3]=Received_Buff[3];
- pointpositionA=3;
- }
- }
- Display[4]=Received_Buff[8];
- Display[5]=Received_Buff[9];
- Display[6]=Received_Buff[10];
- Display[7]=Received_Buff[11];
- }
- smgdisplay();
- }
- }
- #pragma vector=0x19//定时器4中断服务函数
- __interrupt void TIM4_UPD_OVF_IRQHandler(void)
- {
- TIM4_cnt++;
- TIM4_SR=0;
- if(TIM4_cnt==500)
- {
- unsigned char i;
- TIM4_cnt=0;
- for(i=0;i<8;i++)
- {
- Display[i]=10;
- }
- }
- }
复制代码
欢迎进群:873434536,虽人数暂时较少,但群内氛围很好,有任何关于51学习中的问题,来一起讨论吧~!
程序源码:
基于NTC热敏电阻和nRF24L01的无线温度计 发布版 凌净清河.zip
(409.08 KB, 下载次数: 250)
请注意,为了方便黑币较少的人也能够下载附件,回复本帖,任何时候我看到,均会给出最高评分作为黑布补贴!
|
评分
-
查看全部评分
|