智能小车1-智能小车的初认识

硬件介绍

小车主要部件:

面包板:

用于扩展接线,由于小车可以扩展许多模块,所以使用面包板增加容错性

L9110s:

电机的驱动模块,接通VCC,GND模块电源指示灯亮;下图模块中集成了两个L9110s

//B-1A -> P3.2; B-1B -> P3.3; A-1A -> P3.4; A-1B -> P3.5;
正转时:B_1A = 0; B_1B = 1; A_1A = 0; A_1B = 1;

反转时:B_1A = 1; B_1B = 0; A_1A = 1; A_1B = 0;

PS:面包板,开关和单片机均采用热熔胶固定,电机及其驱动模块均由电池供电,除了上面提到L9110s和单片机的控制接线和电源之外,注意要有一根杜邦线让单片机和L9110s共地

小车L9110s电机驱动

将小车组装完成后,首先就是要让小车动起来,由刚刚对于电机驱动模块的讲解可以很容易实现让电机正反转,基于此,前进后退,左转右转的代码就都能写出来了:

void Motor_back()
{
	RightconlA = 1;
	RightconlB = 0;
	
	LeftconlA = 1;
	LeftconlB = 0;
	
}

void Motor_front()
{
	RightconlA = 0;
	RightconlB = 1;
	
	LeftconlA = 0;
	LeftconlB = 1;
	
}

void Motor_Left()
{
	RightconlA = 0;
	RightconlB = 1;
	
	LeftconlA = 0;
	LeftconlB = 0;
	
}

void Motor_Right()
{
	RightconlA = 0;
	RightconlB = 0;
	
	LeftconlA = 0;
	LeftconlB = 1;
	
}

由于家中没有电烙铁,导线与电机连接的地方不稳定,因此拍摄效果也难以保证,简单验证实验效果能达到就可以了

代码封装

由于小车代码肯定会巨长无比,所以养成良好的习惯,习惯性的完成一个模块之后就封装,方法和上节DHT11的末尾方法一样, 创建motor的c和h文件。

小车的控制

在熟悉了小车如何进行移动之后,就可以利用先前学习的各种模块对小车进行控制

1. 串口/蓝牙控制小车

依然采用封装函数的方法:

UART.c:
#include "reg52.h"
#include <motor.h>
#include <string.h>

#define SIZE 12

sbit D5 = P3^7;
sfr AUXR =  0x8E;
char buffer[SIZE];

void UartInit()		//9600bps@11.0592MHz
{
	SCON = 0x50;  //配置串口工作方式1,REN使能接收
	
	//配置定时器1,工作方式为8位自动重载
	TMOD &= 0x0f;//定时器1工作方式位8位自动重装
	TMOD |= 0x20;
	
	TH1 = 0xFD; 
	TL1 = 0xFD; //9600波特率的初值
	
	TR1 = 1;//启动定时器
	ES  = 1;//开启串口中断
	EA  = 1;//开启总中断
	
	
}



//TI 发送请求中断标志位,是指单片机向电脑发送
//RI 接收请求中断标志位,是指单片机接收电脑的消息


//M1前进     M2后退       M3左    M4右  
void Uart_Handler() interrupt 4
{
	static int i = 0;//静态变量,被初始化一次
	char temp;

	if(RI == 1)//中断处理函数中,对于接收中断的响应
	{
		RI = 0;//清除接收中断标志位
		temp = SBUF;
		
		if(temp == 'M')
			{
			i = 0;			
			}
		
		buffer[i++] = temp;
		
		
		if(buffer[0] == 'M')
			{
			switch(buffer[1])
				{
				case '1':
					D5 = 0;
					Motor_front();
					break;
				case '2':Motor_back();
					break;
				case '3':Motor_Left();
					break;
				case '4':Motor_Right();
					break;
				default:
					Motor_Stop();
					break;
				}
				
			}
			if(i == 12)
			{
				memset(buffer,'\0',SIZE);
				i =0;
			}
	
	}
	if(TI)
	{
		
	}
}

main.c

#include "reg52.h"
#include <delay.h>
#include <motor.h>
#include <uart.h>

void main()
{
	UartInit();
	while(1)
		{
			
		}

} 

实现效果:

向串口发送M1,小车前进。如果不知道串口是通讯,可以发送心跳包验证一下,即:


void Send_byte(char data_msg)
{
	SBUF = data_msg;
	while(TI == 0);//在请求中断时,TI= 1,既!TI=0,等待数据的发送完成;响应中断结束后TI = 0,既!TI = 1,将TI清零
	TI = 0;

}

void Send_string(char* str)
{
	while(*str != '\0')
	{
		Send_byte(*str);
		str++;
	}
}

可以不断接受心跳指令的同时,写下M1,M2,M3,M4,M5电机会做出对应的动作。

实现了串口,就相当于实现了蓝牙,因为蓝牙模块也使用了串口,所以接上蓝牙模块即可进行同样的通讯

  PS: 连一根杜邦线接面包板的正极和单片机的VCC,加上之前连的共地线,就可以实现电池给单片机的供电,从而实现小车的无线控制。并且,这种方式不是点动,比如左转一点点我要输入M3,然后再输入M5停下,但是现实生活中的遥控车,按下左转的时候左转,不按就不会左转,即现实中的遥控车是点动的,而我以上实现的并不是。

 小车的PWM调速

在刚刚的控制中,实现了上下左右的控制,但是小车的速度无法控制,所以需要用PWM波来对小车的速度来进行控制:已知,对于电机,写1就是全速前进,那么比如在20ms内,如果一半的时间写1,一半的时间写0,那就会比20ms一直是1来的速度慢一半,基于这种思路就可以用PWM波,通过调整占空比来控制小车的速度: 

timer: 

#include <motor.h>
#include "reg52.h"


char speed;
char cnt = 0;

void Time0Init()
{
	//1.配置定时器0工作模式为16位计时
	TMOD = 0x01;
	//2.给初值,定一个500us=0.5ms出来
	TL0 = 0x33;				//设置定时初始值
	TH0 = 0xFE;	
	//3、开始计时
	TR0 = 1;
	TF0 = 0;	
	//4.打开定时器0中断 ET0
	ET0 = 1;
	//5.打开总中断EA
	EA = 1;
}


void Time0_Handler() interrupt 1
{
	/*
//	if(TF0 == 1)//当爆表的时候,硬件会修改bit5(TF0)位上面的数据,改成1(置1),向cpu请求中断
//		{
//			TF0 = 0;//不用中断,我们代码清零
	使用了中断,直接清零了的*/
	cnt++;//统计爆表的次数
	//重新给初值
	TL0 = 0x33;			
	TH0 = 0xFE;	
	
	//控制pwm波形
	if(cnt < speed)
	{
		//前进
		Motor_front();
	}
	else
	{
		//停止
		Motor_Stop();
	}
	
	if(cnt == 40)//爆表40次,经过了20ms
	{
		cnt = 0;//当40次表示20ms,重新让cnt从0开始,计算下一次的20ms
 		
	}
//}
	
	
}
main.c:
#include "reg52.h"
#include <delay.h>
#include <motor.h>
#include <uart.h>
#include <Timer.h>

sbit led2 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口

extern char speed;

void main()
{
	Time0Init();
	UartInit();
	while(1)
		{
			speed = 10;//10份单位时间全速运行,30份停止,所以慢,20ms是40份的500us
		  Delay1000ms();
			Delay1000ms();
			speed = 20;
			Delay1000ms();
			Delay1000ms();
			speed = 40;
			Delay1000ms();
			Delay1000ms();
			
		}

} 

左右轮的分别调速:

要实现这个效果,首先要在motor.c中添加单独控制左右轮前进后退的代码:

void Motor_forward_right()
{
	RightconlA = 1;
	RightconlB = 0;
}

void Motor_stop_right()
{
	RightconlA = 0;
	RightconlB = 0;
}

void Motor_forward_left()
{
	LeftconlA = 1;
	LeftconlB = 0;
}

void Motor_stop_left()
{
	LeftconlA = 0;
	LeftconlB = 0;
}

 然后在timer.c中进行修改,要是要实现左右轮的控制,就需要两个定时器,一个控制左轮一个控制右轮:

#include <motor.h>
#include "reg52.h"


char speedLeft;
char cntLeft = 0;

char speedRight;
char cntRight = 0;

void Time0Init()
{
	//1.配置定时器0工作模式为16位计时
	TMOD &= 0xF0;
	TMOD |= 0x01;
	//2.给初值,定一个500us=0.5ms出来
	TL0 = 0x33;				//设置定时初始值
	TH0 = 0xFE;	
	//3、开始计时
	TR0 = 1;
	TF0 = 0;	
	//4.打开定时器0中断 ET0
	ET0 = 1;
	//5.打开总中断EA
	EA = 1;
}

void Time1Init()
{
	//1.配置定时器1工作模式为16位计时
	TMOD &= 0x0F;
	TMOD |= 0x10;
	//2.给初值,定一个500us=0.5ms出来
	TL1 = 0x33;				//设置定时初始值
	TH1 = 0xFE;	
	//3、开始计时
	TR1 = 1;
	TF1 = 0;	
	//4.打开定时器1中断 ET0
	ET1 = 1;
	//5.打开总中断EA
	EA = 1;
}




void Time1_Handler() interrupt 3
{

	cntRight++;//统计爆表的次数
	//重新给初值
	TL1 = 0x33;			
	TH1 = 0xFE;	
	
	//控制pwm波形
	if(cntRight < speedRight)
	{
		//右前进
		Motor_forward_right();
	}
	else
	{
		//右停止
		Motor_stop_right();
	}
	
	if(cntRight == 40)//爆表40次,经过了20ms
	{
		cntRight = 0;//当40次表示20ms,重新让cnt从0开始,计算下一次的20ms
 		
	}

	
}


void Time0_Handler() interrupt 1
{
	/*
//	if(TF0 == 1)//当爆表的时候,硬件会修改bit5(TF0)位上面的数据,改成1(置1),向cpu请求中断
//		{
//			TF0 = 0;//不用中断,我们代码清零
	使用了中断,直接清零了的*/
	cntLeft++;//统计爆表的次数
	//重新给初值
	TL0 = 0x33;			
	TH0 = 0xFE;	
	
	//控制pwm波形
	if(cntLeft < speedLeft)
	{
		//左前进
		Motor_forward_left();
	}
	else
	{
		//左停止
		Motor_stop_left();
	}
	
	if(cntLeft == 40)//爆表40次,经过了20ms
	{
		cntLeft = 0;//当40次表示20ms,重新让cnt从0开始,计算下一次的20ms
 		
	}
//}
	
	
}

main.c

#include "reg52.h"
#include <delay.h>
#include <motor.h>
#include <uart.h>
#include <Timer.h>

sbit led2 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口

extern char speedLeft;
extern char speedRight;
void main()
{
	Time0Init();
	Time1Init();
	UartInit();
	while(1)
		{
			speedLeft = 10;//10份单位时间全速运行,30份停止,所以慢,20ms是40份的500us
			speedRight = 40;
		    Delay1000ms();
			Delay1000ms();
			speedLeft = 20;
			speedRight = 20;
			Delay1000ms();
			Delay1000ms();
			speedLeft = 40;
			speedRight = 10;
			Delay1000ms();
			Delay1000ms();
			
		}

} 

  • 38
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值