STM32入门_PWM_数字引脚输出正弦波实现呼吸灯

引言

通过配置STM32的输出可以对负载进行控制,对于只有开启、关闭两种工作状态的负载,GPIO + 继电器 可以完成对此类负载的控制,通过GPIO控制继电器的闭合、断开,从而达到控制开启与关闭的目的。

对于具有多种状态的负载,例如直流电机,不仅只有开启、关闭两种状态,还需要运行在不同转速,需要STM32具有能够输出"模拟量"的能力,进而控制负载运行在不同的状态。

本文将介绍 PWM + 低通滤波器 方案,实现数字引脚输出正弦波,并驱动LED进行测试,实现呼吸灯的效果,为后续使用PWM控制电机等负载做基础。

1、基本原理

下图展示了固定占空比的PWM,只能等效固定电平,不同占空比PWM信号可以等效不同大小的电压,那么按照正弦规律输出不同占空比可以等效出正弦波。

输出正弦规律占空比最简单的方法:使用 锯齿波 + 比较器

  • 锯齿波(蓝色线)为载波,周期信号,其周期决定PWM信号的周期
  • 正弦波(红色线)为调制波,与载波进行比较,决定PWM信号的占空比
  • 粉红色线为PWM信号

比较逻辑:当调制波比载波大是,PWM输出高,调制波比载波小,PWM输出低。

根据面积等效原理(Voltage-Second Balance) ,每个周期内,冲量相等(即窄脉冲的面积)而形状不同的窄脉冲加在具有惯性的环节上时,输出响应波形基本相同,红色波形窄脉冲与粉红色窄脉冲围成的面积相等,所以两者等效。

综上,需要使用STM32实现,

  • 硬件生成锯齿波
  • 软件生成调制波
  • 执行比较逻辑
  • 输出PWM信号

下面使用STM32的高级定时器TIM1输出可以等效50Hz的正弦波的PWM信号,驱动LED实现呼吸灯。

2、PWM底层配置

使用STM32CubeMx进行底层配置,并自动生成代码,

步骤1:配置定时器的时钟

时钟配置为72MHz,

步骤2:配置载波频率、PWM输出

载波频率 = 定时器时钟 / (Prescaler + 1) / (Period + 1) = 72MHz/72/200 = 5KHz

步骤3:配置定时器中断

配置定时器上溢中断,应用代码中在上溢中断中更新PWM输出比较值,

步骤4:生成底层配置代码

3、编写应用代码

底层配置已经生成锯齿波,配置PWM输出后可执行比较逻辑输出PWM信号,如何生成正弦波?如何控制正弦波频率?

步骤5:软件生成正弦波

  • 通过C标准库中sin函数生成正弦波数组
  • 正弦波频率由正弦波周期内的采样点个数决定,正弦波频率 = 载波频率 / 采样点个数。需求正弦波频率是50Hz,载波频率是5KHz,采样点个数100。
c 复制代码
#define SIN_SAMPLES 100
#define PI 3.14
uint16_t sin_table[SIN_SAMPLES];
for (int i = 0; i < SIN_SAMPLES; i++) {
    sin_table[i] = (uint16_t)(100* (1 + sin(2 * PI * i / SIN_SAMPLES))); 
}

程序运行后生成的正弦数组如下所示,

步骤6:定时器中断查表更新比较值

打开定时器、启用中断,

c 复制代码
  HAL_TIM_Base_Start_IT(&htim1);             //启动定时器并启用中断
  HAL_TIM_PWM_Start_IT(&htim1,TIM_CHANNEL_1);//启动PWM输出

在定时器中断查正弦表更新PWM占空比,

c 复制代码
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 
{
    if (htim->Instance == TIM1) 
	{
		if(count < 100)
		{
			 __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, sin_table[count]);//查表更新占空比
			count++;
		}
		else
		{
			count = 0;
		}
   }
}

步骤6:PWM输出引脚增加RC低通滤波器

在PWM输出引脚后连接RC低通滤波器,RC低通滤波器的截止频率需要略高于目标正弦波频率。

RC电路的截止频率为 f c = 1 2 π R C f_c = \frac{1}{2\pi RC} fc=2πRC1

  • R R R为电阻值(单位:欧姆)
  • C C C为电容值(单位:法拉)

4、测试

示波器测量PWM输出引脚的输出波形。

PWM的频率为5KHz,符合预期设计,如下图所示, 正弦波的频率为50Hz,符合设计预计,如下视频所示,

B站视频链接

参考

1 CSDN博客: STM32开发板上生成PWM正弦波

2 百科: 脉冲宽度调制

3 B站: 【STM32】动画讲解轻松学会STM32的PWM

4 CSDN博客: SPWM基本原理详解(图文并茂+公式推导+C程序实现)

相关推荐
handler017 小时前
【C++】二叉搜索树详解及其模拟实现(代码)
开发语言·c++·算法·c··二叉搜索树·搜索树
爱学习的程序媛2 天前
C 语言全景指南:从底层原理到工业级实战
c++·c#·c
dozenyaoyida3 天前
RISC-V嵌入式开发:彻底解决“undefined reference to isatty“错误全攻略
经验分享·c·cmake·嵌入式开发·isatty·没有定义问题
Shadow(⊙o⊙)4 天前
模拟实现:glibc_1.0-文件操作函数fopen fclose fwrite fflush实现。
开发语言·c++·学习·c
liulilittle5 天前
TCP UCP:基于卡尔曼滤波的BBR增强型拥塞控制算法
linux·网络·c++·tcp/ip·算法·c·通讯
weixin_421725266 天前
C语言、C++与C#深度研究报告:从底层控制到现代企业级开发的演进
c语言·c++·c·内存管理·编译模型
不吃土豆的马铃薯8 天前
Spdlog 入门:日志记录器与日志槽基础详解
服务器·开发语言·c++·c·日志·spdlog
金创想9 天前
积木移动题目分析及解题思路——木块问题(1)
c++·算法·字符串·c·刷题·信息学奥赛·积木
不吃土豆的马铃薯12 天前
5.SGI STL 二级空间配置器 _S_chunk_alloc核心函数解析
开发语言·c++·vscode·c·内存池
一只小灿灿13 天前
深度详解计算机补码原理
c·补码