综合实例:51单片机(AT89C52)万年历(温度闹钟年月日时分秒星期)

功能说明:

LCD1602液晶显示年、月、日、时、分、秒、星期、温度,三个按键控制时间日期调整以及闹钟设定。

 

三个按键:

1、“校时”键,每次按下分别对应调整秒、调整分钟、调整小时、调整星期、调整日、调整月份、调整年份、调整闹钟分钟、调整闹钟小时、退出校时模式;

2、“增加/开闹钟功能”键,校时模式下按下此键则数值加一,非校时模式下按下此键则显示出闹钟时间并打开闹钟功能(屏幕显示字母A);

3、“减小/关闹钟功能”键,校时模式下按下此键则数值减一,非校时模式下按下此键则关闭闹钟显示并关闭闹钟功能(屏幕字母A消失);

 

 

#include   
typedef unsigned char uchar;  
typedef unsigned int uint;  
#define rs_h P3|=0x01//单片机向LCD1602液晶RS引脚输出高电平   
#define rs_l P3&=0xfe   
#define rw_h P3|=0x02   
#define rw_l P3&=0xfd   
#define en_h P3|=0x04    
#define en_l P3&=0xfb   
#define temp_h P3|=0x40//单片机向DS18B20输出高电平   
#define temp_l P3&=0xbf//单片机向DS18B20输出低电平   
#define rst_h P3|=0x08//单片机向DS1302时钟芯片RST引脚输出高电平   
#define rst_l P3&=0xf7   
#define sck_h P3|=0x10   
#define sck_l P3&=0xef   
#define io_h P3|=0x20   
#define io_l P3&=0xdf   
#define SECADD 0X80//秒寄存器地址   
#define MINADD 0x82   
#define HRADD 0x84   
#define DATEADD 0x86   
#define MONTHADD 0x88   
#define DAYADD 0x8a   
#define YEARADD 0x8c   
#define CONTROLADD 0x8e   
#define PORT (P2)//P2连接LCD1602的8个数据引脚   
sbit time=P3^5;//DS1302输入输出引脚   
sbit tmp=P3^6;//DS18B20输入输出引脚   
void delayms(uint x);//延时函数   
void lcd_com(uchar com);//LCD1602液晶写命令函数   
void lcd_dat(uchar dat);//LCD1602液晶写数据函数   
void lcd_write(uchar c,uchar r,uchar dat);//向LCD1602液晶指定行、指定列写数据函数   
void lcd_init();//LCD1602液晶初始化   
void Ds1302Init();//DS1302初始化   
void WriteByte(uchar dat);//往DS1302写一字节   
uchar ReadByte();//从DS1302读一字节   
uchar BCDtoDex(uchar dat);//BCD码转十进制   
uchar DextoBCD(uchar dat);//十进制转BCD码   
void Ds1302Write(uchar add,uchar dat);//往DS1302指定地址写数据   
uchar Ds1302Read(uchar add);//读DS1302制定地址的数据   
void Ds18b20_reset();//DS18B20温度传感器复位   
void Ds18b20_write(uchar dat);//往DS18B20写一字节   
void showtem();//显示温度   
uchar Ds18b20_read();//从DS18B20读一字节   
char keyscan();//按键检测,有键按下返回1,否则返回0   
uchar Timflag;//表示50ms时间到   
uchar Temflag;//让"命令DS18B20转换温度"和"读温度值"两个模块错开执行   
uchar dat1,dat2;//读回的温度值,dat1保存低字节,dat2保存高字节   
uchar keystate=2;//按键状态标志,初始化为2,是为了程序第一次运行时能够进入keystat1分支   
#define keystate0 1//keystate0在keyscan()函数中,代表按下确认功能   
#define keystate1 2//keystate1在keyscan()函数中,代表无按键按下   
uchar keynum;//调用keyscan()函数,如果该函数返回1,说明有键按下,keynum保存按键值   
uchar keynum1=0;//指示键1按下了多少次   
uchar TimeShowEn=1;//设置此变量是为了在校时状态期间,不让主函数再刷新时间显示   
uchar TimeChanged;//用来指示用户是否修改了时间   
sbit led1=P0^0;//键1指示灯,按下键1此灯变换状态   
sbit led2=P0^1;//键2指示灯,按下键2此灯变换状态   
sbit led3=P0^2;//键3指示灯,按下键3此灯变换状态   
sbit buzz=P1^0;//蜂鸣器接口   
uchar AlarmEn,AlarmCome;//AlarmEn指示是否开启了闹钟功能,AlarmCome指示定时时间是否到了   
char AlarmMin,AlarmHr;//保存闹钟分钟、闹钟小时   
uchar CountForAlarm;//用于累加时间,时间到,翻转蜂鸣器接口电平,决定蜂鸣器响声频率   
uchar ToShowAlarm;//ToShowAlarm为1,则允许主函数中显示闹钟时间模块执行   
uchar CountForShowAlarm;//CountForShowAlarm用于累加闹钟显示时间
...
...
...
...
...
...
void Timer0() interrupt 1   
{  
    TH0=(65536-50000)/256;  
    TL0=(65536-50000)%256;  
    Timflag=1;//Timflag 为1说明50ms定时时间到了   
}  
void Ds1302Init()  
{  
    rst_l;  
    sck_l;  
    Ds1302Write(CONTROLADD,0);//关闭写保护   
    Ds1302Write(MINADD,DextoBCD(06));  
    Ds1302Write(HRADD,DextoBCD(19));  
    Ds1302Write(DATEADD,DextoBCD(20));  
    Ds1302Write(MONTHADD,DextoBCD(5));  
    Ds1302Write(DAYADD,DextoBCD(7));  
    Ds1302Write(YEARADD,DextoBCD(12));  
    Ds1302Write(SECADD,DextoBCD(30));//写秒,同时启动时钟   
    //Ds1302Write(CONTROLADD,0x80);//写保护   
}  
void WriteByte(uchar dat)//上升沿输出   
{  
    uchar i;  
    for(i=8;i>0;i--)  
    {  
        sck_l;//低电平时数据线可变   
        if(dat&0x01)  
            io_h;  
        else  
            io_l;  
        sck_h;  
        dat>>=1;  
    }  
}  
uchar BCDtoDex(uchar dat)//BCD码转十进制   
{  
    uchar i;  
    i=dat/16;  
    dat%=16;  
    i=i*10+dat;  
    return i;  
}  
uchar DextoBCD(uchar dat)//十进制转BCD码   
{  
    uchar i;  
    i=dat/10;  
    dat%=10;  
    i=i*16+dat;  
    return i;  
}  
uchar ReadByte()//下降沿输出   
{  
    uchar i;  
    uchar dat;  
    for(i=8;i>0;i--)//要考虑之前写完后的状态,第一次进入此循环体即有下降沿   
    {  
        dat>>=1;  
        sck_l;  
        if(time==1)  
            dat|=0x80;  
        sck_h;  
    }  
    return dat;  
}  
void Ds1302Write(uchar add,uchar dat)  
{  
    rst_l;  
    sck_l;  
    rst_h;  
    WriteByte(add);//最低位为0表示写   
    WriteByte(dat);  
    rst_l;  
}  
uchar Ds1302Read(uchar add)  
{  
    uchar dat;  
    rst_l;  
    sck_l;  
    rst_h;  
    WriteByte(add+1);//地址最低位置1表示读   
    dat=ReadByte();  
    rst_l;  
    return dat;  
}  
void delayms(uint x)//延时1ms   
{  
    uint y,z;  
    for(y=x;y>0;y--)  
        for(z=111;z>0;z--);  
}  
void lcd_init()//LCD1602初始化   
{  
    lcd_com(0x38);  
    lcd_com(0x0c);  
    lcd_com(0x06);  
    lcd_write(0,5,0xb0);//显示-   
    lcd_write(0,8,0xb0);//显示-   
    lcd_write(1,3,0x3a);//显示:   
    lcd_write(1,6,0x3a);//显示:   
}  
void lcd_com(uchar com)//向LCD1602写命令   
{  
    rs_l;  
    rw_l;  
    PORT=com;  
    delayms(1);  
    en_h;  
    delayms(1);  
    en_l;  
}  
void lcd_dat(uchar dat)//向LCD1602写数据   
{  
    rs_h;  
    rw_l;  
    PORT=dat;  
    delayms(1);  
    en_h;  
    delayms(1);  
    en_l;  
}  
void lcd_write(uchar c,uchar r,uchar dat)//向LCD1602指定行、指定列、写数据   
{  
    lcd_com(0x80+0x40*c+r);  
    lcd_dat(dat);  
}  
...  
...
...
...
...
...


 


你可能感兴趣的:(51单片机,C语言)