AT89C51单片机万年历仿真图+代码

首先申明,这篇博客是用作记录本人实训内容的,代码我个人一字一字码的,就上网查了下数字温度传感器DS18B20的处理方法,基本都是个人完成的。
在这里吐槽下,本人辛辛苦苦码的代码,最后实训分数还没那些抄的人高,吐槽下老师- -,好了接下来说正事。
注意:可能有些人复制代码后会报错,可能是环境问题,也可能其他问题,反正自己简单调试下就行了,不过大部分肯定没问题。

:在评论有附本人交通灯的图噢,不过我还是建议各位先自己画。噢还要注意图里芯片,双击.hex的路径,可能链接是带本人的,大家要自己编译换成自己的.hex文件路径
在这里插入图片描述

一、实验内容

设计定时器每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
在这里插入图片描述
注意:图的链接
链接:https://pan.baidu.com/s/1CW0Gnp78XZyaWoIuW-Vryw?pwd=jhvj
提取码:jhvj
为方便懒人们这里加个我的仿真图原图,里面已经装载好了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摄氏度(按那两个红色按钮调温度):
在这里插入图片描述

五、最后

希望能对你有用!!

当然还有最重要的事,麻烦各位大佬给个三连,毕竟码字不容易。
如果三连不行就点个赞吧(卑微)。
在这里插入图片描述

  • 250
    点赞
  • 585
    收藏
    觉得还不错? 一键收藏
  • 83
    评论
**********************************************/ #include<reg52.h> #define uchar unsigned char #define uint unsigned int uchar code table[]=" 2013-07-30 WED "; uchar code table1[]=" 21:14:55"; uchar code table2[]=" 579259 "; uchar code table3[]="Made by Lisongze"; uchar code table4[]="MONTUEWEDTHUFRISATSUN"; uchar count,s1num; char miao,fen,shi,ri,yue; uint nian; sbit lcd_rs = P0^5; sbit lcd_rw = P0^6; sbit lcd_en = P0^7; sbit s1=P3^7; sbit s2=P3^6; sbit s3=P3^5; sbit g=P3^0; void delay(uint z)//延时子函数 { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void write_com(uchar com)//写命令函数 { lcd_rs = 0; P2= com; delay(5); lcd_en=1; delay(5); lcd_en=0; } void write_date(uchar date)//写数据函数 { lcd_rs = 1; P2= date; delay(5); lcd_en=1; delay(5); lcd_en=0; } void init()//初始化函数 { int num; shi=21; fen=14; miao=55; ri=30; yue=7; nian=2013; lcd_en=0; lcd_rw=0; write_com(0x38);//显示设置模式 write_com(0x0c);//00001100开显示,不显示光标,光标不闪烁 write_com(0x06);//00000110地址指针加一,整屏不移动 write_com(0x01);//清屏 write_com(0x80); for(num=0;num<16;num++)//显示数字579259 { write_date(table2[num]); delay(300); } write_com(0x80+0x40); for(num=0;num<16;num++)//显示made by lisongze { write_date(table3[num]); delay(300); } delay(5000); write_com(0x01); write_com(0x80); for(num=0;num<16;num++)//显示日期 { write_date(table[num]); delay(5); } write_com(0x80+0x40); for(num=0;num<12;num++)//显示时间 { write_date(table1[num]); delay(5); } TMOD=0x01;//启动定时器中断 TH0=(65535-50000)/256; TL0=(65535-50000)%256; EA=1; ET0=1; TR0=1;//打开定时器 } void write_sfm(uchar add,uchar date)//写时分秒函数 { uchar shi,ge; shi=date/10; ge=date; write_com(0x80+0x40+add); write_date(0x30+shi); write_date(0x30+ge); } void write_nyr(uint add,uint date)//写年月日函数,此处若用uchar范围只有0-255 { //不够,改用uint(0-65535) uint qian,bai,shi,ge; qian=date/1000; bai=date00/100; shi=date0/10; ge=date; write_com(0x80+add); write_date(0x30+qian); write_date(0x30+bai); write_date(0x30+shi); write_date(0x30+ge); } void write_yr(uchar add,uchar date)//写月日函数 { uchar shi,ge; shi=date/10; ge=date; write_com(0x80+add); write_date(0x30+shi); write_date(0x30+ge); } void keyscan()//按键扫描函数 { int m,n; g=0;//将矩阵键盘当做独立键盘使用 if(s1==0) { delay(5); if(s1==0)//按键1光标移位扫描 { s1num++; if(s1num==1) { while(!s1);//等待按键松手 write_com(0x80+0x40+10); TR0=0;//关闭定时器 write_com(0x0f); } if(s1num==2) { while(!s1); write_com(0x80+0x40+7); } if(s1num==3) { while(!s1); write_com(0x80+0x40+4); } if(s1num==4) { while(!s1); write_com(0x80+3); } if(s1num==5) { while(!s1); write_com(0x80+6); } if(s1num==6) { while(!s1); write_com(0x80+9); } if(s1num==7) { while(!s1) write_com(0x80+13); } if(s1num==8) { while(!s1); s1num=0; write_com(0x0c); TR0=1;//开定时器 } } } if(s1num!=0) { if(s2==0)//按键2加功能 { delay(5); if(s2==0) { while(!s2); if(s1num==1)//秒加 { miao++; if(miao==60) { miao=0; } write_sfm(10,miao); write_com(0x80+0x40+10); } if(s1num==2)//分加 { fen++; if(fen==60) { fen=0; } write_sfm(7,fen); write_com(0x80+0x40+7); } if(s1num==3)//时加 { shi++; if(shi==24) { shi=0; } write_sfm(4,shi); write_com(0x80+0x40+4); } if(s1num==4)//年加 { nian++; if(nian==10000) { nian=2000; } write_nyr(1,nian); write_com(0x80+3); } if(s1num==5)//月份加 { yue++; if(yue==13) { yue=1; } write_yr(6,yue); write_com(0x80+6); } if(s1num==6)//日期加 { ri++; if(ri==29&&yue==2&&!((nian%4==0&&nian0!=0)||nian%400==0)) { ri=1;//平年 } if(ri==30&&yue==2&&((nian%4==0&&nian0!=0||nian%400==0))) { ri=1;//闰年 } if(ri==31&&(yue==4||yue==6||yue==9||yue==11)) { ri=1; } if(ri==32) { ri=1; } write_yr(9,ri); write_com(0x80+9); } if(s1num==7)//星期加 { m=m+3; if(m==21) m=0; write_com(0x80+12); for(n=m;n<m+3;n++) { write_date(table4[n]); delay(5); } write_com(0x80+13); } } } if(s3==0)//按键3减功能 { delay(5); if(s3==0) { while(!s3); if(s1num==1)//秒减 { miao--; if(miao==-1) { miao=59; } write_sfm(10,miao); write_com(0x80+0x40+10); } if(s1num==2)//分减 { fen--; if(fen==-1) fen=59; write_sfm(7,fen); write_com(0x80+0x40+7); } if(s1num==3)//时减 { shi--; if(shi==-1) shi=23; write_sfm(4,shi); write_com(0x80+0x40+4); } if(s1num==4)//年减 { nian--; if(nian==1999) nian=2000; write_nyr(1,nian); write_com(0x80+3); } if(s1num==5)//月份减 { yue--; if(yue==0) yue=12; write_yr(6,yue); write_com(0x80+6); } if(s1num==6)//日减 { ri--; if(ri==0) { if(yue==2&&!((nian%4==0&&nian0!=0)||nian%400==0)) { ri=28;//平年 } if(yue==2&&((nian%4==0&&nian0!=0||nian%400==0))) { ri=29;//闰年 } if(yue==4||yue==6||yue==9||yue==11) { ri=30; } if(yue==1||yue==3||yue==5||yue==7||yue==9||yue==11) ri=31; } write_yr(9,ri); write_com(0x80+9); } if(s1num==7)//星期减 { m=m-3; if(m==0) m=21; write_com(0x80+12); for(n=m;n-3<m;n++) { write_date(table4[n-3]); delay(5); } write_com(0x80+13); } } } } } void main() { int i,j; init(); while(1) { keyscan(); if(count==18) { count=0; miao++; if(miao==60) { miao=0; fen++; if(fen==60) { fen=0; shi++; if(shi==24) { shi=0; ri++; j=j+3; if(j==21) j=0; write_com(0x80+12); for(i=j;i<j+3;i++) { write_date(table4[i]); delay(5); } if(ri==29&&yue==2&&!((nian%4==0&&nian0!=0)||nian%400==0)) { ri=1;yue++;//平年 } if(ri==30&&yue==2&&((nian%4==0&&nian0!=0||nian%400==0))) { ri=1;yue++;//闰年 } if(ri==31&&(yue==4||yue==6||yue==9||yue==11)) { ri=1;yue++; } if(ri==32) { ri=1;yue++; } if(yue==13) { yue=1; nian++; if(nian==10000) { nian=2000; } write_nyr(1,nian); } write_yr(6,yue); } write_yr(9,ri); write_sfm(4,shi); } write_sfm(7,fen); } write_sfm(10,miao); } } } void timer() interrupt 1 { TH0=(65535-50000)/256; TL0=(65535-50000)%256; count++; }
评论 83
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值