实际上两个电机即使型号相同还是有转速差,所以小车走直线的时候会偏航,这个时候就需要对两个轮子的转速进行调整以达到同步。
这里使用到定时器中断T0和T2进行PWM调速,这里定时器中断时间设定为0.5ms,40个定时器中断为一个周期,也就是20ms。
如本程序中设定LeftSpeed=33; RightSpeed=40;左轮的占空比为33/40,右轮占空比为40/40.这样就可以调节左轮速度降下来,这里的左转右转也进行了PWM调速,方法类似。
这里还需要注意定时器中断触发时间不能过短,否则轮子不转。
#include "motor.h"
#include "reg52.h"
#include "Usart_Init.h"
#include "delay.h"
#include "intrins.h"
#include "string.h"
#define bufferlen 12
char buffer[12];
char leftcnt=0;
char righrcnt=0;
char LeftSpeed;
char RightSpeed;
//管脚配置
//右轮
sbit RightA=P3^3;
sbit RightB=P3^2;
//左轮
sbit LeftA=P3^4;
sbit LeftB=P3^5;
sbit LeftSersor =P2^6;
sbit RightSersor =P2^7;
//直接通过调节电机的占空比来达到左右轮分明调速的目的。
//前进,左轮动力较强,右轮动力较弱,调节左轮占空比
void ForWard()
{
LeftSpeed=33;//调节左轮占空比位33/40
RightSpeed=40;//右轮占空比100/100
//左轮前进
RightA=1;
RightB=0;
//右轮前进
LeftA=1;
LeftB=0;
}
//后退
void BackWard()
{
LeftSpeed=33;//调节左轮占空比位33/40
RightSpeed=40;//右轮占空比100/100
//左轮后退
RightA=0;
RightB=1;
//右轮后退
LeftA=0;
LeftB=1;
}
//左转
void LeftWard()
{
LeftSpeed=3;//调节左轮占空比位5/40
RightSpeed=25;//右轮占空比25/40
//左轮前进
RightA=1;
RightB=0;
//右轮前进
LeftA=1;
LeftB=0;
}
//右转
void RightWard()
{
LeftSpeed=24;//调节左轮占空比位5/40
RightSpeed=5;//右轮占空比25/40
//左轮前进
RightA=1;
RightB=0;
//右轮前进
LeftA=1;
LeftB=0;
}
void Stop()
{
//左右轮不动
RightA=0;
RightB=0;
LeftA=0;
LeftB=0;
}
void TrackCar()
{
//左边探测器和右边探测器都返回信号,保持直线。
if (LeftSersor==0&&RightSersor==0)
{
ForWard();//
}
//如果左边有黑线,右边没有黑线,左转一点。
else if(LeftSersor==1&&RightSersor==0)
{
RightWard();//
}
//如果左边没有黑线,右边有黑线,右转一点。
else if(LeftSersor==0&&RightSersor==1)
{
LeftWard();//
}
//如果两边都是黑线停止
else if(LeftSersor==1&&RightSersor==1)
{
Stop();//
}
}
void main ()
{
uart_Init();//串口的初始化设置
Timer0Init();//定时器0的初始化
Timer2Init();//定时器2的初始化
while(1)
{
TrackCar();
}
}
void Speed_L()interrupt 1 //定时器1中断调节PWM,控制左轮速度
{
leftcnt++;
//重新赋初值
TH1 = 0x0FE;
TL1 = 0x33;
if(leftcnt<LeftSpeed)
{
LeftWard();//左转
}
else
{
Stop();//停止
}
if(leftcnt==40)
{
leftcnt=0;
}
}
void Speed_R() interrupt 5 //计时器2,调节PWM,控制右轮速度
{
righrcnt++;
TF2=0;//定时器2需要手动复位
if(righrcnt<RightSpeed)
{
ForWard();//右转
}
else
{
Stop();//停止
}
if(righrcnt==40)
{
righrcnt=0;
}
}
//由模块Tx发出的有两种指令,1,AT功能设置指令的反馈 2,服务器串口发送的数据传到WiFi模块,再由模块发给单片机
void uart_Interrupt () interrupt 4 //中段函数。每次接收到WiFi模块发过来的数据进入中断
{
static int i=0; //只在开始的时候执行一次
if (RI)//当串口中断事件为接收到数据
{
RI=0;
if(i==12)//不超过十二个字符
{
i=0;
}
buffer[i++]=SBUF;//全局变量接收WiFi模块Tx发送过来的数据
if(buffer[i-1]=='M')//第一个数据M
{
buffer[0] =buffer[i-1];//buffer[i-1]才是刚才接收的数据
i=1;
}
if (buffer[1]=='F') //当接受的数据为“MF”
{
ForWard();
Delay500ms() ;
memset(buffer, '\0', bufferlen);
}
if (buffer[1]=='B')//当接受的数据为“MB”
{
BackWard();
Delay500ms() ;
memset(buffer, '\0', bufferlen);
}
if (buffer[1]=='L')//当接受的数据为“ML”
{
LeftWard();
Delay200ms();;
memset(buffer, '\0', bufferlen);
}
if (buffer[1]=='R')//当接受的数据为“MR”
{
RightWard();
Delay200ms();;
memset(buffer, '\0', bufferlen);
}
}
}
Usart_Init.c
#include "reg52.h"
#include "motor.h"
sfr T2MOD = 0xC9;//定时器2的模式寄存器
sfr P4 = 0xE8;
sfr XICON = 0xC0;//拓展外部中断寄存器,外部中断2
sbit EX2 = XICON^2;
sbit IT2 = XICON^0;
void Timer0Init()//定时器0的初始化函数,
{
TMOD &= 0xF0; //定时器0设定重置
TMOD |= 0x01; //设置16位计时器
TH1 = 0x0FE;//0.5MS
TL1 = 0x33;
EA = 1;//总开关连接
ET0 = 1;//定时器0支路开关连接
TF0=0;//溢出标志位清零
}
void Timer2Init() //定时器2初始化
{
T2MOD = 0; //设置为向上计数
T2CON = 0; //设置为计时模式 16位重装模式
TH2 = 0xFE;//0.5MS
TL2 = 0x33;
RCAP2H= 0xFE; //设置定时重载值
RCAP2L = 0x33; //设置定时重载值
ET2=1;
TF2=0;
TR2 = 1; //定时器2开始计时
}
void uart_Init()//串口初始化
{
SCON=0X50;//设置串口的寄存器工作模式
TMOD &=0X0F;//定时器1的工作模式
TMOD |=0X2F;
TH1=0XFD;//设置波特率9600
TL1=TH1;
TR1=1;//定时器开始计时
EA=1;
ES=1;
}
delay.c
# include "intrins.h"
void Delay100ms() //@11.0592MHz
{
unsigned char i, j;
i = 180;
j = 73;
do
{
while (--j);
} while (--i);
}
void Delay2000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 15;
j = 2;
k = 235;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay500ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 4;
j = 129;
k = 119;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay200ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 2;
j = 103;
k = 147;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
头文件
delay.h
void Delay2000ms();
void Delay50ms();
void Delay200ms();
void Delay100ms();
void Delay500ms() ;
Usart_Init.h
void uart_Init();
void Timer0Init();
void Timer2Init();