51系列单片机无PWM输出功能,可以采用定时器配合软件的方法输出。对精度要求不高的场合,非常实用。
一般可以使用两个定时器来实现,如果单片机是S51的话使用T0和T1,如果是S52的话建议使用T0和T2,因为定时器在工作方式2的八位重装模式下定时比较准确,这里我们使用T0和T1
用T0定时器完成PWM输出,脉宽固定,T1来决定高平的宽带来进行PWM调制
具体程序如下:
其中晶振12M,载波频率20KHZ,直接用P0.1来驱动直流电机,直流电机正极接电源正,单片机低平驱动,这样灌电流大。
#include < reg51.h >#include < intrins.h >sbitK1 =P1^4 ; //增加键sbitK2 =P1^5 ; //减少键sbitP00 =P0^1;sbitBEEP =P3^7 ; //蜂鸣器unsigned char PWM=0xe7; //赋初值void Beep();void delayms(unsigned char ms);void delay(unsigned char t);/*********************************************************/void main(){ P1=0xff; TMOD=0x21 ; TH0=0xff ; //50us延时常数 TL0=0xce ; //频率调节 TH1=PWM ; //脉宽调节 TL1=0 ; EA=1; ET0=1; ET1=1; TR0=1 ; while(1) { do{ if(PWM!=0xff) {PWM++ ;delayms(10);} else Beep() ; } while(K1==0); do{ if(PWM!=0xce) {PWM-- ;delayms(10);} else Beep() ; } while(K2==0); }}void timer0() interrupt 1{ TR1=0 ; TH0=0xff ; TL0=0xce ; TH1=PWM ; TR1=1 ; P00=0 ; //启动输出}void timer1() interrupt 3{ TR1=0 ; P00=1 ; //结束输出}/*********************************************************///蜂鸣器子程序/*********************************************************/void Beep() { unsigned char i; for (i=0;i<100;i++) { delay(100); BEEP=!BEEP; //Beep取反 } BEEP=1; //关闭蜂鸣器 delayms(100);}/*********************************************************/// 延时子程序/*********************************************************/void delay(unsigned char t){ while(t--) ;}/*********************************************************/// 延时子程序/*********************************************************/void delayms(unsigned char ms){ unsigned char i ; while(ms--) { for(i = 0 ; i < 120 ; i++) ; }}/*********************************************************/