在模拟远程温度监控的时候,用到了DS18B20温度传感器,在远程的通信方面用了433M无线模块,以及USB转串口来连接上位,上位机中数据的读取用了Python脚本。
DS18B20传感器的基本信息
DS18B20 单线数字温度传感器,即“一线器件”,其具有独特的优点:
( 1 )采用单总线的接口方式 与微处理器连接时仅需要一条口线即可实现微处理器与 DS18B20 的双向通讯。单总线具有经济性好,抗干扰能力强,适合于恶劣环境的现场温度测量,使用方便等优点,使用户可轻松地组建传感器网络,为测量系统的构建引入全新概念。
( 2 )测量温度范围宽,测量精度高 DS18B20 的测量范围为 -55 ℃ ~+ 125 ℃ ; 在 -10~+ 85°C范围内,精度为 ± 0.5°C 。
( 3 )在使用中不需要任何外围元件。
( 4 )持多点组网功能 多个 DS18B20 可以并联在惟一的单线上,实现多点测温。
( 5 )供电方式灵活 DS18B20 可以通过内部寄生电路从数据线上获取电源。因此,当数据线上的时序满足一定的要求时,可以不接外部电源,从而使系统结构更趋简单,可靠性更高。
( 6 )测量参数可配置 DS18B20 的测量分辨率可通过程序设定 9~12 位。
( 7 ) 负压特性电源极性接反时,温度计不会因发热而烧毁,但不能正常工作。
( 8 )掉电保护功能 DS18B20 内部含有 EEPROM ,在系统掉电以后,它仍可保存分辨率及报警温度的设定值。
DS18B20 具有体积更小、适用电压更宽、更经济、可选更小的封装方式,更宽的电压适用范围,适合于构建自己的经济的测温系统,因此也就被设计者们所青睐。
DS18B20内部结构
主要由4部分组成:64 位ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。ROM中的64位序列号是出厂前被光刻好的,它可以看作是该DS18B20的地址序列码,每个DS18B20的64位序列号均不相同。64位ROM的排的循环冗余校验码(CRC=X^8+X^5+X^4+1)。 ROM的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20的目的。
DS18B20管脚排列:
1. GND为电源地;
2. DQ为数字信号输入/输出端;
3. VDD为外接供电电源输入端(在寄生电源接线方式时接地)
433M 模块
在连接单片机的一端,由于m0 m1是不能悬空的,所以就让这两个引脚接地即可,AUX一般情况下不会使用,悬空即可,RXD接收引脚接单片机的T(发送),TXD接单片机的R(接收),供电使用5V供电即可;另一端要连接USB转串口模块来连接上位机,连接的方法与433M连接单片机的方法基本类似,然后单片机写入代码就能实现通信。
这里有一个 串口调试助手,可以用来调试。
Python脚本
直接上代码吧
import serial
import sys
try:
ser = serial.Serial('COM4', 9600)
except Exception, e:
print 'open serial failed.'
exit(1)
print 'The temprature is'
while True:
# echo
s = ser.read()
if(s!='#'):
ser.write(s)
# write to stdout and flush it
sys.stdout.write(s)
sys.stdout.flush()
#include <reg51.h>
#include <uart.h>
#define uchar unsigned char
code unsigned char seg7code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //?????????????
code unsigned char seg7codeB[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff}; //????????????
int count = 0;
sbit DQ=P3^6; //???????????????
unsigned char tempL=0; //?????
unsigned char tempH=0;
unsigned int sdata; //???????????
unsigned char xiaoshu1; //?????
unsigned char xiaoshu2; //?????
unsigned char xiaoshu; //????
bit fg=1; //??????
sbit key = P3^2;
void delay(unsigned char i)
{
for(i;i>0;i--);
}
void delay1(uchar i)
{
uchar j,k;
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
void Init_DS18B20(void)
{
unsigned char x=0;
DQ=1; //DQ???
delay(8); //???
DQ=0; //??????
delay(80); //??(>480us)
DQ=1; //?????
delay(5); //??(15~60us)
x=DQ; //?X?????????????,18B20????X=0,??X=1
delay(20);
}
//?????
ReadOneChar(void) //?????????????1us??,??????????,???????
{
unsigned char i=0; //?????????????60us,??????????1us?????????
unsigned char dat=0;
for (i=8;i>0;i--) //?????8?
{
DQ=1;
delay(1);
DQ=0;
dat>>=1;
DQ=1;
if(DQ)
dat|=0x80;
delay(4);
}
return(dat);
}
//?????
void WriteOneChar(unsigned char dat)
{
unsigned char i=0; //????????????,????????15us??????????????,
for(i=8;i>0;i--) //?15~60us??????????,????????1,??0???
{
DQ=0; //?????????????1us??????????
DQ=dat&0x01;
delay(5);
DQ=1;
dat>>=1;
}
delay(4);
}
//????(???tempL;???tempH;)
void ReadTemperature(void)
{
Init_DS18B20(); //???
WriteOneChar(0xcc); //?????????
WriteOneChar(0x44); //??????
delay(125); //????????,??
Init_DS18B20(); //???
WriteOneChar(0xcc); //?????????
WriteOneChar(0xbe); //??????(???????????????)
tempL=ReadOneChar(); //???????LSB
tempH=ReadOneChar(); //???????MSB
if(tempH>0x7f) //????1?????
{
tempL=~tempL; //????,????
tempH=~tempH+1;
fg=0; //???????fg=0
}
sdata = tempL/16+tempH*16; //????
xiaoshu1 = (tempL&0x0f)*10/16; //?????
xiaoshu2 = (tempL&0x0f)*100/16%10; //?????
xiaoshu=xiaoshu1*10+xiaoshu2; //????
}
//????
void Led(unsigned int date)
{
if(fg==1)
{
P2=0xef; //P1.0=0,?????
P0=seg7code[date/10]; //???,??,??
delay1(5);
P0=0xff; //??
//sendmsg(date/10+'0');
P2=0xdf; //P1.1=0,?????,???
P0=seg7codeB[date%10];
delay1(5);
P0=0xff; //??
//sendmsg(date%10+'0');
//sendmsg('.');
P2=0xbf; //P1.3=0,?????,??????
P0=seg7code[xiaoshu1];
delay1(5);
P0=0xff; //??
//sendmsg(xiaoshu1+'0');
P2=0x7f; //P1.3=0,?????,??????
P0=seg7code[xiaoshu2];
delay1(5);
P0=0xff; //??
//sendmsg(xiaoshu2+'0');
}
if(fg==0) //??????????
{
P2=0xfe; //P1.0=0,?????
P0=seg7code[11]; //????
delay1(5);
P0=0xff; //??
P2=0xfd; //P1.1=0,?????,???
P0=seg7code[date/10];
delay1(5);
P0=0xff; //??
P2=0xfb; //P1.3=0,?????,???
P0=seg7codeB[date%10];
delay1(5);
P0=0xff; //??
P2=0xf7; //P1.3=0,?????,??????
P0=seg7code[xiaoshu1];
delay1(5);
P0=0xff; //??
}
}
void send(int date)
{
sendmsg(date/10+'0');
sendmsg(date%10+'0');
//sendmsg('.');
//sendmsg(xiaoshu1+'0');
//sendmsg(xiaoshu2+'0');
//count++;
sendmsg('C');
sendmsg(' ');
}
/*int keyflag(int a)
{
int cc = 20;
if(a == 0)
{
while(cc--);
if(a == 0)
{
return 1;
}
else
{
return 0;
}
while(a == 0);
}
} */
void delay_ms(unsigned int xms) // xms??????????
{
unsigned int x,y;
for(x=xms;x>0;x--)
for(y=110;y>0;y--);
}
void main()
{
initcom();
//init_time();
while(1)
{
delay_ms(3000);
ReadTemperature();
count++;
Led(sdata);
//count = 0;
if(count>=2) send(sdata);
}
}
头文件uart.h
#ifndef __COM_H__
#define __COM_H__
#define uchar unsigned char
#define uint unsigned int
#define XTAL 11059200 // CUP 晶振频率
#define baudrate 9600 // 通信波特率
void sendmsg(uchar ps)
{
SBUF = ps; // 要发送的字符放入缓冲区
while(TI == 0); // 一直等等,直到发送完数据为止
TI = 0;
}
uchar rcvmsg(void) //调用此函数前,要先调用RI,查看是否收到数据,确定已收到的话,再调用此函数
{
RI=0; //要先将RI=0再返回,否则,返回后,RI=0这句就不执行了。
return SBUF;
}
void initcom()
{
TMOD = 0x20; // 定时器1工作于8位自动重载模式, 用于产生波特率
TH1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate)));
TL1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate))); // 定时器1赋初值
SM0 = 0; //串口工作方式控制
SM1 = 1; //串口工作方式控制 //这两个共同控制了串口工作方式为 0;
REN = 1; //串口接收允许
PCON = 0x00;
TR1 = 1; //允许串口接收
ES = 0; //关闭串口中断
}
#endif