lezjin 发表于 2024-11-20 07:59:55

晓飛飛 发表于 2024-11-19 11:05
没搞清楚之前,先用这个方法顶上
专用的星期快速计算代码

好的,试下这个

xxkj2010 发表于 2024-11-20 09:36:07

本帖最后由 xxkj2010 于 2024-11-20 11:05 编辑

今天试了,果真日期变了,而那个星期不会变。
星期初始化寄存器INIWEEK你写什么,星期计数寄存器WEEK读取出来就一直是什么。
估计是星期初始化寄存器与计数寄存器用了同一个寄存器,


还有,手册里面的RTC计数寄存器就没有星期这个寄存器,估计官方本来就知道这情况的:



xxkj2010 发表于 2024-11-20 10:03:17

本帖最后由 xxkj2010 于 2024-11-20 11:04 编辑

经过测试,这个WEEK可以变化,就是在跳月的瞬间(即每月1日 00:00:00)可以加1,而后如果修改了当前时间就会回到原来初始化的数值。

下面是设置INIWEEK=3的情况:


但是如果修改了时间(只修改INIHOUR、INIMIN、INISEC的数值),
星期就会从INIWEEK拷贝数值过来(如果修改了当前时间,而INIWEEK没有再次赋值的话)
原因很简单,就是因为修改时间的同时触发了初始化:
RTCCFG |= 0x01;   //触发RTC寄存器初始化


看起来,星期暂时只能通过公式计算了。

xxkj2010 发表于 2024-11-20 11:04:29

补充,STC芯片中的RTC如果需要修改时间,所有的初始化寄存器都得写入正确的数据,如果保护不变,可以将计数寄存器的值赋给初始化寄存器,如:
    INIYEAR = YEAR;   //继承当前年月日
    INIMONTH = MONTH;
    INIDAY = DAY;
    INIWEEK=WEEK;

lezjin 发表于 2024-11-21 09:05:20

xxkj2010 发表于 2024-11-20 10:03
经过测试,这个WEEK可以变化,就是在跳月的瞬间(即每月1日 00:00:00)可以加1,而后如果修改了当前时间 ...

那是不是硬件逻辑错误?

lezjin 发表于 2024-11-21 09:08:08

xxkj2010 发表于 2024-11-20 09:36
今天试了,果真日期变了,而那个星期不会变。
星期初始化寄存器INIWEEK你写什么,星期计数寄存器WEEK读取出 ...

手册中有一页些有WEEK的描述

lezjin 发表于 2024-11-21 09:08:39

WEEK的描述

xxkj2010 发表于 2024-11-21 09:18:53

lezjin 发表于 2024-11-21 09:08
WEEK的描述

没错,是从这里读取的

xxkj2010 发表于 2024-11-21 10:33:01

源码如下:

/*
24MHz+波特率115200

使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。
edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。

*/





#include "AI8051U.h"
#include "stdio.h"
#include "intrins.h"

/***********************************************************/

typedef   unsigned char   u8;
typedef   unsigned int    u16;
typedef   unsigned long   u32;

/****************************** 用户定义宏 ***********************************/

#define MAIN_Fosc       24000000L   //定义主时钟
#define PrintUart       1         //1:printf 使用 UART1; 2:printf 使用 UART2
#define Baudrate      115200L
#define TM            (65536 -(MAIN_Fosc/Baudrate/4))
#define Timer0_Reload   (65536UL -(MAIN_Fosc / 1000))   //Timer 0 中断频率, 1000次/秒
/*****************************************************************************/


u8 B_10ms;          //10ms标志
bit B_1s;                        //1s标志
bit B_Alarm;      //闹钟标志

u8hour,minute,sec; //RTC变量
u16 msecond;
#define LED P35

/*************本地函数声明    **************/

void WriteRTC(void);
void RTC_config(void);
void Timer0_Init(void);                //1000毫秒@24.000MHz
void delay_ms(u8 ms);

void UartInit(void)
{
#if(PrintUart == 1)
    S1_S1 = 0;      //UART1 switch to, 0x00: P3.0 P3.1, 0x40: P3.6 P3.7, 0x80: P1.6 P1.7, 0xC0: P4.3 P4.4
    S1_S0 = 0;
    SCON = (SCON & 0x3f) | 0x40;
    T1x12 = 1;      //定时器时钟1T模式
    S1BRT = 0;      //串口1选择定时器1为波特率发生器
    TL1= TM;
    TH1= TM>>8;
    TR1 = 1;      //定时器1开始计时

//    SCON = (SCON & 0x3f) | 0x40;
//    T2L= TM;
//    T2H= TM>>8;
//    AUXR |= 0x15; //串口1选择定时器2为波特率发生器
#else
    S2_S = 1;       //UART2 switch to: 0: P1.2 P1.3,1: P4.2 P4.3
    S2CFG |= 0x01;//使用串口2时,W1位必需设置为1,否则可能会产生不可预期的错误
    S2CON = (SCON & 0x3f) | 0x40;
    T2L= TM;
    T2H= TM>>8;
    AUXR |= 0x14;   //定时器2时钟1T模式,开始计时
#endif
}






/**********************************************/
void main(void)
{

    WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

    Timer0_Init();
    UartInit();
    RTC_config();
    EA = 1;   //打开总中断
        delay_ms(100);
    while(1)
    {
      if(B_1s)
      {
            B_1s = 0;
                        LED=~LED;
//                        printf("LED---");
                        printf("20%d-%d-%dWeek=%d%d:%d:%d\r\n",YEAR,MONTH,DAY,WEEK,HOUR,MIN,SEC);//
            
      }

//      if(B_Alarm)
//      {
//            B_Alarm = 0;
//            printf("RTC Alarm!\r\n");
//      }
    }
}

void Timer0_Isr(void) interrupt 1
{
        B_1s=1;       
}

void Timer0_Init(void)                //1000毫秒@24.000MHz
{
        TM0PS = 0x1E;                        //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
        AUXR &= 0x7F;                        //定时器时钟12T模式
        TMOD &= 0xF0;                        //设置定时器模式
        TL0 = 0xFC;                                //设置定时初始值
        TH0 = 0x03;                                //设置定时初始值
        TF0 = 0;                                //清除TF0标志
        TR0 = 1;                                //定时器0开始计时
        ET0 = 1;                                //使能定时器0中断
}





///********************** 写RTC函数 ************************/
//void WriteRTC(void)
//{
//    INIYEAR = YEAR;   //继承当前年月日
//    INIMONTH = MONTH;
//    INIDAY = DAY;

//    INIHOUR = hour;   //修改时分秒
//    INIMIN = minute;
//    INISEC = sec;
//    INISSEC = 0;
//    RTCCFG |= 0x01;   //触发RTC寄存器初始化
//}


/******************** RTC中断函数 *********************/
void RTC_Isr() interrupt 13
{
    if(RTCIF & 0x80)    //闹钟中断
    {
      RTCIF &= ~0x80;
      B_Alarm = 1;
    }

    if(RTCIF & 0x08)    //秒中断
    {
      RTCIF &= ~0x08;
//      B_1s = 1;
    }
}


//========================================================================
// 函数: void RTC_config(void)
// 描述: RTC初始化函数。
// 参数: 无.
// 返回: 无.
// 版本: V1.0, 2020-6-10
//========================================================================
void RTC_config(void)
{
    INIYEAR = 24;   //年
    INIMONTH = 11;    //月
    INIDAY = 30;      //日
        INIWEEK=3;      //星期
    INIHOUR = 23;   //H:23
    INIMIN = 59;      //M:59
    INISEC = 55;      //S:50
    INISSEC = 0;      //S/128:0

    ALAHOUR = 0;    //闹钟小时
    ALAMIN= 0;    //闹钟分钟
    ALASEC= 0;    //闹钟秒
    ALASSEC = 0;    //闹钟1/128秒

    IRC32KCR = 0x80;   //启动内部32K晶振.
    while (!(IRC32KCR & 1));//等待时钟稳定
    RTCCFG = 0x03;    //选择内部32K时钟源,触发RTC寄存器初始化

//    X32KCR = 0x80 + 0x40;   //启动外部32K晶振, 低增益+0x00, 高增益+0x40.
//    while (!(X32KCR & 1));//等待时钟稳定
//    RTCCFG = 0x01;    //选择外部32K时钟源,触发RTC寄存器初始化

    RTCIF = 0x00;   //清中断标志
    RTCIEN = 0x88;    //中断使能, 0x80:闹钟中断, 0x40:日中断, 0x20:小时中断, 0x10:分钟中断, 0x08:秒中断, 0x04:1/2秒中断, 0x02:1/8秒中断, 0x01:1/32秒中断
    RTCCR = 0x01;   //RTC使能

    while(RTCCFG & 0x01);    //等待初始化完成,需要在 "RTC使能" 之后判断.
    //设置RTC时间需要32768Hz的1个周期时间,大约30.5us. 由于同步, 所以实际等待时间是0~30.5us.
    //如果不等待设置完成就睡眠, 则RTC会由于设置没完成, 停止计数, 唤醒后才继续完成设置并继续计数.
}

void UartPutc(unsigned char dat)
{
#if(PrintUart == 1)
    SBUF = dat;
    while(TI == 0);
    TI = 0;
#else
    S2BUF= dat;
    while(S2TI == 0);
    S2TI = 0;    //Clear Tx flag
#endif
}

char putchar(char c)
{
    UartPutc(c);
    return c;
}

void Delay1ms(void)        //@24.000MHz
{
        unsigned long edata i;

        _nop_();
        _nop_();
        _nop_();
        i = 5998UL;
        while (i) i--;
}
void delay_ms(u8 ms)
{
        while(ms--)Delay1ms();

}



lezjin 发表于 2024-11-21 14:07:34

xxkj2010 发表于 2024-11-21 10:33
源码如下:

嗯,代码都差不多的,应该没有什么逻辑上的问题,我感觉是共用一个地址造成的,不过看你的好像月份变化的时候星期会变,说明也是可以计数的,这个得官方看下是什么原因了
页: 1 [2] 3
查看完整版本: AI8051U RTC星期计数器没有计数