1、如何利用 51 单片机输出 PWM 波1、理论知识2、程序及分析1、理论知识PWM 这个功能在飞思卡尔、STM32 等高档的单片机内部有专用的模块,用此类芯片实现 PWM 功能时只需要通过设置相应的寄存器就可实现周期和占空比的控制。但是如果要用 51 单片机的话,也是可以的,但是比较的麻烦。此时需要用到内部定时器来实现,可用两个定时器实现,也可以用一个定时器实现。用两个定时器的方法是用定时器 T0 来控制频率,定时器 T1 来控制占空比。大致的的编程思路是这样的:T0 定时器中断让一个 I0 口输出高电平,在这个定时器 T0 的中断当中起动定时器 T1,而这个 T1 是让 IO 口输出低电平,
2、这样改变定时器 T0 的初值就可以改变频率,改变定时器 T1 的初值就可以改变占空比。下面重点介绍用一个定时器的实现 PWM 的方法。因为市面上的智能小车所采用的电机大多数为 TT 减速电机,通过复杂的实验此电机最佳的工作频率为1000HZ(太高容易发生哨叫,太低电机容易发生抖动),所以下面以周期为1ms(1000HZ)进行举例,要产生其它频率的 PWM 波,程序中只需作简单修改即可。用一个定时器时(如定时器 T0),首先你要确定 PWM 的周期 T 和占空比 D,确定了这些以后,你可以用定时器产生一个时间基准 t,比如定时器溢出 n 次的时间是 PWM 的高电平的时间,则 D*T=n*t,类
3、似的可以求出 PWM 低电平时间需要多少个时间基准 n。因为这里我们是产生周期为 1ms(1000HZ)的 PWM,所以可设置中断的时间基准为 0.01ms,,然后中断 100 次即为 1ms。在中断子程序内,可设置一个变量如time,在中断子程序内,有三条重要的语句:1、当 time=100 时,time 清零(此语句保证频率为 1000HZ),2、当 timen 时(n 应该在 0100 之间变化开),让单片相应的 I/O 口输出高电平,当 time#define uint unsigned int#define uchar unsigned charsbit PWM1=P20;/接 IN
4、1 控制正转sbit PWM2=P21;/接 IN2 控制反转uchar time;void main()TMOD=0x01;/定时器 0 工作方式 1TH0=0xff;/(65536-10)/256;/赋初值定时TL0=0xf7;/(65536-10)%256;/0.01msEA=1;/开总中断ET0=1;/开定时器 0 中断TR0=1;/启动定时器 0 while(1)void delay(uint z)uint x,y;for(x=z;x0;x-)for(y=500;y0;y-);void tim0() interrupt 1TR0=0;/赋初值时,关闭定时器TH0=0xff;/(655
5、36-10)/256;/赋初值定时TL0=0xf7;/(65536-10)%256;/0.01msTR0=1;/打开定时器time+;if(time=100) time=0;/1khzif(time#define uint unsigned int #define uchar unsigned charuchar time,count=50,flag=1;/低电平的占空比sbit PWM1=P20;/PWM 通道 1,反转脉冲sbit PWM2=P21;/PWM 通道 2,正转脉冲sbit key_turn=P37; /电机换向/*函数声明*/void delayxms(uint z);voi
6、d Motor_turn(void);void timer0_init(void);/*主函数*/void main(void)timer0_init();while(1)Motor_turn();/*延时处理*/void delayxms(uint z)/延时 xms 程序uint x,y;for(y=z;x0;x-)for(y=110;y0;y-);/*电机正反向控制*/void Motor_turn(void)if(key_turn=0)delayxms(2);/此处时间不能太长,否者会的中断产生冲突if(key_turn=0)flag=flag;while(!key_turn);/*定
7、时器 0 初始化*/void timer0_init(void)TMOD=0x01; /定时器 0 工作于方式 1TH0=(65536-10)/256;TL0=(65536-10)%256;TR0=1;ET0=1;EA=1;/*定时 0 中断处理*/void timer0_int(void) interrupt 1 TR0=0;/设置定时器初值期间,关闭定时器TH0=(65536-10)/256;TL0=(65536-10)%256;TR0=1;if(flag=1)/电机正转PWM1=0; time+;if(time=100)time=0;else /电机反转PWM2=0; time+;if(
8、time=100)time=0;4、程序 4、使单片机输出 PWM,并能控制正反转和实现调速为了使大家彻底掌握此方面,下面再给出一个复杂一点的程序,实现的功能为通过一个按键控制正反转并通过另外两个按键使之可以在 0 到 20 级之间调速的程序。/*/* 程序名:PWM 直流电机调速 */* 晶振:11.00592 MHz CPU 型号:STC89C52 */* 直流电机的 PWM 波控制,可以通过按键控制正反转并在 0 到 20 级之间调速 */ /*/ #include#define uint unsigned int #define uchar unsigned charuchar tim
9、e,count=50,flag=1;/低电平的占空比sbit PWM1=P20;/PWM 通道 1,反转脉冲sbit PWM2=P21;/PWM 通道 2,正转脉冲sbit key_add=P35;/电机加速sbit key_dec=P36;/电机减速sbit key_turn=P37;/电机换向/*函数声明*/void delayxms(uint z);void Motor_turn();void Motor_add();void Motor_dec();void timer0_init();/*主函数*/void main()timer0_init();while(1)Motor_turn
10、();Motor_add();Motor_dec();/*延时处理*/void delayxms(uint z)/延时 xms 程序uint x,y;for(y=z;x0;x-)for(y=110;y0;y-);/*电机正反向控制*/void Motor_turn()if(key_turn=0)delayxms(2);/此处时间不能太长,否者会的中断产生冲突if(key_turn=0)flag=flag;while(!key_turn);void Motor_add()/电机加速if(key_add=0)delayxms(2);/此处时间不能太长,否者会的中断产生冲突if(key_add=0)count+=5;if(count=100)count=0;while(!key_add);