STM8L TIMx ETR并不能够实现完全的外部时钟计数
在工程中,原来利用GPIO外部中断实现脉冲计数,因为是低功耗设计,所以MCU平时都是Halt状态。觉得如果利用ETR的输入,配合TIM的计数溢出中断可以减少从低功耗模式中恢复的次数,以降低系统占空比。但是发现TIMx的设计必须依赖于内部sysclk的存在,如果halt模式下停止sysclk,则TIMx的CNTL/CNTH完全不更新。#include "stm8l15x.h"
#include <stdbool.h>
uint32_t ul2;
uint32_t ul3;
INTERRUPT_HANDLER(TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQHandler,19)
{
if(TIM2_GetITStatus(TIM2_IT_Update) != RESET)
{
ul2++;
TIM2_ClearITPendingBit(TIM2_IT_Update);
}
}
INTERRUPT_HANDLER(TIM3_UPD_OVF_TRG_BRK_USART3_TX_IRQHandler,21)
{
if(TIM3_GetITStatus(TIM3_IT_Update) != RESET)
{
ul3++;
TIM3_ClearITPendingBit(TIM3_IT_Update);
}
}
void setup( void )
{
CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);
CLK->ICKCR |= 0x40;
// enable CCKO 38kHz
CLK->CCOR = CLK_CCOSource_LSI;
GPIO_Init(GPIOC, GPIO_Pin_4, GPIO_Mode_Out_PP_Low_Slow);
GPIO_Init(GPIOB, GPIO_Pin_3, GPIO_Mode_In_PU_No_IT);
GPIO_Init(GPIOD, GPIO_Pin_1, GPIO_Mode_In_PU_No_IT);
GPIO_Init(GPIOE, GPIO_Pin_2, GPIO_Mode_Out_PP_Low_Slow);
GPIO_Init(GPIOA, GPIO_Pin_4, GPIO_Mode_In_PU_No_IT);
GPIO_Init(GPIOA, GPIO_Pin_5, GPIO_Mode_In_PU_No_IT);
SYSCFG->RMPCR3 |= SYSCFG_RMPCR3_CCO_REMAP;
SYSCFG->RMPCR2 |= SYSCFG_RMPCR2_TIM2TRIG_REMAP;
SYSCFG->RMPCR2 |= SYSCFG_RMPCR2_TIM3TRIG_REMAP1;
// short cut PC4/PB3 or PC4/PD1 without changing SYSCFG_Remap.
// SYSCFG_RMPCR3, CCO_REMAP = 0:1 = PC4:PE2
// SYSCFG_RMPCR2, TIM2_TRG_REMAP = 0:1 = PB3:PA4
// SYSCFG_RMPCR2, TIM3_TRG_REMAP = 0:1 = PD1:PA5
TIM2_DeInit();
CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, ENABLE);
//TIM2_ETRClockMode2Config(TIM2_ExtTRGPSC_DIV2, TIM2_ExtTRGPolarity_NonInverted,0x00);
TIM2_ETRClockMode2Config(TIM2_ExtTRGPSC_OFF, TIM2_ExtTRGPolarity_Inverted,0x00);
//TIM2_TimeBaseInit(TIM2_Prescaler_1,TIM2_CounterMode_Up,9999);
TIM2_TimeBaseInit(TIM2_Prescaler_1,TIM2_CounterMode_Up,100);
TIM2_ITConfig(TIM2_IT_Update,ENABLE);
TIM2_SetCounter(0x0);
TIM2_ClearITPendingBit(TIM2_IT_Update);
TIM2_Cmd(ENABLE);
TIM3_DeInit();
CLK_PeripheralClockConfig(CLK_Peripheral_TIM3, ENABLE);
//TIM3_ETRClockMode2Config(TIM3_ExtTRGPSC_DIV2, TIM3_ExtTRGPolarity_NonInverted,0x00);
TIM3_ETRClockMode2Config(TIM3_ExtTRGPSC_OFF, TIM3_ExtTRGPolarity_Inverted,0x00);
//TIM3_TimeBaseInit(TIM3_Prescaler_1,TIM3_CounterMode_Up,9999);
TIM3_TimeBaseInit(TIM3_Prescaler_1,TIM3_CounterMode_Up,100);
TIM3_ITConfig(TIM3_IT_Update,ENABLE);
TIM3_SetCounter(0x0);
TIM3_ClearITPendingBit(TIM3_IT_Update);
TIM3_Cmd(ENABLE);
enableInterrupts();
}
void Halt_Init(void)
{
/* Set STM8 in low power */
PWR->CSR2 = 0x2;
/* Stop RTC Source clock */
CLK_RTCClockConfig(CLK_RTCCLKSource_Off, CLK_RTCCLKDiv_1);
#ifdef USE_LSE
CLK_LSEConfig(CLK_LSE_OFF);
while ((CLK->ECKCR & 0x04) != 0x00);
#else
CLK_LSICmd(DISABLE);
while ((CLK->ICKCR & 0x04) != 0x00);
#endif
/* Stop clock RTC and LCD */
CLK_PeripheralClockConfig(CLK_Peripheral_RTC, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_TIM3, DISABLE);
}
int main( void )
{
setup();
while(true){
Halt_Init();
asm("nop");
halt();
}
//return 0;
}
在Halt_Init中,如果把TIM2/TIM3 DISABLE掉,TIMx_CNTL/TIMx_CNTH一直保持初始值,无法进入中断服务程序。从RM0031.pdf中看到的图也发现,fsysclk一直存在于所谓的外部时钟源模式2(ETR)。也就是说所谓外部时钟源模式,其内部时钟必须始终存在。
我现在有两个选择:
1. 把LSI 38KHz作为sysclk赋给TIM2/TIM3,但是我TIM4的sysclk必须是HSI,因为我需要1ms的系统定时中断;
2. 恢复EXTI中断服务。
就是不清楚那种功耗更低些。
STM32L外设与STM8L外设类似,也欢迎纠错和讨论。
如果有其他的模式,请指教一二。 STM8L的外设工作需要系统时钟支持,而低功耗模式下(HALT),系统时钟停止,降低功耗。相应的定时器TIMX也没有了时钟,所以整个外设就不能工作了。 而部分STM32L系列产品是有低功耗定时器的外设,可以在STOP模式下利用低速时钟工作。所以可以根据你的需求平衡一下功耗或者选择:)
页:
[1]