8051单片机设置去年

8051 microcontroller setting on elapse year

我有一个关于日期、星期一和年份设置的问题。我们知道每 4 年的二月等于 29 天,其余为 28 天。所以我尝试编写一些代码让程序知道二月的哪一年等于 28 或 29 天。

下面是我的代码,我想问的是,有没有更简单、更简短的方法来做到这一点?

void Timer(void) interrupt 1
{
if(start_timer == 1)
{
TF0 = 0;
TH0 = 0xB1;
TL0 = 0XE0;
msec++;

if(msec==100)
{
    sec++;
    msec=0;
}
if(sec==60)
{
    min++;
    sec=0;          
}
if(min==60)
{
    hour++;
    min=0;  
}
if(hour==24)
{
    date++;
    hour=0;
}
if(date== 30 && mon == 2 ( && year == 2016 || year == 2020 || year == 2024 ))
{
    mon++;
    date=1;
}
if(date== 29 && mon == 2 ( && year == 2015 || year == 2017 || year == 2018 || year == 2019|| year == 2021 || year == 2022 || year == 2023))
{
    mon++;
    date=1;
}
if(date==32 ( && mon == 1 || mon == 3 || mon == 5 || mon == 7 || mon == 9 || mon == 11))
{
    mon++;
    date=1;
}
if(date==31 ( && mon == 4 || mon == 6 || mon == 8 || mon == 10 || mon == 12))
{
    mon++;
    date=1;
}
if(mon==13)
{
    sec = 0;
    min = 0;
    hour = 0;
    date = 1;
    mon = 1;
    year = year++;
}
}
}

已更新:

void Timer(void) interrupt 1 {
    static const int daymon[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    int daysinmon, leapyear;
    if (start_timer == 1) {
        TF0 = 0;
        TH0 = 0xB1;
        TL0 = 0XE0;
        msec++;
        if (msec >= 100)   {              
            msec -= 100;
            if (++sec >= 60) {
                sec -= 60;          
                if (++min >= 60) {
                    min -= 60;  
                    if (++hour >= 24) {     
                        hour -= 24;
                        daysinmon = daymon[mon-1];
                        if (mon == 2) {     // months 1-based
                            if (year % 4 == 0)
                                leapyear = 1;
                            else if (year % 100 != 0)
                                leapyear = 0;
                            else if (year % 400 == 0)
                                leapyear = 1;
                            else leapyear = 0;

                            if (leapyear == 1)
                                daysinmon++;
                        }

                        if (++date > daysinmon) {
                            date = 1;                 // days 1-based
                            if (++mon > 12) {
                                mon = 1;
                                year++;
                            }
                        }
                    }
                }
            }
        }
    }
}

也许 if ((year-2000)%4==0) 会更适合未来

编辑:是的,因为它会在 2100 年失败,但这将是其他人的问题。

闰年

if ((year & 3) == 0) ...

对于平年

if ((year & 3) != 0) ...

编辑:

& 是按位与。二进制

0000 & 0011 = 0000
0001 & 0011 = 0001
0010 & 0011 = 0010
0011 & 0011 = 0011
0100 & 0011 = 0000

当一个数能被 4 整除时,按位加 3 的结果是 0。您不必担心 2100、2200 或 2300,除非您希望您的硬件在接下来的几个世纪中得到很好的使用.

可能您需要确定闰年的通用规则。 See this page

To determine whether a year is a leap year, follow these steps:
1.If the year is evenly divisible by 4, go to step 2. Otherwise, go to step 5
2.If the year is evenly divisible by 100, go to step 3. Otherwise, go to step 4.
3.If the year is evenly divisible by 400, go to step 4. Otherwise, go to step 5.
4.The year is a leap year (it has 366 days).
5.The year is not a leap year (it has 365 days).

确定闰年的代码通用方法可以是

uint8 leapYearTest(uint16 year) {
if ( year % 4 == 0)
    {if ( year % 100 == 0)
        if (year % 400 == 0)
            return true;
    }
else
    return false; 
return false;
}

以上代码可以缩短为一行

if ( (year%400==0)|| ((year%4==0) && (year%100!=0)))
    return true;
else
    return false;

然后你可以根据函数的结果递增日期return。

if (mon==2)
{
     date = (date+1)%(leapYearTest(year)+28);
}

我怀疑算法可以通过预处理来完成。

你给了中断处理程序太多的工作要做,在每次中断时检查所有内容。我也做了一些其他更改,可能不是必需的但更强大,以检查每个元素换行时的调整。未来对代码的修改可能会看到中断函数中断本身,或者被更高优先级的中断延迟。

编辑 日期和月份现在以 1 为基础,以避免混淆。

void Timer(void) interrupt 1 {
    static const int daymon[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    int daysinmon, leapyear;
    if (start_timer == 1) {
        TF0 = 0;
        TH0 = 0xB1;
        TL0 = 0XE0;
    msec++;
    // and now you could re-enable interrupts to make it re-entrant
    if (msec >= 1000)   {               // altered to 1000, and the conditional test
        msec -= 1000;
        if (++sec >= 60) {
            sec -= 60;          
            if (++min >= 60) {
                min -= 60;  
                if (++hour >= 24) {     // the last time we adjust rather than zero
                    hour -= 24;
                    daysinmon = daymon [mon];
                    if (mon == 2) {
                        if (year % 400 == 0)
                            leapyear = 1;
                        else if (year % 100 == 0)
                            leapyear = 0;
                        else if (year % 4 == 0)
                            leapyear = 1;
                        else leapyear = 0;
                        if (leapyear)
                            daysinmon++;
                    }
                    if (++date > daysinmon) {
                        date = 1;
                        if (++mon > 12) {
                            mon = 1;
                            year++;
                        }
                    }
                }
            }
        }
    }

示例测试输出:

27  2 2000
28  2 2000
29  2 2000
 1  3 2000