首先申明,这篇博客是用作记录本人实训内容的,代码我个人一字一字码的,就上网查了下数字温度传感器DS18B20的处理方法,基本都是个人完成的。
在这里吐槽下,本人辛辛苦苦码的代码,最后实训分数还没那些抄的人高,吐槽下老师- -,好了接下来说正事
万年历
- 一、实验内容
- 二、电路仿真图
- 三、代码
- 四、效果图
-
- 1.开始
- 2.日期
- 3.温度
- 四、最后
一、实验内容
设计定时器每50ms中断一次,在中断服务程序中,对中断次数进行计数,50ms计数20次,就是1秒,然后再对秒计数得到分的值,对分计数得到小时的值,分别将各值送到相应的段地址端口和位地址端口,通过数码管显示结果,达到电子时钟的计数效果。在计数的基础上,程序增加了按键程序,对电子时钟进行可调(对秒/分/时进行加1,此功能的增加使电子时钟功能更强、更实用,同理对日期也可以日/月/年进行加1。
a. 用AT89S51单片机的定时/计数器T0产生一秒的定时时间,作为秒计数时间。
b. 当一秒产生时,秒计数加1。
c. 开机时,显示00-00-00,并开始连续计时。计时满23-59-59时,返回00-00-00重新开始计时。
在以上设计基础上,在单片机的P1.0-P1.3口分别接入4个按键:
d. P1.0控制“秒”的调整,每按一次加1秒
e. P1.1控制“分”的调整,每按一次加1分
f. P1.2控制“时”的调整,每按一次加1时
g. P1.3用作功能选择键,在程序运行过程中如果按下功能选择键,则在年月日、时分秒和显示温度之间进行功能切换。
用AT89C52控制DS18B20,读取数据,并对DS18B20转换后的数据进行处理,最后在数码管上显示DS18B20测出的温度。
a.使用6位数码管显示测得的温度
b.最高位为符号位,如果温度值为正,不显示,如果温度为负,则显示负号
c.第2—4位显示温度值的整数部分,并在第4位数据上显示小数点
d.第5位显示小数部分
e.6,7位显示摄氏度符号“C”。
二、电路仿真图
这里我用的是ISIS Professional仿真,写代码用到是keil4
这是图中所用到的元器件
三、代码
#include <reg51.h> //头文件
unsigned char bitcode[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; //选择LED位码
unsigned char code
pcode[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f}; //无小数点0~9
ncode[] = { 0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd, 0x87, 0xff, 0xef}; //有小数点0~9
unsigned char riqi[] = { 2, 0, 2, 1, 0, 2, 0, 8};//在这里改日期
unsigned int key1=1,key2=1,key3=1,key4=1,year=0,month=0,day=0,d;
unsigned int bitcnt;
unsigned int flag = 0;
unsigned int s = 0,m = 0,h = 0;
unsigned int n = 0;
unsigned int bitcnt;
unsigned char Tools[] = { 0x63, 0x39,0x40};
sbit p10 = P1 ^ 0;
sbit p11 = P1 ^ 1;
sbit p12 = P1 ^ 2;
sbit p13 = P1 ^ 3;
sbit DQ = P2 ^ 4;
void DATE(); //声明函数
void changed();
void runnian();
void delay();
void delay2(int z);
void time_init();
void button();
void jishu();
void delay3(unsigned int j);
void Init_DS18B20(void);
char ReadOneChar(void);
void WriteOneChar(unsigned char dat);
int ReadTemperature(void);
void display_tempmain(unsigned int i);
void delay()
{
int i, j;
for (i = 0; i <= 10; i++)
for (j = 0; j <= 20; j++);
}
void DATE() //日期
{
for (bitcnt = 0; bitcnt < 8; bitcnt++)
{
P3 = bitcode[bitcnt];
if (bitcnt == 3 || bitcnt == 5)
P0 = ncode[riqi[bitcnt]];
else
P0 = pcode[riqi[bitcnt]];
delay();
runnian();
if(p10==0) //判断天数按键是否按下
key1=0;
if (p10==1&&key1==0)
{
riqi[7]+=1;
key1=1;
if (riqi[7]==10)
{
riqi[7]=0;
riqi[6]+=1;
}
if(day==d)
{
riqi[6]=0;
riqi[7]=1;
riqi[5]+=1;
}
if(month==12&&day==31)
{
riqi[5]=1;
riqi[4]=0;
riqi[3]+=1;
}
}
if(p11==0) //判断月份按键是否按下
key2=0;
if(p11==1&&key2==0)
{
riqi[5]+=1;
key3=1;
if(riqi[5]==10)
{ riqi[4]+=1;
riqi[5]=0;}
if(month==12)
{
riqi[5]=1;
riqi[4]=0;
riqi[3]+=1;
}
key2=1;
}
if(p12==0) //判断年份按键是否按下
key3=0;
if(p12==1&&key3==0)
{
riqi[3]+=1;
key3=1;
if(riqi[3]==10)
{
riqi[3]=0;
riqi[2]+=1;
}
}
}
}
void runnian(void) //判断是否为闰年
{
year=riqi[0]*1000+riqi[1]*100+riqi[2]*10+riqi[3];
month=riqi[4]*10+riqi[5];
day=riqi[6]*10+riqi[7];
if ((year%4==0)&&(year%100!=0)||(year%400==0))
{
if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==10)||(month==10)||(month==12))
{ d=31;}
if((month==4)||(month==6)||(month==9)||(month==11))
{ d=30;}
if(month==2)
{ d=28;}
}
else
{
if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==10)||(month==10)||(month==12))
{ d=31;}
if((month==4)||(month==6)||(month==9)||(month==11))
{ d=30;}
if(month==2)
{ d=29;}
}
}
void delay2(int z)
{
int x, y;
for (x = z; x > 0; x--)
for (y = 50; y > 0; y--)
;
}
void time_init() //定时器初始化
{
TMOD = 0x01;
TH0 = (65536 - 50000) / 256;
TL0 = (65536 - 50000) % 256;
EA = 1;
TR0 = 1;
ET0 = 1;
}
void button()
{
if (p10==0) //判断s按键是否按下
key1=0;
if (p10==1&&key1==0)
{
s++;
key1=1;
}
if (p11==0) //判断m按键是否按下
key2=0;
if (p11==1&&key2==0)
{
m++;
key2=1;
}
if (p12==0) //判断h按键是否按下
key3=0;
if (p12==1&&key3==0)
{ h++;
key3=1;}
}
void jishu()
{
for (bitcnt = 0; bitcnt < 8; bitcnt++)
{
P3 = bitcode[bitcnt];
button();
if(P3==0xfe)
P0=pcode[h/10]; //取小时的十位
else if(P3==0xfd)
P0=pcode[h%10]; //取小时的个位
else if(P3==0xfb)
P0=0x40; //取段码显示为-
else if(P3==0xf7) //取分的十位
P0=pcode[m/10];
else if(P3==0xef) //取分的个位
P0=pcode[m%10];
else if(P3==0xdf)
P0=0x40; //取段码显示为-
else if(P3==0xbf) //取秒的十位
P0=pcode[s/10] ;
else if(P3==0x7f) //取秒的个位
P0=pcode[s%10];
delay();
}
}
void delay3(unsigned int j)
{
while (j--)
;
}
void Init_DS18B20(void)
{
unsigned char x = 0;
DQ = 1;
delay3(8);
DQ = 0;
delay3(80);
DQ = 1;
delay3(14);
x = DQ;
delay3(20);
}
char ReadOneChar(void)
{
unsigned char i = 0;
unsigned char dat = 0;
for (i = 8; i > 0; i--)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if (DQ)
dat |= 0x80;
delay3(4);
}
return (dat);
}
void WriteOneChar(unsigned char dat)
{
unsigned char i = 0;
for (i = 8; i > 0; i--)
{
DQ = 0;
DQ = dat & 0x01;
delay3(5);
DQ = 1;
dat >>= 1;
}
delay3(4);
}
int ReadTemperature(void) //读取温度
{
unsigned char a = 0;
unsigned char b = 0;
unsigned int t = 0;
Init_DS18B20();
WriteOneChar(0xCC);
WriteOneChar(0x44);
Init_DS18B20();
WriteOneChar(0xCC);
WriteOneChar(0xBE);
a = ReadOneChar();
b = ReadOneChar();
t = b << 8;
t = t | a;
return (t);
}
void display_tempmain(unsigned int i) //显示温度
{
float temp;
unsigned char xiaoshu;
unsigned int zhengshu;
if ((0xf000 & i) == 0xf000)
{
i = ~i + 1;
P0 = 0x00;
if((zhengshu % 100 / 10)==0)
{
P0 = Tools[2];
P3 = 0xfb;
}
else
{
P0 = Tools[2];
P3 = 0xfd;
}
delay3(500);
}
temp = (0x000f & i) * 10.0 * 0.0625;
xiaoshu = temp;
zhengshu = i >> 4;
P0 = 0x00;
if((zhengshu / 100)==0) //温度百位
{
delay3(500);
P3 = 0xff;
}
else
{
P0 = pcode[zhengshu / 100];
P3 = 0xfd;
}
if((zhengshu / 100)==0&&(zhengshu % 100 / 10)==0) //温度十位
{
delay3(500);
P3 = 0xff;
}
else
{
P0 = pcode[zhengshu % 100 / 10];
P3 = 0xfb;
}
delay3(500);
P0 = 0x00;
P0 = pcode[zhengshu % 100 % 10] | ~0x7f; //温度个位
P3 = 0xf7;
delay3(500);
P0 = 0x00;
P0 = pcode[xiaoshu]; //小数
P3 = 0xef;
delay3(500);
P0 = 0x00;
P0 = Tools[0]; //度
P3 = 0xdf;
delay3(500);
P0 = 0x00;
P0 = Tools[1]; //摄氏度C
P3 = 0xbf;
delay3(500);
P3 = 0xff;
}
void changed() //判断按键是否按下
{
if (flag == 0)
{
while (flag == 0)
{
jishu();
if (p13 == 0) //判断转换键是否按下
key4=0;
if (p13==1&&key4==0)
{
flag++;
key4=1;
}
}
}
else if (flag == 1)
while (flag == 1)
{
DATE();
if (p13 == 0) //判断转换键是否按下
key4=0;
if (p13==1&&key4==0)
{
flag++;
key4=1;
}
}
else if (flag == 2)
{
unsigned int temp;
while (flag == 2) //涓诲惊鐜?
{
temp = ReadTemperature();
display_tempmain(temp);
if (p13 == 0) //判断转换键是否按下
key4=0;
if (p13==1&&key4==0)
{
flag=0;
key4=1;
}
}
}
}
void main(void)
{
time_init();
while (1)
{
changed();
}
}
void timer() interrupt 1 //1s中断
{
TH0 = (65536 - 50000) / 256;
TL0 = (65536 - 50000) % 256;
n++;
if (n == 20)
{
n = 0;
s++;
if (s == 60)//
{
s = 0;
m++;
}
if (m == 60)
{
m = 0;
h++;
}
if (h == 24)
{
h = 0;
}
}
}
四、效果图
如果你图画对,代码没问题,hex文件也没问题,程序运行应该如下图所示:
1.开始
从00-00-00开始计时,充当计时器
这是按键的功能,比如在刚开始的计时器状态,第一个(从上到下)就+1s,第二个+1m,第三个+1h,第四个就是切换led显示状态,按下就切换到日期,再按下就切换到温度,在按下就又切换到显示计时器的状态。简单的说就是(计时-日期-温度)循环.
注意:按下切换功能按键后计时不会停止,而是在后台继续计时。
2.日期
注意:这里日期是代码里改的固定的,不会随系统日期的,同样按左边的按键可以实现+天,+月,+年
3.温度
注意:温度是读取DS18B20的数据来显示的,也就是改变DS18B20的温度,就可以改变显示的温度,所以左边的按键对这个是无效的,只有第四个切换功能的按键有用,按一下就切换到计时的去了
如下图改成4摄氏度(按那两个红色按钮调温度):
四、最后
希望能对你有用!!
当然还有最重要的事,麻烦各位大佬给个三连,毕竟码字不容易。
如果三连不行就点个赞吧(卑微)。