Cortex-M3 (NXP LPC1788)之PWM
1,PWM使用公共的PCLK,因此要配置系統(tǒng)時鐘和外設時鐘。之前的文章中有具體的時鐘配置過程。
本文引用地址:http://2s4d.com/article/201611/318448.htm2,使能PWM模塊。配置外設功率配置寄存器PCONP,使能PWM0的時鐘控制位。
3,PWM0.1的輸出管腳和P1_2管腳復用,因此要配置IOCON_P1_02寄存器,將其設置成PWM0.1的輸出。
4,設置PWM的脈沖寬度,基本的原理就是比較PWM定時器計數(shù)器TC和匹配寄存器MR中的值,如果匹配我們可以通過匹配控制寄存器MCR選擇操作,如產(chǎn)生一個中斷,復位TC,停止TC和預分頻計數(shù)器PC且停止計數(shù)。匹配寄存器MR0通過在匹配是將計數(shù)器TC復位來控制PWM的周期頻率。另一個匹配寄存器控制PWM沿的位置。如PWM0.1的輸出,將使用MR0控制PWM的周期頻率,MR1控制邊沿的位置。
5,最后是對于PWM的具體控制,配置PWM預分頻寄存器PWMPR,該32位寄存器規(guī)定了PWM預分頻計數(shù)的最大值,PWM預分頻計數(shù)器寄存器PWMPC在每個PCLK上遞增一次,當PWMPC和PWMPR值相等時,PWMTC的值會遞增,而PWMPR在系一個PCLK周期被復位。這樣,當PWMPR=0時,PWMTC會在每個PCLK上遞增,而當PWMPR=1時,在每2個PCLK上遞增。匹配寄存器PWMMR中的值和PWMTC的值比較,如果相等則觸發(fā)在PWMMCR中配置的操作。當MR0和TC相等時,我們進行復位TC從新計數(shù)從而固定了PWM的周期頻率。當定時器處于PWM模式時,軟件對PWM匹配寄存器MR的寫操作,寫入值實際上被保存在一個映像寄存器中,不會被立即使用。所以在我們需要操作PWM鎖存使能寄存器PWMLER,典型序列為:將新值寫入MR,寫PWMLER中相應的位,更改的MR值將在下一次定時器復位時生效。
在下面的程序中,將給MR1中寫入不同的匹配值,來控制PWM的占空比。為了方便使用LED燈進行示意。
- #defineCCLK120000000
- #definePCLK60000000
- #definerFIO1DIR(*(volatileunsigned*)(0x20098020))
- #definerFIO1MASK(*(volatileunsigned*)(0x20098030))
- #definerFIO1PIN(*(volatileunsigned*)(0x20098034))
- #definerFIO1SET(*(volatileunsigned*)(0x20098038))
- #definerFIO1CLR(*(volatileunsigned*)(0x2009803c))
- #definerCLKSRCSEL(*(volatileunsigned*)(0x400FC10C))//時鐘源選擇寄存器
- #definerPLL0CON(*(volatileunsigned*)(0x400FC080))//PLL0控制寄存器
- #definerPLL0CFG(*(volatileunsigned*)(0x400FC084))//PLL0配置寄存器
- #definerPLL0STAT(*(volatileunsigned*)(0x400FC088))//PLL0狀態(tài)寄存器
- #definerPLL0FEED(*(volatileunsigned*)(0x400FC08C))//PLL0饋送寄存器
- #definerPLL1CON(*(volatileunsigned*)(0x400FC0A0))
- #definerPLL1CFG(*(volatileunsigned*)(0x400FC0A4))
- #definerPLL1STAT(*(volatileunsigned*)(0x400FC0A8))
- #definerPLL1FEED(*(volatileunsigned*)(0x400FC0AC))
- #definerCCLKSEL(*(volatileunsigned*)(0x400FC104))//CPU時鐘選擇寄存器
- #definerUSBCLKSEL(*(volatileunsigned*)(0x400FC108))//USB時鐘選擇寄存器
- #definerPCLKSEL(*(volatileunsigned*)(0x400FC1A8))//外設時鐘寄存器
- #definerPCON(*(volatileunsigned*)(0x400FC0C0))
- #definerPXCONP(*(volatileunsigned*)(0x400FC0C4))
- #definerSCS(*(volatileunsigned*)(0x400FC1A0))//系統(tǒng)控制和狀態(tài)寄存器
- #definerCLKOUTCFG(*(volatileunsigned*)(0x400FC1C8))
- #definerIOCON_P1_02(*(volatileunsigned*)(0x4002C088))
- #definerPCONP(*(volatileunsigned*)(0x400FC0C4))
- #definerPWM0IR(*(volatileunsigned*)(0x40014000))
- #definerPWM0TCR(*(volatileunsigned*)(0x40014004))
- #definerPWM0TC(*(volatileunsigned*)(0x40014008))
- #definerPWM0PR(*(volatileunsigned*)(0x4001400C))
- #definerPWM0CTCR(*(volatileunsigned*)(0x40014070))
- #definerPWM0MCR(*(volatileunsigned*)(0x40014014))
- #definerPWM0MR0(*(volatileunsigned*)(0x40014018))
- #definerPWM0MR1(*(volatileunsigned*)(0x4001401C))
- #definerPWM0CCR(*(volatileunsigned*)(0x40014028))
- #definerPWM0PCR(*(volatileunsigned*)(0x4001404C))
- #definerPWM0LER(*(volatileunsigned*)(0x40014050))
- #definerISER1(*(volatileunsigned*)(0xE000E104))
- #definerCER1(*(volatileunsigned*)(0xE000E184))
- unsignedintduty=10;
- unsignedcharmatch_cnt=0;
- voidPWM0_IRQHandler(void)
- {
- if(rPWM0IR&0x1)
- {
- rFIO1PIN|=(1<<18);
- match_cnt++;
- rPWM0IR|=0x1;//MR0中斷復位
- }
- if(rPWM0IR&(0x1<<1))
- {
- rFIO1PIN&=~(1<<18);
- rPWM0IR|=0x1<<1;//MR1中斷復位
- }
- }
- voidSystemInit()
- {
- rSCS&=~(0x1<<4);//頻率12M
- rSCS|=(0x1<<5);//使能主振蕩器
- while(0==(rSCS&(0x1<<6)));//等待主振蕩器穩(wěn)定
- 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);
- }
- voidPWMInit()
- {
- 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.并且產(chǎn)生中斷
- rPWM0MR1=duty;
- rPWM0LER|=0x1<<1;
- rPWM0MCR|=0x1<<3;//MR1和TC匹配時產(chǎn)生中斷
- }
- intmain()
- {
- PWMInit();
- rFIO1DIR|=(0x1<<18);
- rISER1|=0x1<<7;//PWM0中斷使能
- rPWM0TCR|=0x1<<1;//復位TC和PC
- rPWM0TCR&=~(0x1<<1);
- rPWM0TCR|=0x1;//PC和TC計數(shù)使能
- 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;
- }
- }
- return1;
- }
LPC1788的PWM可以進行雙邊沿的控制。如PWM0.2可以用MR0控制PWM的周期頻率,用MR1和MR2控制PWM0.2的邊沿。
評論