基于51单片机直流电机PWM调速设计

1、设计需求及目标

设计以单片机STC89C51和三极管控制的直流电机脉宽调制调速系统。利用STC89C51芯片进行低成本直流电动机控制系统的设计,能够简化系统构成、降低系统成本、增强系统性能、满足更多应用场合的需要。系统实现对电机的正转、反转、急停、加速、减速的控制,以及PWM的占空比在液晶上的实时显示。同时显示实时的电机转速。

2、设计思路及方案

采用三极管组成PWM信号的驱动系统,并且对PWM信号的原理、产生方法以及如何通过软件编程对PWM信号占空比进行调节,从而控制其输入信号波形等均作了详细的阐述。另外,本系统中使用了霍尔元件对直流电机的转速进行测量,经过处理后,将测量值送到液晶显示出来。电路图:

3、部分代码

#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int 
void displaym();
sbit en=P2^5;		//1602  6管脚
sbit rs=P2^7;	 //1602端口	4管脚
sbit rw=P2^6;//lcd1602控制端口 5管脚
sbit num1=P1^0;						//占空比加1
sbit num2=P1^1;								   //占空比减一
sbit num3=P1^2;											   //正传
sbit num4=P1^3;													 //反转
sbit num5=P1^4;														   //开始停止切换

sbit out=P3^4;							 //PWM输出用于正传
sbit out1=P3^7;			//PWM输出用于反转

uint zhuansu,flag,z1,z2,m,flag_1,zheng,fan,kai;




void delay(uint z)//延时1ms函数
{

 uint x,y;
 for(x=0;x<z;x++)
     for(y=0;y<110;y++);
}



void write_com(uchar com)//向1602写一字节(控制指令)
{
  rs=0;
  P0=com;
  delay(5);
  en=0;
  delay(10);
  en=1;
}
void write_data(uchar date)//向1602写一字节(数据)
{
  rs=1;
  P0=date;
  delay(5);
  en=0;
  delay(5);
  en=1;
}
void init()//初始化函数
{ 
  en=0;
  rw=0;
  write_com(0x01);         //lcd初始化
  write_com(0x38);					   //5X7显示
  write_com(0x0c);			 //关闭光标
  TMOD=0x01;               //定时器方式1           
  TH0=0xdc;
  TL0=0x00;                //定时器装入初值 
  EA=1;                    //开总中断 
  ET0=1;                   //定时器0开中断
  TR0=1; 
  EX1=1;
IT1=1;                 //定时器启动  
 TH1=0xfc;
  TL1=0x66;//定时100us
  ET1=1;                   //定时器1开中断
  TR1=1;
  write_com(0x80);
  write_data('V');
  write_data(':');
  write_com(0x87);		 //第一行显示转速
  write_data('r');
  write_data('p');
  write_data('m');
  write_com(0xc0); 
  write_data('z');
  write_data('h');
  write_data('a');
  write_data('n');
  write_data('k');
  write_data('o');
  write_data('n');
  write_data('g');
  write_data('b');
  write_data('i');	  //在第二行显示zhankongbi:
  write_data(':');
  displaym();
}
void keyscan()  //键盘扫描函数
{ 
  if(num1==0)     
  {
    delay(5);      //消除抖动
	 if(num1==0)
	 {
		if(m<=199)
		 m++;
			displaym();								  //设定占空比加一
     }
  }
  if(num2==0)
  {
    delay(5);
	 if(num2==0)
	 {
	  	if(m>=1)
		m--;
			displaym();					//设定占空比减一
	
	 }
  }
    if(num3==0)
  {
    delay(5);
	 if(num3==0)
	 {
	  zheng=1;		//正传标志置1
	  fan=0;	  // 反转标志置0
	
	 }
  }
      if(num4==0)
  {
    delay(5);
	 if(num4==0)
	 {
	  zheng=0;		 //正传标志置0
	  fan=1;	  // 反转标志置1
	
	 }
  }
      if(num5==0)
  {
    delay(5);
	 if(num5==0)
	 {
	 while(num5==0)	 ;
	  kai=1-kai;
	 }
  }
}
void display()
{
  write_com(0x82);
  zhuansu=zhuansu*30;	  //将两秒内的计数乘以30得到转每分

  if(zhuansu/10000!=0)
   write_data(zhuansu/10000+0x30);						  //如果转速的万位不为0	正常显示否则显示空格
   else
   write_data(' ');

  if(zhuansu/1000==0)
  write_data(' ');
  else 
  write_data(zhuansu%10000%1000+0x30);								//如果转速小于1000 千位为空格 否则正常显示
  
  if(zhuansu/100==0)
  write_data(' ');
  else
  write_data(zhuansu%10000%1000/100+0x30);					   //如果转速小于100 百位为空格 否则正常显示

    if(zhuansu/10==0)
  write_data(' ');
  else
  write_data(zhuansu%10000%1000%100/10+0x30);				  //如果转速小于10 十位为空格 否则正常显示

  write_data(zhuansu%10000%1000%100%10+0x30);
  write_com(0xd0);			  //如果没有这句,当中断内的显示函数执行完,就会在转速的位置显示占空比数据,导致乱码
}
void displaym()
{
 write_com(0xcb);
   if(m/200%10!=0)
  write_data(m/200%10+0x30);			   //如果占空比百位不为0则显示百位否则显示空格
  else 
  write_data(' ');
  
  if(m/200%10==0&&m/20%10==0)
  write_data(' ');
  else
  write_data(m/20%10+0x30);				 //如果占空比小于10 十位正常显示  否则显示空格
  
  write_data(m/2%10+0x30);				 //显示个位
}
void main()
{
    flag_1=0;
	m=100;							 //占空比为100
	zhuansu=0;					   //转速初值0
	flag=0;
	zheng=1;				  //初始化电机正转动
	fan=0;

    init();              //初始化

	while(1)
	{
	keyscan();				//键盘扫描程序


 
	  
	}

}
void int1()interrupt 2				//外部中断1脉冲技术记录电机的转速 电机转一圈zhuansu加一
{
  zhuansu++;
}
void int2()interrupt 3				  //定时器0显示转速
{
 
  TH0=0xdc;
  TL0=0x00;//定时10ms
  flag++;
  	
  if(flag==200)				   //计时到达2s
    {


	display();					//显示转速
	zhuansu=0;					  //转速置0
	flag=0;

	}
}
void int3()interrupt 1					 //产生PWM
{
  
  TH1=0xff;
  TL1=0x00;//定时100us
  
  	flag_1++;
	if(flag_1>199)
	flag_1=1;
	if(kai==1)		  //如果kai==1电机启动
	{
	if(zheng==1)				//电机正转
	{
	if(flag_1<m)				  	//小于占空比m输出PWM=0输出电压为1
     {out=0;
	 out1=1;}
	 else
	 {
	   out=1;
	   out1=1;
	 }
	 }
	 	if(fan==1)			   //电机反转
	{
	if(flag_1<m)				//小于占空比m输出PWM=0输出电压为1
	  {
	    out=1;
		out1=0;
	  }
	 else									 //大于m输出PWM=1输出电压为0
	  {
	    out=1;
		out1=1;
	  }
	 }
	 }
	 if(kai==0)			  //kai=0电机停止转动
	 {
	   out=1;
	   out1=1;
	 
	 }
}

完整资料:https://market.m.taobao.com/app/idleFish-F2e/widle-taobao-rax/page-detail?wh_weex=true&wx_navbar_transparent=true&id=614513458599&ut_sk=1.WUpxx7gpwUoDAMmnnrBIzAno_12431167_1585228024499.Copy.detail.614513458599.1828622527&forceFlush=1

发布了23 篇原创文章 · 获赞 7 · 访问量 317

猜你喜欢

转载自blog.csdn.net/weixin_41017942/article/details/105128128