新手入门
积分 19
金钱 19
注册时间 2016-3-9
在线时间 2 小时
1 金钱
STM32的RTC时间跳秒问题,用的UCOSII 2.86
实际使用过程中,发现RTC会跳秒,具体表现就是32分钟34秒左右,偶尔会发生一次,比如:1,2,3,4,下一秒应该是5,结果就成了6,然后下一秒还是6,最后是7。
代码如下:
初始化代码:
u8 RTC_Init(void)
{
//检查是不是第一次配置时钟
u8 temp = 0;
//使能电源和后备接口时钟
RCC->APB1ENR |= 1<<28; //使能电源时钟
RCC->APB1ENR |= 1<<27; //使能备份时钟
//使能对后备寄存器和RTC的访问
PWR->CR |= 1<<8; //取消备份区写保护
if(BKP->DR1 != 0XA5A5) //第一次配置
{
RCC->BDCR |= 1<<16; //备份区域软复位
RCC->BDCR &= ~(1<<16);//备份区域软复位结束
RCC->BDCR |= 1<<0; //开启外部低速振荡器
while((!(RCC->BDCR&0X02)) && temp<250)//等待外部时钟就绪
{
temp++;
delay_ms(10);
};
if(temp>=250) return 1; //初始化时钟失败,晶振有问题
RCC->BDCR |= 1<<8; //LSE作为 RTC 时钟
RCC->BDCR |= 1<<15; //RTC 时钟使能
RTC->PRLH = 0X0000;
RTC->PRLL = 32774; //时钟周期设置(有待观察,看是否跑慢了?)理论值:32767 ---32770
while(!(RTC->CRL&(1<<5)));//等待 RTC 寄存器操作完成
while(!(RTC->CRL&(1<<3)));//等待 RTC 寄存器同步
RTC->CRH|=0X01; //允许秒中断
while(!(RTC->CRL&(1<<5)));//等待 RTC 寄存器操作完成
//RTC->CRL|=1<<4; //允许配置
RTC_Set(2000,10,1,10,39,30);//设置时间
//RTC->CRL&=~(1<<4);//配置更新
// while(!(RTC->CRL&(1<<5)));//等待RTC 寄存器操作完成
BKP->DR1 = 0XA5A5;
// BKP->DR4 = 0; ////里程统计临时存储器
// BKP->DR5 = 0;
}
else//系统继续计时
{
while(!(RTC->CRL&(1<<3)));//等待 RTC 寄存器同步
RTC->CRH|=0X01; //允许秒中断
while(!(RTC->CRL&(1<<5)));//等待 RTC 寄存器操作完成
}
MY_NVIC_Init(0,0,RTC_IRQn,2);//RTC,G2,P2,S2.优先级最低
RTC_Get();//更新时间
return 0; //ok
}
这个: RTC->PRLL = 32774; //时钟周期设置(有待观察,看是否跑慢了?)理论值:32767 ---32770 我是参考http://www.openedv.com/posts/list/162.htm 修改的,分别是32767 32770 32774都会出现这样的问题。
void RTC_IRQHandler(void)
{
// u16 temp = 0;
u8 Tmp[25];
OSIntEnter();
if(RTC -> CRL & 0x0001)//秒钟中断
{
RTC_Get();//更新时间
DT_HexToBCD(DateTimeBCD,DateTimeHex);
Strncpy_u8(&Tmp[0],"time200ms=",10);
Tmp[10]=asc(time200ms);
Tmp[11] = ',';
rcdtime = ((u32)DateTimeBCD[2]<<24) + ((u32)DateTimeBCD[3]<<16) + ((u32)DateTimeBCD[4]<<8) + (u32)DateTimeBCD[5];
LongToAsc(rcdtime ,&Tmp[12],1);
Tmp[20] = 'B';
Tmp[21] = '\n';
Print_Debug(Tmp,22);
}
if(RTC -> CRL & 0x0002)//闹钟中断
{
RTC->CRL &= ~(0x0002);//清闹钟中断
Strncpy_u8(&Tmp[0],"time200ms=",10);
Tmp[10]=asc(time200ms);
Tmp[11] = ',';
rcdtime = ((u32)DateTimeBCD[2]<<24) + ((u32)DateTimeBCD[3]<<16) + ((u32)DateTimeBCD[4]<<8) + (u32)DateTimeBCD[5];
LongToAsc(rcdtime ,&Tmp[12],1);
Tmp[20] = 'A';
Tmp[21] = '\n';
Print_Debug(Tmp,22);
}
RTC -> CRL &= 0X0FFA; //清除溢出,秒钟中断标志
while(!(RTC -> CRL & (1 << 5)));//等待 RTC 寄存器操作完成
if(m_time200ms!=time200ms)
{
m_time200ms=time200ms;
Strncpy_u8(&Tmp[0],"time200ms=",10);
Tmp[10]=asc(time200ms);
Tmp[11] = ',';
rcdtime = ((u32)DateTimeBCD[2]<<24) + ((u32)DateTimeBCD[3]<<16) + ((u32)DateTimeBCD[4]<<8) + (u32)DateTimeBCD[5];
LongToAsc(rcdtime ,&Tmp[12],1);
Tmp[20] = '\n';
Print_Debug(Tmp,21);
}
OSIntExit();
}
以上是中断服务函数中,我加入了调试信息,time200ms是Timer4_Init中的时钟200毫秒触发一次,timer200ms++,到5赋值为0。Timer4_Init(1999,7199)。
//1999,7199
void Timer4_Init(u16 arr,u16 psc)
{
RCC->APB1ENR |= 1<<2;//TIM3时钟使能
TIM4->ARR = arr; //设定计数器自动重装值
TIM4->PSC = psc; //预分频器72,得到1Mhz的计数时钟
//这两个东东要同时设置才可以使用中断
TIM4->DIER |= 1<<0; //允许更新中断
TIM4->DIER |= 1<<6; //允许触发中断
TIM4->CR1 |= 0x01; //使能定时器3
MY_NVIC_Init(1,2,TIM4_IRQn,2);//抢占2,子优先级3,组2
}
打印出来的调试信息,我进行了整理如下:
[00:56:06.834] time200ms=3,09005606B
[00:56:07.834] time200ms=3,09005608B
[00:56:08.816] t~ime200ms=2,09005608B
[00:56:08.835] time200ms=2,09005608
[00:56:09.835] time200ms=2,09005609B
[00:56:10.835] time200ms=2,09005610B
[02:33:57.398] time200ms=0,09023357B
[02:33:58.398] ime200ms=0,09023359B
[02:33:59.400] time200ms=4,09023359B
[02:33:59.400] time200ms=4,09023359
[02:34:00.397] time200ms=4,09023400B
[02:34:01.397] ime200ms=4,09023401B
[03:39:08.107] time200ms=3,09033908B
[03:39:09.107] time200ms=3,09033910B
[03:39:10.109] time200ms=2,09033910B
[03:39:10.109] time200ms=2,09033910
[03:39:11.107] time200ms=2,09033911B
[04:11:42.962] time200ms=2,09041143B
[04:11:43.962] time200ms=2,09041145B
[04:11:44.964] time200ms=1,09041145B
[04:11:44.964] time200ms=1,09041145
[04:11:45.962] time200ms=1,09041146B
[04:11:46.962] time200ms=1,09041147B
[04:44:17.816] time200ms=1,09044418B
[04:44:18.816] time200ms=1,09044420B
[04:44:19.816] time200ms=0,09044420B
[04:44:19.816] time200ms=0,09044420
[04:44:20.819] time200ms=0,09044421B
[05:16:51.670] time200ms=0,09051652B
[05:16:52.669] time200ms=0,09051654B
[05:16:53.671] time200ms=4,09051654B
[05:16:53.671] time200ms=4,09051654
[05:16:54.669] time200ms=4,09051655B
[06:21:59.378] ime200ms=3,09062200B
[06:22:00.378] ime200ms=3,09062202B
[06:22:01.380] ime200ms=2,09062202B
[06:22:01.380] time200ms=2,09062202
[06:22:02.378] ime200ms=2,09062203B
[06:54:33.233] ime200ms=2,09065434B
[06:54:34.233] ime200ms=2,09065436B
[06:54:35.235] ime200ms=1,09065436B
[06:54:35.235] time200ms=1,09065436
[06:54:36.232] ime200ms=1,09065437B
[07:27:06.086] time200ms=1,09072707B
[07:27:07.086] time200ms=1,09072709B
[07:27:08.088] time200ms=0,09072709B
[07:27:08.088] time200ms=0,09072709
[07:27:09.086] time200ms=0,09072710B
time200ms=3,09002329
time200ms=2,09005608----32 39
time200ms=1,09012845 32 37
time200ms=0,09020122 32 37
time200ms=4,09023359--- 32 37
time200ms=3,09030634 32 35
time200ms=2,09033910--- 32 36
time200ms=1,09041145--- 32 35
time200ms=0,09044420----32 35
time200ms=4,09051654--- 32 34
time200ms=3,09054928 32 34
time200ms=2,09062202--- 32 34
time200ms=1,09065436--- 32 34
time200ms=0,09072709--- 32 33
带---地方是发生跳秒的时间点,后面的32 34是遇上一个点间隔是32分34秒。跳秒基本上都会发生在200ms错位的地方。
希望大侠给分析下,看看有可能是哪里的问题?
我来回答