一、什么是PWM?
1、科普一下什么是PWM,嘿嘿,莫閑啰嗦,好好看看,可能大多數人聽過,但可能沒詳細了解過,至此不妨花費幾分鍾,詳細了解哈,PWM中文譯名為:脈沖寬度調制,即控制電路在輸出頻率不變的情況下,通過微控制器控制電平在一個周期內輸出高低電平的比例來等效出模擬電壓的大小。舉個“栗子”吧:
若電池9V,設9V工作時燈狀態為全亮,1.8V工作時為微亮。
若開關持續20%時間通,80%時間斷,則可近似為用一個1.8V(9V*20%)的電池持續供電,此時為半亮。當然,開關通斷時間需要特別短,否則,比如20s通80s斷,燈泡會20s全亮,80s滅,而達不到微亮的效果。
在上述例子中,即將持續通斷高低電平代替模擬信號(1.8V)。
占空比為:正脈沖的持續時間與脈沖總周期的比值。此例中占空比即為20%。(尊重原創)
--------------------- 本文來自 HejaBVB 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/u013131866/article/details/36672671?utm_source=copy
二、軟件如何模擬
1、上面已經解釋了什么是脈寬調制PWM,我們使用單片機模擬的思路是,首先使用單片機定時器來定個最小分辨的時間t;
2、在定時器中斷中,設置一個標志位(pwm_time),每次進中斷,也就是每隔 t 時間加1,這就是我們要產生的PWM頻率,則PWM周期為(100xt),頻率為1/(100xt);
3、再設置在100個t中,需要n個高電平(1)則需要的低電平(0)為(100-n)個,其實這個就是調節占空比(高電平時間占整個周期時間的比值);
4、舉個“栗子”,假如我要產生一個PWM頻率是1Khz ,占空比為 20%的信號,則,需要首先計算出,最小分辨時間t,1Khz的頻率,則周期為1ms=1000us,則t=1000us/100=10us;n呢,就是n/100%=20%,n=20;
三、程序示例
1 unsigned char pwm_time=0; 2 unsigned char pwm_r_data=0; 3 unsigned char pwm_g_data=0; 4 unsigned char pwm_b_data=0; 5 /* 6 使用定時器T1,設定中斷時間為10us,在中斷函數面,設置一個標志位(pwm_time),來確定產生的PWM頻率 7 因為這里我們是產生周期為1ms(1kHZ)的PWM,所以可設置中斷的時間基准為0.01ms,,然后中斷100次即為1ms。在中斷子程序內,可設置一個變量如pwm_time,在中斷子程序內,有三條重要的語句: 8 9 1、當time>=100時,time清零(此語句保證頻率為1kHZ); 10 11 2、當time>n時(n應該在0-100之間變化開),讓單片相應的I/O口輸出低電平; 12 13 3、當time<=n時,讓單片相應的I/O口輸出高電平,此時占空比就為%n。 14 15 */ 16 17 18 void IO_init() //設置P0.0口為上拉輸入,(INT0),P0.1-P0.3為推挽輸出 19 { 20 P0DPL=0XA9; 21 } 22 23 24 void pwm_init() 25 { 26 TMOD=TMOD|0X20; //定時器T1設置為模式2 8位自動重載模式 27 TIMPRS=0X00; //定時器工作時鍾位PCLK/2 2分頻 28 TR1=1; //開啟定時器T1 29 TL1=235; //約10us,示波器測得 30 TH1=TL1; //8位自動重載 31 ET1=1; //允許定時器T1中斷 32 EA=1; //開總中斷 33 } 34 void LED_PWM(unsigned char a,unsigned char b,unsigned char c) //三路PWM,R/G/B 35 { 36 pwm_r_data=a; 37 pwm_g_data=b; 38 pwm_b_data=c; 39 } 40 void main() 41 { 42 SPKEY=0X36; //打開寫保護開關 43 CKDS=0X03; //4分頻 MLCK=pclk=32mhz/4=8mhz 主時鍾頻率為8MHz 44 IO_init(); //I/O口初始化 45 pwm_init(); //定時器初始化 46 LED_PWM(20,20,20); 47 while(1); 48 } 49 void timer1(void) interrupt 3 //定時器T1中斷函數入口 //10us進一次中斷 10usX100=1000us=1ms f=1/1ms=1Khz 50 { 51 pwm_time++; 52 if(pwm_time>=100) pwm_time=0; 53 54 if(pwm_time<=pwm_r_data) R=1; 55 else R=0; 56 57 if(pwm_time<=pwm_g_data) G=1; 58 else G=0; 59 60 if(pwm_time<=pwm_b_data) B=1; 61 else B=0; 62 }