要求是51和DS18B20显示当下温度;精确到小数点后一位;有上下限后报警(灯);按键可加可不加的;帮着看下接线图和程序正确否?谢谢各位专业人士了;
#include
#define PORT_DATA P0
#define PORT_SELECT P2
#define PORT_KEY P1
#define KEY_UP 0x01 //按键+
#define KEY_DOWN 0x02 //按键-
***it DQ = P1^7; //数据引脚定义
//***it SPEAKER = P2^4;
unsigned charSPEAKER = 0;
unsigned charTrg; //按键触发
unsigned charCont; //长按值
unsigned intT_max;
unsigned charcode SEG_CODE[] = {
0xA0,/*0*/
0xBB,/*1*/
0x62,/*2*/
0x2A,/*3*/
0x39,/*4*/
0x2C,/*5*/
0x24,/*6*/
0xBA,/*7*/
0x20,/*8*/
0x28,/*9*/
0x64,/*E10*/
0x77,/*r11*/
0x7F,/*-12*/
0xFF /* 13*/
}; //共阳表
unsigned charcode SEG_SEL[]={
0xFB,
0xF7,
0xFD,
0xFE
};
/*******微秒延时*********/
void Delayus(unsignedint dUT)
{
while(dUT--);
}
/*******毫秒延时*********/
void Delayms(unsignedint dT)
{
unsigned intdA,dB;
for(dA=0;dA
for(dB=0; dB<113;dB++)
;
}
/******************************************************************************/
unsigned charInit_DS18B20(void)//初始化ds1820温度传感器
{
unsigned charx=0,dsExt;
DQ = 1; //DQ复位
Delayus(16); //稍做延时
DQ = 0; //单片机将DQ拉低
Delayus(100); //精确延时 大于 480us
DQ = 1; //拉高总线
Delayus(4);
x = DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
Delayus(60);
return x;
}
/******************************************************************************/
unsigned charReadOneChar(void)//读一个字节(DS18B20驱动)
{
unsigned chari=0;
unsigned chardat=0;
for (i=8;i>0; i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat |= 0x80;
Delayus(4);
}
return(dat);
}
/******************************************************************************/
void WriteOneChar(unsignedchar dat)//写一个字节(DS18B20驱动)
{
unsigned chari=0;
DQ = 0;
Delayus(5);
for (i=8;i>0; i--)
{
DQ = 0;
DQ = dat & 0x01;
Delayus(4);
DQ = 1;
dat>>=1;
}
}
/******************************************************************************/
unsigned intReadTemperature(void)//读取温度(DS18B20驱动)
{
unsigned charTL,TH;
unsigned intt=0;
float tt=0;
bit flag=0;
if ( Init_DS18B20() == 1 )
return 2345; //不存在标志
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
if ( Init_DS18B20() == 1 )
return 2345;
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器
TL = ReadOneChar(); //读低8位
TH = ReadOneChar(); //读高8位
t = TH;
t <<= 8;
t = t|TL;
if( t>0x8000) {
t = ~t+1;
tt = t*0.0625;
t = tt*10+0.5; //放大10倍输出并四舍五入
t = t | 0x8000; //存入负温度标志
} else {
tt=t*0.0625;
t= tt*10+0.5; //放大10倍输出并四舍五入
}
return(t);
}
void DispTem(unsignedint tC)
{
unsigned chari,sT[4];
if (tC == 2345) { //DS18B20不存在
sT[0]= 13; //
sT[1]= 10; //E
sT[2]= 11; //r
sT[3]= 11; //r
for (i=0; i<4; i++)
{
PORT_DATA = SEG_CODE[ sT];
PORT_SELECT =SEG_SEL&(~(SPEAKER<<4));
Delayms(2); //延时,显示一段时间
PORT_SELECT = 0xff&(~(SPEAKER<<4)); //关闭显示,防止重影
}
} else {
if ( tC& 0x8000)
{
tC &= 0x7FFF; //去掉最高位的负温度标志
sT[0]= 12; //-
}
else
sT[0]= 13; //空
if (tC> T_max*10) //超温报警
{
SPEAKER = 1;
} else {
SPEAKER = 0;
}
sT[0]= tC / 1000; //百位
sT[1]= tC % 1000 / 100;//十位
sT[2]= tC % 100 / 10; //个位
sT[3]= tC % 10; //小数位
if (sT[0] == 0){ //去左边的0
sT[0]= 13;
if(sT[1] == 0){
sT[1] = 13;
}
}
for (i=0; i<4; i++)
{
if(i == 2)
PORT_DATA =SEG_CODE[ sT] & 0xDF; //点亮小数点
else
PORT_DATA =SEG_CODE[ sT];
PORT_SELECT = SEG_SEL&(~(SPEAKER<<4));
Delayms(2); //延时,显示一段时间
PORT_SELECT = 0xff&(~(SPEAKER<<4)); //关闭显示,防止重影
}
}
}
//读按键值
void KeyRead( void)
{
unsigned charReadData = P1^0xff; //读端口值,并取反
ReadData &= (KEY_UP | KEY_DOWN); //只取有效按键值
Trg = ReadData & (ReadData ^ Cont); //只在第一次按下时为按键值,以后为0
Cont = ReadData; //长按、短按都为按键值
}
//报警上限温度显示函数
void DispMaxTem(void)
{
PORT_DATA = SEG_CODE[T_max/10]; //显示报警上限温度
PORT_SELECT = SEG_SEL[2];
Delayms(2);
PORT_SELECT = 0xFF;
PORT_DATA = SEG_CODE[T_max%10];
PORT_SELECT = SEG_SEL[3];
Delayms(2);
PORT_SELECT = 0xFF;
}
//最高温度修改函数
void MaxTem(void)
{
unsigned intcount=0;
while(1){ //如果处于修改状态
PORT_KEY = 0xFF;
KeyRead(); //读按键
if ((Cont == 0x00) && (count > 0) ) //“+”处理
{
T_max++;
if(T_max>99)
{
T_max = 99; //上限为99
}
count = 0;
}
if (Cont& KEY_UP)
{
count++;
if(count > 200)
{
count = 0;
break; //长按,跳出该程序,进入主程序显示温度
}
}
if (Trg& KEY_DOWN) //“-”处理
{
if(T_max < 1)
{
T_max = 0; //下限为0
} else{
T_max--;
}
}
DispMaxTem(); //显示上限温度
ReadTemperature(); //增加刷新间隔时间,降低亮度
}
}
void main(void)
{
unsigned inttem,count;
T_max = 50; //初始报警上限温度
SPEAKER = 0; //关蜂鸣器
while(1)
{
tem = ReadTemperature(); //读温度
DispTem(tem); //显示温度
PORT_KEY = 0xFF;
KeyRead(); //读按键状态
if(Cont&KEY_UP) //“+”键按下
{
count++;
if(count > 150) //长按+,松开后进入修改模式
{
count = 0;
while(Cont != 0) //等待按键松开
{
PORT_KEY = 0xFF;
KeyRead();
DispMaxTem(); //显示最高温度
ReadTemperature(); //增加刷新间隔时间,降低亮度
}
MaxTem(); //到报警上限修改模式
}
}
if ((Cont== 0x00) && (count>0))//短按,重新计数
{
count = 0;
}
}
}