STM32软件模拟输出PWM(HAL库)
我们知道在单片机上许多硬件能实现的操作都能通过软件模拟,比如USARR,I2C等通信协议。定时器通道输出PWM从根本上说也是通过硬件实现的。这里分享一种软件模拟输出PWM的方法。
定时器通道输出PWM的原理是:设置好ARR。PSC,CCR的值,计数器寄存器从0开始递增或者递减,到了设定的CCR值进行电平的反转,这样就做到了在一个定时器周期内存在连续的高低电平,进而输出一个0-3.3V之间的模拟电压,既然知道了原理,只要把每一部分用软件替换就可以
(1)初始化任意GPIO口,设置成输出模式
(2)用一定时器开启定时中断,这里的中断频率设置和采用定时器通道输出频率一致即可。
(3)定时中断执行电平反转
uint8_t g_pwm_angle[MAX_PWM_SERVO] = {90, 90, 90, 90};
uint16_t g_angle_num[MAX_PWM_SERVO] = {149, 149, 149, 149};
// The Angle is converted to the number of pulses, angle= [0, 180]
static uint16_t PwmServo_Angle_To_Pulse(uint8_t angle)
{
uint16_t pulse = (angle * 11 + 500) / 10;
return pulse;
}
// PWM舵机控制,在定时器中调用,模拟输出PWM信号
// PWM steering gear control, in the timer call, analog output PWM signal
void PwmServo_Handle(void)
{
g_pwm_pulse++;
#ifdef USE_SERVO_J1
if (g_pwm_pulse <= g_angle_num[0])
SERVO_1_HIGH();
else
SERVO_1_LOW();
#endif
#ifdef USE_SERVO_J2
if (g_pwm_pulse <= g_angle_num[1])
SERVO_2_HIGH();
else
SERVO_2_LOW();
#endif
#ifdef USE_SERVO_J3
if (g_pwm_pulse <= g_angle_num[2])
SERVO_3_HIGH();
else
SERVO_3_LOW();
#endif
#ifdef USE_SERVO_J4
if (g_pwm_pulse <= g_angle_num[3])
SERVO_4_HIGH();
else
SERVO_4_LOW();
#endif
if (g_pwm_pulse >= 2000)
g_pwm_pulse = 0;
}
该方法适用于定时器数量不够时,可以让一个定时器同时执行中断和输出PWM
’
作者:海晏河清@