本帖最后由 abner_ma 于 2025-10-29 16:47 编辑
CH32V317 的定时器强大,种类齐全,从简单的 SysTick 到复杂的 TIM1,覆盖了所有常见的定时/计数应用场景。功能强大:高级定时器支持死区控制和刹车,通用定时器支持编码器模式,这对于工业控制至关重要。 可靠性高:提供了 IWDG 和 WWDG 两种看门狗,增强了系统在恶劣环境下的稳定性。低功耗设计:独立的 RTC 模块保证了超低功耗下的持续计时。CH32V317 的定时器可以分为以下几大类,与 STM32 的定时器分类类似:
1. 高级控制定时器
型号: TIM1
位数: 16位
主要特点:
具备所有通用定时器的功能。
支持互补输出的死区时间控制,这是驱动三相无刷电机等应用的关键。
支持刹车功能,用于在紧急情况下快速关闭输出。
可以产生高频率的 PWM 信号。
典型应用: 电机控制、数字电源(PFC、LLC)、逆变器。
2. 通用定时器
型号: TIM2, TIM3, TIM4
位数: 16位(TIM2 是 32位)
主要特点:
支持向上、向下、向上/下自动重装载计数模式。
拥有独立的 4 个通道,可用于:
输入捕获(测量脉冲宽度、频率)
输出比较(产生特定波形、驱动 DAC)
PWM 生成
支持编码器接口,可以直接连接正交编码器。
可以与其他定时器级联。
典型应用: 测量传感器信号周期、生成多路 PWM、编码器读数、通用延时。
3. 基本定时器
型号: TIM6, TIM7
位数: 16位
主要特点:
功能最简单,主要用于时基生成。
只有计时功能,没有外部输入/输出通道。
通常用于为 DAC 提供触发信号,或者作为操作系统的滴答定时器。
典型应用: 操作系统心跳时钟、DAC 触发、提供精确的基准时间间隔。
4. 独立看门狗定时器
型号: IWDG
特点:
由独立的低速内部时钟驱动,即使主时钟失效也能工作。
用于检测和解决由软件错误或外界干扰引起的程序“跑飞”问题。
需要软件在溢出前“喂狗”,否则将产生系统复位。
应用: 提高系统可靠性,抗干扰。
5. 窗口看门狗定时器
型号: WWDG
特点:
时钟来自系统主时钟。
要求在一个精确的时间窗口内“喂狗”,过早或过晚都会导致复位。
更适合监测那些要求代码必须在规定时间内执行的应用程序。
应用: 监测关键任务的执行是否超时或提前结束。
6. 系统时基定时器
型号: SysTick
特点:
这是一个 24 位的递减计数器,是 RISC-V 内核的一部分。
专用于为实时操作系统提供规律的定时中断,即“心跳”。
即使没有操作系统,也常用于实现精准的微秒或毫秒级延时函数。
应用: 操作系统任务调度、`HAL_Delay()` 等延时函数的基础。
7. 实时时钟
型号: RTC
特点:
由一个外部的 32.768kHz 晶振驱动,功耗极低。
即使在主电源断开、仅由备份电池供电的情况下也能持续运行。
提供日历时钟(年、月、日、时、分、秒)和闹钟功能。
具有秒中断功能。
应用: 电子钟、数据记录仪、需要记录时间的设备。
- #include "./BSP/LED/led.h"
- #include "./BSP/TIMER/btim.h"
- void BTIM_TIMX_INT_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
- /**
- * [url=/u/brief]@brief[/url] 基本定时器TIMX中断服务函数
- * @param 无
- * @retval 无
- */
- void BTIM_TIMX_INT_IRQHandler(void)
- {
- if (TIM_GetITStatus(BTIM_TIMX_INT, TIM_IT_Update) != RESET) /* 检查TIMx更新中断是否发生 */
- {
- TIM_ClearITPendingBit(BTIM_TIMX_INT, TIM_IT_Update ); /* 清除TIMx更新中断标志 */
- LED1_TOGGLE(); /* LED1翻转 */
- }
- }
- /**
- * @brief 基本定时器TIMX定时中断初始化函数
- * @note
- * 基本定时器的时钟来自APB1,当PPRE1 ≥ 2分频的时候
- * 基本定时器的时钟为APB1时钟的2倍, 而APB1为72M, 所以定时器时钟 = 144Mhz
- * 定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
- * Ft=定时器工作频率,单位:Mhz
- *
- * @param arr: 自动重装值。
- * @param psc: 时钟预分频数
- * @retval 无
- */
- void btim_timx_int_init(uint16_t arr, uint16_t psc)
- {
- TIM_TimeBaseInitTypeDef tim_init_struct;
- NVIC_InitTypeDef nvic_init_struct;
- BTIM_TIMX_INT_CLK_ENABLE(); /* 使能TIMx时钟 */
- tim_init_struct.TIM_Period = arr; /* 设置自动重装载值 */
- tim_init_struct.TIM_Prescaler =psc; /* 设置预分频系数 */
- tim_init_struct.TIM_CounterMode = TIM_CounterMode_Up; /* 向上计数模式 */
- TIM_TimeBaseInit(BTIM_TIMX_INT, &tim_init_struct); /* 定时器初始化 */
- nvic_init_struct.NVIC_IRQChannel = BTIM_TIMX_INT_IRQn; /* TIMx中断 */
- nvic_init_struct.NVIC_IRQChannelPreemptionPriority = 0; /* 抢占优先级0 */
- nvic_init_struct.NVIC_IRQChannelSubPriority = 3; /* 响应优先级3 */
- nvic_init_struct.NVIC_IRQChannelCmd = ENABLE; /* IRQ通道使能 */
- NVIC_Init(&nvic_init_struct); /* 初始化NVIC */
- TIM_ITConfig(BTIM_TIMX_INT,TIM_IT_Update,ENABLE ); /* 使能指定的TIMx中断,允许更新中断 */
- TIM_Cmd(BTIM_TIMX_INT, ENABLE); /* 使能TIMx */
- }
下面用普通定时器做程序设计
无需main函数,定时器中断实现开关灯
|