在上一篇文章中,我们了解了有关使用STM32进行ADC转换的信息。在本教程中,我们将学习STM32中的PWM(脉冲宽度调制),以及如何使用PWM技术控制LED的亮度或DC风扇的速度。
我们知道信号有两种类型:模拟和数字。模拟信号的电压为(3V,1V等),数字信号的电压为(1'和0')。传感器的输出为模拟信号,并且由于微控制器仅了解数字,因此使用ADC将这些模拟信号转换为数字。处理完这些ADC值之后,再次需要将输出转换为模拟形式以驱动模拟设备。为此,我们使用某些方法,例如PWM,数模(DAC)转换器等。
什么是PWM(带调制脉冲)?
PWM是一种使用数字值控制模拟设备的方法,例如控制电动机的速度,LED的亮度等。我们知道电动机和LED都可处理模拟信号。但是PWM不提供纯模拟输出,PWM看起来像是由短脉冲产生的模拟信号,由占空比提供。
PWM的占空比
PWM信号保持高电平(导通时间)的时间百分比称为占空比。如果信号始终为ON,则占空比为100%;如果信号始终为OFF,则占空比为0%。
占空比=打开时间/(打开时间+关闭时间)
STM32中的PWM
STM32F103C8具有15个PWM引脚和10个ADC引脚。有7个定时器,每个PWM输出由连接到4个定时器的通道提供。它具有16位PWM分辨率(2 16),即计数器和变量可以高达65535。在72MHz时钟速率下,PWM输出的最大周期约为1毫秒。
- 因此65535的值可提供LED的全亮度和DC风扇的全速(100%占空比)
- 同样,值32767可提供LED的一半亮度和DC风扇的一半速度(占空比为50%)
- 值13107可提供(20%)亮度和(20%)速度(20%占空比)
在本教程中,我们将使用电位计和STM32通过PWM技术改变LED的亮度和直流风扇的速度。16x2 LCD用于显示ADC值(0-4095)和输出的修改变量(PWM值)(0-65535)。
以下是其他微控制器的一些PWM示例:
- 使用带有MPLAB和XC8的PIC单片机生成PWM
- Raspberry Pi伺服电机控制
- 使用PWM的基于Arduino的LED调光器
- 使用MSP430G2的脉冲宽度调制(PWM)
在此处检查所有与PWM相关的项目。
所需组件
- STM32F103C8
- 直流风扇
- ULN2003电机驱动器IC
- LED(红色)
- 液晶屏(16x2)
- 电位器
- 面包板
- 电池9V
- 跳线
直流风扇:这里使用的直流风扇是旧PC上的BLDC风扇。它需要外部电源,因此我们使用的是9V直流电池。
ULN2003电动机驱动器IC:由于电动机是单向的,因此也用于向一个方向驱动电动机,并且风扇需要外部电源。在此处了解有关基于ULN2003的电机驱动器电路的更多信息。下面是ULN2003的图片图:
引脚(IN1至IN7)为输入引脚,引脚(OUT 1至OUT 7)为对应的输出引脚。为COM提供输出设备所需的正电源电压。
LED:使用红色的led发出红色光。可以使用任何颜色。
电位器:使用两个电位器,一个用于分压器,用于ADC的模拟输入,另一个用于控制led的亮度。
STM32的引脚详细信息
如我们所见,PWM引脚以波形格式(〜)表示,共有15个此类引脚,ADC引脚以绿色表示,那里有10个ADC引脚用于模拟输入。
电路图和连接
STM32与各种组件的连接说明如下:
带有模拟输入(ADC)的STM32
电路左侧的电位计用作稳压器,可调节来自3.3V引脚的电压。电位计的输出,即电位计的中心引脚连接到STM32的ADC引脚(PA4)。
带LED的STM32
STM32 PWM输出引脚(PA9)通过串联电阻和电容器连接到LED的正极。
带电阻和电容的LED
串联的电阻器和并联的电容器与LED相连,可从PWM输出生成正确的模拟波,因为模拟输出并非直接由PWM引脚生成时纯。
带有ULN2003的STM32和带有风扇的ULN2003
STM32 PWM输出引脚(PA8)连接到ULN2003 IC的输入引脚(IN1),而ULN2003的相应输出引脚(OUT1)连接到DC FAN的负极线。
DC风扇的正极连接到ULN2003 IC的COM引脚,外部电池(9V DC)也连接到ULN2003 IC的同一COM引脚。ULN2003的GND引脚连接到STM32的GND引脚,而电池负极连接到同一GND引脚。
带有LCD的STM32(16x2)
LCD引脚号 |
LCD引脚名称 |
STM32引脚名称 |
1个 |
地面(地) |
地线(G) |
2 |
VCC |
5伏 |
3 |
VEE |
电位器中心引脚 |
4 |
寄存器选择(RS) |
PB11 |
5 |
读/写(RW) |
地线(G) |
6 |
启用(EN) |
PB10 |
7 |
数据位0(DB0) |
无连接(NC) |
8 |
数据位1(DB1) |
无连接(NC) |
9 |
数据位2(DB2) |
无连接(NC) |
10 |
数据位3(DB3) |
无连接(NC) |
11 |
数据位4(DB4) |
PB0 |
12 |
数据位5(DB5) |
PB1 |
13 |
数据位6(DB6) |
PC13 |
14 |
数据位7(DB7) |
PC14 |
15 |
LED正极 |
5伏 |
16 |
LED负极 |
地线(G) |
右侧的电位器用于控制LCD显示屏的对比度。上表显示了LCD和STM32之间的连接。
编程STM32
像上一教程一样,我们通过Arduino IDE通过USB端口对STM32F103C8进行了编程,而无需使用FTDI编程器。要了解使用Arduino IDE编程STM32的信息,请点击链接。我们可以像在Arduino中一样进行编程。最后给出了完整的代码。
在此编码中,我们将从ADC引脚(PA4)取得输入模拟值,该引脚连接至左电位计的中心引脚,然后将模拟值(0-3.3V)转换为数字或整数格式(0-4095)。此数字值还作为PWM输出提供,以控制LED亮度和DC风扇速度。16x2 LCD用于显示ADC和映射值(PWM输出值)。
首先,我们需要包含LCD头文件,声明LCD引脚并使用以下代码对其进行初始化。在此处了解有关将LCD与STM32接口的更多信息。
#包括
接下来声明并使用STM32的引脚定义引脚名称
const int模拟输入= PA4; //来自电位计的输入 const int led = PA9; // LED输出 const int fan = PA8; //风扇输出
现在在 setup() 内部,我们需要显示一些消息并在几秒钟后清除它们,并指定INPUT引脚和PWM输出引脚
lcd.begin(16,2); //准备好LCD lcd.clear(); //清除LCD lcd.setCursor(0,0); //将光标置于第0行和第0列 lcd.print(“ CIRCUIT DIGEST”); //显示电路摘要 lcd.setCursor(0,1); //在第0列和第1行设置游标 lcd.print(“ PWM USING STM32”); //使用STM32 delay(2000) 显示PWM ; //延迟时间lcd.clear(); //清除LCD pinMode(analoginput,INPUT); //将引脚模式模拟输入设置为INPUT pinMode(led,PWM); //将引脚模式led设置为PWM输出 pinMode(fan,PWM); //将引脚模式风扇设置为PWM输出
模拟输入引脚(PA4)通过 pinMode(模拟输入,INPUT) 设置为INPUT , LED引脚通过 pinMode(led,PWM) 设置为PWM输出,风扇引脚通过 pinMode(fan,PWM) 设置为PWM输出。这里的PWM输出引脚连接到LED(PA9)和风扇(PA8)。
接下来在 void loop() 函数中,我们从ADC引脚(PA4)读取模拟信号,并将其存储在一个整数变量中,该变量通过使用以下代码 int value 将模拟电压转换为数字整数值(0-4095) adc = AnalogRead(analoginput) );
这里要注意的重要一点是PWM引脚,因为STM32的通道具有16位分辨率(0-65535),因此我们需要使用如下所示的映射函数将其与模拟值映射
int结果= map(valueadc,0,4095,0,65535)。
如果不使用映射,则通过改变电位计将无法获得风扇的全速或LED的全亮度。
然后,我们使用 pwmWrite(led,result) 将PWM输出写入LED, 并使用 pwmWrite(fan,result )函数将PWM输出写入风扇。
最后,我们使用以下命令在LCD显示屏上显示模拟输入值(ADC值)和输出值(PWM值)
lcd.setCursor(0,0); //将光标设置在第0行和第0列 lcd.print(“ ADC value =”); //打印单词“” lcd.print(valueadc); //显示valueadc lcd.setCursor(0,1); //在第0列和第1行设置游标 lcd.print(“ Output =”); //打印“” lcd.print(result);中的单词 //显示值结果
完整的代码和演示视频如下。