AVR的PWM波
這個程序是用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);
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)
評論