基于51单片机的直流电机转速显示+加速减速启停

这篇具有很好参考价值的文章主要介绍了基于51单片机的直流电机转速显示+加速减速启停。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

做了一个实战项目,这个实战项目主要是实现对直流电机转速的控制,可以实现电机加速,减速,报警、启停以及显示转速。在本电路的基础上也可以进行一些拓展改变电机正反转的状态,只需要外加一个按键和修改部分程序即可,在文章的最后会对拓展进行一个说明。基础代码来源于普中科技的基础例程,代码经过我的验证并且实践到了实际项目中,如果想要进行实战测试的话,请仔细对照着我这篇文章进行调试学习,实际电路要对应好。


一、前期准备

1、功能实现思路

首先先分析需求:

51单片机有很多种,鉴于本人只有AT系列单片机的下载器,因此选用的芯片型号为AT89S52/AT89C52,都兼容,任意选择一种都可以。

直流电机驱动电路。这个比较通用的就几个,常见的有L298N驱动电路,由于是直接设计到电路板上,所以在网上copy了开源的直流电机驱动电路,就不用L298N驱动芯片了。直接通过三极管和二极管配合对马达进行驱动控制。

需要显示转速,用LCD1602进行显示,两行可以显示N多数据

需要进行测速,通用的就是霍尔传感器+磁铁,那么根据个人的需求,你可以选择低电平触发也可以选择高电平触发的霍尔传感器。其出发原理就是磁铁的一极靠近霍尔传感器的时候,霍尔传感器一引脚会产生触发电平,通过检查触发电平即可知道磁铁经过的次数。通常的软件检测方法是利用外部中断检测上升沿或者下降沿

按键模块,普通的按键按下检测就可以

特此提醒一下,我用的霍尔传感器是低电平有效,因此在我的程序里面外部中断被设置为下降沿触发。只要是低电平有效的霍尔传感器都可以,只需要注意触发速率,因为电机转速很快,所以需要高速率的检测。

2、软件实现思路

话不多说,直接上图。整体流程就是先将该初始化的初始化,比如外部中断,定时器一和定时器二中断。霍尔传感器的存在主要是为了检测转速,由于直流电机每转动一圈霍尔传感器就会产生一个下降沿,故可以通过判断下降沿的多少从而转换成某段时间内电机的转速。定时器一的功能是进行2s的计时,因为要统计一段时间内的下降沿个数,故通过定时器一进行赋值和复位。定时器二的作用是与设置的占空比进行比较,比如定义的占空比最大100%的时候对应一个参数量为200,那么可以设置一个定量duty为100,可以调节duty的大小,100的时候就代表50%的占空比,当计数小于100时输出为高电平,大于100时输出为低电平,这样就实现了PWM的输出。
基于51单片机的直流电机转速显示+加速减速启停

二、硬件电路

1.总电路

下图是硬件连接图
基于51单片机的直流电机转速显示+加速减速启停## 2.硬件电路解读
除单片机最小系统以外,需要注意的地方有:

霍尔传感器的连接方式:在VCC和数据输出口也就是定义的P33引脚口需要接一个上拉电阻,在没有触发信号的时候,数据口能够一直以高电平的状态存在,这样不会存在误触发的情况。

直流电机驱动电路:尤其要注意三极管的型号和所处的位置,不要焊接错误了,焊接对了就能正常运行。想要让电机正常运行的话,只需要P34和P37之间存在着电平差,即P34高电平,P37低电平就可以运行,反之即可。

LCD背光显示:此处采用电阻直接分压,并没有用到滑动变阻器分压,背光固定,可通过改变电阻自由选择。

三、软件解读

1.代码解读

在参数定义部分,主要是定义多个数组。数组的作用是为了将数据存放并显示,由于LCD1602写入数据是通过地址写入的,在这里博主采用的是单字符逐步写入,所以将数据拆分开放到定义的数组里面,这样就能够单独进行显示。

unsigned char Limit[5];   //报警阈值存放位置
unsigned int  max=10000;  //设置报警阈值
unsigned char duty1[3];   //报警阈值存放位置
unsigned char zhuansu[5]; //转速存放位置
unsigned int  zhuansu1=0; //显示转速大小
unsigned int  zhuansu2=0; //显示转速大小
unsigned char code wenzi1[14]={"now_V:     m/h"};
unsigned char code wenzi2[16]={"Limit:     m    "};
uint flag=0;
u16 duty=100;              //占空比
u16 duty2=0;
u16 work_status=0;        //工作状态,为0的时候不工作,为1的时候工作

IO口的定义分别为。P1.0-P1.4是按键控制口,分别代表电机加速,减速,报警阈值增加,报警阈值减少以及电机的启停。P1.5-P1.6分别代表LED灯控制端口和蜂鸣器控制端口,控制方式也就是给高低电平就能控制蜂鸣器鸣叫或者LED亮。P3.4和P3.7是控制直流电机两端的IO口,通过控制其中某个口为高电平,某个口为低电平就能实现直流电机的正转或者反转。此外,虽然没有定义,但是在外部中断里面对应的IO口为P3.3口,所以要通过杜邦线去连接霍尔传感器的数据输出端。

sbit beep=P1^6;
sbit led=P1^5;
sbit out=P3^4;					  //PWM输出用于正传
sbit out1=P3^7;			      //PWM输出用于反转
sbit duty_add=P1^0;				//占空比加1
sbit duty_reduce=P1^1;		//占空比减一
sbit limit_add=P1^2;			//阈值加1
sbit limit_reduce=P1^3;		//阈值减1
sbit start=P1^4;					//开始或者停止工作

延时函数和按键处理函数。在按键处理函数里面,对五个按键进行扫描判断,当检测到按键按下以后执行相对应的程序。其中duty是我们定义的占空比数值,占空比为100%的时候duty为200,初始值duty设置为100,对应占空比为50%。通过判断第一个或者第二个按键按下从而实现对占空比的加减。同理第三个第四个也是对阈值进行判断,第五个按键有所不同的地方在于里面有work_status的切换,当然直接用!语句也行,我这里是用习惯了这种方式。在每个按键处理函数后面加一个while循环是为了防止连续按下导致疯狂加减。

/*******************************************************************************
* 函 数 名         : delay
* 函数功能		   : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
	while(i--);	
}
/*******************************************************************************
* 函 数 名         : keypros
* 函数功能		   : 按键处理函数,判断按键K1是否按下
*******************************************************************************/
void keypros()
{
	if(duty_add==0)		  //检测按键K1是否按下
	{	
		delay(1000);   //消除抖动 一般大约10ms
		if(duty_add==0)	 //再次判断按键是否按下
		{
			duty+=1;
		}
		while(!duty_add);	 //检测按键是否松开
	}	
	if(duty_reduce==0)		  //检测按键K1是否按下
	{	
		delay(1000);   //消除抖动 一般大约10ms
		if(duty_reduce==0)	 //再次判断按键是否按下
		{
			duty-=1;
		}
		while(!duty_reduce);	 //检测按键是否松开
	}
	if(limit_add==0)		  //检测按键K1是否按下
	{	
		delay(1000);   //消除抖动 一般大约10ms
		if(limit_add==0)	 //再次判断按键是否按下
		{
			max+=100;
		}
		while(!limit_add);	 //检测按键是否松开
	}
	if(limit_reduce==0)		  //检测按键K1是否按下
	{	
		delay(1000);   //消除抖动 一般大约10ms
		if(limit_reduce==0)	 //再次判断按键是否按下
		{
			max-=100;
		}
		while(!limit_reduce);	 //检测按键是否松开
	}
	if(start==0)		  //检测按键K1是否按下
	{	
		delay(1000);   //消除抖动 一般大约10ms
		if(start==0)	 //再次判断按键是否按下
		{
			work_status+=1;
			if(work_status>=2)work_status=0;
		}
		while(!start);	 //检测按键是否松开
	}	
}

三个函数的初始化。在初始化函数里面对每一个都进行了配置,每条语句有其对应的解释,具体操作是通过寄存器层面去操作的,在reg52.h里面类似于IT1这种符号都有被定义。需要注意的是,定时器的工作模式为方式1。由于每一次单片机一个周期是1us,所以若想实现10ms的定时,就需要计10000个周期,那么定时器的TH和TL就可设置为65535-计数周期+1。其中TH代表高八位,TL代表低八位。比如定时10ms就为55536,用十六进制表示为D8F0。

/*******************************************************************************
* 函数名         : Int1Init()
* 函数功能		   : 霍尔传感器接收信号
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void Int1Init()
{
	IT1=1;//下降沿触发
	EX1=1;//打开中断0允许
	EA=1;	//打开总中断
}
/*******************************************************************************
* 函 数 名         : Timer0Init
* 函数功能		   : 定时器0初始化
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Timer0Init()
{
	TMOD|=0X11;//选择为定时器0模式,工作方式1,仅用TR0打开启动。

	TH0=0XD8;	//给定时器赋初值,定时10ms
	TL0=0XF0;	
	ET0=1;//打开定时器0中断允许
	EA=1;//打开总中断
	TR0=1;//打开定时器			
}
/*******************************************************************************
* 函 数 名         : Timer1Init
* 函数功能		   : 定时器1初始化
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Timer1Init()
{
	TMOD|=0X11;//选择为定时器1模式,工作方式1,仅用TR1打开启动。

	TH1=0XFF;	//给定时器赋初值,定时100us
	TL1=0X9C;	
	ET1=1;//打开定时器1中断允许
	EA=1;//打开总中断
	TR1=1;//打开定时器			
}

主函数其实就是对所有的函数进行初始化以后,再对数据进行显示,所有控制方式生效都是在后续的定时器中断或者外部中断里面去执行。

*******************************************************************************
* 函数名         : main
* 函数功能		   : 主函数
* 输入           :* 输出         	 :*******************************************************************************/
void main()
{
	unsigned char i;
	beep=1;                           //蜂鸣器不叫
	led=0;
	Int1Init(); 	                    //初始化霍尔传感器外部中断1
	Timer0Init();                     //定时器0初始化
	Timer1Init();                     //定时器1初始化
	LcdInit();
	LcdWriteCom(0x80);
	for(i=0;i<14;i++)
	{
		LcdWriteData(wenzi1[i]);	
	}
	LcdWriteCom(0x80+0x40);
	for(i=0;i<16;i++)
	{
		LcdWriteData(wenzi2[i]);	
	}
	while(1)
	{
		duty2=duty/2;
		if(zhuansu1>=max)beep=0,led=1;
		else beep=1,led=0;
		//按键处理
		keypros();
		//显示转速
	  zhuansu[0]=zhuansu1/10000;
    zhuansu[1]=zhuansu1%10000/1000;
    zhuansu[2]=zhuansu1%10000%1000/100;
    zhuansu[3]=zhuansu1%10000%1000%100/10;
    zhuansu[4]=zhuansu1%10;
		if(zhuansu[0]>9)
		{
			LcdWriteCom(0x80+0x06);			//设置显示位置
			LcdWriteData(0x37+zhuansu[0]);	//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0x80+0x06);
			LcdWriteData(zhuansu[0]+0x30);	//将数值转换为该显示的ASCII码
		}
		
		if(zhuansu[1]>9)
		{
			LcdWriteCom(0x80+0x07);
			LcdWriteData(zhuansu[1]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0x80+0x07);
			LcdWriteData(zhuansu[1]+0x30);		//将数值转换为该显示的ASCII码
		}	
		
		if(zhuansu[2]>9)
		{
			LcdWriteCom(0x80+0x08);
			LcdWriteData(zhuansu[2]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0x80+0x08);
			LcdWriteData(zhuansu[2]+0x30);		//将数值转换为该显示的ASCII码
		}			
		
		if(zhuansu[3]>9)
		{
			LcdWriteCom(0x80+0x09);
			LcdWriteData(zhuansu[3]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0x80+0x09);
			LcdWriteData(zhuansu[3]+0x30);		//将数值转换为该显示的ASCII码
		}			
		
		if(zhuansu[4]>9)
		{
			LcdWriteCom(0x80+0x0a);
			LcdWriteData(zhuansu[4]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0x80+0x0a);
			LcdWriteData(zhuansu[4]+0x30);		//将数值转换为该显示的ASCII码
		}	
    //显示阈值
    Limit[0]=max/10000;
    Limit[1]=max%10000/1000;
    Limit[2]=max%10000%1000/100;
    Limit[3]=max%10000%1000%100/10;
    Limit[4]=max%10;		
		if(Limit[0]>9)
		{
			LcdWriteCom(0xc0+0x06);			//设置显示位置
			LcdWriteData(0x37+Limit[0]);	//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0xc0+0x06);
			LcdWriteData(Limit[0]+0x30);	//将数值转换为该显示的ASCII码
		}
		
		if(Limit[1]>9)
		{
			LcdWriteCom(0xc0+0x07);
			LcdWriteData(Limit[1]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0xc0+0x07);
			LcdWriteData(Limit[1]+0x30);		//将数值转换为该显示的ASCII码
		}	
		
		if(Limit[2]>9)
		{
			LcdWriteCom(0xc0+0x08);
			LcdWriteData(Limit[2]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0xc0+0x08);
			LcdWriteData(Limit[2]+0x30);		//将数值转换为该显示的ASCII码
		}			
		
		if(Limit[3]>9)
		{
			LcdWriteCom(0xc0+0x09);
			LcdWriteData(Limit[3]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0xc0+0x09);
			LcdWriteData(Limit[3]+0x30);		//将数值转换为该显示的ASCII码
		}			
		
		if(Limit[4]>9)
		{
			LcdWriteCom(0xc0+0x0a);
			LcdWriteData(Limit[4]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0xc0+0x0a);
			LcdWriteData(Limit[4]+0x30);		//将数值转换为该显示的ASCII码
		}	
		duty1[0]=duty2/100;
    duty1[1]=duty2/10;
    duty1[2]=duty2%10;
		LcdWriteCom(0xc0+0x0d);
		LcdWriteData(duty1[0]+0x30);		//将数值转换为该显示的ASCII码
		LcdWriteCom(0xc0+0x0e);
		LcdWriteData(duty1[1]+0x30);		//将数值转换为该显示的ASCII码
		LcdWriteCom(0xc0+0x0f);
		LcdWriteData(duty1[2]+0x30);		//将数值转换为该显示的ASCII码
	}
}									 

在三个中断里面,首先先说明外部中断。外部中断里面这个zhuansu2的意思就是在每触发一次下降沿就加1,清零则在timer0里面进行实现。在timer0里面,定义了一个暂态变量i,i累加到200以后执行一次if语句。由于我们单次定时的时间是10ms,所以执行200次以后就是2s钟。2s一到我们就将zhuansu2的值经过处理后赋值给zhuansu1,当然由于这个转速我们无法真正测量,所以就随便在后面乘以了一个2.82,显得有零有整也更加真实一点。同时清零zhuansu2和i,这样再下一个循环zhuansu2这个参量又可以通过外部中断累加。在定时器1里面呢则是输出PWM信号。由于定时器1的速度很快,为100us一次。所以最快可以100us改变一次IO口的输出电平。在里面设置了flag变量,flag变量的作用就是从0累加到200,当我们定义的duty,也就是占空比对应的数值大于flag的时候,就停止运行。当小于flag的时候,out就给高电平,out1就给低电平,这样保证电机处于正转的工作状态。那么想要电机反转也很简单,就是令out给低电平,out1给高电平,本质上就是通过左边电压高于右边或者左边电压低于右边电压来决定的。当我们定义的work_status参数为0时,我们默认不工作,故两个IO口都直接拉高。

/*******************************************************************************
* 函 数 名         : Int1()	interrupt 2
* 函数功能		   : 外部中断1的中断函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Int1()	interrupt 2		//外部中断1的中断函数
{
  zhuansu2++;
}
/*******************************************************************************
* 函 数 名         : void Timer0() interrupt 1
* 函数功能		   : 定时器0中断函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Timer0() interrupt 1
{
	static u16 i;
	TH0=0XD8;	//给定时器赋初值,定时10ms
	TL0=0XF0;
	i++;
	if(i==200)
	{
		 zhuansu1=zhuansu2*30*2.82;
		 zhuansu2=0;
		 i=0;
	}	
}
/*******************************************************************************
* 函 数 名         : void Timer1() interrupt 3
* 函数功能		   : 定时器0中断函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Timer1() interrupt 3
{
  TH1=0xFF;
  TL1=0x9C;//定时100us
	flag++;
	if(flag>199)
	{
     flag=1;
	}	
	if(work_status==1)
	{
		if(flag<=duty)
		{
			out=1;
			out1=0;
		}
		else
		{
			out=1;
			out1=1;
		}
	}
	if(work_status==0)
	{
		out=1;
		out1=1;
	}
}

2.代码

总代码main.c,像LCD的代码和52的代码都是普中科技通用的,copy粘贴一下就行,请注意LCD三个数据口的连接方式,根据板子不同记得更改数据口的顺序。

#include<reg51.h>
#include"lcd.h"
#define uchar unsigned char
#define uint  unsigned int
typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;
void DelayMs(unsigned int );
/*******************************************************************************
* 函数名         : 变量定义
* 函数功能		   : 新的变量
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
unsigned char Limit[5];   //报警阈值存放位置
unsigned int  max=10000;  //设置报警阈值
unsigned char duty1[3];   //报警阈值存放位置
unsigned char zhuansu[5]; //转速存放位置
unsigned int  zhuansu1=0; //显示转速大小
unsigned int  zhuansu2=0; //显示转速大小
unsigned char code wenzi1[14]={"now_V:     m/h"};
unsigned char code wenzi2[16]={"Limit:     m    "};
uint flag=0;
u16 duty=100;              //占空比
u16 duty2=0;
u16 work_status=0;        //工作状态,为0的时候不工作,为1的时候工作
sbit beep=P1^6;
sbit led=P1^5;
sbit out=P3^4;					  //PWM输出用于正传
sbit out1=P3^7;			      //PWM输出用于反转
sbit duty_add=P1^0;				//占空比加1
sbit duty_reduce=P1^1;		//占空比减一
sbit limit_add=P1^2;			//阈值加1
sbit limit_reduce=P1^3;		//阈值减1
sbit start=P1^4;					//开始或者停止工作
/*******************************************************************************
* 函 数 名         : delay
* 函数功能		   : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
	while(i--);	
}
/*******************************************************************************
* 函 数 名         : keypros
* 函数功能		   : 按键处理函数,判断按键K1是否按下
*******************************************************************************/
void keypros()
{
	if(duty_add==0)		  //检测按键K1是否按下
	{	
		delay(1000);   //消除抖动 一般大约10ms
		if(duty_add==0)	 //再次判断按键是否按下
		{
			duty+=1;
		}
		while(!duty_add);	 //检测按键是否松开
	}	
	if(duty_reduce==0)		  //检测按键K1是否按下
	{	
		delay(1000);   //消除抖动 一般大约10ms
		if(duty_reduce==0)	 //再次判断按键是否按下
		{
			duty-=1;
		}
		while(!duty_reduce);	 //检测按键是否松开
	}
	if(limit_add==0)		  //检测按键K1是否按下
	{	
		delay(1000);   //消除抖动 一般大约10ms
		if(limit_add==0)	 //再次判断按键是否按下
		{
			max+=100;
		}
		while(!limit_add);	 //检测按键是否松开
	}
	if(limit_reduce==0)		  //检测按键K1是否按下
	{	
		delay(1000);   //消除抖动 一般大约10ms
		if(limit_reduce==0)	 //再次判断按键是否按下
		{
			max-=100;
		}
		while(!limit_reduce);	 //检测按键是否松开
	}
	if(start==0)		  //检测按键K1是否按下
	{	
		delay(1000);   //消除抖动 一般大约10ms
		if(start==0)	 //再次判断按键是否按下
		{
			work_status+=1;
			if(work_status>=2)work_status=0;
		}
		while(!start);	 //检测按键是否松开
	}	
}
/*******************************************************************************
* 函数名         : Int1Init()
* 函数功能		   : 霍尔传感器接收信号
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void Int1Init()
{
	IT1=1;//下降沿触发
	EX1=1;//打开中断0允许
	EA=1;	//打开总中断
}
/*******************************************************************************
* 函 数 名         : Timer0Init
* 函数功能		   : 定时器0初始化
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Timer0Init()
{
	TMOD|=0X11;//选择为定时器0模式,工作方式1,仅用TR0打开启动。

	TH0=0XD8;	//给定时器赋初值,定时10ms
	TL0=0XF0;	
	ET0=1;//打开定时器0中断允许
	EA=1;//打开总中断
	TR0=1;//打开定时器			
}
/*******************************************************************************
* 函 数 名         : Timer1Init
* 函数功能		   : 定时器1初始化
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Timer1Init()
{
	TMOD|=0X11;//选择为定时器1模式,工作方式1,仅用TR1打开启动。

	TH1=0XFF;	//给定时器赋初值,定时100us
	TL1=0X9C;	
	ET1=1;//打开定时器1中断允许
	EA=1;//打开总中断
	TR1=1;//打开定时器			
}
/*******************************************************************************
* 函数名         : main
* 函数功能		   : 主函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void main()
{
	unsigned char i;
	beep=1;                           //蜂鸣器不叫
	led=0;
	Int1Init(); 	                    //初始化霍尔传感器外部中断1
	Timer0Init();                     //定时器0初始化
	Timer1Init();                     //定时器1初始化
	LcdInit();
	LcdWriteCom(0x80);
	for(i=0;i<14;i++)
	{
		LcdWriteData(wenzi1[i]);	
	}
	LcdWriteCom(0x80+0x40);
	for(i=0;i<16;i++)
	{
		LcdWriteData(wenzi2[i]);	
	}
	while(1)
	{
		duty2=duty/2;
		if(zhuansu1>=max)beep=0,led=1;
		else beep=1,led=0;
		//按键处理
		keypros();
		//显示转速
	  zhuansu[0]=zhuansu1/10000;
    zhuansu[1]=zhuansu1%10000/1000;
    zhuansu[2]=zhuansu1%10000%1000/100;
    zhuansu[3]=zhuansu1%10000%1000%100/10;
    zhuansu[4]=zhuansu1%10;
		if(zhuansu[0]>9)
		{
			LcdWriteCom(0x80+0x06);			//设置显示位置
			LcdWriteData(0x37+zhuansu[0]);	//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0x80+0x06);
			LcdWriteData(zhuansu[0]+0x30);	//将数值转换为该显示的ASCII码
		}
		
		if(zhuansu[1]>9)
		{
			LcdWriteCom(0x80+0x07);
			LcdWriteData(zhuansu[1]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0x80+0x07);
			LcdWriteData(zhuansu[1]+0x30);		//将数值转换为该显示的ASCII码
		}	
		
		if(zhuansu[2]>9)
		{
			LcdWriteCom(0x80+0x08);
			LcdWriteData(zhuansu[2]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0x80+0x08);
			LcdWriteData(zhuansu[2]+0x30);		//将数值转换为该显示的ASCII码
		}			
		
		if(zhuansu[3]>9)
		{
			LcdWriteCom(0x80+0x09);
			LcdWriteData(zhuansu[3]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0x80+0x09);
			LcdWriteData(zhuansu[3]+0x30);		//将数值转换为该显示的ASCII码
		}			
		
		if(zhuansu[4]>9)
		{
			LcdWriteCom(0x80+0x0a);
			LcdWriteData(zhuansu[4]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0x80+0x0a);
			LcdWriteData(zhuansu[4]+0x30);		//将数值转换为该显示的ASCII码
		}	
    //显示阈值
    Limit[0]=max/10000;
    Limit[1]=max%10000/1000;
    Limit[2]=max%10000%1000/100;
    Limit[3]=max%10000%1000%100/10;
    Limit[4]=max%10;		
		if(Limit[0]>9)
		{
			LcdWriteCom(0xc0+0x06);			//设置显示位置
			LcdWriteData(0x37+Limit[0]);	//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0xc0+0x06);
			LcdWriteData(Limit[0]+0x30);	//将数值转换为该显示的ASCII码
		}
		
		if(Limit[1]>9)
		{
			LcdWriteCom(0xc0+0x07);
			LcdWriteData(Limit[1]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0xc0+0x07);
			LcdWriteData(Limit[1]+0x30);		//将数值转换为该显示的ASCII码
		}	
		
		if(Limit[2]>9)
		{
			LcdWriteCom(0xc0+0x08);
			LcdWriteData(Limit[2]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0xc0+0x08);
			LcdWriteData(Limit[2]+0x30);		//将数值转换为该显示的ASCII码
		}			
		
		if(Limit[3]>9)
		{
			LcdWriteCom(0xc0+0x09);
			LcdWriteData(Limit[3]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0xc0+0x09);
			LcdWriteData(Limit[3]+0x30);		//将数值转换为该显示的ASCII码
		}			
		
		if(Limit[4]>9)
		{
			LcdWriteCom(0xc0+0x0a);
			LcdWriteData(Limit[4]+0x37);		//将数值转换为该显示的ASCII码
		}
		else
		{
			LcdWriteCom(0xc0+0x0a);
			LcdWriteData(Limit[4]+0x30);		//将数值转换为该显示的ASCII码
		}	
		duty1[0]=duty2/100;
    duty1[1]=duty2/10;
    duty1[2]=duty2%10;
		LcdWriteCom(0xc0+0x0d);
		LcdWriteData(duty1[0]+0x30);		//将数值转换为该显示的ASCII码
		LcdWriteCom(0xc0+0x0e);
		LcdWriteData(duty1[1]+0x30);		//将数值转换为该显示的ASCII码
		LcdWriteCom(0xc0+0x0f);
		LcdWriteData(duty1[2]+0x30);		//将数值转换为该显示的ASCII码
	}
}									 
/*******************************************************************************
* 函 数 名         : Int1()	interrupt 2
* 函数功能		   : 外部中断1的中断函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Int1()	interrupt 2		//外部中断1的中断函数
{
  zhuansu2++;
}
/*******************************************************************************
* 函 数 名         : void Timer0() interrupt 1
* 函数功能		   : 定时器0中断函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Timer0() interrupt 1
{
	static u16 i;
	TH0=0XD8;	//给定时器赋初值,定时10ms
	TL0=0XF0;
	i++;
	if(i==200)
	{
		 zhuansu1=zhuansu2*30*2.82;
		 zhuansu2=0;
		 i=0;
	}	
}
/*******************************************************************************
* 函 数 名         : void Timer1() interrupt 3
* 函数功能		   : 定时器0中断函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Timer1() interrupt 3
{
  TH1=0xFF;
  TL1=0x9C;//定时100us
	flag++;
	if(flag>199)
	{
     flag=1;
	}	
	if(work_status==1)
	{
		if(flag<=duty)
		{
			out=1;
			out1=0;
		}
		else
		{
			out=1;
			out1=1;
		}
	}
	if(work_status==0)
	{
		out=1;
		out1=1;
	}
}

总结

实测效果还不错,可以用来实战演练一番。文章来源地址https://www.toymoban.com/news/detail-426618.html

到了这里,关于基于51单片机的直流电机转速显示+加速减速启停的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 51单片机-直流电机学习

    51单片机采用的是5V的直流电机 轴长:8mm 轴径:2mm 电压:1-6V 参考电流:0.35-0.4A 3V 转速:17000-18000 转每分钟 直流电机的结构应由 定子 和 转子 两大部分组成。 直流电机运行时静止不动的 部分称为定子 定子的主要作用是产生磁场,由机座、主磁极、 换向极、 端盖、 轴承和

    2024年02月09日
    浏览(43)
  • 通过51单片机实现直流电机调速

    随着各种工业生产设备和机械设备的广泛使用,直流电机调速技术的研究和应用越来越受到人们的重视,具有广泛的应用前景。本项目通过51单片机实现直流电机调速功能,为实际工程应用提供一个可靠和有效的调速方案。 如果需要下载项目工程,可以去这里: https://blog.c

    2024年02月14日
    浏览(43)
  • 51单片机-PWM调速(直流电机,智能小车的电机调速)

    这次来对PWM做一个总结 最近学习时,发现PWM控制在很多地方都会用到,比如使用PWM来控制电机的速度,使用PWM来生成想要的波形。 那么到底什么是PWM呢? PWM即 脉冲宽度调制 ,在具有惯性的系统中,可以通过对 一系列脉冲的宽度进行调制 ,来等效的获得所需要的模拟参量。

    2024年02月02日
    浏览(46)
  • 【51单片机】直流电机驱动(PWM)(江科大)

    · 直流电机是一种将电能转换为机械能的装置。一般的直流电机有两个电极,当电极正接时,电机正转,当电极反接时,电机反转 · 直流电机主要由永磁体(定子)、线圈(转子)和换向器组成 · 除直流电机外,常见的电机还有步进电机、舵机、无刷电机、空心杯电机等 电机的驱动无法

    2024年02月20日
    浏览(46)
  • 【51单片机】直流电机的驱动和PWM调速

    51单片机驱动直流电机与 PWM 调速是通过使用 51 单片机来控制直流电机的转速和方向。51 单片机通过控制电机的电流来实现驱动,并通过生成 PWM 信号来调节电机的转速。使用 PWM 调速可以使得直流电机的转速精确可控,并且减少了电机的功率损耗。在 51 单片机的控制系统中,

    2023年04月09日
    浏览(39)
  • 【Proteus仿真】【51单片机】直流电机PID调速系统设计

    本项目使用Proteus8仿真51单片机控制器,使用L298N电机模块、数码管模块、按键模块、LED指示灯模块等。 主要功能: 系统运行后,可通过按键K4启动系统,数码管显示实际速度和目标速度,再次按下K4键停止系统;按键K1加速、按键K2减速,按键K3换向;速度范围为0-150;通过P

    2024年02月11日
    浏览(87)
  • 基于单片机串口控制直流电机调速

    一、系统方案 (2)本设计采用STC89C5单片机作为主控器,串口控制直流电机调速,串口助手发送1-8,改变电机速度,数码管显示对应速度。 二、硬件设计 原理图如下: 三、单片机软件设计 1、首先是系统初始化 TMOD=0x21;//定时器0工作方式1 ET1=0; SM0=0; SM1=1; REN=1; EA=1; ES=1; 2、数码管

    2024年02月12日
    浏览(46)
  • 基于STM32单片机的直流电机PWM调速(数码管显示)(Proteus仿真+程序)

          由 STM32单片机+数码管显示模块+键盘模块+L298N电机驱动模块+直流电机 1、采用STM32F103单片机为主控制器 2、四个按键,分别为启动/暂停、方向切换、加速、减速功能 3、数码管显示PWM占空比和电机转动方向(0正转,1反转) 注意:proteus8.11版本才能打开   24、基于STM32单

    2024年02月11日
    浏览(59)
  • 基于STM32单片机直流电机控制加减速正反转系统proteus仿真原理图程序

    功能: 0.本项目采用STM32F103C8T6作为单片机系统的控制MCU 1.通过按键可以控制电机,正转、反转、加速、减速、停止。 2.总共六个功能按键可实现正转、反转、加速、减速、停止。 3.启停和正反转均有指示灯,测试采用的霍尔传感器方案 4.采用DC002作为电源接口可直接输入5V给

    2024年02月12日
    浏览(54)
  • 【单片机】11-步进电机和直流电机

    电能转换为动能 (1) 交流电机【大功率】 :两相【200W左右】,三相【1000W左右】 (2) 直流电机【小功率】 :永磁【真正的磁铁】,励磁【电磁铁】 (3) 步进电机【精确控制功率】,伺服电机【非常精确功率】 (1)外观 (2)接线和工作原理 在电池位置有VCC和GND (3)

    2024年02月03日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包