一、PWM介绍:
1、简介:
PWM波形(Pulse width modulation wave),PWM就是脉冲宽度调制,也就是占空比可变的脉冲波形。脉冲宽度调制是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用PWM进行编码。
2、电路图:
XL
XL555芯片:
可以用于定时、触发、脉冲产生和振荡电路,所有和时钟相关的领域都可以考虑采用。由于其易用性、低廉的价格和良好的可靠性,这颗芯片在业内很流行,成为很多学生、创客在电子DIY制作中热爱的经典IC。
生成两路PWM波:
1、Cubemx配置
2、代码
main.c:
HAL_TIM_PWM_Start(&htim16,TIM_CHANNEL_1); //PWM输出开启
HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);
__HAL_TIM_SetCompare(&htim16,TIM_CHANNEL_1,pa6_duty); //生成PWM波(把占空比用到输出中)
二、定时器——输入捕获
如果你玩过小车就会知道小车的编码器测速就用到了定时器的输入捕获。STM32 的输入捕获,简单的说就是通过检测 TIMx_CHx 上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的通道的捕获/比较寄(TIMx_CCRx)里面,完成一次捕获。
1、测频率:
1、Cubemx配置
2、代码
interrupt.c:
uint ccr1_val1=0,ccr1_val2=0;
uint frq=0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM2)
{
ccr1_val1=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1); //读取计时值
__HAL_TIM_SetCounter(htim,0); //计时值清零
//实现定时器的计数器值的设置和超时时间控制,实现精确计时
frq=(80000000/80)/ccr1_val1; //计算频率
HAL_TIM_IC_Start(htim,TIM_CHANNEL_1); //重新开启定时器
if(htim->Instance==TIM3)
{
ccr1_val2=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1); //读取计时值
__HAL_TIM_SetCounter(htim,0); //计时值清零
//实现定时器的计数器值的设置和超时时间控制,实现精确计时
frq=(80000000/80)/ccr1_val2; //计算频率
HAL_TIM_IC_Start(htim,TIM_CHANNEL_1); //重新开启定时器
}
main.c:
extern uint frq1,frq2;
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1); //初始化,频率测量捕获定时器开启
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
2、测占空比:
1、Cubemx配置
2、代码
double ccr1_val1a=0,ccr1_val2a=0;
uint ccr1_val1b=0,ccr1_val2b=0;
uint ccr1_val1=0,ccr1_val2=0;
uint frq1=0,frq2=0;
float duty1=0,duty2=0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM2)
{
if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)
{
ccr1_val1a=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
ccr1_val1b=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2);
__HAL_TIM_SetCounter(htim,0);
frq1=(80000000/80)/ccr1_val1a;
duty1=(ccr1_val1b/ccr1_val1a)*100;
HAL_TIM_IC_Start(htim,TIM_CHANNEL_1);
HAL_TIM_IC_Start(htim,TIM_CHANNEL_2);
}
}
if(htim->Instance==TIM3)
{
if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)
{
ccr1_val2a=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
ccr1_val2b=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2);
__HAL_TIM_SetCounter(htim,0);
frq2=(80000000/80)/ccr1_val2a;
duty2=(ccr1_val2b/ccr1_val2a)*100;
HAL_TIM_IC_Start(htim,TIM_CHANNEL_1);
HAL_TIM_IC_Start(htim,TIM_CHANNEL_2);
}
}
}
3、最终效果