在模拟远程温度监控的时候,用到了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