📄 ds18b20.c
字号:
/****************************************************************/
/*数码管驱动演示程序,只给出了基本的原理,实现需独立思考*********/
/*By Tony 2008.5.13 */
/****************************************************************/
#include <reg51.H>
//声明
unsigned char LedT0; //数码管驱动中的5个变量
unsigned char Led1;
unsigned char Led2;
unsigned char Led3;
unsigned char Led4;
sbit P2_4=P2^4; //4个数码管开关
sbit P2_5=P2^5;
sbit P2_6=P2^6;
sbit P2_7=P2^7;
sbit P3_3=P3^3; //5个按键
sbit P3_4=P3^4;
sbit P3_5=P3^5;
sbit P3_6=P3^6;
sbit P3_7=P3^7;
sbit BUZZER=P2^3; //蜂鸣接口
bit flag=0; //温度正负的标志,0表示正温度
unsigned char Buzz=0; //蜂鸣状态开关,默认蜂鸣关闭
unsigned int h_temp=399,l_temp=199; //默认温度上限39.9°和温度下限19.9°
unsigned int time=0; //临时变量,用来在中断中计数,实现 0.9秒刷新一次管子
const unsigned char table[19]=
{0x28,0xEB,0x32,0xA2,0xE1,0xA4,0x24,0xEA,0x20,0xA0,0x60,0x25,0x3c,0x23,0x34,0x74,0xF7,0xD7,0xFF};
sbit DQ =P2^2; //定义1Wire总线通信端口
//延时函数,在1Wire总线中实现时序的延时
void delay(unsigned int i)
{
while(i--);
}
//初始化1Wire总线函数
Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1; //DQ复位
delay(8); //稍做延时
DQ = 0; //单片机将DQ拉低
delay(80); //精确延时 大于 480us
DQ = 1; //拉高总线
delay(14);
x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
delay(20);
}
//1Wire总线读一个字节
ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat = 0;
EA=0;
for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay(4);
}
EA=1;
return(dat);
}
//1Wire总线写一个字节
WriteOneChar(unsigned char dat)
{
unsigned char i=0;
EA=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay(5);
DQ = 1;
dat>>=1;
}
EA=1;
delay(4);
}
//1Wire总线读取温度
ReadTemperature(void)
{
union uni_a{ //利用union来实现温度低八位和高八位组合在一起
unsigned int temp;
unsigned char a[2];
} uni;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
uni.a[1]=ReadOneChar(); //读取温度值低位
uni.a[0]=ReadOneChar(); //读取温度值高位
if(uni.temp<0x0fff) //如果正温度
{
flag=0; //正温度标志
}
else //如果负温度
{
flag=1; //负温度标志
uni.temp=~uni.temp+1; //取反加一
}
uni.temp=uni.temp*0.625; //计数温度,为方面显示扩大了10倍
return(uni.temp);
}
//中断处理函数,实现4个数码管的动态驱动
void int1() interrupt 1 using 1
{
TF0 = 0; //清定时0中断标志
TH0 = 0xF6; //2.5MS
TL0 = 0x3D;
time++; //利用来作为每0.9秒刷新显示一次的变量
if(Buzz==1) //温度超过上限,报警蜂鸣
{
if(time%50==0) //高温报警一种频率蜂鸣提示
{
BUZZER=!BUZZER;
}
}
else if(Buzz==2) //温度超过下限,报警蜂鸣
{
if(time%70==0) //低温报警一种频率蜂鸣提示
{
BUZZER=!BUZZER;
}
}
P2 |= 0xF0; //对P2口的高四位置1,关数码管
switch(LedT0)
{
case 0:
P0 = table[Led1];
P2_4 = 0;
LedT0 = 1;
break;
case 1:
P0 = table[Led2];
P2_5 = 0;
LedT0 = 2;
break;
case 2:
P0 = table[Led3];
P2_6 = 0;
LedT0 = 3;
break;
case 3:
P0 = table[Led4];
P2_7 = 0;
LedT0 = 0;
break;
default://语句d
LedT0 = 0;
break;
}
}
//延时函数,利用参数控制实现不同时间的延时
void delay1(int i)
{
int j,k;
for(j=0;j<i;j++)
{
for(k=0;k<125;k++);
}
}
//设置函数,可以设置上下限温度值
void shezhi()
{
unsigned int a;
unsigned char Ledn;
for(;;)
{
if(P3_3==0) //按键(SW1)按下
{
for (a=0; a<1000; a++); //去抖动,延时
if(!P3_3)
{
if(Led1<9) //数码管1显示a到f表示可以设置6个参数
{ //a表示温度上限,b表示温度下限,其余4个参数暂未使用
Led1=9;
}
Led1++;
if(Led1>15) //如果超过了f参数,则循环到a参数
{
Led1=10;
}
if(Led1==10) //如果设置a参数,温度上限,则将之前的值在数码管2,3,4上显示出
{
//可以增加h_temp从E2prom器件读回
Led2=h_temp/100;
Led3=h_temp%100/10;
Led4=h_temp%10;
}
else if(Led1==11) //如果设置b参数,温度下限,则将之前的值在数码管2,3,4上显示出
{
Led2=l_temp/100;
Led3=l_temp%100/10;
Led4=l_temp%10;
}
else //其余4个参数暂未使用,数码管显示000
{
Led2=0;
Led3=0;
Led4=0;
}
while(!P3_3); //等待放开手
}
}
if(P3_4==0) //按键(SW2)按下
{
for (a=0; a<1000; a++); //去抖动,延时
if(!P3_4)
{
if(Ledn==0) //根据SW3键的选择,改变数码管的值
{
Led2+=1;
if(Led2==10)
Led2=0;
}
else if(Ledn==1)
{
Led3+=1;
if(Led3==10)
Led3=0;
}
else
{
Led4+=1;
if(Led4==10)
Led4=0;
}
while(!P3_4); //等待放开手
}
}
else if(!P3_5) //按键(SW3)按下
{
for (a=0; a<1000; a++); //去抖动,延时
if(!P3_5)
{
if(Ledn==0) //切换改变的数码管
{
Ledn=1;
}
else if(Ledn==1)
{
Ledn=2;
}
else
{
Ledn=0;
}
while(!P3_5); //等待放开手
}
}
else if(!P3_6) //按键(SW4)按下,保存退出
{
for (a=0; a<1000; a++); //去抖动,延时
if(!P3_6)
{
if(Led1==10)
{
h_temp= Led4+Led3*10+Led2*100; //将设置的值计算保存下
//这里可以加IIC保存
}
else if(Led1==11)
{
l_temp= Led4+Led3*10+Led2*100; //将设置的值计算保存下
//这里可以加IIC保存
}
else //其余4个参数暂未使用
{
}
break; //退出for循环
while(!P3_6); //等待放开手
}
}
else if(!P3_7) //按键SW5按下,不做任何修改退出
{
for (a=0; a<1000; a++); //去抖动,延时
if(!P3_7)
{
break;
while(!P3_7); //等待放开手
}
}
}
}
void main(void) //主程序
{
unsigned int temp,a;
unsigned char Ledn;
TMOD = 0x01; //设定T0为十六位定时模式。
TH0 = 0xF6;
TL0 = 0x3D; //2MS
TR0 = 1; //开定时器0
ET0 = 1; //致能定时0中断
TF0 = 0; //清定时0中断标志
EA = 1; //开总中断
LedT0 = 0;
Led1 = 0;
Led2 = 0;
Led3 = 0;
Led4 = 0;
Ledn = 0;
P1=0Xfe; //上电做一个流水灯
for(a=0;a<8;a++)
{
P1<<=1;
delay1(200);
}
P1=0xff;
for(;;) //空循环,等待
{
if(time>350) //利用定时完成大概0.9秒刷新一次温度显示
{
time=0;
temp=ReadTemperature();//读回来温度,注意已经处理为当前温度的10倍
if(!flag) //如果温度为正
{
Led1 = temp/1000; //显示温度的百位
Led2 = temp%1000/100; //显示温度的十位
Led3 = temp%100/10; //显示温度的个位
Led4 = temp%10; //显示温度的小数点后1位
}
else
{
Led1 = 17; //显示负号温度标志
Led2 = temp%1000/100;//显示温度的十位
Led3 = temp%100/10; //显示温度的个位
Led4 = temp%10; //显示温度的小数点后1位
}
}
if(P3_3==0) //按键(SW1)按下
{
for (a=0; a<1000; a++); //去抖动,延时
if(!P3_3)
{
shezhi(); //进入参数设置,可以设置上下限温度等6个参数。
// while(!P3_3); //等待放开手
}
}
if(temp>=h_temp) //温度超过报警上限
{
Buzz=1; //一种频率的蜂鸣声音,相对下限比较急促
P1=0XF0; //报警灯,可以自己修改
//可以自己增加其他的处理
}
else if(temp<=l_temp) //温度超过报警下限
{
Buzz=2; //令一种频率的蜂鸣声音
P1=0X0F; //报警灯,可以自己修改
//可以自己增加其他的处理
}
else if(Buzz) //正常温度范围
{
Buzz=0; //关闭蜂鸣,熄灭报警灯
BUZZER=1;
P1=0XFF;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -