51单片机控制电动机正反转,PWM调速,记录转动圈数。

今天的实验需要用到的材料有:51单片机最小系统,4X4的矩阵键盘,DC直流6V-12V带编码器电机,L298N模块,一个led小灯。下面把产品截图展示一下:

单片机就不展示了,都一样,下面是接线图:

下面是电机的脉冲信号接法:4个脉冲1圈,图中单片机处接到51单片机的P3.2口,外部中断0

接下来就是我组装完了的一张图片了。

下面介绍一下程序的大体流程:按A键正转,按B键反转,0停止,1到9设置脉冲的高电平占用的百分比,10%到90%,也就是1最慢,9最快了。还能再快,没有写,到100%就是最快了,不管什么情况下,转够十圈都会停止转动。

下面就是整个程序,有注释,程序测试没有问题,特此记录:

#include<reg52.h>
sbit IN1=P3^5;   //接L298N 7
sbit IN2=P3^6;   //接L298N 6
sbit EN1=P3^7;   //接L298N 5
sbit LED=P2^7;   //接一个小led灯检测信号用

#define uc unsigned char
#define uint unsigned int
	
uint dat_H[2];  // 定时器初值的高位取值数组
uint dat_L[2];  // 定时器初值的低位取值数组
uint num=1000;   // 定时器的定时时间(高电平时间为0.1毫秒)

uc flag=0;   //记录按键是否被按下的标志
uc count=0;  //用来记录电机转的圈数,4个数为1圈

//电动机停止函数
void motor_stop()
{
	IN1=1;
	IN2=1;
	EN1=1;
	EA=0;
}

//电动机正转函数
void motor_zheng()
{
	IN1=1;
	IN2=0;
	EA = 1;
}

//电动机反转函数
void motor_fan()
{
	IN1=0;
	IN2=1;
	EA = 1;
}


//数据初始化
void dat_init()
{
	dat_H[0]=(65536-(10000-num))/256;
	dat_L[0]=(65536-(10000-num))%256;
	
	dat_H[1]=(65536-num)/256;
	dat_L[1]=(65536-num)%256;
	
}

void key()
{
	uc temp=0, temp1=0, temp2=0;
	P0 = 0x0F;
	if(P0 != 0x0F && flag == 0)
	{
		flag=1;    
	}
	if(P0 != 0x0F && flag == 1)
	{
		flag=0;    // 
		temp1 = P0;
	}
	
	P0 = 0xF0;
	if(P0 != 0xF0  && flag == 0)
	{
		flag = 1;//temp2 = P0;
	}
	if(P0 != 0xF0  && flag == 1)
	{
		flag = 0;//
		temp2 = P0;
	}
	
	temp = temp1 + temp2;
	
	//按键1按下       修改num值达到修改定时器定时时间的目的
	if(temp == 0xEE)
	{
		
		num = 1000;
	}
	
	//按键2按下
	if(temp == 0xDE)
	{
		num = 2000;
	}
	
	//按键3按下
	if(temp == 0xBE)
	{
		num = 3000;
	}
	
	//按键A按下
	if(temp == 0x7E)
	{
		motor_zheng();  // 电机正转
	}
	
	//按键4按下
	if(temp == 0xED)
	{
		num = 4000;
	}
	
	//按键5按下
	if(temp == 0xDD)
	{
		num = 5000;
	}
	
	//按键6按下
	if(temp == 0xBD)
	{
		num = 6000;
	}
	
	//按键B按下
	if(temp == 0x7D)
	{
		motor_fan();  // 电机反转
	}
	
	//按键7按下
	if(temp == 0xEB)
	{
		num = 7000;
	}
	
	//按键8按下
	if(temp == 0xDB)
	{
		num = 8000;
	}
	
	//按键9按下
	if(temp == 0xBB)
	{
		num = 9000;
	}
	
	//按键C按下
//	if(temp == 0x7B)
//	{
//	
//	}
	
	//按键*按下
//	if(temp == 0xE7)
//	{
//	
//	}
	
	//按键0按下
	if(temp == 0xD7)
	{
		motor_stop();   //停止转动
	}
	
	//按键#按下
//	if(temp == 0xB7)
//	{
//	
//	}
//	
//	//按键D按下
//	if(temp == 0x77)
//	{
//	
//	}
	LED=0;
	dat_init();      // 所有按键都检测完了就要重新设置一下初值,好叫按键更改的num值起效
}

//定时器初始化
void time_init()
{
	TMOD=0x01;
	TH0=dat_H[0];
	TL0=dat_L[0];
	ET0=1;
	EA=1;
	TR0=1;
	IN1=1;
	IN2=0;
	EN1=0;
	LED=0;   //P2的7口接了一个led小灯检测信号有没有用的。
	
	//下面是外部中断初始化
	IT0=1;    //  外部中断设置成1,边沿触发方式
	EX0=1;    //  使用INT0的中断
	
}

//  主函数
int main()
{
	time_init();  //初始化定时器
	
	while(1)
	{
		key();    // 检测按键
	}
	
	return 0;
}

// 定时器中断入口函数
void zd() interrupt 1
{ 
	EN1=~EN1;     // 电动机转动使能,每次取反, 得1时转动,得0时停止
	if(EN1==0)         //  如果是停止转动时,就设置初值为(65536-(10000-num))num为定时时间1000为1毫秒
	{ 
		TH0=dat_H[0];
		TL0=dat_L[0];
	}
	if(EN1==1)          //  如果是转动时,就设置初值为(65536-num),num为定时时间1000为1毫秒
	{
		TH0=dat_H[1];
		TL0=dat_L[1];
	}
}

// 外部中断入口函数
void wbzd() interrupt 0
{
	count++;
	if(count == 40)  //记录电机转10圈的时候就停止转动,点亮led灯,圈数置0.
	{
		LED=1;
		count=0;
		motor_stop();
	}
}

猜你喜欢

转载自blog.csdn.net/xingyuncao520025/article/details/133378488