本帖最后由 Alden 于 2023-12-21 17:48 编辑
#技术资源#
APM32F003系列,作为一颗20pin小封装的32位MCU,其中的外设资源却也一点没少。
通讯接口就有3*USART、1*I2C、1*SPI
ADC采样就有8个通道
而定时器更是高级定时器、通用定时器、基本定时器、滴答定时器、看门狗定时器等应有尽有。
今天主要测试了解独立看门狗和高级定时器TMR1的关联。
APM32F003的独立看门狗时钟源是MCU的内部低速时钟LIRC/2 ,在主时钟失效的情况下也可以正常工作。
频率典型值为128kHz,但精度只有±5%
这会导致独立看门狗的定时时间在不同芯片和不同电压温度下都会有一定差异,如果需要比较精准的确定独立看门狗就需要比较精准的知道LIRC的时钟频率。
APM32F003也是具备LIRC测量的功能的
在SDK中有对应代码配置
uint32_t LIRC_Measurment(void)
{
uint16_t icValue[2];
uint32_t freqLIRC;
uint32_t freqMasterClk;
TMR1_ICConfig_T icConfig;
freqMasterClk = RCM_GetMasterClockFreq();
WUPT_EnableLIRCMeasurement();
icConfig.channel = TMR1_CHANNEL_1;
icConfig.div = TMR1_IC_DIV_8;
icConfig.filter = 0;
icConfig.polarity = TMR1_IC_POLARITY_FALLING;
icConfig.selection = TMR1_IC_SELECT_DIRECTTI;
TMR1_ConfigInputCapture(TMR1, &icConfig);
TMR1_Enable(TMR1);
while(TMR1_ReadStatusFlag(TMR1, TMR1_FLAG_CH1CC) == RESET);
icValue[0] = TMR1_ReadCompareCapture(TMR1, TMR1_CHANNEL_1);
TMR1_ClearStatusFlag(TMR1, TMR1_FLAG_CH1CC);
while(TMR1_ReadStatusFlag(TMR1, TMR1_FLAG_CH1CC) == RESET);
icValue[1] = TMR1_ReadCompareCapture(TMR1, TMR1_CHANNEL_1);
TMR1_ClearStatusFlag(TMR1, TMR1_FLAG_CH1CC);
TMR1_DisableCompareCapture(TMR1, TMR1_CHANNEL_1);
TMR1_Disable(TMR1);
freqLIRC = (8 * freqMasterClk) / (icValue[1] - icValue[0]);
WUPT_DisableLIRCMeasurement();
return freqLIRC;
}
LIRC的频率测量会用到TMR1的CH1进行输入捕获测量。
可以看到运行测量出来的LIRC频率为122.84kHz,确实会有一定偏差。
而使用TIM1对LIRC测量校准后需要注意TMR1的配置没有被完全复位清空。
要使用TMR1的CH1进行其他的输入输出配置,可能会出现与设定不符的情况。
需要在TMR1初始化前对TMR1的寄存器进行复位。
在库函数中调用TMR1_Reset(TMR1);即可
void TMR1_Init(void)
{
TMR1_OCConfig_T ocConfigStruct;
TMR1_TimeBaseConfig_T timeBaseConfig;
TMR1_Reset(TMR1);
/* Up-counter */
timeBaseConfig.cntMode = TMR1_CNT_MODE_UP;
/* Set counter = 500 */
timeBaseConfig.count = 500;
/* Set divider = 47.So TMR1 clock freq ~= 24/(47 + 1) = 500KHZ */
timeBaseConfig.divider = 47;
/* Repetition counter = 0x0 */
timeBaseConfig.repetitionCount = 0;
TMR1_ConfigTimerBase(TMR1, &timeBaseConfig);
/* Select channen1 3 */
ocConfigStruct.channel = TMR1_CHANNEL_1;
/* Set compare value = 250 */
ocConfigStruct.count = 250;
/* PWM1 mode */
ocConfigStruct.mode = TMR1_OC_MODE_PWM1;
/* Idle State is reset */
ocConfigStruct.OCxIdleState = TMR1_OC_IDLE_RESET;
/* Idle State is reset */
ocConfigStruct.OCxNIdleState = TMR1_OC_IDLE_RESET;
/* Disable CH1N ouput */
ocConfigStruct.OCxNOutputState = TMR1_OC_OUTPUT_DISABLE;
/* Enable CH1 ouput */
ocConfigStruct.OCxOutputState = TMR1_OC_OUTPUT_ENABLE;
/* CH1N polarity is high */
ocConfigStruct.OCxNPolarity = TMR1_OC_POLARITY_HIGH;
/* CH1 polarity is high */
ocConfigStruct.OCxPolarity = TMR1_OC_POLARITY_HIGH;
TMR1_ConfigOutputCompare(TMR1, &ocConfigStruct);
/* Enable PWM output */
TMR1_EnableOutputPWM(TMR1);
/* Enable TMR1 */
TMR1_Enable(TMR1);
}
|