<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          AVR的PWM波

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

          這個程序是用ICC的向?qū)傻?,很簡單?br />T0是作為普通8位定時器,頻率100KHz,每次中斷將PB0(pin1)狀態(tài)反轉(zhuǎn),產(chǎn)生的是200KHz占空比50%的方波。
          T1是作為工作模式9:相頻可調(diào)PWM波發(fā)生器,頻率初始化16KHz,占空比50%。請注意:
          TCNT1是T0的定時器計數(shù)值,就是每個定時器時鐘加1,和普通定時器的計數(shù)值寄存器作用一樣。
          OCR1A作為比較的TOP值。 OCR1B作為匹配輸出值。
          當(dāng)TCNT1的值增加到OCR1B相等時,OC1B(pin18)清零,就是對應(yīng)低電平;
          然后TCNT1繼續(xù)增加到OCR1A(就是TOP)的值,然后TCNT1開始減少,這個中間,OC1B(Pin18)狀態(tài)不變;當(dāng)TCNT1減少到OCR1B相等時,OC1B(pin18)置1,就是對應(yīng)高電平。 然后TCNT1繼續(xù)減少到0x00(就是BOTTOM),然后TCNT1又開始增加,這個中間,OC1B(pin18)狀態(tài)不變。
          OCR1B的值與OCR1A的比值就是PWM的占空比! 所以這個值必須比OCR1A小。當(dāng)OCR1B為0時,PWM波就一直為低電平(相當(dāng)于占空比為0);當(dāng)OCR1B為OCR1A時,PWM波就一直為高電平(相當(dāng)于占空比為100);當(dāng)OCR1B為OCR1A的一半時,PWM波就是占空比為50%。
          你可以修改OCR1B的值,然后重新下載程序運(yùn)行,看看占空比的改變;也可以修改OCR1A的值,然后重新下載程序運(yùn)行,看看頻率的改變,不過要注意修改OCR1A時,同時注意OCR1B的值不要比OCR1A大。
          模式9算是PWM生成中最復(fù)雜的一種,只要你理解了這個,對別的幾種PWM都好理解。
          TCNT0 = 0xB0; //set count
          OCR0 = 0x50;
          即使工作在normal模式下,這個OCR0仍然在和TCNT0進(jìn)行比較,一旦匹配后,就會產(chǎn)生中斷或者改變OC0腳上的電平(產(chǎn)生PWM)。改變這個值,就會改變中斷發(fā)生的時間,或者改變OC0腳上的方波的頻率了。
          T1定時器1的模式9,相頻修正模式,可以用來產(chǎn)生波形非常完整的PWM波。TCNT1設(shè)置初值,增加到0xFFFF的時間,然后從0開始計數(shù),這個理解是正確的??梢援嬕粋€波形圖對應(yīng)理解一下:畫一個占空比50%的方波,高電平上平分為1、2兩段,低電平上平分為3、4兩段。
          1就是TCCNT1從初值加,-->0xFFFF階段,這個階段OCR1B為高電平;
          2就是TCCNT1從0x00加-->OCR1B階段,這個階段為高電平;匹配后,變?yōu)榈碗娖?br />3就是TCCNT1從OCR1B加-->OCR1A階段,這個階段為低電平;
          4就是TCCNT1從OCR1A減-->OCR1B階段,這個階段為低電平;匹配后,變?yōu)楦唠娖?br />TCCNT1的初值,就是保證第一段高電平的時間,這樣才能形成一個完整周期的方波。而且,這個初值應(yīng)該根據(jù)OCR1B的值而設(shè),就是TCCNT1 = 0xffff-OCR1B+1;這樣才能保證時間的匹配。
          如果是模式9,那么每次變化后,算出占空比,算出OCR1B的值并賦值,會自動在下一個周期改變占空比為新值。easy。。。重點(diǎn)是:每次給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.ex-cimer.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) // 減少佔(zhàn)空比
          {
          OCR0_V -= 10;
          OCR0 = OCR0_V;
          };

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

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

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

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

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



          關(guān)鍵詞: AVRPWM

          評論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();