首页 > 其他分享 >基于51单片机车速测量控制

基于51单片机车速测量控制

时间:2024-06-09 11:28:52浏览次数:17  
标签:Write 51 unsigned 车速 char 单片机 LCD sbit define

基于51单片机车速测量控制

(仿真+程序)

功能介绍

具体功能:

1.通过L298驱动直流电机模拟转动;

2.LCD1602显示转动状态和速度;

3.按键可以控制启动/停止、加/减速、正/反转;

​演示视频:

<iframe allowfullscreen="true" data-mediaembed="bilibili" frameborder="0" id="H7vJdHSY-1717641914137" src="https://player.bilibili.com/player.html?aid=1605429221"></iframe>

基于51单片机车速测量控制 

添加图片注释,不超过 140 字(可选)

程序

#include <REG52.H>
#include <intrins.h>

#define uchar unsigned char	 //宏定义方便以后用
#define uint unsigned int  
#define ulong unsigned long
#define CLK_WISE 0//顺时针方向转动
#define INVERSE 1//逆时针方向转动
#define HIGH 2//高电平
#define LOW 1//低电平
#define NULL 0//低电平

uchar levelflag=0;//高低电平标志,取值为HIGH或LOW,分别代表高电平和低电平,或为NULL
bit direction=CLK_WISE;/***方向标志,取值为CLK_WISE 或INVERSE*/
char speedcount=1;//加速标志,越大转速越快,最大到10循环。
						//程序中可以依据它来改变占空比
uchar highcount;	//记录高电平定时次数
bit  start_flag=0;	//启动标志
int Motor_speed=0;//电机的速度

uchar motor_time_count=0;
sbit CTRL0=P1^0;//CTRL0为高电平,CTRL1为低电平时顺时针方向转动
sbit CTRL1=P1^1;//CTRL0为低电平,CTRL1为高电平时逆时针方向转动
//定义按键的接口
sbit K1= P2^5;
sbit K2= P2^6;
sbit K3= P2^7;
sbit K4= P3^0;
sbit K5= P3^1;

//LCD port
sbit LcdRs= P2^0;
sbit LcdRw= P2^1;
sbit LcdEn= P2^2;
sfr  DBPort= 0x80;		//P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口


//向LCD写入命令或数据************************************************************
#define LCD_COMMAND			0      // Command
#define LCD_DATA			1      // Data
#define LCD_CLEAR_SCREEN	0x01      // 清屏
#define LCD_HOMING  		0x02      // 光标返回原点


//设置显示模式************************************************************
#define LCD_SHOW			0x04    //显示开
#define LCD_HIDE			0x00    //显示关	  

#define LCD_CURSOR			0x02 	//显示光标
#define LCD_NO_CURSOR		0x00    //无光标		     

#define LCD_FLASH			0x01    //光标闪动
#define LCD_NO_FLASH		0x00    //光标不闪动
//内部等待函数**************************************************************************
unsigned char LCD_Wait(void)
{
	LcdRs=0;
	LcdRw=1;	_nop_();
	LcdEn=1;	_nop_();
	//while(DBPort&0x80);//在用Proteus仿真时,注意用屏蔽此语句,在调用GotoXY()时,会进入死循环,
						 //可能在写该控制字时,该模块没有返回写入完备命令,即DBPort&0x80==0x80
						 //实际硬件时打开此语句
	LcdEn=0;
	return DBPort;		
}

void LCD_Write(bit style, unsigned char input)
{
	LcdEn=0;
	LcdRs=style;
	LcdRw=0;		_nop_();
	DBPort=input;	_nop_();//注意顺序
	LcdEn=1;		_nop_();//注意顺序
	LcdEn=0;		_nop_();
	LCD_Wait();	
}

void LCD_SetDisplay(unsigned char DisplayMode)
{
	LCD_Write(LCD_COMMAND, 0x08|DisplayMode);	
}

//设置输入模式************************************************************
#define LCD_AC_UP			0x02
#define LCD_AC_DOWN			0x00      // default

#define LCD_MOVE			0x01      // 画面可平移
#define LCD_NO_MOVE			0x00      //default

void LCD_SetInput(unsigned char InputMode)
{
	LCD_Write(LCD_COMMAND, 0x04|InputMode);
}


//初始化LCD************************************************************
void LCD_Initial()
{
	LcdEn=0;
	LCD_Write(LCD_COMMAND,0x38);           //8位数据端口,2行显示,5*7点阵
	LCD_Write(LCD_COMMAND,0x38);
	LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR);    //开启显示, 无光标
	LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);   //清屏
	LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE);       //AC递增, 画面不动
}

//************************************************************************
void GotoXY(unsigned char x, unsigned char y)
{
	if(y==0)
		LCD_Write(LCD_COMMAND,0x80|x);
	if(y==1)
		LCD_Write(LCD_COMMAND,0x80|(x-0x40));
}

void Print(unsigned char *str)	 //在LCD上显示数据,内部调用
{
	while(*str!='\0')
	{
		LCD_Write(LCD_DATA,*str);
		str++;
	}
}

void LCD_Print(unsigned char x, unsigned char y, unsigned char *str) //指定的位置打印指定数据
{
  GotoXY(x,y);
  Print(str);
}

void LCD_Print_num(unsigned char x, unsigned char y,long int num) //指定的位置显示数值
{
 uchar temp_tab[7]=0;
 uchar i=0;
 GotoXY(x,y);
  if(num<0)
  {
	  num=0-num;
	  LCD_Write(LCD_DATA,'-');
  }
  temp_tab[0]=num/1000000%10+0x30;
  temp_tab[1]=num/100000%10+0x30;
  temp_tab[2]=num/10000%10+0x30;
  temp_tab[3]=num/1000%10+0x30;
  temp_tab[4]=num/100%10+0x30;  
  temp_tab[5]=num/10%10+0x30;
  temp_tab[6]=num%10+0x30;
  for(i=0;i<7;i++)
  {
	 if(temp_tab[i]!=0x30)break;
  }
  
  if(i==7)
  {
	 LCD_Write(LCD_DATA,0x30);
  }
  else
  {
	  while(i<7)
	  {
		  LCD_Write(LCD_DATA,temp_tab[i]);
		  i++;
	  }
  }
}

/****延时****/
void delay(uint i)
{
	while(i--);
}

/*****改变转向*****/
void run(void)
{
	if(direction==CLK_WISE)	//顺时针转
	{
		CTRL1=0;
		if(levelflag==HIGH)//高电平
		{
			levelflag=NULL;
			CTRL0=1;
		}
		if(levelflag==LOW)//低电平
		{
			levelflag=NULL;
			CTRL0=0;
		}
	}
	if(direction==INVERSE)	//逆时针转
	{
		CTRL0=0;
		if(levelflag==HIGH)//高电平
		{
			levelflag=NULL;
			CTRL1=1;
		}
		if(levelflag==LOW)//低电平
		{
			levelflag=NULL;
			CTRL1=0;
		}
	}
	
}
//*********************************
//按键扫描程序
//mode:0,不支持连续按;1,支持连续按;
//*********************************
uchar KEY_Scan(uchar mode)
{	 
	static uchar key_up=1;//按键按松开标志
	if(mode)key_up=1;  //支持连按		  
	if(key_up&&(K1==0||K2==0||K3==0||K4==0||K5==0))
	{
		delay(5);//去抖动 
		key_up=0;
		if(K1==0)return 1;
		else if(K2==0)return 2;
		else if(K3==0)return 3;
		else if(K4==0)return 4;
		else if(K5==0)return 5;
	}else if(K1==1&&K2==1&&K3==1&&K4==1&&K5==1)key_up=1; 	    
 	return 0;// 无按键按下
}
//******************************
//**定时器初始化
//******************************
void Time_Init(void)
{
 	TMOD=0x15;
	ET0=0;//定时器0初始化
	TR0=1;
	TH1=(65536-10000)/256;//0xff;
	TL1=(65536-10000)%256;//0xCE;
	ET1=1;
	TR1=1;
	EA=1;
}
//*****************************
//**显示数据
//*****************************
void Display_data(void)
{ 
	if(start_flag==0)
	{
		LCD_Print(0,0,"Direction: STOP  "); //显示正转
		LCD_Print(0,1,"Speed:"); //显示速度
		LCD_Print_num(0,2,Motor_speed);
		LCD_Print(0,3,"m/min         ");
	}
	else
	{

 
	   if(direction==0)	  //正转
	   {
		   LCD_Print(0,0,"Direction: FWD  "); //显示正转
		   LCD_Print(0,1,"Speed:+"); //显示速度
		   LCD_Print_num(0,2,Motor_speed);
		   LCD_Print(0,3,"m/min");
		   
	   }
	   else
	   {
		   LCD_Print(0,0,"Direction: REV  "); //显示反转
		   LCD_Print(0,1,"Speed:-"); //显示速度
		   LCD_Print_num(0,2,Motor_speed);
		   LCD_Print(0,3,"m/min");
	   }

   }
}

void main()
{	
	uchar Key_num=0;
	LCD_Initial();
	Time_Init();
    LCD_Print(0,0,"Hello"); //
	LCD_Print(0,1,"Welcome to use!"); //显示欢迎
	delay(60000);  //延时
	delay(60000);
	delay(60000);
	delay(60000);

	while(1)
	{
		Key_num = KEY_Scan(0); //扫描按键
		switch(Key_num)
		{
		   case 1://启动
		   start_flag=1;
		   break;
		   case 2://加速
		   speedcount++;//记录加减速次数		
		if(speedcount>10)
			speedcount=10;//最大为10,然后从0开始循环。
		   break;
			case 3://减速
			speedcount--;//记录加减速次数		
		if(speedcount<1)
			speedcount=0;//最大为10,然后从0开始循环。
			break;
			
			case 4:	//反转
			direction=!direction;
			break;
			case 5:	//停止
			start_flag=0;
			break;

		}
		if(start_flag)	//启动
		{
			run();
		}
		else  		//停止
		{
		  CTRL0=0;
		  CTRL1=0;
		}

		if(motor_time_count>=30) //30*10=300ms
		{
			motor_time_count=0;
			Motor_speed=((TH0<<8)+TL0);//r/min
			Motor_speed=Motor_speed*1.9;
			TH0=0;
			TL0=0;	
		}

		Display_data();
	 
	}
}
										  

硬件设计

使用元器件:

单片机:AT89C52;

(注意:单片机是通用的,无论51还是52、无论stc还是at都一样,引脚功能都一样。程序也是一样的。)

添加图片注释,不超过 140 字(可选)

设计资料

01仿真图

本设计使用proteus7.8和proteus8.9两个版本设计!具体如图!

添加图片注释,不超过 140 字(可选)

02程序

本设计使用软件keil5版本编程设计!具体如图!

添加图片注释,不超过 140 字(可选)

03设计资料

        资料获取请关注同名公众号,全部资料包括仿真源文件 、程序(含注释)等。具体内容如下,全网最全! !

资料获取请观看前面演示视频!

点赞分享一起学习成长。

标签:Write,51,unsigned,车速,char,单片机,LCD,sbit,define
From: https://blog.csdn.net/2401_82402501/article/details/139521816

相关文章

  • ATcoder ABC 351 补题记录(A~F)
    A按照顺序直接模拟即可。#pragmaGCCoptimize(3)#include<bits/stdc++.h>#defineintlonglong#definepbpush_back#defineememplace_back#defineF(i,x,y)for(inti=x;i<=y;i++)#defineG(i,x,y)for(inti=x;i>=y;i--)#defineW(G,i,x)for(auto&i:G[x......
  • 51单片机八个灯连续闪烁实例展示
    声明:该内容皆为原创,仅供业内人士相互学习交流经验,任何未经授权复制、转载、传播或使用本网站(或应用程序)内容的行为,将受到法律的制裁。如因侵权行为给本网站(或应用程序)或任何第三方造成损失的,侵权人应当承担相应的法律责任)原理图实现:Proteus8Professional执行代码实现:μVis......
  • 【leetcode 1510 石子游戏】【记忆化搜索】
    存在和对于一切的语言importjava.util.Arrays;classSolution{publicbooleanwinnerSquareGame(intn){dp=newBoolean[n+1];dp2=newBoolean[n+1];Arrays.fill(dp,null);Arrays.fill(dp2,null);dp[0]=fa......
  • 基于51单片机蓄电池充电器过充过放保护控制电路系统
    **单片机设计介绍,基于51单片机蓄电池充电器过充过放保护控制电路系统文章目录一概要二、功能设计设计思路三、软件设计原理图五、程序六、文章目录一概要  基于51单片机蓄电池充电器过充过放保护控制电路系统概要如下:一、系统背景与意义蓄电池作为电子......
  • 基于51单片机自动防火卷帘门烟雾检测报警步进电机
    **单片机设计介绍,基于51单片机自动防火卷帘门烟雾检测报警步进电机文章目录一概要二、功能设计设计思路三、软件设计原理图五、程序六、文章目录一概要  基于51单片机自动防火卷帘门烟雾检测报警步进电机概要如下:一、系统概述本系统旨在通过51单片机实......
  • 基于单片机超市存物箱存包柜储物柜管理密码锁系统
    **单片机设计介绍,基于单片机超市存物箱存包柜储物柜管理密码锁系统文章目录一概要二、功能设计设计思路三、软件设计原理图五、程序六、文章目录一概要  基于单片机超市存物箱存包柜储物柜管理密码锁系统的概要可以从以下几个方面进行阐述:一、设计背景......
  • 基于51单片机红外避障车辆汽车测速仪表系统设计
    **单片机设计介绍,基于51单片机红外避障车辆汽车测速仪表系统设计文章目录一概要二、功能设计设计思路三、软件设计原理图五、程序六、文章目录一概要  基于51单片机红外避障车辆汽车测速仪表系统设计概要如下:一、设计背景与意义随着汽车技术的快速发展......
  • 基于51垃圾箱自动分类_加料机_快递物流分拣器系统设计
    **单片机设计介绍,基于51垃圾箱自动分类_加料机_快递物流分拣器系统设计文章目录一概要二、功能设计设计思路三、软件设计原理图五、程序六、文章目录一概要  基于51单片机的垃圾箱自动分类、加料机及快递物流分拣器系统设计概要如下:一、系统组成核心控......
  • 基于MSP430单片机超声波测距仪倒车防撞报警器系统
    **单片机设计介绍,基于MSP430单片机超声波测距仪倒车防撞报警器系统文章目录一概要二、功能设计设计思路三、软件设计原理图五、程序六、文章目录一概要  基于MSP430单片机超声波测距仪倒车防撞报警器系统概要如下:一、系统组成MSP430单片机核心电路:作为......
  • Codeforces Round 951 (Div. 2)
    A题没什么好说的。B题目读懂了基本就会了。首先很明显,如果x和y的某一位不一样,那这两位异或同一个数字自然也是不一样的。所以要做的就是找到二进制里面最长的连续相同的数量。这个时候看看样例,148全是2的整数次方,33554432,计算器算一下,发现居然也是。那就非常明显了。直接......