知不足而奋进·望远山而前行
目录
前言
在微控制器开发中,理解和掌握PWM(脉宽调制)技术以及与定时器的关系是至关重要的。PWM技术可以广泛应用于工业自动化、电机控制、LED调光等领域,通过改变信号的脉冲宽度来控制电路输出。本文将介绍PWM原理、开发流程,以及如何通过定时器实现PWM功能。通过学习本文,您将掌握通用定时器开发流程,理解周期、分频系数、周期计数、分频计数等概念,以及掌握分频计数、周期计数和占空比的计算策略。
学习目标
- 理解PWM和定时器的关系
- 掌握通用定时器开发流程
- 理解周期,分频系数,周期计数,分频计数。
- 掌握分频计数、周期计数和占空比的计算策略
学习内容
PWM
PWM全称是脉宽调制(Pulse Width Modulation),是一种通过改变信号的脉冲宽度来控制电路输出的技术。PWM技术在工业自动化、电机控制、LED调光等领域广泛应用。
PWM是一种将数字信号转换为模拟信号的技术,它通过改变信号的占空比来控制输出的电平。
在ARM32系列芯片中,PWM输出的频率和占空比可以由程序控制,因此可以用来控制各种电机、灯光和其他设备的亮度、速度等参。
在ARM32系列芯片中,PWM的调制是通过Timer来实现的。PWM与引脚相关,除了基本定时器以外,其他类型的Timer都可以作为PWM来进行使用。
pwm原理
CHxCV是输入捕获和输出比较寄存器
需求
以PD14
对应的LED4为例,我们做一个呼吸灯的效果。
我们采用TIMER3CH2进行实现:
开发流程
- 添加Timer依赖
- 初始化PWM
- PWM占空比控制
初始化PWM
#define PRESCALER 10 // [1, 65536]
#define FREQ 1000 // 1000Hz
// 保证分母 (FREQ * PRESCALER) >= 2564
#define PERIOD SystemCoreClock / (FREQ * PRESCALER)
// TIMER3_CH2
static void Timer_config() {
// 通用定时器
// GPIO PD14 =================================================================
rcu_periph_clock_enable(RCU_GPIOD);
gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14);
gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_14);
gpio_af_set(GPIOD, GPIO_AF_2, GPIO_PIN_14);
// TIMER3C0 =================================================================
// 初始化定时器配置
rcu_periph_clock_enable(RCU_PERIPH);
timer_deinit(TIMER_PERIPH);
// 升级频率
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
// 初始化参数
timer_parameter_struct initpara;
/* initialize TIMER init parameter struct */
timer_struct_para_init(&initpara);
/* 根据需要配置值 */
initpara.prescaler = PRESCALER - 1; // 分频系数 (可以实现更低的timer频率)
// 1个周期的计数(period Max: 65535) Freq > 2564
initpara.period = PERIOD - 1;
/* initialize TIMER counter */
timer_init(TIMER_PERIPH, &initpara);
// TIMER通道输出配置
timer_oc_parameter_struct ocpara;
/* 初始化结构体参数 initialize TIMER channel output parameter struct */
timer_channel_output_struct_para_init(&ocpara);
/* 启用TM1 CH0的OP极(正极) */
ocpara.outputstate = (uint16_t)TIMER_CCX_ENABLE;
/* 配置输出参数configure TIMER channel output function */
timer_channel_output_config(TIMER_PERIPH, TIMER_CH, &ocpara);
/* 配置通达输出比较模式 configure TIMER channel output compare mode */
timer_channel_output_mode_config(TIMER_PERIPH, TIMER_CH, TIMER_OC_MODE_PWM0);
/* 设置通道输出脉冲值 (修改占空比) configure TIMER channel output pulse value */
timer_channel_output_pulse_value_config(TIMER_PERIPH, TIMER_CH, (PERIOD - 1) * 1.0f);
/* enable a TIMER */
timer_enable(TIMER_PERIPH);
}
PWM占空比控制
void PWM_update(float duty) { // 0 -> 100
if(duty > 100) {
duty = 100;
} else if (duty < 0) {
duty = 0;
}
// pulse / (PERIOD - 1) == duty / 100;
uint32_t pulse = (PERIOD - 1) * duty / 100.0f;
/* 设置通道输出脉冲值 (修改占空比) configure TIMER channel output pulse value */
timer_channel_output_pulse_value_config(TIMER_PERIPH, TIMER_CH, pulse);
}
main函数修改duty
int main(void)
{
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
systick_config();
USART0_init();
Timer_config();
printf("Init Complete!\n");
PWM_update(0);
float duty = 0;
int dir = 1;
while(1) {
// printf发送字符串
// 0 -> (PERIOD - 1) -> 0 -> ....
if(duty >= 100) {
dir = -1;
} else if(duty <= 0) {
dir = 1;
}
duty += dir;
PWM_update(duty);
delay_1ms(10);
}
}
输出通道
这里完整配置为多种:
void timer_channel_output_struct_para_init(timer_oc_parameter_struct *ocpara)
{
/* initialize the channel output parameter struct member with the default value */
ocpara->outputstate = (uint16_t)TIMER_CCX_DISABLE;
ocpara->outputnstate = TIMER_CCXN_DISABLE;
ocpara->ocpolarity = TIMER_OC_POLARITY_HIGH;
ocpara->ocnpolarity = TIMER_OCN_POLARITY_HIGH;
ocpara->ocidlestate = TIMER_OC_IDLE_STATE_LOW;
ocpara->ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
}
我们具体的可以分为两类:
ocpara->outputstate = (uint16_t)TIMER_CCX_DISABLE;
ocpara->ocpolarity = TIMER_OC_POLARITY_HIGH;
ocpara->ocidlestate = TIMER_OC_IDLE_STATE_LOW;
ocpara->outputnstate = TIMER_CCXN_DISABLE;
ocpara->ocnpolarity = TIMER_OCN_POLARITY_HIGH;
ocpara->ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
特别观察API,带N的为反向,带P的为正向。赋值的结果常量也是需要注意是否带N。
P和N的配置主要出现在互补PWM中,如果当前的Timer不是高级定时器,那么就不具备互补的功能,那么我们一律认为他是P类型,也就是设置P才有用。
通过设置outputstate 的 ENABLE来控制输出通道的开启。
关心的内容
- 哪个定时器
- 哪个引脚输出pwm
- 周期和分频系数
重要的关键词
周期
pwm中,一个周期就是一次高低电平的变化。
分频
将原来的活增加几倍时间干完。
占空比
1个周期内,高电平出现的比例。
总结
本文详细介绍了PWM技术以及与定时器的关系,通过示例代码演示了在ARM32系列芯片中如何实现PWM功能。首先,我们了解了PWM技术是如何将数字信号转换为模拟信号,并通过改变占空比来控制输出电平的。接着,我们学习了开发流程,包括如何初始化PWM以及如何控制PWM占空比。最后,我们通过具体的代码示例演示了如何在实际开发中应用PWM技术,实现呼吸灯效果。通过本文的学习,相信您已经掌握了有关PWM和定时器的基本知识和开发技巧,希望本文能够对您的学习和开发有所帮助。