新聞中心

        AVR的PWM波

        作者: 時間:2016-12-02 來源:網絡 收藏
        (1)一個實例:

        這個程序是用ICC的向導生成的,很簡單。
        T0是作為普通8位定時器,頻率100KHz,每次中斷將PB0(pin1)狀態反轉,產生的是200KHz占空比50%的方波。
        T1是作為工作模式9:相頻可調PWM波發生器,頻率初始化16KHz,占空比50%。請注意:
        TCNT1是T0的定時器計數值,就是每個定時器時鐘加1,和普通定時器的計數值寄存器作用一樣。
        OCR1A作為比較的TOP值。 OCR1B作為匹配輸出值。
        當TCNT1的值增加到OCR1B相等時,OC1B(pin18)清零,就是對應低電平;
        然后TCNT1繼續增加到OCR1A(就是TOP)的值,然后TCNT1開始減少,這個中間,OC1B(Pin18)狀態不變;當TCNT1減少到OCR1B相等時,OC1B(pin18)置1,就是對應高電平。 然后TCNT1繼續減少到0x00(就是BOTTOM),然后TCNT1又開始增加,這個中間,OC1B(pin18)狀態不變。
        OCR1B的值與OCR1A的比值就是PWM的占空比! 所以這個值必須比OCR1A小。當OCR1B為0時,PWM波就一直為低電平(相當于占空比為0);當OCR1B為OCR1A時,PWM波就一直為高電平(相當于占空比為100);當OCR1B為OCR1A的一半時,PWM波就是占空比為50%。
        你可以修改OCR1B的值,然后重新下載程序運行,看看占空比的改變;也可以修改OCR1A的值,然后重新下載程序運行,看看頻率的改變,不過要注意修改OCR1A時,同時注意OCR1B的值不要比OCR1A大。
        模式9算是PWM生成中最復雜的一種,只要你理解了這個,對別的幾種PWM都好理解。
        TCNT0 = 0xB0; //set count
        OCR0 = 0x50;
        即使工作在normal模式下,這個OCR0仍然在和TCNT0進行比較,一旦匹配后,就會產生中斷或者改變OC0腳上的電平(產生PWM)。改變這個值,就會改變中斷發生的時間,或者改變OC0腳上的方波的頻率了。
        T1定時器1的模式9,相頻修正模式,可以用來產生波形非常完整的PWM波。TCNT1設置初值,增加到0xFFFF的時間,然后從0開始計數,這個理解是正確的。可以畫一個波形圖對應理解一下:畫一個占空比50%的方波,高電平上平分為1、2兩段,低電平上平分為3、4兩段。
        1就是TCCNT1從初值加,-->0xFFFF階段,這個階段OCR1B為高電平;
        2就是TCCNT1從0x00加-->OCR1B階段,這個階段為高電平;匹配后,變為低電平
        3就是TCCNT1從OCR1B加-->OCR1A階段,這個階段為低電平;
        4就是TCCNT1從OCR1A減-->OCR1B階段,這個階段為低電平;匹配后,變為高電平
        TCCNT1的初值,就是保證第一段高電平的時間,這樣才能形成一個完整周期的方波。而且,這個初值應該根據OCR1B的值而設,就是TCCNT1 = 0xffff-OCR1B+1;這樣才能保證時間的匹配。
        如果是模式9,那么每次變化后,算出占空比,算出OCR1B的值并賦值,會自動在下一個周期改變占空比為新值。easy。。。重點是:每次給OCR1B賦值,會在 下一個 周期改變占空比。
        //實例:利用pwm控制led光暗及峰鳴器音量大小
        //ICC-AVR application builder : 2005-4-18 12:46:03
        // Target : M16
        // Crystal: 4.0000Mhz
        #include
        #include
        #define uchar unsigned char
        #define uint unsigned int
        void port_init(void);
        void timer0_init(void);
        void init_devices(void);
        void delay_short(uint t);
        uchar scan_key(void);

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

        void port_init(void)
        {
        PORTA = 0x00;
        DDRA = 0x00;
        PORTB = BIT(PB3);
        DDRB = BIT(PB3);
        PORTC = 0x00; //m103 output only
        DDRC = 0x00;
        PORTD = 0x00;
        DDRD = 0x00;
        }
        // WGM: PWM Phase correct
        // desired value: 1KHz
        // actual value: 0.980KHz (-2.0%)
        void timer0_init(void)
        {
        TCCR0 = 0x00; //stop
        TCNT0 = 0x01; //set count
        OCR0 = 0xFF; //set compare
        TCCR0 = 0x62; //start timer ; 相位修正, 8分頻
        }
        //call this routine to initialize all peripherals
        void init_devices(void)
        {
        //stop errant interrupts until set up
        CLI(); //disable all interrupts
        port_init();
        timer0_init();
        MCUCR = 0x00;
        GICR = 0x00;
        TIMSK = 0x00; //timer interrupt sources
        SEI(); //re-enable interrupts
        //all peripherals are now initialized
        }
        void delay_short(uint t) // 短延時
        {
        uint i;
        for (i=0;i}
        uchar scan_key(void) // 按鍵掃瞄
        {
        uchar v;

        v = 0;

        if ((PIND & 0x07) != 0x07)
        {

        if ((PIND & 0x01) == 0)
        {
        v = 1;
        delay_short(1000);
        }

        if ((PIND & 0x2) == 0)
        {
        v = 2;
        delay_short(1000);
        }

        if ((PIND & 0x4) == 0)
        {
        v = 3;
        delay_short(1000);
        }
        };
        while((PIND & 0x07) != 0x07); // 判斷按鍵是不是放開
        return v;
        }
        //
        void main(void)
        {
        uchar key, OCR0_V;

        init_devices();
        OCR0_V = 0xff;

        while(1)
        {
        key = scan_key();

        if (key > 0)
        {
        if (key==1) // 減少佔空比
        {
        OCR0_V -= 10;
        OCR0 = OCR0_V;
        };

        if (key==2) // 增加佔空比
        {
        OCR0_V += 10;
        OCR0 = OCR0_V;
        };

        if (key==3) // 全黑,佔空比為100%
        {
        OCR0_V = 0xff;
        OCR0 = OCR0_V;
        };
        }
        };
        }

        實驗板接線:
        PB3 -----> JA.1 及 JM
        PD0 -----> K1
        PD1 -----> K2
        PD2 -----> K3
        (2)相關詳細理論說明:
        符號定義:
        BOTTOM 計數器計到0x0000 時即達到BOTTOM
        MAX 計數器計到0xFFFF ( 十進制的65535) 時即達到MAX
        TOP 計數器計到計數序列的最大值時即達到TOP。
        TOP 值可以為固定值0x00FF、0x01FF或 0x03FF,或是存儲于寄存器 OCR1A或ICR1里的數值,具體有賴于工作模式 分5種工作類型
        1 普通模式 WGM1=0
        跟51的普通模式差不多,有TOV1溢出中斷標志,發生于MAX(0xFFFF)時
        1 采用內部計數時鐘 用于 ICP捕捉輸入場合---測量脈寬/紅外解碼
        (捕捉輸入功能可以工作在多種模式下,而不單單只是普通模式)
        2 采用外部計數脈沖輸入 用于 計數,測頻
        其他的應用,采用其他模式更為方便,不需要像51般費神

        2 CTC模式 [比較匹配時清零定時器模式] WGM1=4,12
        跟51的自動重載模式差不多
        1 用于輸出50%占空比的方波信號
        2 用于產生準確的連續定時信號
        WGM1=4時, 最大值由OCR1A設定,TOP時產生OCF1A比較匹配中斷標志
        WGM1=12時,最大值由ICF1設定, TOP時產生ICF1輸入捕捉中斷標志
        ------如果TOP=MAX,TOP時也會產生TOV1溢出中斷標志
        注:WGM=15時,也能實現從OC1A輸出方波,而且具備雙緩沖功能
        計算公式: fOCn="fclk"_IO/(2*N*(1+TOP))
        變量N 代表預分頻因子(1、8、64、256、1024),T2多了(32、128)兩級。

        3 快速PWM模式 WGM1=5,6,7,14,15
        單斜波計數,用于輸出高頻率的PWM信號(比雙斜波的高一倍頻率)
        都有TOV1溢出中斷,發生于TOP時[不是MAX,跟普通模式,CTC模式不一樣]
        比較匹配后可以產生OCF1x比較匹配中斷.
        WGM1=5時, 最大值為0x00FF, 8位分辨率
        WGM1=6時, 最大值為0x01FF, 9位分辨率
        WGM1=7時, 最大值為0x03FF,10位分辨率
        WGM1=14時,最大值由ICF1設定, TOP時產生ICF1輸入捕捉中斷 (單緩沖)
        WGM1=15時,最大值由OCR1A設定,TOP時產生OCF1A比較匹配中斷(雙緩沖,但OC1A將沒有PWM能力,最多只能輸出方波)
        改變TOP值時必須保證新的TOP值不小于所有比較寄存器的數值
        注意,即使OCR1A/B設為0x0000,也會輸出一個定時器時鐘周期的窄脈沖,而不是一直為低電平
        計算公式:fPWM=fclk_IO/(N*(1+TOP))
        4 相位修正PWM模式 WGM1=1,2,3,10,11
        雙斜波計數,用于輸出高精度的,相位準確的,對稱的PWM信號
        都有TOV1溢出中斷,但發生在BOOTOM時
        比較匹配后可以產生OCF1x比較匹配中斷.
        WGM1=1時, 最大值為0x00FF, 8位分辨率
        WGM1=2時, 最大值為0x01FF, 9位分辨率
        WGM1=3時, 最大值為0x03FF,10位分辨率
        WGM1=10時,最大值由ICF1設定, TOP時產生ICF1輸入捕捉中斷 (單緩沖)
        WGM1=11時,最大值由OCR1A設定,TOP時產生OCF1A比較匹配中斷(雙緩沖,但OC1A將沒有PWM能力,最多只能輸出方波)
        改變TOP值時必須保證新的TOP值不小于所有比較寄存器的數值
        可以輸出0%~100%占空比的PWM信號
        若要在T/C 運行時改變TOP 值,最好用相位與頻率修正模式代替相位修正模式。若TOP保持不變,那么這兩種工作模式實際沒有區別
        計算公式:fPWM=fclk_IO/(2*N*TOP)
        5 相位與頻率修正PWM模式 WGM1=8,9
        雙斜波計數,用于輸出高精度的、相位與頻率都準確的PWM波形
        都有TOV1溢出中斷,但發生在BOOTOM時
        比較匹配后可以產生OCF1x比較匹配中斷.
        WGM1=8時,最大值由ICF1設定, TOP時產生ICF1輸入捕捉中斷 (單緩沖)
        WGM1=9時,最大值由OCR1A設定,TOP時產生OCF1A比較匹配中斷(雙緩沖,但OC1A將沒有PWM能力,最多只能輸出方波)
        相頻修正修正PWM 模式與相位修正PWM 模式的主要區別在于OCR1x 寄存器的更新時間
        改變TOP值時必須保證新的TOP值不小于所有比較寄存器的數值
        可以輸出0%~100%占空比的PWM信號
        使用固定TOP 值時最好使用ICR1 寄存器定義TOP。這樣OCR1A 就可以用于在OC1A輸出PWM 波。
        但是,如果PWM 基頻不斷變化(通過改變TOP值), OCR1A的雙緩沖特性使其更適合于這個應用。
        計算公式:fPWM=fclk_IO/(2*N*TOP)



        關鍵詞: AVRPWM

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 通化县| 昭平县| 兴安县| 张家口市| 丰原市| 济阳县| 无为县| 扎兰屯市| 越西县| 静乐县| 姚安县| 台南市| 宁德市| 丰都县| 区。| 浮梁县| 阳江市| 丁青县| 台前县| 乐安县| 诸城市| 武陟县| 阿荣旗| 昭苏县| 婺源县| 佛学| 南皮县| 荥经县| 长沙县| 肥乡县| 宜州市| 新平| 乌兰浩特市| 连江县| 尼木县| 镶黄旗| 土默特左旗| 新密市| 道孚县| 海南省| 惠州市|