⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 基于AT89S52控制芯片的电子万年历程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "reg52.h"
#include "intrins.h"
#include "1602lib.h"
#include "PCF8563lib.h"

#define PAI_BASE 15
#define SCAN_CYCLE 10000

#define SECONDL 12                                  /*定义显示字符位置*/
#define SECONDH 11
#define MINUTEL 9
#define MINUTEH 8
#define HOURL 6
#define HOURH 5
#define DAYL 10
#define DAYH 9
#define WEEKDAY 15
#define MONTHS 5
#define YEARL 15
#define YEARH 14
#define AMPM 14

typedef enum{                                     /*定义枚举以标识当前设定位置*/
    CUR_SECOND,
    CUR_MINUTE,
    CUR_HOUR,
    CUR_DAY,
    CUR_WEEKDAY,
    CUR_MONTH,
    CUR_YEAR
} Current;

typedef enum{                                     /*定义枚举以标识显示内容*/
    SHOW_TIME,
    SHOW_ALARM
} ShowItem;

uchar str1[] = "TIME:15:23:14 W7";                  /*初始显示时间*/
uchar str2[] = "DATE:JUN.30,2007";
bit alarmflg = 0;
bit timerflg = 0;
bit flg_100ms = 0;
struct c_s cs;
struct time tm;
struct alarm alm;
uchar set_min = 0,set_hour = 0,set_day = 0,set_weekday = 0,set_month = 0,set_year = 0,set_second = 0;
uchar setalarm_min = 0,setalarm_hour = 0;
Current current = CUR_MINUTE;
ShowItem showitem = SHOW_TIME;
uint keyFlag;

bit Int0Flag = 0;
uchar s_tableCounter,musicplayflg = 0;
uchar TH0Temp,TL0Temp;
const char code c_music[] = { 0x82,0x01,0x81,0x94,0x84,     /*闹钟用生日快乐歌*/
                              0xb4,0xa4,0x04,
                              0x82,0x01,0x81,0x94,0x84,
                              0xc4,0xb4,0x04,
                              0x82,0x01,0x81,0xf4,0xd4,
                              0xb4,0xa4,0x94,
                              0xe2,0x01,0xe1,0xd4,0xb4,
                              0xc4,0xb4,0x04,
                              0x00};
const uint code c_musicFreq[] = {64260,64400,64524,64580,  /*低音5,6,7,中音1*/
                                  64684,64777,64820,64898,  /*中音2,3,4,5*/
                                  64968,65030,65058,65110,  /*中音6,7,高音1,2*/
                                  65157,65178,65217};       /*高音2,3,4,5*/
                                  
void TxData(uchar dat);
void Delay(uint n);
void ModShow(struct time tm);                         /*调整显示内容函数*/
uchar Ascii(uchar dat);                                /*获取数字ASCII码函数*/
void Months(uchar dat);                               /*月份数字转字符函数*/
void PCF8563_Init(void);                 /*初始化PCF8563,包括控制状态寄存器,时间及闹钟*/
void ModAlarm(struct alarm* alm);                    /*调整闹钟时间模块*/
void ModTime(struct time * tm);                       /*调整时间模块*/
void ScanKeys(void);                                 /*扫描键盘模块*/
uchar KeyJudge(void);                                  /*按键预处理*/    
void KeyHandle(uchar KeyIndex);                       /*按键处理模块*/

void main(void)
{
    TMOD = 0x11;          /*TIMER0工作在MODE1,16位定时器,TIMER1工作在MODE2,自动重新装载模式*/
    
    TH0 = 65536;
    TL0 = 65536;
    TH1 = (65536-SCAN_CYCLE)/256;       /*设定TIMER1每隔SCAN_CYCLE 毫秒中断一次*/
    TL1 = (65536-SCAN_CYCLE)%256;
    TR1 = 1;                               /*启动TIMER1*/
    T2CON =0X38;                           /*令定时器2作为串口波特率发生器*/
    TL2 = 0Xd9;                             /*设定串口波特率为9600,晶振为12MHz*/
    TH2 = 0Xff;
    RCAP2L = 0Xd9;                           /*根据串口波特率9600设定自动重载寄存器*/
    RCAP2H = 0xff;
    TR2 = 1;
    SCON = 0X50;         /*设定UART工作在MODE3模式,可传送和接收数据,REN=1*/
    IE = 0X8a;            /*使能中断,TIMER0,1中断,外部中断1,2*/
    P2 = 0Xff;
    
    LCD_init();                         /*LCD初始化*/
    DisplayString(0,0,str1);            /*显示第一行字符*/
    DisplayString(0,1,str2);            /*显示第二行字符*/
    PCF8563_Init();                     /*PCF8563初始化*/
    
while(1)
{
    uchar keyPtr;
    keyPtr = KeyJudge();                /*键盘扫描判断*/
    if(keyPtr!=0x55)                    /*如果按某键则进行相应处理*/
    {
        KeyHandle(keyPtr);
    }
    
    if(flg_100ms){                      /*判断100MS到否*/
       flg_100ms = 0;
       if(showitem == SHOW_TIME){       /*如果需要时间显示*/
            PCF8563_ReadTime(&tm);        /*读PCF8563时间*/
            ModShow(tm);                  /*调整显示内容*/
            DisplayString(0,0,str1);      /*显示第一行字符*/
            DisplayString(0,1,str2);      /*显示第二行字符*/
            
            PCF8563_ReadCS(&cs);          /*读PCF8563控制/状态字*/
            if((cs.cs2&0x08)==0x08){      /*如果闹钟时间到*/
                musicplayflg = 1;         /*设置播放音乐标志*/
                TR0 = 1;                  /*启动TIMER0*/
                cs.cs2 &= 0xf7;           /*清闹钟标志位*/
                PCF8563_SetCS(cs);        /*写PCF8563控制/状态字*/
            }      
       }else if(showitem == SHOW_ALARM);{  /*如果需要显示闹钟时间*/
            ModAlarm(&alm);                /*调整闹钟时间*/
            tm.minutes = alm.minute;        /*将闹钟时间作为时间显示*/
            tm.hours = alm.hour;
            tm.days = alm.day;
            tm.weekdays = alm.weekday;
            ModShow(tm);                     /*调整显示内容*/
            DisplayString(0,0,str1);         /*显示第一行字符*/
            DisplayString(0,1,str2);          /*显示第二行字符*/
            }
        }
}
}
void PCF8563_Init(void)
{
    cs.cs1 = 0x00;
    cs.cs2 = 0x02;                            /*使能闹钟*/
    PCF8563_SetCS(cs);                        /*设置控制/状态字*/
    
    tm.seconds = 50;                          /*设置初始时间*/
    tm.minutes = 58;
    tm.hours = 23;
    tm.days = 31;
    tm.weekdays = 2;
    tm.mon_cen = 12;
    tm.years = 6;
    PCF8563_SetTime(tm);                      
    
    alm.minute = 59;                          /*设定初始闹钟时间*/
    alm.hour = 23;
    alm.day = 00;
    alm.weekday = 2;
    PCF8563_SetAlarm(alm,1,1,0,0);              /*设置闹钟*/   
}

void ModShow(struct time tm)
{
    uchar tmpL,tmpH;
    
    tmpL = tm.seconds & 0x0f;                   /*调整秒显示*/
    tmpH = (tm.seconds & 0x7f)>>4;               /*屏蔽VL位*/
    str1[SECONDL] = Ascii(tmpL);
    str1[SECONDH] = Ascii(tmpH);
    
    tmpL = tm.minutes & 0x0f;                    /*调整分钟显示*/
    tmpH = tm.minutes>>4;
    str1[MINUTEL] = Ascii(tmpL);
    str1[MINUTEH] = Ascii(tmpH);
    
    tmpL = tm.hours & 0x0f;                     /*调整小时显示*/
    tmpH = tm.hours>>4;
    str1[HOURL] = Ascii(tmpL);
    str1[HOURH] = Ascii(tmpH);
    
    tmpL = tm.days & 0x0f;                    /*调整天显示*/
    tmpH = tm.days>>4;
    str2[DAYL] = Ascii(tmpL);
    str2[DAYH] = Ascii(tmpH);
    
    tmpL = tm.weekdays & 0x07;              /*调整星期显示*/
    str1[WEEKDAY] = Ascii(tmpL);
    
    tmpL = ((tm.mon_cen&0x7f)>>4)*10 + tm.mon_cen & 0x0f; /*体制哦啊横月份显示(BCD到HEX)*/
    Months(tmpL);                             /*月份数字转字符*/
    
    tmpL = tm.years & 0x0f;                    /*调整年显示*/
    tmpH = tm.years>>4;
    str2[YEARL] = Ascii(tmpL);
    str2[YEARH] = Ascii(tmpH);
}

uchar Ascii(uchar dat)
{
      return dat + 0x30;                     /*0~9得Ascii码为其+0x30*/
}

void Months(uchar dat)
{
    switch(dat){
    case 1:str2[MONTHS]='J';str2[MONTHS+1]='A';str2[MONTHS+2]='N';break;
    case 2:str2[MONTHS]='F';str2[MONTHS+1]='E';str2[MONTHS+2]='B';break;
    case 3:str2[MONTHS]='M';str2[MONTHS+1]='A';str2[MONTHS+2]='R';break;
    case 4:str2[MONTHS]='A';str2[MONTHS+1]='P';str2[MONTHS+2]='R';break;
    case 5:str2[MONTHS]='M';str2[MONTHS+1]='A';str2[MONTHS+2]='Y';break;
    case 6:str2[MONTHS]='J';str2[MONTHS+1]='U';str2[MONTHS+2]='N';break;
    case 7:str2[MONTHS]='J';str2[MONTHS+1]='U';str2[MONTHS+2]='L';break;
    case 8:str2[MONTHS]='A';str2[MONTHS+1]='U';str2[MONTHS+2]='G';break;
    case 9:str2[MONTHS]='S';str2[MONTHS+1]='E';str2[MONTHS+2]='P';break;
    case 10:str2[MONTHS]='O';str2[MONTHS+1]='C';str2[MONTHS+2]='T';break;
    case 11:str2[MONTHS]='N';str2[MONTHS+1]='O';str2[MONTHS+2]='V';break;
    case 12:str2[MONTHS]='D';str2[MONTHS+1]='E';str2[MONTHS+2]='C';break;
    
    }
}

void Delay(uint n)
{
    uint i;
    for(i=0;i<n;i++);
}

void TxData(uchar dat)
{
    SBUF = dat;
    while(TI!=1);
    TI = 0;
}

void Timer0Int() interrupt 1 using 2
{
    if(Int0Flag==1) /*如果需要产生音乐频率则按音频改变TIMER0得中断周期*/
	{
       	P3^3 = ~P3^3; /*每个TIMER0中断翻转一下P3.3的电平以产生相应频率的方波*/
        TH0 = TH0Temp;
        TL0 = TL0Temp;
    }
}

void Timer1Int() interrupt 3 using 3 /*TIMER1中断服务程序,中断周期为10MS*/
 {
    uchar ucharTemp,ucharTemp1;
    static uchar s_paiCounter,s_paiNum;
    uint temp;
    static uint counter = 0;
    
    if(++counter>=10){                   /*如果100ms到则这只100ms标志位*/
        flg_100ms = 1;
        counter = 0;
    }
    temp = 65536-SCAN_CYCLE;              /*中断周期为10ms*/
    TH1 = temp>>8;                         /*temp/256相当于右移8位*/
    TL1 = temp-((temp>>8)<<8);             /*temp%256*/
    
    if(musicplayflg==1){                      /*如果需要播放音乐*/
    if(++s_paiCounter>=s_paiNum)          /**音乐一拍的时间*/
    {
        s_paiCounter = 0;                    
        ucharTemp = c_music[s_tableCounter++];
            if(ucharTemp==0x00)           /*如果差到0x00则标识本首歌曲结束*/
            {
                Int0Flag = 0;             /*产生音乐平率标志置零*/
                s_paiNum = 4*PAI_BASE;  /*歌曲结束后停止播放*/
                P3^3 = 1;                /*把喇叭关掉*/
                s_tableCounter = 0;
                musicplayflg = 0;
                TR0 = 0;
            }
            else                               /*如果查到非0X00则标识是音乐标识码*/
            {
                s_paiNum = (ucharTemp&0x0f)*PAI_BASE; /*音乐包是吗的低四位为节拍码*/
                ucharTemp1 = (ucharTemp&0xf0)>>4;
                if(ucharTemp1 == 0)                   /*如果音频码为零则标识不发音*/
                {
                    Int0Flag = 0;
                }
            else      /*如果音频码不为零则按此改变TIMER0得中断周期*/
            {
            Int0Flag = 0;
            temp = c_musicFreq[ucharTemp1-1];
                TH0 = temp>>8;                   /*temp/256相当于右移8位*/
                TL0 = temp-((temp>>8)<<8);       /*temp%256*/
                TH0Temp = TH0;                   /*保存新的代表音频得TIMER0周期值*/
                TL0Temp = TL0;
                Int0Flag = 1;
            }
          }
      }
    }
}

void ScanKeys(void)                             /*扫描键盘模块*/
{
    uchar scanValue = 0xef,iScan,scanTempUchar;
    for(iScan = 0;iScan<4;iScan++)
      {
          P1 = scanValue;                         /*发扫描值*/
          scanTempUchar = P1;                     /*读入扫描值*/
          if((scanTempUchar&0X01) == 0X00)        /*第一列被按*/
          {
              keyFlag|=(0x0001<<(iScan*4+0));     /*设置此键的标志位*/
          }
          else
          {
              keyFlag&=~(0x0001<<(iScan*4+0));    /*清此键的标志位*/
          }
          if((scanTempUchar&0x02) == 0x00)        /*第二列被按*/
          {
              keyFlag|=(0x0001<<(iScan*4+1));       /*置此键的标志位*/
          }
          else
          {
              keyFlag&=~(0x0001<<(iScan*4+1));      /*清此键的标志位*/
          }
          if((scanTempUchar&0x04) == 0x00)          /*第三列被按*/
          {
              keyFlag|=0x0001<<(iScan*4+2);         /*置此键的标志位*/
          }
          else
          {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -