在学习51单机后进行的小小总结和记录,欢迎指正
工作器件:电动马达;红外模块;最小系统板;红外模块;电机驱动模块等
工作原理:
使用定时器来进行pwm调速
红外模块接收信号
使用io口控制L298N驱动模板
装小车时候注意的地方:
注意:l298n电机驱动模块别接短路了,额接短路了直接烧了,
还有最小开发板的接线端子正确对接电机驱动模块的正负极;
对于电机驱动模块L298N:
我是当时使用的是7.5v左右的电源供电
两个使能模块接口 ENA ENB
IN1 IN2 IN3 IN4控制 电机反转和正转的
高低分别为置1,0 杜邦线对着自己定义的io口进行对接
对于红外模块:红外模块默认发送的是1,当接收信号之后是发送0;
就 一个信号线 和一个VCC,一个GND
虽然本代码是三个红外,自己加以修改,两个红外也是可以的
对于代码可以多加调试,对于每个人电机插线的不同,需要修改0 1的数值,还有供电的电压,可能也需要修改 本人使用12v电源也是可以正常使用。想把循迹小车做好,还得多加修改
本代码对于复杂赛道,比如锐角暂时不能做到,本代码提供了个人的一点思路
总的代码:(供参考)
#include<reg52.h>
typedef unsigned int uint;
typedef unsigned char uchar;
uchar Duty_left,Duty_right; //左右占空比标志,取1-100
uchar i=0,j=0;
uchar flag; //用于循迹方向的判断
uchar g=0;
//驱动L298N---->
//ENA,ENB为使能端; ENA,1,2和ENB,3,4分别控制一个电机;
//设置啥io口自行设置
sbit IN1 = P1^0;
sbit IN2 = P1^1;
sbit IN3 = P1^2;
sbit IN4 = P1^3;
sbit ENA = P1^4;
sbit ENB = P1^5;
sbit left=P0^0; //左边的传感器
sbit right=P0^2; //右边的传感器
sbit mid=P0^1; //中间的传感器
void delay_ms(unsigned int n)
{
unsigned int i=0,j=0;
for(i=0;i<n;i++)
for(j=0;j<123;j++);
}
//小车直行速度赋值
void forward_move()
{
Duty_left=100; //我8v电源速度拉满啥事没有
Duty_right=100;
IN1=1; //两个电机均正转 具体0 1还是1 0看自己电机接线设置 我8v电源速度拉满啥事没用
IN2=0;
IN3=1;
IN4=0;
}
//小车停止
void stop()
{ Duty_left=50;
Duty_right=50; //停车代码
IN1=0;
IN2=0;
IN3=0;
IN4=0;
}
void Left_turning()//左拐
{
Duty_left=70;
Duty_right=60;
IN1=1; //两个电机一个正转一个反转
IN2=0;
IN3=0;
IN4=1;
}
void Right_turning()
{
Duty_left=60;
Duty_right=60; //两个电机一个正转一个反转
IN1=0;
IN2=1;
IN3=1;
IN4=0 ;
}
void timer0init()
{
TMOD|=0x01;//定时器T0, 工作方式1, 16位
TH0=0xff;//定时 ff9c 0.1ms
TL0=0x9c;
EA=1; //开启总中断
ET0=1;//开启中断允许
TR0=1;//开启定时器中断
}
void timer0() interrupt 1
{
TH0=0xff;
TL0=0x9c;
i++;
j++;
if(i<=Duty_left)
ENA=1;
else
ENA=0;
if(j<=Duty_right)
ENB=1;
else
ENB=0;
if(i==100) //设置pwm周期=0.1ms*100=10ms,这样开头定义的变量正好表示占空比数值
{
i=0;//加到100后变为0,重新计数
}
if(j==100)
{
j=0;
}
//由于我使用while来写,这边使用中断来给红外循迹的判断
if((left==1)&&(right==0))
{
flag=0;//右边检测到线 //右拐
}
else if((left==0)&&(right==1))
{
flag=1;//左边检测到线 左拐
}
else if((left==0)&&(right==0)&&(right==0))
{
flag=3; //三个红外都检测到的时候直行
}
else if((mid==0)&&(right==1)&&(right==1))
{
flag=5; //中间检测到,两边没用检测到直行
}
}
//循迹模块
void xunji()
{
//使用while来写发现可以效果更好。原本我使用的是switch来写
while(flag==1)
{
Right_turning();
if((flag==3)||(flag==5)||(flag==0))break;//跳出循环
}
while(flag==0)
{
Left_turning();
if((flag==3)||(flag==5)||(flag==1))break;//跳出循环
}
if((flag==3)||(flag==5))//直行
{
forward_move();
}
if((flag==3))//检测三红外
{
forward_move();
delay_ms(100);//延时判断 如果还是三个红外都亮,说明抵达终点
{
if(flag==3)
{
stop(); //终点停车代码,很粗糙可以自己修改
delay_ms(1500);
if(g<1)
{
Left_turning(); //摆尾掉头代码,不要可以自己修改
delay_ms(800);
if(flag==3)
forward_move();
g++;
}
}
}
}
}
void main()
{
timer0init();
while(1)
{
xunji();
}
}