答案:可以。AMP32E103XE可通过HSE作为参考,对LSI进行校准(RTC 24小时最多偏差86.4秒)。
实验效果:实验思路:PCBA上有外部HSE晶振,可以使用HSE晶振校准内部LSI。具体思路是使用内核SYSTICK定时器做计数校准。实验使用E103RET6芯片+DEMO板+SDK例程验证。实验结果:在极海官网SDK例程的基础上修改程序后验证2PCS,确认不同芯片+不同主频情况下,LSI校准后RTC秒中断每秒最多偏差1ms,RTC 24小时最多偏差1ms*60*60*24=86.4秒。
/************************************* Copyright(C)******************************
** @FileName : main.c
** @brief : 使用SYSTICK校准LSI
** @author :
** @version : V1.0
** @date :
********************************************************************************/
/* Includes */
#include "main.h"
#include "stdio.h"
volatile uint32_t sys_ms=0; //全局变量,系统时间
volatile uint32_t test_time; //测试用时间
/****************************** BEGIN ********************************
**@name : USART1_Init
**@Brief : 配置串口,方便打印信息
**@Author :
**@Version : V1.0
**@time :
******************************** END *********************************/
void USART1_Init(void)
{
USART_Config_T USART_ConfigStruct;
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_USART1);
USART_ConfigStruct.baudRate = 115200;
USART_ConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;
USART_ConfigStruct.mode = USART_MODE_TX_RX;
USART_ConfigStruct.parity = USART_PARITY_NONE;
USART_ConfigStruct.stopBits = USART_STOP_BIT_1;
USART_ConfigStruct.wordLength = USART_WORD_LEN_8B;
USART_Config(USART1, &USART_ConfigStruct);
GPIO_Config_T GPIO_configStruct;
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA);
GPIO_configStruct.mode = GPIO_MODE_AF_PP;
GPIO_configStruct.pin = GPIO_PIN_9;
GPIO_configStruct.speed = GPIO_SPEED_50MHz;
GPIO_Config(GPIOA, &GPIO_configStruct);
GPIO_configStruct.mode = GPIO_MODE_IN_FLOATING;
GPIO_configStruct.pin = GPIO_PIN_10;
GPIO_Config(GPIOA, &GPIO_configStruct);
USART_Enable(USART1);
}
/****************************** BEGIN ********************************
**@Name : LSI_Calibration
**@Brief : LSI校准,返回LSI频率
**@Author :
**@Version : V1.0
**@Time :
******************************** END *********************************/
uint32_t LSI_Calibration(void)
{
uint32_t lsi_freq=32767;
uint32_t time;
//LSI RTC配置
RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU);
PMU_EnableBackupAccess();
RCM_EnableLSI();
while (RCM_ReadStatusFlag(RCM_FLAG_LSIRDY) == RESET);
RCM_ConfigRTCCLK(RCM_RTCCLK_LSI);
RCM_EnableRTCCLK();
RTC_WaitForSynchro();
RTC_WaitForLastTask();
RTC_ConfigPrescaler(lsi_freq);
RTC_WaitForLastTask();
RTC_ConfigCounter(0);
RTC_WaitForLastTask();
//获取1000ms实际计数
time=sys_ms;
RTC_ClearStatusFlag(RTC_FLAG_SEC);
RTC_WaitForLastTask();
while (RTC_ReadStatusFlag(RTC_FLAG_SEC)==0);
time=sys_ms-time;
printf("before_calibration_time: %dms\r\n", time);
lsi_freq=lsi_freq*1000/time;
printf("lsi_freq: %d\r\n", lsi_freq);
//RTC disable
RTC_ClearStatusFlag(RTC_FLAG_SEC);
RTC_WaitForLastTask();
RCM_DisableLSI();
RCM_DisableAPB1PeriphClock((RCM_APB1_PERIPH_T)RCM_APB1_PERIPH_PMU);
return lsi_freq;
}
/****************************** BEGIN ********************************
**@Name : LSI_Verify
**@Brief : LSI按照输入频率分频后验证秒中断时间
**@Author :
**@Version : V1.0
**@Time :
******************************** END *********************************/
void LSI_Verify(uint32_t prescaler)
{
RCM_EnableAPB1PeriphClock((RCM_APB1_PERIPH_T)RCM_APB1_PERIPH_PMU);
PMU_EnableBackupAccess();
RCM_EnableLSI();
while (RCM_ReadStatusFlag(RCM_FLAG_LSIRDY) == RESET);
RCM_ConfigRTCCLK(RCM_RTCCLK_LSI);
RCM_EnableRTCCLK();
RTC_WaitForSynchro();
RTC_WaitForLastTask();
RTC_ConfigPrescaler(prescaler);
RTC_WaitForLastTask();
RTC_ConfigCounter(0);
RTC_WaitForLastTask();
test_time=sys_ms;
//开启中断
RTC_EnableInterrupt(RTC_INT_SEC);
RTC_WaitForLastTask();
NVIC_EnableIRQRequest(RTC_IRQn, 0, 0);
}
int main(void)
{
uint32_t lsi_freq;
SysTick_Config(RCM_ReadSYSCLKFreq()/ 1000); //配置systick,1ms中断一次
USART1_Init();
printf("LSI_CAL_TEST\r\n");
printf("SYS CLK: %d MHZ\r\n", RCM_ReadSYSCLKFreq()/1000000);
lsi_freq=LSI_Calibration();
LSI_Verify(lsi_freq);
while (1)
{
}
}
void SysTick_Handler(void)
{
sys_ms++;
}
void RTC_IRQHandler(void)
{
if (RTC_ReadIntFlag(RTC_INT_SEC) != RESET)
{
printf("after_calibration_time: %dms\r\n", sys_ms-test_time);
test_time=sys_ms;
RTC_ClearIntFlag(RTC_INT_SEC);
RTC_WaitForLastTask();
}
}
int fputc(int ch, FILE* f)
{
/* send a byte of data to the serial port */
USART_TxData(USART1, (uint8_t)ch);
/* wait for the data to be send */
while (USART_ReadStatusFlag(USART1, USART_FLAG_TXBE) == RESET);
return (ch);
}
我要赚赏金
