51单片机PWM控制电机

Posted Yuri800

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51单片机PWM控制电机相关的知识,希望对你有一定的参考价值。

    小时候玩的四驱车,给直流马达接通电源就嗤嗤的跑出去了。电机种类众多,就属控制直流电机最简单,只要对调正负极就能改变电机的转向。另外,直流电机负载能力强,适合做越野车的驱动电机。为了做可调速的越野车,就有了这篇文章。

    电源电压输出是固定的,电机的转速也因此是固定的,为了调节电机的转速,就得改变电源电压的输出(为嘛要改变电机转速?举个简单的列子,双电机驱动小车-一边一个电机-如何实现转向?让两边轮胎上的速度不同即可)。how?用PWM调制的方法,把恒定的直流电源电压调制成频率一定宽度可变的脉冲电压序列,从而可以改变平均输出电压的大小,以调节电机的转速。电源电压在此处就是51MCU的引脚输出,4.5-5V,只要在引脚上产生频率可调的波形即可。假设在一个周期内,就10ms吧,前5ms引脚输出高电平,后5ms引脚输出低电平,周而复始,引脚上输出50%占空比的稳定方波;再改改,前2ms输出高电平,后8ms输出低电平,引脚上输出20%占空比的稳定方波。

    MCU产生周期性事件很简单,用定时器定时产生中断即可。一般差不多一下形式:

void Isr01() interrupt 1

    static unsigned int cnt;
    cnt++;
    if(cnt==40)
    
        cnt=0;
    
假设每250us产生一次中断,以上中断函数统计40次中断,即10ms。
为了完成"可改变占空比的方波"这个命题,来试试给这个函数增加一些统计事件,在一个统计事件中做一些事,另一个统计事件中做其他的事。

unsigned int condition=20;
void Isr01() interrupt 1

    static unsigned int cnt;
    cnt++;
    //一个周期
    if(cnt==40)
    
        cnt=0;
    
    //事件1
    if(cnt<condition)
    
    //do sth
    
    //事件2
    else
    
    //do other thing
    
condition就是新增加的统计事件,前半个周期为一个事件,后半个周期为另一个事件。这里,当cnt小于5ms,输出高电平,当cnt大于输出低电平,合在一起生成一个50%占空比的方波。

unsigned int condition=20;
void Isr01() interrupt 1

    static unsigned int cnt;
    cnt++;
    //一个周期
    if(cnt==40)
    
        cnt=0;
    
    if(cnt<condition)
    
    //前半个周期do sth
    pin=0x00;
    
    else
    
    //后半个周期do other thing
    pin=0x01;
    
为了改变占空比,只要在ISR外修改condition即可,贴出最终的代码:

#include <REG52.H>   
#include <INTRINS.H>  
  
sbit P2_0 = P2^0;  
sbit P2_1 = P2^1;
#define MakeByte(target, Hi,Lo) \\  
do \\  
    target |= (((Hi)<<4)|(Lo)); \\   
while(0); \\  
  
#define SetTH(n,val) \\  
do \\  
    TH##n = val; \\  
while(0); \\  
  
#define SetTL(n,val)  \\  
do \\  
    TL##n = val; \\  
while(0); \\  
  
#define EnableET(n) \\  
do \\  
    ET##n = 0x01; \\  
    IE |= 0x80; \\  
while(0); \\ 

enum KEYSTAT

	KEYDOWN=0,KEYUP,
;

unsigned char iterator = 0x00;

void DelayMs(unsigned int ms)

	int i=0,j=0;
	for(;i<ms;i++)
	
		for(j=0;j<1000;j++)
		
			_nop_();
		
	


void OnKeyDown()
 
	if(iterator == 0x28)
		iterator = 0x00;
	else
		iterator += 0x04;


OnKeyUp()


int main()

	unsigned char curKeyStat = KEYUP;
	unsigned char preKeyStat = KEYUP;

	SetTH(0,0x06);
	SetTL(0,0x06);
	MakeByte(TMOD,0x02,0x02);
	EnableET(0);
	TR0 = 0x01;

	while(1)
	
		while(1)
		
			curKeyStat = P2_1;
			switch(curKeyStat)
			
			case KEYDOWN:
				if(curKeyStat == preKeyStat)
				
					//确实按下键
					OnKeyDown();
				
				else
				
					//两次按键不同 状态待定
				
				preKeyStat = curKeyStat;
				break;
			case KEYUP:
				if(curKeyStat == preKeyStat)
				
					//确实松开键
					OnKeyUp();
				
				else
				
					//两次按键不同 状态待定
				
				preKeyStat = curKeyStat;
				break;
			
			DelayMs(200);	
		
	

	return 0;


void IsrT0() interrupt 1

	static unsigned int enterIsr = 0;
	TR0 = 0x00;
	//每250us进入isr
	enterIsr++;
	//10ms一个周期
	if(enterIsr == 0x28)
	
		enterIsr = 0x00;
		P2_0 = 0x0;	
	
	if(enterIsr<=iterator)
	
		P2_0 = 0x00;
	
	else
	
		P2_0 = 0x01;
	
	TR0 = 0x01;	
在主函数中,通过判断按下键来改变condition。


结尾部分,贴上仿真图和仿真结果:

1)占空比100%:

2)差不多55%占空比:


3)0%的占空比,电机休息了:


以上是关于51单片机PWM控制电机的主要内容,如果未能解决你的问题,请参考以下文章

51单片机PWM控制电机

基于51单片机霍尔测速直流电机控制设计(含源码+原理图+论文+PCB封装)

基于51单片机霍尔测速直流电机控制设计(含源码+原理图+论文+PCB封装)基于STM32闭环步进电机控制系统设计(仿真,程序,说明)-转发分享

想实现用PWM经RC后的电压驱动风扇,调节PWM占空比可改变RC后的输出电压从而实现调节风扇转速

Verilog直流电机的pwm控制设计

51单片机实现pwm对电机调速