#申请原创# @21小跑堂
实时时钟(RTC)是一个专用的计数器 / 定时器,可提供日历信息,包括小时、分钟、秒、日、月份、年份以及星期
CW32L031的RTC日历使用BCD码,这个码下23年10月1日分别会被表示为0x23 0x10 0x01,在写入时会自动进行合法性检查,任何非法的时间或日期值将不能被写入,另外支持自动闰年修正,CW32L031 内置经独立校准的 32kHz 频率的 RC 时钟源,为 RTC 提供驱动时钟,RTC 可在深度休眠模式下运行
接下来编程测试,用LCD屏显示RTC日期和时间,在闹钟触发后LCD显示ALARMA
void rtc_init()
{
RTC_InitTypeDef RTC_InitStruct = {0};
RTC_AlarmTypeDef RTC_AlarmStruct = {0};
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_LSE_Enable(RCC_LSE_MODE_OSC, RCC_LSE_AMP_NORMAL, RCC_LSE_DRIVER_NORMAL);
__RCC_RTC_CLK_ENABLE();
RTC_InitStruct.DateStruct.Day = 0x02;
RTC_InitStruct.DateStruct.Month = 0x10;
RTC_InitStruct.DateStruct.Week = 0x01;
RTC_InitStruct.DateStruct.Year = 0x23;
RTC_InitStruct.TimeStruct.Hour = 0x11;
RTC_InitStruct.TimeStruct.Minute = 0x58;
RTC_InitStruct.TimeStruct.Second = 0x59;
RTC_InitStruct.TimeStruct.AMPM = 0;
RTC_InitStruct.TimeStruct.H24 = 1;
RTC_InitStruct.RTC_ClockSource = RTC_RTCCLK_FROM_LSE;
RTC_Init(&RTC_InitStruct);
RTC_AlarmStruct.RTC_AlarmMask = RTC_AlarmMask_WeekMON | RTC_AlarmMask_WeekTUE |
RTC_AlarmMask_WeekWED | RTC_AlarmMask_WeekTHU |
RTC_AlarmMask_WeekFRI | RTC_AlarmMask_WeekSAT | RTC_AlarmMask_WeekSun;
RTC_AlarmStruct.RTC_AlarmTime.Hour = 0x12;
RTC_AlarmStruct.RTC_AlarmTime.Minute = 0x00;
RTC_AlarmStruct.RTC_AlarmTime.Second = 0x00;
RTC_SetAlarm(RTC_Alarm_A, &RTC_AlarmStruct);
RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
RTC_SetInterval(RTC_INTERVAL_EVERY_1S);
RTC_ITConfig(RTC_IT_ALARMA | RTC_IT_INTERVAL, ENABLE);
NVIC_EnableIRQ(RTC_IRQn);
}
uint8_t *WeekdayStr[7]= {"SUN","MON","TUE","WED","THU","FRI","SAT"};
void lcd_showrtctime()
{
char out[20];
RTC_TimeTypeDef RTC_TimeStruct = {0};
RTC_DateTypeDef RTC_DateStruct = {0};
RTC_GetDate(&RTC_DateStruct);
RTC_GetTime(&RTC_TimeStruct);
sprintf(out,"20%02X-%02X-%02X %s",RTC_DateStruct.Year,RTC_DateStruct.Month,RTC_DateStruct.Day,WeekdayStr[RTC_DateStruct.Week]);
yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,2,0,(uint8_t *)out);
sprintf(out,"%02X:%02X:%02X",RTC_TimeStruct.Hour,RTC_TimeStruct.Minute,RTC_TimeStruct.Second);
yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,4,0,(uint8_t *)out);
}
void RTC_IRQHandler(void)
{
if (RTC_GetITState(RTC_IT_ALARMA))
{
RTC_ClearITPendingBit(RTC_IT_ALARMA);
yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,4,68,(uint8_t *)"ALARMA");
}
if (RTC_GetITState(RTC_IT_INTERVAL))
{
RTC_ClearITPendingBit(RTC_IT_INTERVAL);
lcd_showrtctime();
}
}
运行效果
CW32L031的RTC还有几个专用的引脚
RTCOUT 可以输出的内容如下,可以作为闹钟输出使用
RTC1HZ可以输出经过补偿或未经补偿的 1Hz信号
RTC_TAMP是个输入引脚,引脚触发后,将当前时间和日期分别保存到时间戳日期寄存器 RTC_TAMPDATE和时间戳时间寄存器 RTC_TAMPTIM,同时可产生时间戳中断
接下来编程测试RTCOUT和RTC1HZ输出,PB14 和PB15分别外接LED
void rtc_ioinit()
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
__RCC_GPIOB_CLK_ENABLE();
PB14_AFx_RTCOUT();
PB15_AFx_RTC1Hz();
GPIO_InitStructure.Pins = GPIO_PIN_14 | GPIO_PIN_15;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init(CW_GPIOB, &GPIO_InitStructure);
RTC_RTCOUT_ALARM_A();
CW_RTC->CR0_f.RTC1HZ = 0x03;
//RTC_RTC1HZ_LSE();
CW_RTC->CR1_f.SOURCE = 0;
}
这里芯源提供的库里RTC_RTC1HZ_PCLK()和RTC_RTC1HZ_LSE()是不能正常使用的,两个宏定义的取值是错误的
另外要注意RTCOUT输出闹钟时引脚输出状态和闹钟中断标志是有关系的在中断中清除闹钟中断RTCOUT输出也会变为0
运行效果
接下来编程测试时间戳记录功能,PA01对应开发板上的按键KEY2按下后记录时间戳,KEY1按下后显示之前记录的时间戳,松开恢复时间显示
void rtc_tampinit()
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
__RCC_GPIOA_CLK_ENABLE();
PA01_AFx_RTCTAMP();
GPIO_InitStructure.Pins = GPIO_PIN_1|GPIO_PIN_2;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
RTC_TAMPEDGE_FALL();
RTC_TAMP_ENABLE();
RTC_IE_TAMP_CLEAR();
}
void lcd_showrtctime()
{
char out[20];
RTC_TimeTypeDef RTC_TimeStruct = {0};
RTC_DateTypeDef RTC_DateStruct = {0};
if(GPIO_ReadPin(CW_GPIOA,GPIO_PIN_2) == GPIO_Pin_RESET)
{
RTC_GetTamperDate(&RTC_DateStruct);
RTC_GetTamperTime(&RTC_TimeStruct);
yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,4,68,(uint8_t *)"TAMP");
RTC_IE_TAMP_CLEAR();
}
else
{
RTC_GetDate(&RTC_DateStruct);
RTC_GetTime(&RTC_TimeStruct);
yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,4,68,(uint8_t *)" ");
}
sprintf(out,"20%02X-%02X-%02X %s",RTC_DateStruct.Year,RTC_DateStruct.Month,RTC_DateStruct.Day,WeekdayStr[RTC_DateStruct.Week]);
yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,2,0,(uint8_t *)out);
sprintf(out,"%02X:%02X:%02X",RTC_TimeStruct.Hour,RTC_TimeStruct.Minute,RTC_TimeStruct.Second);
yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,4,0,(uint8_t *)out);
}
运行效果,不知为什么年和时和秒没被时间戳记录下来
|
|