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
源码如下:
嗯,代码都差不多的,应该没有什么逻辑上的问题,我感觉是共用一个地址造成的,不过看你的好像月份变化的时候星期会变,说明也是可以计数的,这个得官方看下是什么原因了