基于金沙滩单片机的L298N智能小车

想着写个按键控制小车跑起来,把程序改了下,用上了按键,
L298N的状态也是网上找的

如果L298N的状态有啥错误,欢迎留言,最后的代码有啥问题,欢迎指正

引脚定义

sbit L298N_IN1 = P1^1;
sbit L298N_IN2 = P1^2;
sbit L298N_IN3 = P1^3;
sbit L298N_IN4 = P1^4;

逻辑输入

该部分有四输入个引脚,两个引脚控制一个电机,该引脚可以根据使用者自己定义接入单片机的哪个引脚。四个引脚分别为IN1、IN2、IN3、IN4,具体控制逻辑如下:IN1输入低电平,IN2输入低电平或者 IN1输入高电平,IN2输入高电平,此时电机停止转动;IN1输入高电平,IN2输入低电平,此时电机顺时针转动;IN2输入高电平,IN1输入低电平,此时电机逆时针转动;但是前提是通道使能了。具体逻辑控制如下图:

#include <reg52.h>
#include <stdio.h>
/*
sbit L298N_IN1 = P1^0;
sbit L298N_IN2 = P1^1;
sbit L298N_IN3 = P1^2;
sbit L298N_IN4 = P1^3;
*/

sbit L298N_IN1 = P1^1;
sbit L298N_IN2 = P1^2;
sbit L298N_IN3 = P1^3;
sbit L298N_IN4 = P1^4;

void Forward(void);//向前行走子程序
void Left_Turn(void);//左转弯子程序
void Right_Turn(void);//右转弯子程序
void Backward(void);//向后行走子程序
void Stop(void);//停止子程序
void delay_nms(int n);

void main()
{
	unsigned int i = 0;  //定义一个无符号整型变量i,并赋初值0
	while(1)
	{
		Forward();//前进
		//delay_nms(500);
		//Left_Turn();//左转
		//delay_nms(500);
		//Right_Turn();//右转
		//delay_nms(500);
		//Backward();//后退
		//delay_nms(500);
		//Stop();//停止
		//delay_nms(500);
	}
}

void delay_nms(int n) //n: millisecond
{
    int i,j;
    for(i = 0; i < n; i++)
        for(j = 0;j < 500; j++)
		{
		}
}

void Forward(void)//向前行走子程序
{
 	unsigned char i;
	unsigned char j;
	L298N_IN1=0;
	L298N_IN2=1;
	L298N_IN3=0;
	L298N_IN4=1;
 	for(i=1;i<=30;i++)
	{
 		for(j=1;j<=30;j++)
		{
			delay_nms(10);
		}
	}
}
void Left_Turn(void)//左转弯子程序
{ 	
	unsigned char i;
	unsigned char j;
	L298N_IN1=0;
	L298N_IN2=1;
	L298N_IN3=1;
	L298N_IN4=1;	
	for(i=1;i<=30;i++)
	{
 		for(j=1;j<=30;j++)
		{
			delay_nms(10);
		}
	}
}
void Right_Turn(void)//右转弯子程序
{
 	unsigned char i;
	unsigned char j;
	L298N_IN1=1;
	L298N_IN2=1;
	L298N_IN3=0;
	L298N_IN4=1;	
	for(i=1;i<=30;i++)
	{
 		for(j=1;j<=30;j++)
		{
			delay_nms(10);
		}
	}
}
void Backward(void)//向后行走子程序
{
 	unsigned char i;
	unsigned char j;
	L298N_IN1=1;
	L298N_IN2=0;
	L298N_IN3=1;
	L298N_IN4=0;	
	for(i=1;i<=30;i++)
	{
 		for(j=1;j<=30;j++)
		{
			delay_nms(10);
		}
	}
}
void Stop(void)//停止子程序
{
 	unsigned char i;
	unsigned char j;
	L298N_IN1=1;
	L298N_IN2=1;
	L298N_IN3=1;
	L298N_IN4=1;	
	for(i=1;i<=20;i++)
	{
 		for(j=1;j<=20;j++)
		{
			delay_nms(10);
		}
	}	
}


上键 前进
下键 后退
左键 左转
右键 右转
ESC 停止

定时器 ,中断

#include <reg52.h>
#include <stdio.h>

//L298N
sbit L298N_IN1 = P1^1;
sbit L298N_IN2 = P1^2;
sbit L298N_IN3 = P1^3;
sbit L298N_IN4 = P1^4;
//按键
sbit KEY_IN_1  = P2^4;
sbit KEY_IN_2  = P2^5;
sbit KEY_IN_3  = P2^6;
sbit KEY_IN_4  = P2^7;
sbit KEY_OUT_1 = P2^3;
sbit KEY_OUT_2 = P2^2;
sbit KEY_OUT_3 = P2^1;
sbit KEY_OUT_4 = P2^0;

unsigned char code KeyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表
    { 0x31, 0x32, 0x33, 0x26 }, //数字键1、数字键2、数字键3、向上键
    { 0x34, 0x35, 0x36, 0x25 }, //数字键4、数字键5、数字键6、向左键
    { 0x37, 0x38, 0x39, 0x28 }, //数字键7、数字键8、数字键9、向下键
    { 0x30, 0x1B, 0x0D, 0x27 }  //数字键0、ESC键、  回车键、 向右键
};
unsigned char KeySta[4][4] = {  //全部矩阵按键的当前状态
    {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1}
};

unsigned char i = 0;   //动态扫描的索引
unsigned int cnt = 0;  //记录T0中断次数
unsigned char flag1s = 0;  //1秒定时标志
unsigned char g_Forward;  
unsigned char g_TurnLeft;  
unsigned char g_TurnRight;
unsigned char g_Backward;  //后退模式 
unsigned char g_Stop;  //停止模式   

void KeyDriver();
void Forward(void);//向前行走子程序
void Left_Turn(void);//左转弯子程序
void Right_Turn(void);//右转弯子程序
void Backward(void);//向后行走子程序
void Stop(void);//停止子程序

static unsigned long sec;	 //记录经过的秒数
static unsigned char dir = 0;


void main()
{
	EA = 1;       //使能总中断
	TMOD = 0x01;  //设置T0为模式1
    TH0  = 0xFC;  //为T0赋初值0xFC67,定时1ms
    TL0  = 0x67;
    ET0  = 1;     //使能T0中断
    TR0  = 1;     //启动T0
	while(1)
	{
	 	KeyDriver();   //调用按键驱动函数
		if (g_Forward) {
		    Forward();
		} else if (g_TurnLeft) {
			Left_Turn();
		} else if (g_TurnRight) {
			Right_Turn();
		} else if (g_Backward) {
			Backward();
		} else if (g_Stop) {
			Stop();	
		}		
	}
}

/*
上键 前进
下键 后退
左键 左转
右键 右转
ESC 停止 
*/
void KeyAction(unsigned char keycode)
{	
    switch (keycode)
	{
		//0x26 上
	    case 0x26: g_Forward = 1; 
		           g_Forward = 0;  
  				   g_TurnLeft = 0;  
  				   g_TurnRight = 0;
  				   g_Backward = 0;  //后退模式 
  				   g_Stop = 0;  //停止模式  
				   break;  
		//0x25 左      
		case 0x25: g_Forward = 0; 
		           g_Forward = 0;  
  				   g_TurnLeft = 1;  
  				   g_TurnRight = 0;
  				   g_Backward = 0;  //后退模式 
  				   g_Stop = 0;  //停止模式  
				   break;
		//0x28 下      
		case 0x28: g_Forward = 0; 
		           g_Forward = 0;  
  				   g_TurnLeft = 0;  
  				   g_TurnRight = 0;
  				   g_Backward = 1;  //后退模式 
  				   g_Stop = 0;  //停止模式  
				   break;
		//0x27 右
		case 0x27: g_Forward = 0; 
		           g_Forward = 0;  
  				   g_TurnLeft = 0;  
  				   g_TurnRight = 1;
  				   g_Backward = 0;  //后退模式 
  				   g_Stop = 0;  //停止模式  
				   break;
		//0x1B 停止
		case 0x1B: g_Forward = 0; 
		           g_Forward = 0;  
  				   g_TurnLeft = 0;  
  				   g_TurnRight = 0;
  				   g_Backward = 0;  //后退模式 
  				   g_Stop = 1;  //停止模式  
				   break;
	}
}

void KeyDriver()
{
    unsigned char i, j;
    static unsigned char backup[4][4] = {  //按键值备份,保存前一次的值
        {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1}
    };
    
    for (i=0; i<4; i++)  //循环检测4*4的矩阵按键
    {
        for (j=0; j<4; j++)
        {
            if (backup[i][j] != KeySta[i][j])    //检测按键动作
            {
                if (backup[i][j] != 0)           //按键按下时执行动作
                {
                    KeyAction(KeyCodeMap[i][j]); //调用按键动作函数
                }
                backup[i][j] = KeySta[i][j];     //刷新前一次的备份值
            }
        }
    }
}

void KeyScan()
{
    unsigned char i;
    static unsigned char keyout = 0;   //矩阵按键扫描输出索引
    static unsigned char keybuf[4][4] = {  //矩阵按键扫描缓冲区
        {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF},
        {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF}
    };

    //将一行的4个按键值移入缓冲区
    keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
    keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
    keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
    keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;
    //消抖后更新按键状态
    for (i=0; i<4; i++)  //每行4个按键,所以循环4次
    {
        if ((keybuf[keyout][i] & 0x0F) == 0x00)
        {   //连续4次扫描值为0,即4*4ms内都是按下状态时,可认为按键已稳定的按下
            KeySta[keyout][i] = 0;
        }
        else if ((keybuf[keyout][i] & 0x0F) == 0x0F)
        {   //连续4次扫描值为1,即4*4ms内都是弹起状态时,可认为按键已稳定的弹起
            KeySta[keyout][i] = 1;
        }
    }
    //执行下一次的扫描输出
    keyout++;                //输出索引递增
    keyout = keyout & 0x03;  //索引值加到4即归零
    switch (keyout)          //根据索引,释放当前输出引脚,拉低下次的输出引脚
    {
        case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
        case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
        case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
        case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
        default: break;
    }
}

void Forward(void)//向前行走子程序
{
	L298N_IN1=0;
	L298N_IN2=1;
	L298N_IN3=0;
	L298N_IN4=1;
}
void Left_Turn(void)//左转弯子程序
{ 	
	L298N_IN1=0;
	L298N_IN2=1;
	L298N_IN3=1;
	L298N_IN4=1;	
}
void Right_Turn(void)//右转弯子程序
{
	L298N_IN1=1;
	L298N_IN2=1;
	L298N_IN3=0;
	L298N_IN4=1;	
}
void Backward(void)//向后行走子程序
{
	L298N_IN1=1;
	L298N_IN2=0;
	L298N_IN3=1;
	L298N_IN4=0;
}
void Stop(void)//停止子程序
{
	L298N_IN1=1;
	L298N_IN2=1;
	L298N_IN3=1;
	L298N_IN4=1;	
}

/* T0中断服务函数,用于数码管显示扫描与按键扫描 */
void InterruptTimer0() interrupt 1
{
    TH0 = 0xFC;  //重新加载初值
    TL0 = 0x67;
	cnt++;       //中断次数计数值加1
    if (cnt >= 1000)  //中断1000次即1秒
    {
        cnt = 0;      //清零计数值以重新开始下1秒计时
        flag1s = 1;   //设置1秒定时标志为1
    }
    //前进
	/*
	if (g_Forward) {
	    L298N_IN1=0;
		L298N_IN2=1;
		L298N_IN3=0;
		L298N_IN4=1;
	}
	//左转
	if (g_TurnLeft) {
	    L298N_IN1=0;
		L298N_IN2=1;
		L298N_IN3=1;
		L298N_IN4=1;
	}
	//右转
	if (g_TurnRight) {
	    L298N_IN1=1;
		L298N_IN2=1;
		L298N_IN3=0;
		L298N_IN4=1;
	}
	//后退
	if (g_Backward) {
		L298N_IN1=1;
		L298N_IN2=0;
		L298N_IN3=1;
		L298N_IN4=0;
	}
	//停止 
	if (g_Stop) {
		L298N_IN1=1;
		L298N_IN2=1;
		L298N_IN3=1;
		L298N_IN4=1;
	}
    */
    KeyScan();   //调用按键扫描函数
}
单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考 单片机 学习资料 项目资料 供学习参考
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值