PWM(脈寬調(diào)制)大家可以上網(wǎng)查查,其原理講解很多。為了更好的學(xué)習(xí)PWM,我特意參照別人寫的文章,自己也寫了一份代碼來實(shí)現(xiàn)PWM。單片機(jī)代碼如下:
- #include <stc12c5a60s2.h>
-
- unsigned long cnt;
- unsigned int cnt_T1;
- unsigned int high;
- unsigned int low;
- unsigned char TH0_high;
- unsigned char TL0_high;
- unsigned char TH0_low;
- unsigned char TL0_low;
- unsigned char T1H1;
- unsigned char T1L1;
- unsigned char flag=0;
-
- unsigned char duty[19] = {5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95};
- unsigned char index=0;
-
- void config_Fy_and_dy(unsigned char fy, unsigned char dy);
- void config_Timer1(unsigned char ms);
- void modify_duty(unsigned char dy);
-
- sbit PWM_OUT = P2^5;
-
- void main()
- {
- TMOD = 0X11; // 定時(shí)器0/1都工作在方式1,是2^16計(jì)數(shù)
- EA=1;
- config_Fy_and_dy(100, 20);
- config_Timer1(50);
- while(1);
- }
-
- void config_Fy_and_dy(unsigned char fy, unsigned char dy) // 輸入頻率fy,占空比dy
- {
- cnt = (11059200/fy)/12; // 要產(chǎn)生頻率為fy,定時(shí)器0所要計(jì)的數(shù)值
- high = (cnt*dy)/100; // 計(jì)算出高電平所要計(jì)的數(shù)值
- low = cnt - high; // 計(jì)算出低電平所要計(jì)的數(shù)值
- high = 65536 - high; // 確定定時(shí)器0,從哪個(gè)初值開始計(jì)時(shí),記錄的是高電平
- low = 65536 - low; // 確定定時(shí)器0,從哪個(gè)初值開始計(jì)時(shí),記錄的是低電平
- TH0_high = (unsigned char)(high>>8); // 高電平,給TH0預(yù)備重裝初值
- TL0_high = (unsigned char)high; // 高電平,給TL0預(yù)備重裝初值
- TH0_low = (unsigned char)(low>>8); // 低電平,給TH0預(yù)備重裝初值
- TL0_low = (unsigned char)low; // 低電平,給TL0預(yù)備重裝初值
- TH0 = TH0_high;
- TL0 = TL0_high;
- PWM_OUT = 1;
- ET0 = 1;
- TR0 = 1;
- }
-
- void config_Timer1(unsigned char ms)
- {
- unsigned long temp;
- temp = 11059200/1000;
- temp = (temp*ms)/12;
- cnt_T1 = 65536 - temp;
- T1H1 = (unsigned char)(cnt_T1>>8);
- T1L1 = (unsigned char)cnt_T1;
- TH1 = T1H1;
- TL1 = T1L1;
- ET1=1;
- TR1=1;
- }
-
- void modify_duty(unsigned char dy)
- {
- high = (cnt*dy)/100;
- low = cnt - high;
- high = 65536 - high;
- low = 65536 - low;
- TH0_high = (unsigned char)(high>>8); // 高電平,給TH0預(yù)備重裝初值
- TL0_high = (unsigned char)high; // 高電平,給TL0預(yù)備重裝初值
- TH0_low = (unsigned char)(low>>8); // 低電平,給TH0預(yù)備重裝初值
- TL0_low = (unsigned char)low; // 低電平,給TL0預(yù)備重裝初值
- }
-
- void T0_Timer0() interrupt 1
- {
- if(PWM_OUT==0) // 準(zhǔn)備產(chǎn)生高電平
- {
- TH0 = TH0_high; // 高電平產(chǎn)生 初值重裝
- TL0 = TL0_high;
- PWM_OUT = 1;
- }
- else
- {
- TH0 = TH0_low; // 低電平產(chǎn)生 初值重裝
- TL0 = TL0_low;
- PWM_OUT = 0;
- }
- }
-
- void T1_Timer1() interrupt 3
- {
- TH1 = T1H1;
- TL1 = T1L1;
- modify_duty(duty[index]);
- if(0 == flag) // flag=0時(shí),表示呼吸燈由暗變亮
- {
- index++;
- if(index >=18)
- {
- flag = 1;
- }
- }
- else
- {
- index--;
- if(index <=0)
- {
- flag=0;
- }
- }
- }
復(fù)制代碼
其實(shí),PWM這種實(shí)現(xiàn)方法并不適合編程,因?yàn)樗加昧藘蓚(gè)定時(shí)器中斷口,會(huì)影響程序的執(zhí)行效率。 我是通過兩個(gè)定時(shí)器來更好的掌握PWM的調(diào)制原理。
|