在线时间7262 小时
UID3426478
注册时间2017-9-25
NXP金币5370
TA的每日心情 | 慵懒 昨天 10:39 |
---|
签到天数: 1873 天 连续签到: 4 天 [LV.Master]伴坛终老
超级版主
 
- 积分
- 112711
- 最后登录
- 2025-8-30
|
本帖最后由 stm1024 于 2021-9-11 11:59 编辑
PWM这个没啥好多说的,在MCU的视角看,其实就是定时器+IO翻转,连51这种入门级的单片机都可以实现,当然这种方式就像软件模拟I2C或者SPI协议一样,自己还要操心时序,而真正的硬件级的PWM,只需要你配置好之后,就可以不用再去查询或者去中断实现IO翻转,能够自动输出PWM,能节省CPU的资源。LPC11U68中使用了EMR和PWMC实现PWM波。
- #include "cmsis.h"
- #include "core_cm0plus.h"
- #include "board.h"
- int main()
- {
- //for led
- LPC_SYSCTL->SYSAHBCLKCTRL|=1<<6;//GPIO clock
- LPC_GPIO->DIR[2]|= 1<<17;//P2.17 output
-
- //config gpio for pwm,see user manual
- LPC_GPIO->DIR[0]|= 1<<8;
- LPC_IOCON->PIO0[8]=IOCON_FUNC2;//P0.8 as CT16B0_MAT0
-
- //for CT16B0
- LPC_SYSCTL->SYSAHBCLKCTRL|=1<<7;//CT16B0 clock
- LPC_TIMER16_0->IR=1;//reset channel 0 interrupt
- LPC_TIMER16_0->PR=1000-1;
- LPC_TIMER16_0->MR[0]=12000;
- LPC_TIMER16_0->MR[1]=48000;
- LPC_TIMER16_0->MCR=17;//allow MR0 generate interrupt,MR1 will clear TC
- LPC_TIMER16_0->TCR=1;//enable TC & PC
-
- //PWM
- LPC_TIMER16_0->EMR=(3<<4);//toggle
- LPC_TIMER16_0->PWMC=1;//enable pwm
- //interrupt enable
- NVIC_ClearPendingIRQ(TIMER_16_0_IRQn);
- NVIC_EnableIRQ(TIMER_16_0_IRQn);
- while(1)
- {
- }
- }
- void TIMER16_0_IRQHandler(void)
- {
- if(1==LPC_TIMER16_0->IR)//Match Pending for ch0
- {
- LPC_TIMER16_0->IR=1;//reset channel 0 interrupt
- LPC_GPIO->NOT[2]=(1<<17);//toggle red led
- }
- }
复制代码 同样,和模拟实现可以选择任何针脚的方式不同,PWM需要接特定的针脚:
通过MR1和PR确定PWM的周期,其中MR1配置为让TC清零,这样周期就是SYSCLK/(1000*48000)=1Hz,刚好是1秒1次。通过MR0确定占空比,由于TC<EM<MR0的时候输出低电平,MR0<EM<MR1时输出高电平,因此,这个占空比是(MR1-MR0)/MR1=(48000-12000)/48000=75%。
编译,下载,上逻辑分析仪:
通道1接P2.17,也就是红色LED的针脚,应该是1秒翻转1次,通道2接P0.8,就是PWM输出端口。抓波:
周期、占空比都符合预期。注意看LED针脚的电平翻转,都是在PWM波的上升沿,因为这个位置就是MR0的值。
PS:感觉这个版块好冷清啊~
|
|