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

📄 wnl.c

📁 51单片机做的万年历
💻 C
字号:
#include <REGX51.H>
#include "delay.h"
#include "type.h"
#include "1602.h"
#include "wnl.h"
#include "display.h"
#include "interupt.h"    

extern  uchar mode;

uchar  ClkTickCtr;           // 系统时钟计数器 
uchar  ClkHr;                //小时计数器
uchar  ClkMin;               //分钟计数器
uchar  ClkSec;               //秒计数器 
                                     

uchar  ClkDay;               //日期计数器                 
uchar  ClkMonth;             //月份计数器
uchar  ClkYear;              //年份计数器
uchar  ClkDOW;               //星期计数器 

uchar  Naozhong_Hr;          //闹钟的小时
uchar  Naozhong_Min;         //闹钟的分钟

#define  TICKS_PER_SEC  100            //每秒钟的节拍数,因为定计0溢出时间为10Ms,所以节拍为100  

typedef struct clk_month 
{         
    char   MonthDays;                // 每个月有多少天                             
    UCHAR  MonthVal;                // 用来计算每月开始星期的参数                                                        
} CLK_MONTH;

static CLK_MONTH code ClkMonthTbl[] =  // 天数、月份名、
{   
    {0 , 0},
    {31, 6},             // 一月                                                      
    {28, 2},             // 二月                
    {31, 2},             // 三月                                                        
    {30, 5},             // 四月                                                       
    {31, 0},             // 五月                                                         
    {30, 3},             // 六月                                                         
    {31, 5},             // 七月                                                         
    {31, 1},             // 八月                                                       
    {30, 4},             // 九月                                                    
    {31, 6},             // 十月                                                      
    {30, 2},             // 十一月                                                     
    {31, 4}              // 十二月    
};

static  char code *ClkDOWTbl[] = {          //星期                             
    "Sun ",
    "Mon ",
    "Tue ",
    "Wed ",
    "Thu ",
    "Fri ",
    "Sat "
};





void  Sys_clk_task (void)                           //时钟任务
{               
     if(++ClkTickCtr==TICKS_PER_SEC)                //每秒检查
      {
         ClkTickCtr=0;
         //(P3_4) = !(P3_4);   
         if (ClkUpdateTime() == TRUE)               //检查时间变化
         {      
          ClkUpdateDate();                          //检查日期变化   
         }   
      }
          
}  


//@@***********************************************************
//
//   功能:  系统时钟中断服务函数
//   函数:  void Sys_tick_isr(void)
//   语言:  C
//
//@@***********************************************************
//-------------------------------------------------------------
void Sys_tick_isr(void)  interrupt 1  using  3     //定计0中断服务程序,使用第三组寄存器
{
    TH0 = 0xD8 ;                                   //TH0 TL0 要实现10ms的计时
    TL0 = 0xF0 ; 
    Sys_clk_task();  
}

//@@***********************************************************
//
//   功能:  系统定时器初始化
//   函数:  void Vtimer_init(void)
//   语言:  C
//@@***********************************************************
//-------------------------------------------------------------
void Init_sys_timer(void)
{  
  Sys_clk_init();    
  TCON=0x05;            //外部中断下降沿触发,响应外部和定计溢出中断后硬件置1,CPU响应后硬件清0
                        //TCON定时器/计数器控制寄存器
                        //D7   D6   D5   D4   D3   D2   D1   D0 
                        //TF1       TF0       IE1  IT1  IE0  IT0                        
 	    
  TMOD&=0xF0;			      //清定时器0的工作方式
                        //TMOD定时器/计数器的方式控制寄存器
                        //D7   D6   D5   D4   D3   D2   D1   D0 
                        //GATE C/T  M1   M0 | GATE C/T  M1   M0
                        //----T/C 1---------|-------T/C 0------//
  
  TMOD|=0x01;           //工作方式为十六位定计器,需要重装载
  
  TH0 = 0xD8 ;                                   //TH0 TL0 要实现100ms的计时
  TL0 = 0xF0 ;

  EA=1;                 //全局中断开
  EX0=1;                //外部中断0开
  EX1=1;                //外部中断1开
  ET0=1;                //定计0允许中断
  TR0=1;                //启动定计0开始定时
  
}


void  Sys_clk_init (void)        //系统时钟、日期初始化
{
    ClkTickCtr = 0;
    Clk_set_time(14,50,0);
    Clk_set_date(7,5,18);
    Clk_set_naozhong(7,30);      
}



void Clk_format_date (void)      //日期格式检查子程序
{
    uchar  year = ClkYear;       
    
    real_date[0] = year /  10 + '0';
    real_date[1] = year %  10 + '0';
    real_date[2] = '-';
    real_date[3] = ClkMonth / 10 + '0';        // Convert DATE to ASCII                              
    real_date[4] = ClkMonth % 10 + '0';
    real_date[5] = '-';
    real_date[6] = ClkDay   / 10 + '0';
    real_date[7] = ClkDay   % 10 + '0';
}


void Clk_format_time (uchar mode)             //时间格式检查子程序
{
    UCHAR hr;
    switch (mode)
    {
      case 0:                                 // 24小时制显示 
             real_time[0] = ClkHr  / 10 + '0';                                       
             real_time[1] = ClkHr  % 10 + '0';
             real_time[2] = ':';
             real_time[3] = ClkMin / 10 + '0';
             real_time[4] = ClkMin % 10 + '0';
             real_time[5] = ':';
             real_time[6] = ClkSec / 10 + '0';
             real_time[7] = ClkSec % 10 + '0';
             real_time[8] = '-';
             real_time[9] = '-';
             break;
      case 1:                                 // 12小时制显示
             real_time[8] = (ClkHr >= 12) ? 'P' : 'A';       //24转12小时                   
             if (ClkHr > 12) 
               {                                    
                 hr   = ClkHr - 12;
               } 
             else
               {
                 hr = ClkHr;
               }
             real_time[0] = hr     / 10 + '0';           
             real_time[1] = hr     % 10 + '0';
             real_time[2] = ':';
             real_time[3] = ClkMin / 10 + '0';
             real_time[4] = ClkMin % 10 + '0';
             real_time[5] = ':';
             real_time[6] = ClkSec / 10 + '0';
             real_time[7] = ClkSec % 10 + '0';
             real_time[9] = 'M';
             break;
    }
}


uchar  ClkUpdateTime (void)                   //时钟子程序
{
    uchar newday;
    newday = FALSE;                           // 保证不会增加日期    
    if (ClkSec >= 59)
     {                                        
          ClkSec = 0;                         //每分钟60秒
          if (ClkMin >= 59)
            {                                
              ClkMin = 0;                     //每小时60分钟
              if (ClkHr >= 23) 
               {                              
                 ClkHr = 0;                   //每天24小时
                 newday    = TRUE;            //日期可以增加了
               } 
              else
               {
                ClkHr++;                      //小时自加
               }
            }
          else
           {
            ClkMin++;                         //分钟自加
           }
     } 
    else
     {
        ClkSec++;                             //秒自加
     }
    return (newday);
}

uchar  ClkIsLeapYear(UINT year)               //闰年检查子程序
{
    if (!(year % 4) && (year % 100) || !(year % 400))           
     {
        return (TRUE);                        //可以被4整除为闰年
     } 
    else 
     {
        return (FALSE);
     }
}

void  Clk_set_time (UCHAR hr, UCHAR min, UCHAR sec)       //设置时间子程序
{
    EA=0;                                
    ClkHr  = hr;
    ClkMin = min;
    ClkSec = sec;
    EA=1;                                       
}

void  Clk_set_date ( uchar year,UCHAR month, UCHAR day)      //设置日期子程序
{
    EA=0;                         
    ClkYear  = year;
    ClkMonth = month;
    ClkDay   = day;
    ClkUpdateDOW();                             
    EA=1;                         
}

void Clk_set_naozhong (uchar hr,uchar min)
{
  EA = 0;
  Naozhong_Hr = hr;           //闹钟的小时
  Naozhong_Min = min;         //闹钟的分钟
  EA = 1;
}

void  ClkUpdateDate (void)
{
    uchar newmonth; 
    if (ClkDay >= ClkMonthTbl[ClkMonth].MonthDays)     //检查是否每月的最后一日
    {  
        if (ClkMonth == 2)                             //检查是否是二月
        {                         
            if (ClkIsLeapYear(ClkYear) == TRUE)        //检查是否闰年
            {    
                if (ClkDay >= 29)                      //检查是否二月最后一日
                {                   
                    ClkDay = 1;
                    newmonth = TRUE;                   //日期变为三月的第一日 
                } 
                else 
                {
                    ClkDay++;
                    newmonth = FALSE;
                }
            } 
            else 
            {
                ClkDay = 1;
                newmonth = TRUE;
            }
        } 
        else 
        {
            ClkDay = 1;
            newmonth = TRUE;
        }
    } 
    else 
    {
        ClkDay++;
        newmonth = FALSE;
    }
    if (newmonth == TRUE)                            //是否新的一个月
    {                                                
        if (ClkMonth >= 12)                          //是否十二月
        {                    
            ClkMonth = 1;                            //十二月
            ClkYear++;                               //年份加1
        } 
        else 
        {
            ClkMonth++;                              //非十二月,月份加1
        }
    }
    ClkUpdateDOW();                                  //计算星期
}

void  ClkUpdateDOW (void)
{
    UINT dow;
    dow = ClkDay + ClkMonthTbl[ClkMonth].MonthVal;
    if (ClkMonth < 3)
    {
        if (ClkIsLeapYear(ClkYear)) 
        {
            dow--;
        }
    }
    dow    += ClkYear + (ClkYear / 4);
    dow    += (ClkYear / 400) - (ClkYear / 100);
    dow    %= 7;
    ClkDOW  = dow;
}

⌨️ 快捷键说明

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