- PWM(脉冲宽度调制)
- ARM7-LPC2148中的PWM引脚
- ARM7-LPC2148中的PWM寄存器
- 所需组件
- 电路图和连接
- 编程用于PWM的ARM7-LPC2148
- 对LPC2148进行PWM和ADC编程的步骤
众所周知,微控制器从模拟传感器获取模拟输入,并使用ADC(模数转换器)处理这些信号。但是,如果微控制器想要产生一个模拟信号来控制诸如伺服电机,直流电机等模拟操作设备怎么办?微控制器不会产生1V,5V的输出电压,而是使用称为PWM的技术来操作模拟设备。PWM的一个示例是笔记本电脑的冷却风扇(DC电动机),它需要根据温度进行速度控制,并且通过在主板上使用脉宽调制(PWM)技术来实现。
在本教程中,我们将使用ARM7-LPC2148微控制器中的PWM控制LED的亮度。
PWM(脉冲宽度调制)
PWM是一种使用数字值控制模拟设备的好方法,例如控制电动机的速度,LED的亮度等。虽然PWM不能提供纯模拟输出,但它会产生不错的模拟脉冲来控制模拟设备。PWM实际上是对矩形脉搏波的宽度进行调制,以便获得所产生波的平均值的变化。
PWM的占空比
PWM信号保持高电平(导通时间)的时间百分比称为占空比。如果信号始终为ON,则占空比为100%;如果信号始终为OFF,则占空比为0%。
占空比=打开时间/(打开时间+关闭时间)
ARM7-LPC2148中的PWM引脚
下图显示了ARM7-LPC2148的PWM输出引脚。共有6个PWM引脚。
PWM通道 |
LPC2148端口引脚 |
PWM1 |
P0.0 |
PWM2 |
P0.7 |
PWM3 |
P0.1 |
PWM4 |
P0.8 |
PWM5 |
P0.21 |
PWM6 |
P0.9 |
ARM7-LPC2148中的PWM寄存器
在进入我们的项目之前,我们需要了解LPC2148中的PWM寄存器。
这是LPC2148中用于PWM的寄存器列表
1. PWMPR:PWM预分频寄存器
使用:这是一个32位寄存器。它包含PCLK在递增PWM计时器计数器之前必须循环的次数(负1)(它实际上保留了预分频计数器的最大值)。
2. PWMPC: PWM预分频器计数器
使用:它是一个32位寄存器。它包含递增计数器值。当此值等于PR值加1时,PWM定时器计数器(TC)递增。
3. PWMTCR:PWM定时器控制寄存器
使用:它包含计数器使能,计数器复位和PWM使能控制位。它是一个8位寄存器。
7:4 |
3 |
2 |
1个 |
0 |
已预留 |
PWM使能 |
已预留 |
计数器重置 |
启用计数器 |
- PWM使能:(位3)
0-禁止
PWM 1-允许PWM
- 计数器使能:(位-0)
0-禁用计数器
1-启用计数器
- 计数器复位:(位1)
0-不执行任何操作。
1-在PCLK的上升沿复位PWMTC和PWMPC。
4. PWMTC:PWM计时器计数器
使用:这是一个32位寄存器。它包含递增的PWM定时器的当前值。当预分频器计数器(PC)达到预分频器寄存器(PR)值加1时,该计数器将递增。
5. PWMIR: PWM中断寄存器
使用:这是一个16位寄存器。它包含PWM匹配通道0-6的中断标志。当该通道发生中断(MRx中断)时,将设置一个中断标志,其中X是通道号(0至6)。
6. PWMMR0-PWMMR6: PWM匹配寄存器
使用:这是一个32位寄存器。 实际上,匹配通道组允许设置6个单边沿控制或3个双边沿控制PWM输出。您可以修改七个匹配通道,以配置这些PWM输出以适合您在PWMPCR中的要求。
7. PWMMCR:PWM匹配控制寄存器
使用:这是一个32位寄存器。它包含控制所选匹配通道的中断,复位和停止位。PWM匹配寄存器和PWM定时器计数器之间发生匹配。
31:21 |
20 |
19 |
18岁 |
.. |
5 |
4 |
3 |
2 |
1个 |
0 |
已预留 |
PWMMR6S |
PWMMR6R |
PWMMR6I |
.. |
PWMMR1S |
PWMMR1R |
PWMMR11 |
PWMMR0S |
PWMMR0R |
PWMMR01 |
这里x从0到6
- PWMMRxI(位0)
启用或禁用PWM中断
0-禁用PWM匹配中断。
1-启用PWM匹配中断。
- PWMMRxR:(位1)
RESET PWMTC-定时器计数器值只要与PWMRx匹配
0-什么都不做。
1-复位PWMTC。
- PWMMRxS:(位2)
当PWMTC达到匹配寄存器值 时停止PWMTC和PWMPC
0-禁用PWM停止功能。
1-启用PWM停止功能。
8. PWMPCR:PWM控制寄存器
使用:这是一个16位寄存器。它包含使能PWM输出0-6并为每个输出选择单边沿或双边沿控制的位。
31:15 |
14:9 |
8:7 |
6:2 |
1:0 |
没用过 |
PWMENA6-PWMENA1 |
没用过 |
PWMSEL6-PWMSEL2 |
没用过 |
- PWMSELx(x:2至6)
- PWMx的单边模式
- 1- PWMx的双沿模式。
- PWMENAx(x:1至6)
- PWMx禁用。
- 1- PWMx使能。
9. PWMLER: PWM锁存使能寄存器
使用:这是一个8位寄存器。它包含每个匹配通道的Match x Latch位。
31:7 |
6 |
5 |
4 |
3 |
2 |
1个 |
0 |
没用过 |
LEN6 |
LEN5 |
LEN4 |
LEN3 |
LEN2 |
LEN1 |
LEN0 |
LENx(x:0到6):
0-禁止加载新的匹配值
1-当定时器复位时,从(PWMMRx)PWMMatch寄存器加载新的匹配值。
现在开始构建硬件设置,以演示ARM微控制器中的脉冲宽度调制。
所需组件
硬件
- ARM7-LPC2148微控制器
- 3.3V稳压器IC
- 10k电位器
- LED(任何颜色)
- LCD(16x2)显示模块
- 面包板
- 连接线
软件
- Keil uVision5
- Flash魔术工具
电路图和连接
LCD和ARM7-LPC2148之间的连接
ARM7-LPC2148 |
液晶屏(16x2) |
P0.4 |
RS(寄存器选择) |
P0.6 |
E(启用) |
P0.12 |
D4(数据引脚4) |
P0.13 |
D5(数据引脚5) |
P0.14 |
D6(数据引脚6) |
P0.15 |
D7(数据引脚7) |
地线 |
VSS,R / W,K |
+5伏 |
VDD,A |
LED与ARM7-LPC2148之间的连接
LED的ANODE连接到LPC2148的PWM输出(P0.0),而LED的CATHODE引脚连接到LPC2148的GND引脚。
带3.3V稳压器的ARM7-LPC2148和电位计之间的连接
3.3V稳压器IC |
引脚功能 |
ARM-7 LPC2148引脚 |
1.左销 |
-来自GND的Ve |
GND引脚 |
2.中心销 |
稳压+ 3.3V输出 |
至电位计输入和电位计的输出至LPC2148的P0.28 |
3.右销 |
+ Ve从5V 输入 |
+5伏 |
注意事项
1.这里使用3.3V的稳压器为LPC2148的ADC引脚(P0.28)提供模拟输入值,由于我们使用的是5V电源,因此需要使用3.3V的稳压器来调节电压。
2.电位计用于在(0V至3.3V)之间变化电压,以向LPC2148引脚P0.28提供模拟输入(ADC)
编程用于PWM的ARM7-LPC2148
要编程ARM7-LPC2148,我们需要keil uVision和Flash Magic工具。我们正在使用USB电缆通过微型USB端口对ARM7 Stick进行编程。我们使用Keil编写代码并创建一个十六进制文件,然后使用Flash Magic将HEX文件闪存到ARM7 Stick。要了解有关安装keil uVision和Flash Magic以及如何使用它们的更多信息,请单击链接ARM7 LPC2148微控制器入门并使用Keil uVision对其进行编程。
在本教程中,我们将使用ADC和PWM技术来控制LED的亮度。在这里,通过ADC输入引脚P0.28给LPC2148提供模拟输入(0至3.3V),然后将该模拟输入转换为数字值(0至1023)。然后,由于LPC2148的PWM输出仅具有8位分辨率(2 8),因此该值再次转换为数字值(0-255 )。LED连接到PWM引脚P0.0,并且可以使用电位计控制LED的亮度。要了解有关ARM7-LPC2148中ADC的更多信息,请单击链接。
对LPC2148进行PWM和ADC编程的步骤
步骤1:第一步是配置PLL以产生时钟,因为它根据程序员的需要设置LPC2148的系统时钟和外设时钟。LPC2148的最大时钟频率为60Mhz。以下几行用于配置PLL时钟生成。
void initilizePLL (void)//使用PLL生成时钟的功能 { PLL0CON = 0x01; PLL0CFG = 0x24; PLL0FEED = 0xAA; PLL0FEED = 0x55; while(!(PLL0STAT&0x00000400)); PLL0CON = 0x03; PLL0FEED = 0xAA; PLL0FEED = 0x55; VPBDIV = 0x01; }
步骤2:-下一步是使用PINSEL寄存器选择LPC2148的PWM引脚和PWM功能。我们将PINSEL0用作LPC2148的PWM输出的P0.0。
PINSEL0 = 0x00000002; //设置引脚P0.0为PWM输出
步骤3:-接下来,我们需要使用PWMTCR(定时器控制寄存器)将定时器复位。
PWMTCR =(1 << 1); //设置PWM定时器控制寄存器为计数器复位
然后,设置决定PWM分辨率的预分频值。我将其设置为零
PWMPR = 0X00; //设置PWM预分频值
步骤4:-接下来,我们需要设置PWMMCR(PWM匹配控制寄存器),因为它可以设置复位,PWMMR0中断等操作。
PWMMCR =(1 << 0)-(1 << 1); //设置PWM匹配控制寄存器
步骤5:-使用PWMMR设置PWM通道的最大周期。
PWMMR0 = PWM值; //给出PWM值的最大值
在我们的示例中,最大值为255(用于最大亮度)
步骤6:-接下来,我们需要使用PWMLER将锁存使能设置为相应的匹配寄存器
PWMLER =(1 << 0); //启用PWM锁存器
(我们使用PWMMR0),因此通过在PWMLER中设置1来启用相应的位
步骤7:-要使能PWM输出到引脚,我们需要使用PWMTCR来使能PWM定时器计数器和PWM模式。
PWMTCR =(1 << 0)-(1 << 3); //启用PWM和PWM计数器
步骤8:-现在我们需要从ADC引脚P0.28获取用于设置PWM占空比的电位器值。因此,我们在LPC2148中使用ADC模块将电位计的模拟输入(0至3.3V)转换为ADC值(0至1023)。
在这里,我们将其值从0-1023转换为0-255,方法是将其除以4,因为LPC2148的PWM具有8位分辨率(2 8)。
步骤9:-为了选择LPC2148中的ADC引脚P0.28,我们使用
PINSEL1 = 0x01000000; //将P0.28设置为ADC INPUT AD0CR =((((14)<< 8)-(1 << 21)); //设置时钟和PDN以进行A / D转换
以下各行捕获模拟输入(0至3.3V)并将其转换为数字值(0至1023)。然后将此数字值除以4,将其转换为(0到255),最后作为PWM输出馈入连接LED的LPC2148的P0.0引脚。
AD0CR-=(1 << 1); //在ADC寄存器 delaytime(10)中 选择AD0.1通道 AD0CR-=(1 << 24); //开始A / D转换 while((AD0DR1&(1 << 31))== 0); //检查ADC数据寄存器中的DONE位 adcvalue =(AD0DR1 >> 6)&0x3ff; //从ADC数据寄存器的 dutycycle = adcvalue / 4中 获取结果 //获得(0到255)占空比值的公式:PWMMR1 =占空比;//将占空比值设置为PWM匹配寄存器 PWMLER-=(1 << 1); //启用占空比值的PWM输出
步骤10:-接下来,我们在LCD(16X2)显示模块中显示这些值。所以我们添加以下几行来初始化LCD显示模块
无效LCD_INITILIZE(void)//准备LCD的功能 { IO0DIR = 0x0000FFF0; //设置引脚P0.12,P0.13,P0.14,P0.15,P0.4,P0.6为OUTPUT delaytime(20); LCD_SEND(0x02); //以4位工作模式初始化LCD LCD_SEND(0x28); // 2行(16X2) LCD_SEND(0x0C); //在光标旁边显示 LCD_SEND(0x06); //自动递增光标 LCD_SEND(0x01); //显示清晰的 LCD_SEND(0x80); //第一行第一位置 }
当我们将4位模式的LCD与LPC2148连接在一起时,我们需要发送值以逐位显示(上半字节和下半字节)。因此,使用以下几行。
void LCD_DISPLAY(char * msg)//打印一一发送的字符的功能 { uint8_t i = 0; while(msg!= 0) { IO0PIN =((IO0PIN&0xFFFF00FF)-(((msg&0xF0)<< 8));; //发送高位半字节 IO0SET = 0x00000050; // RS HIGH&ENABLE HIGH以打印数据 IO0CLR = 0x00000020; // RW LOW写模式 delaytime(2); IO0CLR = 0x00000040; // EN = 0,RS和RW不变(即RS = 1,RW = 0) delaytime(5); IO0PIN =((IO0PIN和0xFFFF00FF)-((msg&0x0F)<< 12)); //发送低位半字节 IO0SET = 0x00000050; // RS&EN HIGH IO0CLR = 0x00000020; delaytime(2); IO0CLR = 0x00000040; delaytime(5); i ++; } }
为了显示这些ADC和PWM值,我们在 int main() 函数中使用了以下几行。
LCD_SEND(0x80); sprintf(displayadc,“ adcvalue =%f”,adcvalue); LCD_DISPLAY(displayadc); //显示ADC值(0至1023) LCD_SEND(0xC0); sprintf(ledoutput,“ PWM OP =%。2f”,亮度); LCD_DISPLAY(LED输出); //显示占空比值(0到255)
该教程的完整代码和视频描述如下。