1875 views|1 replies

58

Posts

0

Resources
The OP
 

[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.

微信图片_20210314131602.jpg (144.62 KB, downloads: 0)

微信图片_20210314131602.jpg
This post is from Domestic Chip Exchange

Latest reply

This post was last edited by Hot Ximixiu on 2021-3-14 22:39 The naming of CH32V103 is obviously a replacement for STM's F103 series. Implementing this kind of clock should not be a problem It depends on controlling other circuits, such as the application in the Internet of Things.   Details Published on 2021-3-14 22:37
 
 

1668

Posts

0

Resources
2
 
This post was last edited by Hot Ximixiu on 2021-3-14 22:39

The naming of CH32V103 is obviously a replacement for STM's F103 series.

Implementing this kind of clock should not be a problem

It depends on controlling other circuits, such as the application in the Internet of Things.

This post is from Domestic Chip Exchange
 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list