[RISC-V MCU CH32V103 Evaluation] +RTC Usage
[Copy link]
Maybe it's because of the benchmark F103 kernel! V103's RTC is also implemented by software. Open the official routine,
/*******************************************************************************
* Function Name : RTC_Init
* Description : Initializes RTC collection.
* Input : None
* Return : 1:Init Fail
* 0:Init Success
*******************************************************************************/
u8 RTC_Init(void)
{
u8 temp=0;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
/* Is it the first configuration */
if(BKP_ReadBackupRegister(BKP_DR1) != 0xA1A1)
{
BKP_DeInit();
RCC_LSEConfig(RCC_LSE_ON);
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET&&temp<250)
{
temp++;
Delay_Ms(20);
}
if(temp>=255)return 1;
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForLastTask();
RTC_WaitForSynchro();
// RTC_ITConfig(RTC_IT_ALR, ENABLE);
RTC_ITConfig(RTC_IT_SEC, ENABLE);
RTC_WaitForLastTask();
RTC_EnterConfigMode();
RTC_SetPrescaler(32767);
RTC_WaitForLastTask();
RTC_Set(2019,10,8,13,58,55); /* Setup Time */
RTC_ExitConfigMode();
BKP_WriteBackupRegister(BKP_DR1, 0XA1A1);
}
else
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_WakeUpPinCmd(DISABLE);
RTC_WaitForSynchro();
// RTC_ITConfig(RTC_IT_ALR, ENABLE);
RTC_ITConfig(RTC_IT_SEC, ENABLE);
RTC_WaitForLastTask();
}
RTC_NVIC_Config();
RTC_Get();
return 0;
}
This is the official initialization code. RTC_ITConfig (RTC_IT_SEC, ENABLE); here the second interrupt is turned on. The interrupt processing function,
void RTC_IRQHandler(void)
{
if (RTC_GetITStatus(RTC_IT_SEC) != RESET) /* Seconds interrupt */
{
RTC_Get();
}
if(RTC_GetITStatus(RTC_IT_ALR)!= RESET) /* Alarm clock interrupt */
{
RTC_ClearITPendingBit(RTC_IT_ALR);
RTC_Get();
}
RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW);
RTC_WaitForLastTask();
}
u8 Is_Leap_Year(u16 year)
{
if(year%4==0)
{
if(year%100==0)
{
if(year%400==0)return 1;
else return 0;
}else return 1;
}else return 0;
}
Here we determine whether it is a leap year.
u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
{
u16 t;
u32 seccount=0;
if(syear<1970||syear>2099)return 1;
for(t=1970;t<syear;t++)
{
if(Is_Leap_Year(t))seccount+=31622400;
else seccount+=31536000;
}
smon-=1;
for(t=0;t<smon;t++)
{
seccount+=(u32)mon_table[t]*86400;
if(Is_Leap_Year(syear)&&t==1)seccount+=86400;
}
seccount+=(u32)(sday-1)*86400;
seccount+=(u32)hour*3600;
seccount+=(u32)min*60;
seccount+=sec;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
RTC_SetCounter(seccount);
RTC_WaitForLastTask();
return 0;
}
Here is used to set the RTC time
u8 RTC_Get(void)
{
static u16 daycnt=0;
u32 timecount=0;
u32 temp=0;
u16 temp1=0;
timecount=RTC_GetCounter();
temp=timecount/86400;
if(daycnt!=temp)
{
daycnt=temp;
temp1=1970;
while(temp>=365)
{
if(Is_Leap_Year(temp1))
{
if(temp>=366)temp-=366;
else {temp1++;break;}
}
else temp-=365;
temp1++;
}
calendar.w_year=temp1;
temp1=0;
while(temp>=28)
{
if(Is_Leap_Year(calendar.w_year)&&temp1==1)
{
if(temp>=29)temp-=29;
else break;
}
else
{
if(temp>=mon_table[temp1])temp-=mon_table[temp1];
else break;
}
temp1++;
}
calendar.w_month=temp1+1;
calendar.w_date=temp+1;
}
temp=timecount%86400;
calendar.hour=temp/3600;
calendar.min=(temp%3600)/60;
calendar.sec=(temp%3600)%60;
calendar.week=RTC_Get_Week(calendar.w_year,calendar.w_month,calendar.w_date);
return 0;
}
This software implements the timing algorithm.
u8 RTC_Get_Week(u16 year,u8 month,u8 day)
{
u16 temp2;
u8 yearH,yearL;
yearH=year/100; yearL=year%100;
if (yearH>19)yearL+=100;
temp2=yearL+yearL/4;
temp2=temp2%7;
temp2=temp2+day+table_week[month-1];
if (yearL%4==0&&month<3)temp2--;
return(temp2%7);
}
Used to get the day of the week
Next, I used OLED to display the RTC time and initialized SPI.
void SPI1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOA, &GPIO_InitStructure );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOA, &GPIO_InitStructure );
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx ;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init( SPI1, &SPI_InitStructure );
SPI_Cmd( SPI1, ENABLE );
}
OLED_ShowNum(20,6,calendar.hour,2,16);//时
OLED_ShowChar(36,6,':',16);
OLED_ShowNum(44,6,calendar.min,2,16);//分
OLED_ShowChar(60,6,':',16);
OLED_ShowNum(68,6,calendar.sec,2,16);//秒
OLED_ShowNum(10,24,calendar.w_year,4,16);//年
OLED_ShowChar(42,24,'-',16);
OLED_ShowNum(56,24,calendar.w_month,2,16);//月
OLED_ShowChar(74,24,'-',16);
OLED_ShowNum(86,24,calendar.w_date,2,16);//日
OLED_ShowChinese(40,45,16,16);//星
OLED_ShowChinese(56,45,17,16);//期
switch(calendar.week)
{
case 1:
OLED_ShowChinese(72,45,18,16);//一
break;
case 2:
OLED_ShowChinese(72,45,19,16);//二
break;
case 3:
OLED_ShowChinese(72,45,20,16);//三
break;
case 4:
OLED_ShowChinese(72,45,21,16);//四
break;
case 5:
OLED_ShowChinese(72,45,22,16);//五
break;
case 6:
OLED_ShowChinese(72,45,23,16);//六
break;
case 0:
OLED_ShowChinese(72,45,24,16);//日
break;
}
OLED_Refresh();
It would be better if it can be optimized to add hardware RTC. Later I saw in the manual that V103 has a sister called F103 (M3 core) and it has been compatible, and the program is universal. In addition, I took the time to compare the registers of ST 103 and V103. The register bits are consistent with the 48-pin stm103. Compared with st103, the bits beyond 48 pins are reserved, which is very advantageous in terms of replacement.
|