新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ARM 學(xué)習(xí)筆記七 (PWM試驗(yàn))

        ARM 學(xué)習(xí)筆記七 (PWM試驗(yàn))

        作者: 時(shí)間:2016-11-20 來源:網(wǎng)絡(luò) 收藏
        PWM-脈寬調(diào)制。我的理解是通過控制一個(gè)計(jì)數(shù)器來實(shí)現(xiàn)不同脈寬的輸出,從而驅(qū)動(dòng)蜂鳴器發(fā)出不同的聲音。

        本實(shí)驗(yàn)用到的寄存器如下:

        本文引用地址:http://www.104case.com/article/201611/318883.htm

        GPBCON -- I/O端口配置寄存器 B
        00=Input 01=Output 10=PWM 11=Reserved

        GPBDAT -- I/O端口數(shù)據(jù)寄存器 B

        GPFUP --I/O端口上拉電阻使能寄存器 B
        0=Enable 1=Disabled

        TCFG0 -- 時(shí)鐘配置寄存器0 (主要是設(shè)置預(yù)分頻)
        定時(shí)器輸入時(shí)鐘頻率=PCLK/{預(yù)分頻}/{分割值}
        {預(yù)分頻}=1~255
        {分割值}=2,4,8,16,32
        Address: 0x51000000
        Reset value:0x00000000
        [7:0]:These 8 bits determine prescaler value for Timer0 and 1

        TCFG1 --時(shí)鐘配置寄存器1(主要是設(shè)置分割值)
        Address: 0x51000004
        Reset value:0x00000000
        [3:0]:Select MUX input for PWM Timer0
        0000=1/2 0001=1/4 0010=1/8
        0011=1/16 01XX=External TCLK0

        TCON -- 時(shí)鐘控制寄存器
        Address:0x51000008
        Reset value:0x00000000
        [0]: Determine start/stop for Timer0 (設(shè)置啟動(dòng)/停止)
        0=Stop 1=Start for Timer0
        [1]: Determine the manual update for Timer0 (設(shè)置允許手動(dòng)修改計(jì)數(shù))
        0=No operation 1=Update TCNTB0 & TCMPB0
        [2]: Determine the output inverter on/off for Timer0 (設(shè)置中斷)
        0=Inverter off 1=Inverter on for TOUT0
        [3]: Determine auto reload on/off for timer0
        0=One-shot 1=Interval mode(auto reload)
        [4]: Determine the dead zone operation
        0=Disable 1=Enable


        TCNTB0 -- timer0計(jì)數(shù)緩存寄存器
        Address:0x5100000c
        Reset value:0x00000000
        [15:0]:Set count buffer value for Timer0

        TCMPB0 -- timer0比較緩存寄存器
        Address:0x51000010
        Reset value:0x00000000
        [15:0]:Set compare buffer value for Timer0

        實(shí)驗(yàn)方法:
        1.按下k1鍵,使TOUT0遞增占空比

        2.按下k2鍵,使TOUT0遞減占空比

        3.按下k3鍵,停止輸出

        //代碼1---參考阿南的例子,這個(gè)簡單

        #include "2410addr.h"


        #define KEY1 (1<<1) // rGPF[1] =1 ;
        #define KEY2 (1<<4) // rGPF[4] =1 ;
        #define KEY3 (1<<2) // rGPF[2] =1 ;

        unsigned short freq =0;

        //===========================[ SYSTEM ]===================================================
        //static int delayLoopCount = 400;
        static int delayLoopCount = FCLK/10000/10;

        void Delay(int time)
        {
        // time=0: adjust the Delay function by WatchDog timer.
        // time>0: the number of loop time
        // resolution of time is 100us.
        int i,adjust=0;
        if(time==0)
        {
        time = 200;
        adjust = 1;
        delayLoopCount = 400;
        //PCLK/1M,Watch-dog disable,1/64,interrupt disable,reset disable
        rWTCON = ((PCLK/1000000-1)<<8)|(2<<3);
        rWTDAT = 0xffff; //for first update
        rWTCNT = 0xffff; //resolution=64us @any PCLK
        rWTCON = ((PCLK/1000000-1)<<8)|(2<<3)|(1<<5); //Watch-dog timer start
        }
        for(;time>0;time--)
        for(i=0;i if(adjust==1)
        {
        rWTCON = ((PCLK/1000000-1)<<8)|(2<<3); //Watch-dog timer stop
        i = 0xffff - rWTCNT; //1count->64us, 200*400 cycle runtime = 64*i us
        delayLoopCount = 8000000/(i*64); //200*400:64*i=1*x:100 -> x=80000*100/(64*i)
        }
        }

        void PWM_Ini(unsigned short cycle,unsigned short duty){

        if(duty > cycle) duty = cycle;

        //定時(shí)器輸入時(shí)鐘頻率=PCLK/{預(yù)分頻}/{分割值}
        rTCFG0 =0x64; //設(shè)置預(yù)分頻為100
        rTCFG1 =0x0;//設(shè)置分割值為1/2

        rTCNTB0 =cycle;
        rTCMPB0 =duty;


        rTCON = 0x0A;//disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, stop timer 0
        //000 01010
        rTCON = 0x09;//disable deadzone, auto-reload, inv-off, no operation, start timer 0
        //1001
        }

        void PWM_Stop(){
        freq = 2000;
        rGPBCON = 0x0;
        rGPBDAT = 0x0;
        }

        void PWM_Output(int number){

        if ( number > 0 ){
        if ( freq < 255 )
        freq += 16;
        else
        freq = 0;
        }

        if ( number < 0 ){
        if ( freq >= 16 )
        freq -= 16;
        else
        freq = 0;
        }

        rTCMPB0=freq;
        }

        void Main(void){

        rGPFUP = 0xf800;// KEY [7:0] => PU En
        rGPFCON=0xfcc0; //KEY[7:0] => INPUT;

        rGPBCON = 0x0;
        rGPBCON = 0x02;//TOUT0為輸出端口

        PWM_Ini(255,freq);

        Delay(0);

        while (1){

        if ( !(rGPFDAT & KEY1) ){
        Delay(1000);
        //if (rGPGDAT & KEY1) continue;
        PWM_Output(1);
        }

        if ( !(rGPFDAT & KEY2) ){
        Delay(1000);
        //if (rGPGDAT & KEY2) continue;
        PWM_Output(-1);
        }

        if ( !(rGPFDAT & KEY3) ){
        Delay(1000);
        //if (rGPGDAT & KEY3) continue;
        PWM_Stop();
        }

        }
        }

        上面的例子就是按鍵去抖功能沒能調(diào)試出來。

        //代碼2---參考開發(fā)板帶的例子,這個(gè)不好理解

        #define GLOBAL_CLK 1

        #include "def.h"
        #include "2440addr.h"
        #include "option.h"


        #define KEY1 (1<<1) // rGPF[1] =1 ;
        #define KEY2 (1<<4) // rGPF[4] =1 ;
        #define KEY3 (1<<2) // rGPF[2] =1 ;


        static unsigned int freq;

        void PWM_Ini(){

        ChangeClockDivider(3,1); //獲得PCLK=67.5MHz
        ChangeMPllValue(127,2,1);

        rGPFUP = 0xf800;// KEY [7:0] => PU En
        rGPFCON=0xfcc0; //KEY[7:0] => INPUT;
        }

        void PWM_Stop(){
        freq = 2000;
        rGPBCON = 0x0;
        rGPBDAT = 0x0;
        }

        void PWM_Output(int number){

        rGPBCON = 0x0;
        rGPBCON = 0x02;//TOUT0為輸出端口
        //rGPBUP = 0x01;//禁止上拉電阻

        //定時(shí)器輸入時(shí)鐘頻率=PCLK/{預(yù)分頻}/{分割值}
        rTCFG0 =0x64; //設(shè)置預(yù)分頻為100
        rTCFG1 =0x0;//設(shè)置分割值為1/2


        if ( number > 0 ){
        if ( freq < 20000 )
        freq += number;
        else
        freq = 2000;
        }

        if ( number < 0 ){
        if ( freq > 300 )
        freq -= number;
        else
        freq = 2000;
        }


        rTCNTB0 =freq;
        rTCMPB0 =rTCNTB0>>1;


        rTCON = 0x0B;//disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0
        //000 01011
        rTCON &= ~2;//clear manual update bit
        }

        void Main(void){

        freq = 2000;

        PWM_Ini();

        while (1){

        if ( !(rGPFDAT & KEY1) )
        PWM_Output(100);

        if ( !(rGPFDAT & KEY2) )
        PWM_Output(-100);

        if ( !(rGPFDAT & KEY3) )
        PWM_Stop();

        }
        }

        這個(gè)例子每次都要重新設(shè)置PGB端口。



        關(guān)鍵詞: ARMPWM試

        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 牟定县| 阿荣旗| 鄄城县| 阿拉善左旗| 徐汇区| 德江县| 阿图什市| 元江| 禄劝| 河源市| 满洲里市| 江孜县| 南丹县| 余庆县| 柳州市| 健康| 兴和县| 太和县| 鹤壁市| 工布江达县| 鄱阳县| 梅州市| 阿坝县| 柘荣县| 新丰县| 永安市| 双城市| 成安县| 信宜市| 苍南县| 西盟| 息烽县| 建德市| 高雄市| 信宜市| 拉孜县| 远安县| 新乐市| 乡城县| 麻栗坡县| 安徽省|