CH32V307 TIM中断 - RISC-V MCU技术社区 - 电子技术论坛 - 广受欢迎的专业电子论坛
分享 收藏 返回

[文章]

CH32V307 TIM中断

1、关于tiM及TIM中断
CH32V307共有8个16位定时器,包含4个高级定时器和4个通用定时器,每个定时器支持四路独立的比较捕获通道,支持输入捕获、输出比较、PWM生成和单脉冲输出等模式。
关于TIM中断,在进行TIM初始化配置时,需要对TIM的计数时钟预分频器以及自动重装值寄存器进行配置,即我们所说的预分频值以及重装载值。当TIM计数达到重装载值之后,若开启了定时器更新中断,此时就会进入定时器更新中断。

2、定时器更新中断初始化配置程序如下
  1. void TIM1_Int_Init(u16 arr,u16 psc)
  2. {
  3.     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure={0};
  4.     NVIC_InitTypeDef         NVIC_InitStructure={0};

  5.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);       //使能TIM1时钟

  6.     TIM_TimeBaseStructure.TIM_Period = arr;                    //指定下次更新事件时要加载到活动自动重新加载寄存器中的周期值。
  7.     TIM_TimeBaseStructure.TIM_Prescaler =psc;                  //指定用于划分TIM时钟的预分频器值。
  8.     TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;    //时钟分频因子
  9.     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM计数模式,向上计数模式
  10.     TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  11.     TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);            //根据指定的参数初始化TIMx的时间基数单位

  12.     //初始化TIM NVIC,设置中断优先级分组
  13.     NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;         //TIM1中断
  14.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //设置抢占优先级0
  15.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;         //设置响应优先级3
  16.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //使能通道1中断
  17.     NVIC_Init(&NVIC_InitStructure);                            //初始化NVIC

  18.     TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE ); //使能TIM1中断,允许更新中断

  19.     TIM_Cmd(TIM1, ENABLE); //TIM1使能
  20. }void TIM1_Int_Init(u16 arr,u16 psc)
  21. {
  22.     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure={0};
  23.     NVIC_InitTypeDef         NVIC_InitStructure={0};

  24.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);       //使能TIM1时钟

  25.     TIM_TimeBaseStructure.TIM_Period = arr;                    //指定下次更新事件时要加载到活动自动重新加载寄存器中的周期值。
  26.     TIM_TimeBaseStructure.TIM_Prescaler =psc;                  //指定用于划分TIM时钟的预分频器值。
  27.     TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;    //时钟分频因子
  28.     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM计数模式,向上计数模式
  29.     TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  30.     TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);            //根据指定的参数初始化TIMx的时间基数单位

  31.     //初始化TIM NVIC,设置中断优先级分组
  32.     NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;         //TIM1中断
  33.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //设置抢占优先级0
  34.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;         //设置响应优先级3
  35.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //使能通道1中断
  36.     NVIC_Init(&NVIC_InitStructure);                            //初始化NVIC

  37.     TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE ); //使能TIM1中断,允许更新中断

  38.     TIM_Cmd(TIM1, ENABLE); //TIM1使能
  39. }
关于该程序,我们主要注意3个参数的配置:重装载值、预分频器值以及计数模式。其中关于时钟分频因子ClockDivision ,一般用于输入捕获模式配置滤波,是决定数字滤波采样频率的参数,此处配置为1分频即可;关于重复计数RepetitionCounter 值,属于高级定时器控制寄存器专用寄存器位,利用它可以非常容易控制输出 PWM 的个数,此处配置为0即可。关于重装载值、预分频器值以及计数模式的配置,计数模式一般配置为向上计数模式,即从0计数到重装载值;关于重装载值arr以及预分频器值psc,决定计数一次的时间以及产生一次中断的时间,计算公式如下:

此外,用到中断,需要对中断优先级进行配置,以及使能开启对应定时器更新中断。

3、定时器更新中断程序
  1. void TIM1_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  2. void TIM1_UP_IRQHandler(void)
  3. {
  4.     static u8 i=0;

  5.     if(TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) //检查TIM1中断是否发生。
  6.     {
  7.         TIM_ClearITPendingBit(TIM1,TIM_IT_Update);      //清除TIM1的中断挂起位。
  8.         GPIO_WriteBit(GPIOA, GPIO_Pin_1, (i==0) ? (i=Bit_SET):(i=Bit_RESET));
  9.     }
  10. }
此处注意中断函数要加中断声明,进入中断后要注意清除对应的中断标志位。

4、main函数配置程序
  1. int main(void)
  2. {
  3.     static u8 i=0;

  4.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  5.         SystemCoreClockUpdate();
  6.         Delay_Init();
  7.         USART_Printf_Init(115200);        
  8.         printf("SystemClk:%d
  9. ",SystemCoreClock);
  10.         printf( "ChipID:%08x
  11. ", DBGMCU_GetCHIPID() );
  12.         printf("This is printf example
  13. ");
  14.         LED_Init();
  15.         TIM1_Int_Init(10000-1,720-1);


  16.         while(1)
  17.     {
  18.             Delay_Ms(100);
  19.         GPIO_WriteBit(GPIOA, GPIO_Pin_0, (i==0) ? (i=Bit_SET):(i=Bit_RESET));
  20.         }
  21. }

5、中断函数现象

此处通过IO翻转查看中断现象,那么对与IO来说,一个高低电平翻转相当于一整个周期,对应高电平和低电平则需要进入两次中断产生,那么对于下图(定时器中断IO翻转产生)来说,脉宽相当于一个定时器一个周期T,IO电平翻转周期则相当于2T,那么这个IO电平翻转的频率:f=1/(2T)。
此处初始化时arr值为10000-1,psc值为720-1,APB2的时钟为72MHz,那么产生一次中断的时间
T=(arr+1)(psc+1)/72M=10000*720/72000000=100ms
频率f=1/2T=5Hz
上述计算结果与采样结果基本一致。


更多回帖

×
发帖