沁恒CH32V307使用记录:使用TIM输出PWM信号
文章目录
- 目的
- 基础说明
- 使用例程
- 总结
目的
使用TIM输出PWM信号是单片机中比较常用的一个功能。这篇文章将对CH32V307中相关内容进行说明。
本文使用沁恒官方的开发板 (CH32V307-EVT-R1沁恒RISC-V模块MCU赤兔评估板) 进行演示。
基础说明
CH32V307拥有多个定时器,只有通用定时器和高级定时器支持PWM输出功能,需要注意的是不同的定时器默认可用时钟源是不同的:
使用TIM输出PWM信号总的来说操作上分为下面几个部分:
- 初始化TIM和输出PWM信号的GPIO口的时钟;
- 配置输出PWM信号的GPIO口为复用输出模式;
- 配置TIM基本定时参数;
- 配置PWM输出的通道与参数;
沁恒官方提供了库函数用于操作TIM,主要是 ch32v30x_tim.h
和 ch32v30x_tim.c
两个文件,前者中声明了提供给用户调用的函数以及相关的枚举和宏定义类型等。
使用TIM输出PWM信号使用中涉及的原理可以参考下面文章中的基础说明部分:
《使用HAL库开发STM32:Timer基础说明与定时功能使用》
《使用HAL库开发STM32:使用Timer输出PWM信号》
使用例程
CH32V307官方的PWM例程中使用的是TIM1,我这里使用TIM4进行演示,两者使用方式基本上是差不多的,下面是测试代码:
#include "debug.h"
// 初始化GPIO、TIM、PWM,使用见下面main函数
void TIM4_PWMOut_Init(u16 psc, u16 arr, u16 ccp) {
// 初始化时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM4, ENABLE);
// 初始化 TIM4_CH1引脚 (PB6)
GPIO_InitTypeDef GPIO_InitStructure = { 0 };
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure);
// 初始化 TIM4
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure = { 0 };
TIM_TimeBaseInitStructure.TIM_Period = arr; // 计数周期(以TIM时钟分频后的时钟最为计数源)
// 该值为9表示计数10次为一个周期,49表示计数50次为一个周期,依此类推
TIM_TimeBaseInitStructure.TIM_Prescaler = psc; // 分频系数(对TIM时钟进行分频)
// 该值为0表示不分频,1表示2分频,2表示3分频,依此类推
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit( TIM4, &TIM_TimeBaseInitStructure);
TIM_ARRPreloadConfig( TIM4, ENABLE); // 使能arr预装载,如果需要TIM启用的情况下修改计数周期,那么通常使能预装载会比较安全
// 初始化 TIM4_CH1 PWM
TIM_OCInitTypeDef TIM_OCInitStructure = { 0 };
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = ccp; // 比较参数,计数值与该值比较,来改变PWM通道输出电平
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init( TIM4, &TIM_OCInitStructure);
// TIM_CtrlPWMOutputs(TIM4, ENABLE); // 高级定时器需要将这个使能才能输出PWM
TIM_OC1PreloadConfig( TIM4, TIM_OCPreload_Disable); // 使能ccr1预装载,如果需要PWM启用的情况下修改比较参数,那么通常使能预装载会比较安全
TIM_Cmd( TIM4, ENABLE); // 使能定时器
}
int main(void) {
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SystemCoreClockUpdate();
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n", SystemCoreClock);
printf("ChipID:%08x\r\n", DBGMCU_GetCHIPID());
TIM4_PWMOut_Init(96 - 1, 1000 - 1, 800); // 默认配置下时钟为96MHz,对时钟源96分频,即TIM计数时钟为1MHz
// 计数周期设置为1000,结合上条每次计数为1ms,相当于频率为1000Hz
// 根据比较模式和PWM模式设置,以及上面的参数设置,这里输出的PWM信号的占空比为80%
while(1) {
Delay_Ms(2500);
TIM_SetCompare1( TIM4, 500); // 修改CCR1的值,此处修改后ARR为1000 - 1, 频率为1kHz,CCR1为500,占空比为50%
Delay_Ms(2500);
TIM_SetCompare1( TIM4, 200); // 修改CCR1的值,此处修改后ARR为1000 - 1,频率为1kHz, CCR1为200,占空比为20%
Delay_Ms(2500);
TIM_SetAutoreload( TIM4, 300 - 1); // 修改ARR的值,此处修改后ARR为300 - 1, 频率为3.33kHz,CCR1为200,占空比为66.67%
Delay_Ms(2500);
TIM_SetAutoreload( TIM4, 1000 - 1); // ARR设置为初始值
TIM_SetCompare1( TIM4, 800); // CCR1设置为初始值
}
}
上面代码演示如下,注意观察示波器波形下面的 频率、周期和占空比 :
总结
使用TIM输出PWM信号操作比较简单,只要了解相关原理基本上就能立马上手使用。