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

你可能感兴趣的:(stm32,嵌入式硬件,单片机)