C 8051微控制器在过去一年中的设置

C 8051微控制器在过去一年中的设置,c,microcontroller,8051,keil,C,Microcontroller,8051,Keil,我有一个关于日期、周一和一年的问题。我们知道,每4年的2月等于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==6

我有一个关于日期、周一和一年的问题。我们知道,每4年的2月等于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++;
                            }
                        }
                    }
                }
            }
        }
    }
}
也许
如果((2000年)%4==0)
更能证明未来

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

对于闰年

if ((year & 3) == 0) ...
if ((year & 3) != 0) ...
非闰年

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的按位and将得到0。你不必担心2100年、2200年或2300年,除非你希望你的硬件在未来几个世纪都能很好地使用。

也许你想要确定闰年的一般规则

要确定一年是否为闰年,请执行以下步骤:
1.如果年份可以被4整除,请转至步骤2。否则,请转至步骤5
2.如果年份可以被100整除,请转至步骤3。否则,请转至步骤4。
3.如果年份可以被400整除,请转至步骤4。否则,请转至步骤5。
4.这一年是闰年(有366天)。
5.年份不是闰年(有365天)。

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

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;
然后可以根据函数返回的结果增加日期

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

您是否正在使用MCU时钟计算日期和时间?我希望你的钟不是标准的。标准的MCU时钟非常不准确,在不到一个月的时间里,你经常会漂移超过一天。不要使用MCU时钟。基本上,我使用定时器中断,这就是我要说的。计时器使用MCU时钟,除非您的计时器是外部RTC。您真的在一秒钟内有100<代码>毫秒吗?但我仍然必须输入我的月份,对吗?对于我这一年,我设置unsigned int=2015谢谢你的解释我尝试了上面的代码,只是2月份没有改变。我所做的是,我设置日期=28,周一=2,年份=2015。23:59:59. 当计时器达到00:00:00时,我设置28-2-2000时,它将日期增加到29,只是为了与您核对。下一个增量应该是29-2-2000,但它更改为01-03-2000,这是因为我将月份和日期都设置为零。如果(++date>=daysinmon){date=0;..可以更改为
如果(++date>daysinmon){date=1;..
您是否也将
=
更改为
?我将其编译为一个从
main()
调用一次的测试函数,我发现它可以测试闰年27-1-2000。它滚动到了28-1-2000(从零开始)然后到0-2-2000Oh!我将
=
更改为
是的,正在工作。谢谢。我感谢您的帮助