Speed measurement based on 51 microcontroller and Hall sensor

Project code:
Link: https://pan.baidu.com/s/1vK3i5r0wnks7lWC4yUP8Jg
Extraction code: vwu0

1. Introduction to small projects

It mainly uses stc89c51/52 microcontroller as the main control, and the Hall sensor as the basic module for speed measurement. The buttons are used to control the speed, and the digital tube displays the current speed.

The final product picture is as follows:
Insert image description here

Please add image description

2. Power supply part

1. The power of the power supply should be as high as possible. I use a Romans power bank for power supply (5V, 2.1A output port). Because the power supply is too small, it will cause hardware bugs such as the motor being unable to drive or the digital tube flickering.
2. If the voltage of the power supply is higher than 5V, a voltage stabilizing circuit needs to be used at the power input end to stabilize the input voltage to 5V to power the microcontroller and other peripherals. Prevent device damage caused by excessive voltage.

3. Hardware part

1. Minimum system of stc89c51/52
Insert image description here
Note: If the general USB interface is used for power supply, when the motor rotates, the power supply to the pins of the microcontroller may be unstable, so it is necessary to remove the external pull-up of the IO of the microcontroller. The P3 port is not required.
The 9-pin resistor is as follows: the end with the small dot is the common end and needs to be connected to the 5V power supply. The other ports can be welded to the microcontroller pins one by one.
Insert image description here
2. Hall sensor.
Insert image description here
Pay attention to the pins. Look at the pin sequence on the narrow side:
Insert image description here
the VOUT port here can be directly connected to the external interrupt port 1 of the microcontroller, and can be supplied to the microcontroller through a voltage comparator lm393 or the like. 3. The output current of the IO port of the DC motor drive 51 microcontroller is too small, and the effect of driving the DC motor is not obvious, and it cannot achieve the later speed change. You need to use a transistor (9015\9013 type) amplifier circuit to drive the motor
Insert image description here
:
The demonstration circuit is as follows: (modify the resistance according to your needs)
Insert image description here
4. Common cathode digital tube

 //数码管位选
sbit S1=P2^4;	 
sbit S2=P2^5;   
sbit S3=P2^6;	 
sbit S4=P2^7;  

//数码管段选:P1的八个IO口。连线的时候一定根据下列图示的段选(注意注意注意:容易连错)

Insert image description here

4. Software part

1. Overall diagram of software engineering:
Insert image description here

2.main.c file code:
Create a keil project file for the 51 microcontroller yourself, copy the following code to the main.c file under your own project file and replace it.

/**************************************************************************************
*		              基于51单片机测速											  *
实现现象:按下按键K1减速
         按下按键K2加速
				 外部中断1对应IO口P3^3
注意事项:电机速度不能过快,否则会造成数码管显示不稳定	
***************************************************************************************/

#include "reg52.h"    //此文件中定义了单片机的一些特殊功能寄存器


typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;

//测试端口(根据自己需要决定)
sbit led=P0^0;	   //将单片机的P0.0端口定义为led

/**************************************************************************************
****************************核心部分*************************************************
***************************************************************************************/
//占空比
u16 time = 0;  // 定义占空比的变量
u16 count=30;  //定义占空比上限
sbit PWM=P0^1;//  P0.1输出pwm

//速度
u16 zhuansu=0;   //转速初值为0
u16 jishu = 0;   //jishu的变量初值为0
u8 flag = 0;     //定时器1计数变量
//按键
sbit k1=P2^0;	 
sbit k2=P2^1;   
sbit k3=P2^2;	 
sbit k4=P2^3;  

//数码管位选
sbit S1=P2^4;	 
sbit S2=P2^5;   
sbit S3=P2^6;	 
sbit S4=P2^7;  

//数码管位选:P1的八个IO口

//共阴数码管段选
u8 code smgduan[]={
    
    0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
					0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值

//数码管存储中间变量
unsigned char Display_data[4];
/*******************************************************************************
* 函 数 名         : delay
* 函数功能		   : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
    
    
	while(i--);	
}


//定时器和外部中断1的初始化函数
void InitSyetem()
{
    
    	
	
	//配置外部中断1:采集霍尔传感器触发下降沿
	IT1 = 1;      //选择下降沿触发
	EX1 = 1;      //打开外部中断1	
	
	//定时器0,1工作方式1
	TMOD=0x11; //定时或者计数模式控制寄存器
	//定时器0配置:产生PWM波
	TH0=(65536-10)/256;//赋初值定时10us
	TL0=(65536-10)%256;//s
	ET0=1;//开定时器0中断
	TR0=1;//启动定时器0 	
	
	//定时1:测速
	TH1=(65536-10000)/256;//赋初值定时10ms
	TL1=(65536-10000)%256;
	ET1=1;//开定时器0中断
	TR1=1;//启动定时器0 	
	
	PX1=1;//设置优先级
	PT1=1;//设定定时器1为最高优先级
	EA=1;//开总中断
}

//外部1中断服务函数
void Service_Int1() interrupt 2
{
    
    
    jishu++;    //霍尔下降沿一次就记一次数
	  if(jishu == 100)  //累加计数有100次,总时间为100 * 10ms = 1s
		{
    
    
			led^=led;   //led闪烁
		}
}


//定时0处理函数产生PWM 调速原理———在PWM高电平时候驱动电机转动 在PWM低电平时候让电机停止转动
void Service_Timer0() interrupt 1
{
    
    
	TR0=0;//赋初值时,关闭定时器
	TH0=(65536-10)/256;//赋初值定时
	TL0=(65536-10)%256;//0.01ms
	TR0=1;
	
	time++;   //计数变量
	if(time>=100) time= 0;  //清零标志变量
	if(time<=count)  //小于设定值,输出高电平
	{
    
    
		PWM = 1;
	}
	else
		PWM = 0;
}

//定时器1中断处理显示转速
void Service_Timer1() interrupt 3				 
{
    
    
	TR1=0;//赋初值时,关闭定时器 
  TH1=(65536 - 10000) / 256;
  TL1=(65536 - 10000) % 256;//定时10ms
	TR1=1;
  flag++;  	      //计数变量加    
  if(flag==100)		//计时到达1s 测量此时的转速
  {
    
    
//			led=~led;	  //led状态取反
			zhuansu = jishu;   //监测霍尔传感器总共计数次数  
			jishu=0;					//转速置0
			flag=0;           //清除计数变量
	}
}

//数码管处理函数
void Deal_data()
{
    
    
	 Display_data[3]=smgduan[zhuansu/1000];  //数码管高位
	 Display_data[2]=smgduan[zhuansu/100%10];//去第二位
	 Display_data[1]=smgduan[zhuansu/10%10];
	 Display_data[0]=smgduan[zhuansu%10];    //数码管低位
}

/*******************************************************************************
* 函 数 名         : DigDisplay
* 函数功能		   : 数码管动态扫描函数,循环扫描4个数码管显示
******************************************************      *************************/
void DigDisplay()
{
    
    
	u8 i;	
	for(i=0;i<4;i++)
	{
    
    
		switch(i)	 //位选,选择点亮的数码管,
		{
    
    
			case 0 : S1 = 0; S2 = 1; S3 = 1; S4 = 1;break;  //点亮第一位数码管
			case 1 : S2 = 0; S1 = 1; S3 = 1; S4 = 1;break;
			case 2 : S3 = 0; S1 = 1; S2 = 1; S4 = 1;break;
			case 3 : S4 = 0; S1 = 1; S2 = 1; S3 = 1;break;			
		}
		P1=Display_data[i];//发送段码
		delay(5); //间隔一段时间扫描 时间越少,一起亮且显示越稳定;时间越多,是流水点亮
		P1=0x00;//消隐	   时间过快时,每个数码管将会有重影
	}
}


/*******************************************************************************
* 函 数 名         : keypros
* 函数功能		   : 按键处理函数,判断按键K1是否按下
*******************************************************************************/
void keypros()
{
    
    
	if(k1==0)		  //检测按键K1是否按下
	{
    
    	
		delay(100);   //消除抖动 一般大约10ms 时间的估算100*n=1(s)
		if(k1==0)	 //再次判断按键是否按下
		{
    
    
			led=~led;	  //led状态取反
			count+=10;
			if(count >= 90)  //设置一个上限
			count+=90;
		}
		while(!k1);	 //检测按键是否松开	为假时候说明按键没有释放
	}	
	if(k2==0)		  //检测按键K1是否按下
	{
    
    	
		delay(100);   //消除抖动 一般大约10ms
		if(k2==0)	 //再次判断按键是否按下
		{
    
    
			led=~led;	  //led状态取反
			count-=10;
			if(count <= 10)
			{
    
    
				count = 10;
			}
		}
		while(!k2);	 //检测按键是否松开
	}	

}

/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{
    
    
  	led = 0;     //上电熄灭小灯
	P1 = 0x00;   //上电初始化熄灭数码管
  	InitSyetem();//定时器和外部中断1的初始化函数
	while(1)
	{
    
    
		keypros();   //按键处理函数
		Deal_data(); //数据处理函数
		DigDisplay(); //数码管显示函数
	}		
}

	

Guess you like

Origin blog.csdn.net/weixin_44236302/article/details/123703448