上一节里,我们了解了如何使用LPC1343内部的32位定时器来产生准确的时间间隔。本节,我们来实现32位定时器的另一个重要的功能,PWM信号的产生。
我们都知道PWM的全称是Pulse Width Modulation,即脉宽调制的意思。多用于电机控制领域,也可以用来实现DA转换。在此不需要累赘它的特点,我们直接切入主题。
user.manual.lpc13xx中对PWM的描述很简单也足够充分:
In PWM mode, three match registers can be used to provide a single-edge controlled
PWM output on the match output pins. One match register is used to control the PWM cycle length.
在定时器的PWM模式里,四个匹配寄存器中的三个可以用来提供单边沿控制的PWM信号在相应引脚输出。同时剩下的一个用来控制PWM波形的周期。
For each timer, a maximum of three-single edge controlled PWM outputs can be selected on the MATn[2:0] outputs. One additional match register determines the PWM cycle length. When a match occurs in any of the other match registers, the PWM output is set to HIGH. The timer is reset by the match register that is configured to set the PWM cycle length. When the timer is reset to zero, all currently HIGH match outputs configured as PWM outputs are cleared.
翻译一下:
每一个定时器可以产生最多三路的单边沿控制的PWM输出,可以在MATn[2:0]里选择输出引脚。另外一个寄存器用以决定PWM周期长度。当匹配事件发生在其PWM控制寄存器中,PWM输出引脚会置高电平。而当计数值和PWM周期长度寄存器匹配时,计数值复位清0,同时PWM输出引脚清零。
此外还需要看到一个寄存器:
上图中唯一的一个Note:
It is recommended to use match channel 3 to set the PWM cycle
意为:推荐使用第三个匹配通道设置PWM的周期。
如此,整体思路就有了:
在MATCH3寄存器设置PWM周期,同时在另外三个寄存器MAT0,1,2设置占空比。当计数值与MAT0,1,2中的数值匹配时,PWM输出引脚输出高电平;当计数值与MATCH3寄存器中的值匹配时,PWM引脚清零。所以PWM的高电平周期是VALUE[MAT0,1,2]-VALUE[MAT3],低电平周期就是0- VALUE[MAT0,1,2]。
我们来看了PWM带的PWM范例:
int main (void)
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);//打开IO时钟
init_timer32PWM(1, period, MATCH0); //设置32位定时器为PWM模式,定义周期,输出通道
enable_timer32(1);//使能32位定时器1
setMatch_timer32PWM (1, 0, period/4);//设置占空比
while (1)
{
}
}
PS:在此做了不小的删改,原本NXP带的例程里,前面做的许多的定时器设置之后,下面居然匪夷所思地来了个模拟PWM。
此程序里,首先是打开AHB中对于GPIO的时钟,这个前面章节提到多次了。
看看32位定时器PWM输出初始化程序:
void init_timer32PWM(uint8_t timer_num, uint32_t period, uint8_t match_enable)
{
disable_timer32(timer_num);//首先要使能定时器,才能对定时器进行设置
if (timer_num == 1)
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<10);//打开定时器时钟
LPC_TMR32B1->EMR = (1<<EMC3)|(1<<EMC2)|(2<<EMC1)
|(1<<EMC0)|(1<<3)|(match_enable);//使能各个匹配寄存器
/*以下四个if函数的作用是切换各个MATCH通道对于的输出IO到普通输出IO状态,因为LPC1343的JTAG接口与32位定时器1的匹配IO存在复用情况,而默认情况下这些IO行使JTAG的IO功能,所以必须切换*/
if (match_enable & 0x01)
{
LPC_IOCON->JTAG_TDO_PIO1_1 &= ~0x07;
LPC_IOCON->JTAG_TDO_PIO1_1 |= 0x03;
}
if (match_enable & 0x02)
{
LPC_IOCON->JTAG_nTRST_PIO1_2 &= ~0x07;
LPC_IOCON->JTAG_nTRST_PIO1_2 |= 0x03;
}
if (match_enable & 0x04)
{
LPC_IOCON->ARM_SWDIO_PIO1_3&= ~0x07;
LPC_IOCON->ARM_SWDIO_PIO1_3|= 0x03;
}
if (match_enable & 0x08)
{
LPC_IOCON->PIO1_4&= ~0x07;
LPC_IOCON->PIO1_4|= 0x02;
}
LPC_TMR32B1->PWMC = (1<<3)|(match_enable);//使用匹配寄存器MATCH3设置PWM周//期,与用户手册推荐的一致
timer32_1_period = period;
LPC_TMR32B1->MR3 = timer32_1_period; //写入周期
LPC_TMR32B1->MR0 = timer32_1_period/2;//设置MATCH0通道占空比为50%
LPC_TMR32B1->MR1 = timer32_1_period/2; //设置MATCH1通道占空比为50%
LPC_TMR32B1->MR2 = timer32_1_period/2; //设置MATCH2通道占空比为50%
LPC_TMR32B1->MCR = 1<<10;//允许当计数值和MAT3寄存器值匹配时请0计数值
}
else
{
/*以下是对定时器0的设置,与上半段程序类同*/
} |