////////////////////////通信协议//////////////////////////////////////
// 发送:(4字符)
// 1.起始位:S
// 2.正负数标识
// 3.发送整数原码(8位)
// 4.发送小数原码(8位)
// 接收:(3字符)
// _ _ _ _ _ _ _ _
// 1.0 0 0 0 0 0 0 0
// 高3位暂时保留
// 3,4,5位为温度通道
// 低两位为精度,11 0.0625;
// 10 0.125
// 01 0.25
// 00 0.5
// 2.温度上限
// 3.温度下限
//
/////////////////////////////////////////////////////////////////////////
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define WORK_MODE 2 //工作模式(0-单片测温;1-读ROM;2-多点测温)
#define RDSCR 0xBE //读暂存器
#define RDROM 0x33 //读ROM
#define SKIPROM 0xCC //Skip ROM
#define MATCHROM 0x55 //Match ROM
#define CONVERTTEM 0x44 //转换温度
sbit DQ=P2^0; //测温总线
sbit LED=P1^0; //LED串行显示的数据输出端
sbit CLK=P1^1; //为74LS164提供时钟信号
sbit DEC=P1^2; //小数点
uchar Rom[8]; //读ROM时用于存储读取的8个字节的ROM
uchar CtlData; //用于保存上位机发送的控制命令
uchar RomIndex=1; //用于多通道测温,选择通道
uchar TemPrecision=0x60; //温度精度,默认为12位
uchar Tem_LSB=0;
uchar Tem_MSB=0;
uchar n=0; //正负数标识
uchar Scr[9]; //暂存器
uchar code Rom1[8]={40,48,197,184,0,0,0,142};
uchar code Rom2[8]={40,49,197,184,0,0,0,185};
uchar code Rom3[8]={40,16,81,137,1,0,0,252};
uchar code Rom4[8]={40,223,50,137,1,0,0,24};
uchar code Rom5[8]={40,161,76,98,1,0,0,129};
uchar code LED_code[12]={0x3F,/*0*/
0x06,/*1*/
0x5B,/*2*/
0x4F,/*3*/
0x66,/*4*/
0x6D,/*5*/
0x7D,/*6*/
0x07,/*7*/
0x7F,/*8*/
0x6F,/*9*/
0x00,/*灭0*/
0x40/*负号*/};
uchar code CRC_Table [256]= //CRC校验数据表
{0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
void delay_ms(uint t) //延时
{
uchar i;
while(t--)
{
for(i=0;i<250;i++)
{}
}
}
void LED_display(uchar temM,uchar temL) //数码管串行显示
{
uchar temp,i,j,k;
uchar LEDData[5]; //存储将要显示的数字的LED编码
/////////////////////////////////////////////
temp=((temL&0x0F)>>3)*5; //小数
LEDData[0]=LED_code[temp];
/////////////////////////////////////////////
LEDData[1]=LED_code[temM%10]+0x80; //个位
/////////////////////////////////////////////
temp=temM/10; //十位
if((temp%10==0)&&(temM/100==0)) LEDData[2]=LED_code[10];
else LEDData[2]=LED_code[temp%10];
////////////////////////////////////////////
if(temM/100==0) //百位或符号位
{
if(n==0) LEDData[3]=LED_code[10];
else LEDData[3]=LED_code[11];
}
else
{
LEDData[3]=LED_code[temM/100];
}
////////////////////////////////////////////
LEDData[4]=LED_code[RomIndex]; //温度通道
////////////////////////////////////////////
for(i=0;i<5;i++)
{
temp=LEDData[i];
for(j=0;j<8;j++)
{
if((temp&0x80)==0x80) LED=1;
else LED=0;
CLK=0;
CLK=1;
CLK=0;
k=temp<<1;
temp=k;
}
}
}
uchar CRC_Check () //CRC校验
{
uchar i,CRC_Data=0;
for(i=0;i++;i<9)
{
CRC_Data=CRC_Data^Scr[i];
CRC_Data=CRC_Table[CRC_Data];
}
return (CRC_Data);
}
/*********************串口函数************************/
/* 函数功能:串口初始化及串口通信 */
/* Load() //串口通信初始化函数 */
/* DataSend() //串口发送函数 */
/* RomSend() //Rom发送函数 */
/*****************************************************/
void Load() //串口通信初始化函数
{
TMOD=0x20;
TH1=0x72;
TL1=0x72;
TR1=1;
IE=0x90;
PCON=0x00;
SCON=0x50;
ES=1; //串行口中断允许位
EA=1; //总中断允许位
}
void DataSend(uchar Data1,uchar Data2) //串口发送函数
{
SBUF='S'; //发送起始位S
while(TI==0);
TI=0;
delay_ms(100);
SBUF=n; //发送符号位
while(TI==0);
TI=0;
delay_ms(100);
SBUF=Data1;
while(TI==0);
TI=0;
delay_ms(100);
SBUF=Data2;
while(TI==0);
TI=0;
delay_ms(100);
}
void RomSend() //ROM发送
{
uchar i=0;
SBUF='S';
while(TI==0);
TI=0;
delay_ms(100);
for(i=0;i<8;i++)
{
SBUF=Rom[i];
while(TI==0);
TI=0;
delay_ms(100);
}
}
/*********************复位函数************************/
/* 函数功能:用于产生复位脉冲,初始化DS18B20 */
/* 实现过程:主机通过拉低单线480us以上,产生复位脉冲 */
/* 单线器件DS18B20检测到该上升沿后,延时 */
/* 15~60us,DS18B20通过拉低总线60~240us */
/* 来产生应答脉冲,主机接收到应答脉冲后, */
/* 说明有单线器件在线。 */
/*****************************************************/
void Reset()
{
uchar i;
DQ=0; //拉低单线
i=150; //拉低约600us
while(i>0) i--;
DQ=1; //产生上升沿,释放总线
while(DQ)
{
i++;
if(i>10) break;
}
while(~DQ);
}
/************************写函数************************/
/* 函数功能:产生写时隙,向DS18B20写入命令与数据 */
/* 实现过程:主机将数据线从高电平拉至低电平时产生写时 */
/* 隙DS18B20在DQ变低的后的15~60us进行采样,*/
/* 为高就写"1",为低就写"0"。 */
/******************************************************/
void WR_byte(uchar bytData)
{
uchar m;
uchar i;
uchar j;
for(j=0;j<8;j++)
{
m=bytData&0x01;
DQ=0;
_nop_(); //延时小于15us
if(m) DQ=1;
bytData=bytData>>1;
i=15; //延时60us以上
while(i>0) i--;
DQ=1;
}
}
void WR_Scr() //写暂存器
{
uchar i;
Reset();
#if WORK_MODE==0 //判断单片机工作模式,若为0则Skip Rom
WR_byte(SKIPROM); //Skip ROM
#elif WORK_MODE==2 //若为2则Match Rom
WR_byte(MATCHROM);
for(i=0;i<8;i++)
{
if(RomIndex==1) WR_byte(Rom1[i]);
else if(RomIndex==2) WR_byte(Rom2[i]);
else if(RomIndex==3) WR_byte(Rom3[i]);
else if(RomIndex==4) WR_byte(Rom4[i]);
else if(RomIndex==5) WR_byte(Rom5[i]);
}
#endif
WR_byte(0x4E);
WR_byte(0x4B);
WR_byte(0x46);
WR_byte(TemPrecision);
}
/**********************读取数据************************/
/* 函数功能:读取传送数据 */
/* 实现过程:读取数据时,把数据线从高电平拉至低电平, */
/* 低电平保持最少1us,来自DS18B20的输出数据 */
/* 在读时隙下降沿之后15us内有效,所有读时隙 */
/* 最短必须持续60us,两时隙之间最少保持1us */
/* 的回复时间。 */
/******************************************************/
bit RD_bit(void) //读取一位
{
bit bit