#define CCLK 120000000
#define PCLK 60000000
#define rFIO1DIR (*(volatile unsigned*)(0x20098020))
#define rFIO1MASK (*(volatile unsigned*)(0x20098030))
#define rFIO1PIN (*(volatile unsigned*)(0x20098034))
#define rFIO1SET (*(volatile unsigned*)(0x20098038))
#define rFIO1CLR (*(volatile unsigned*)(0x2009803c))
#define rCLKSRCSEL (*(volatile unsigned *)(0x400FC10C)) //时钟源选择寄存器
#define rPLL0CON (*(volatile unsigned *)(0x400FC080)) //PLL0控制寄存器
#define rPLL0CFG (*(volatile unsigned *)(0x400FC084)) //PLL0配置寄存器
#define rPLL0STAT (*(volatile unsigned *)(0x400FC088)) //PLL0状态寄存器
#define rPLL0FEED (*(volatile unsigned *)(0x400FC08C)) //PLL0馈送寄存器
#define rPLL1CON (*(volatile unsigned *)(0x400FC0A0))
#define rPLL1CFG (*(volatile unsigned *)(0x400FC0A4))
#define rPLL1STAT (*(volatile unsigned *)(0x400FC0A8))
#define rPLL1FEED (*(volatile unsigned *)(0x400FC0AC))
#define rCCLKSEL (*(volatile unsigned *)(0x400FC104)) //CPU时钟选择寄存器
#define rUSBCLKSEL (*(volatile unsigned *)(0x400FC108)) //USB时钟选择寄存器
#define rPCLKSEL (*(volatile unsigned *)(0x400FC1A8)) //外设时钟寄存器
#define rPCON (*(volatile unsigned *)(0x400FC0C0))
#define rPXCONP (*(volatile unsigned *)(0x400FC0C4))
#define rSCS (*(volatile unsigned *)(0x400FC1A0)) //系统控制和状态寄存器
#define rCLKOUTCFG (*(volatile unsigned *)(0x400FC1C8))
#define rIOCON_P1_02 (*(volatile unsigned *)(0x4002C088))
#define rPCONP (*(volatile unsigned *)(0x400FC0C4))
#define rPWM0IR (*(volatile unsigned *)(0x40014000))
#define rPWM0TCR (*(volatile unsigned *)(0x40014004))
#define rPWM0TC (*(volatile unsigned *)(0x40014008))
#define rPWM0PR (*(volatile unsigned *)(0x4001400C))
#define rPWM0CTCR (*(volatile unsigned *)(0x40014070))
#define rPWM0MCR (*(volatile unsigned *)(0x40014014))
#define rPWM0MR0 (*(volatile unsigned *)(0x40014018))
#define rPWM0MR1 (*(volatile unsigned *)(0x4001401C))
#define rPWM0CCR (*(volatile unsigned *)(0x40014028))
#define rPWM0PCR (*(volatile unsigned *)(0x4001404C))
#define rPWM0LER (*(volatile unsigned *)(0x40014050))
#define rISER1 (*(volatile unsigned *)(0xE000E104))
#define rCER1 (*(volatile unsigned *)(0xE000E184))
unsigned int duty = 10;
unsigned char match_cnt = 0;
void PWM0_IRQHandler(void)
{
if(rPWM0IR&0x1)
{
rFIO1PIN |= (1<<18);
match_cnt++;
rPWM0IR |= 0x1; //MR0中断复位
}
if(rPWM0IR&(0x1<<1))
{
rFIO1PIN &= ~(1<<18);
rPWM0IR |= 0x1<<1; //MR1中断复位
}
}
void SystemInit()
{
rSCS &= ~(0x1<<4); //频率12M
rSCS |= (0x1<<5); //使能主振荡器
while(0 == (rSCS & (0x1<<6)));//等待主振荡器稳定
rCLKSRCSEL = 0x1;
rPLL0CFG = 0x9; //配置CCLK = 120M
rPLL0CON = 0x01;
rPLL0FEED = 0xAA;
rPLL0FEED =0x55;
while( 0 == (rPLL0STAT & (0x1<<10)));
rCCLKSEL = (0x1 | (0x1<<8));
rPCLKSEL = 0x2; //配置PCLK = 60M
rCLKOUTCFG = 0x0 | (0xb<<4) | (0x1<<8);
}
void PWMInit()
{
rIOCON_P1_02 &= ~0x7;
rIOCON_P1_02 |= 0x3; //P1.02配置成PWM0[1]
rPCONP |= 0x1<<5; //使能PWM0外设
rPWM0IR = 0x73F; //初始化PWM相关控制寄存器
rPWM0TCR = 0;
rPWM0CTCR = 0;
rPWM0MCR = 0;
rPWM0CCR = 0;
rPWM0PCR = 0;
rPWM0LER = 0;
rPWM0PR = 0x1<<20; //每0x1<<20+1个PLCK上升沿,TC递增
rPWM0TCR |= 0x1<<1; //复位TC和PC
rPWM0TCR &= ~(0x1<<1);
rPWM0MR0 = 100;
rPWM0LER |= 0x1;
rPWM0MCR |= 0x1<<1 | 0x1; //MR0和TC匹配时复位TC和PC.并且产生中断
rPWM0MR1 = duty;
rPWM0LER |= 0x1<<1;
rPWM0MCR |= 0x1<<3; //MR1和TC匹配时产生中断
}
int main ()
{
PWMInit();
rFIO1DIR |= (0x1<<18);
rISER1 |= 0x1<<7; //PWM0中断使能
rPWM0TCR |= 0x1<<1; //复位TC和PC
rPWM0TCR &= ~(0x1<<1);
rPWM0TCR |= 0x1; //PC和TC计数使能
rPWM0TCR |= 0x1<<3; //PWM模式使能
while(1)
{
if(match_cnt >= 1)
{
match_cnt = 0;
duty = duty+10;
if(duty >= 100)
{
duty = 0;
}
rPWM0MR1 = duty;
rPWM0LER |= 0x1<<1;
rPWM0MCR |= 0x1<<3;
}
}
return 1;
}
程序在MR0匹配时复位TC,在MR1匹配时触发边沿。可以看到随着MR1匹配值的改变,LED灯的亮灭时间对应改变。(程序中的预分频寄存器PR设置为了让LED效果明显)
LPC1788的PWM可以进行双边沿的控制。如PWM0.2可以用MR0控制PWM的周期频率,用MR1和MR2控制PWM0.2的边沿。