CH32V307共有8个16位定时器,包含4个高级定时器和4个通用定时器,每个定时器支持四路独立的比较捕获通道,支持输入捕获、输出比较、PWM生成和单脉冲输出等模式。 关于TIM中断,在进行TIM初始化配置时,需要对TIM的计数时钟预分频器以及自动重装值寄存器进行配置,即我们所说的预分频值以及重装载值。当TIM计数达到重装载值之后,若开启了定时器更新中断,此时就会进入定时器更新中断。
2、定时器更新中断初始化配置程序如下 - void TIM1_Int_Init(u16 arr,u16 psc)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure={0};
- NVIC_InitTypeDef NVIC_InitStructure={0};
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能TIM1时钟
- TIM_TimeBaseStructure.TIM_Period = arr; //指定下次更新事件时要加载到活动自动重新加载寄存器中的周期值。
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //指定用于划分TIM时钟的预分频器值。
- TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频因子
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM计数模式,向上计数模式
- TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
- TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
- //初始化TIM NVIC,设置中断优先级分组
- NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; //TIM1中断
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //设置抢占优先级0
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //设置响应优先级3
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能通道1中断
- NVIC_Init(&NVIC_InitStructure); //初始化NVIC
- TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE ); //使能TIM1中断,允许更新中断
- TIM_Cmd(TIM1, ENABLE); //TIM1使能
- }void TIM1_Int_Init(u16 arr,u16 psc)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure={0};
- NVIC_InitTypeDef NVIC_InitStructure={0};
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能TIM1时钟
- TIM_TimeBaseStructure.TIM_Period = arr; //指定下次更新事件时要加载到活动自动重新加载寄存器中的周期值。
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //指定用于划分TIM时钟的预分频器值。
- TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频因子
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM计数模式,向上计数模式
- TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
- TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
- //初始化TIM NVIC,设置中断优先级分组
- NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; //TIM1中断
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //设置抢占优先级0
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //设置响应优先级3
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能通道1中断
- NVIC_Init(&NVIC_InitStructure); //初始化NVIC
- TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE ); //使能TIM1中断,允许更新中断
- TIM_Cmd(TIM1, ENABLE); //TIM1使能
- }
复制代码 关于该程序,我们主要注意3个参数的配置:重装载值、预分频器值以及计数模式。其中关于时钟分频因子ClockDivision ,一般用于输入捕获模式配置滤波,是决定数字滤波采样频率的参数,此处配置为1分频即可;关于重复计数RepetitionCounter 值,属于高级定时器控制寄存器专用寄存器位,利用它可以非常容易控制输出 PWM 的个数,此处配置为0即可。关于重装载值、预分频器值以及计数模式的配置,计数模式一般配置为向上计数模式,即从0计数到重装载值;关于重装载值arr以及预分频器值psc,决定计数一次的时间以及产生一次中断的时间,计算公式如下:
此外,用到中断,需要对中断优先级进行配置,以及使能开启对应定时器更新中断。
3、定时器更新中断程序
- void TIM1_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
- void TIM1_UP_IRQHandler(void)
- {
- static u8 i=0;
- if(TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) //检查TIM1中断是否发生。
- {
- TIM_ClearITPendingBit(TIM1,TIM_IT_Update); //清除TIM1的中断挂起位。
- GPIO_WriteBit(GPIOA, GPIO_Pin_1, (i==0) ? (i=Bit_SET):(i=Bit_RESET));
- }
- }
复制代码 此处注意中断函数要加中断声明,进入中断后要注意清除对应的中断标志位。
4、main函数配置程序
- int main(void)
- {
- static u8 i=0;
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- SystemCoreClockUpdate();
- Delay_Init();
- USART_Printf_Init(115200);
- printf("SystemClk:%d
- ",SystemCoreClock);
- printf( "ChipID:%08x
- ", DBGMCU_GetCHIPID() );
- printf("This is printf example
- ");
- LED_Init();
- TIM1_Int_Init(10000-1,720-1);
- while(1)
- {
- Delay_Ms(100);
- GPIO_WriteBit(GPIOA, GPIO_Pin_0, (i==0) ? (i=Bit_SET):(i=Bit_RESET));
- }
- }
复制代码
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
上述计算结果与采样结果基本一致。
|