STM32
直播中

张艳

7年用户 1621经验值
私信 关注
[问答]

STM8L TIMx ETR并不能够实现完全的外部时钟计数是怎么回事?

在工程中,原来利用GPIO外部中断实现脉冲计数,因为是低功耗设计,所以MCU平时都是Halt状态。觉得如果利用ETR的输入,配合tiM的计数溢出中断可以减少从低功耗模式中恢复的次数,以降低系统占空比。但是发现TIMx的设计必须依赖于内部sysclk的存在,如果halt模式下停止sysclk,则TIMx的CNTL/CNTH完全不更新。

  • #include "stm8l15x.h"
  • #include

  • 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外设类似,也欢迎纠错和讨论。

回帖(1)

李润基

2024-4-23 09:51:21
STM8L的外设工作需要系统时钟支持,而低功耗模式下(HALT),系统时钟停止,降低功耗。相应的定时器TIMX也没有了时钟,所以整个外设就不能工作了。 而部分STM32L系列产品是有低功耗定时器的外设,可以在STOP模式下利用低速时钟工作。所以可以根据你的需求平衡一下功耗或者选择
举报

更多回帖

发帖
×
20
完善资料,
赚取积分