📄 dianji.c
字号:
//////////////////////////////////////////////////////////
//文件名称:dianji.c
//功能描述:包括前轮转向电机驱动程序,后轮电机驱动程序等
///////////////////////////////////////////////////////////
#include "reg52.h"
#include "dianji.h"
#include "disp.h"
#define uchar unsigned char
#define uint unsigned int
///////////////////////////////////////////////////////////////////////
//占用的IO口定义
//后驱直流电机
sbit HQ_EN=P0^4;
sbit HQ_IN1=P0^5;
sbit HQ_IN2=P0^6;
//前轮转向步进电机
sbit GW_CE=P3^5;
sbit GW_A=P3^7;
sbit GW_B=P3^6;
sbit GW_MID=P3^4; //中点检测端
sbit LC_IN=P3^3; //里程检测输入端
sbit FEN=P0^7; //漏粉控制端
///////////////////////////////////////////////////////////////////
//记录小车需要达到的速度,正值表示前进,负值表示后退,0表示停止
//前进和后退的速度各有5级
data char speed=0;
data char now_speed=0; //记录小车目前的速度
//记录小车需要转到的角度,正值表示右转,负值表示左转,0表示转到正前
data char degree=0; //需要转到的角度,单位:步数
data char temp_dg=0; //需要转到的角度,单位:度
data char now_degree=0;//记录小车目前的转角,单位:步数
bdata bit flag_turn; //记录小车前一次是左转还是右转,以便正确消除空程
//0:左传,1:右转
bdata bit t_gw_mid; //记录GW_MID的值,以便校正角度值
data uchar kongcheng; //记录空程的步数,0~N_KC
#define N_KC 4
/////////////////////////////////////////////////////////////////////
data unsigned int li_cheng=0; //记录里程,单位是检测到的脉冲数,即1/8圈
data unsigned int li_cheng_limi=0;//记录里程值,单位是厘米
//二者关系是li_cheng_limi=2.095*li_cheng
/////////////////////////////////////////////////////////////////////
//内部函数的声明
void step_left(void); //前轮左转一步
void step_right(void); //前轮右转一步
//电机驱动程序,由定时器中断调用
void dianji(void)
{
if(speed>0)
{
HQ_IN1=0;
HQ_IN2=1;
HQ_EN=1;
}
else if(speed<0)
{
HQ_IN1=1;
HQ_IN2=0;
HQ_EN=1;
}
else if(speed==0)
{
HQ_EN=0;
}
}
/////////////////////////////////////////////////////////////////////
//前轮转向步进电机驱动程序
void gw_dianji(void)
{
//角度校正,红外对管被遮挡的时间大概有22步
if((!t_gw_mid)&&GW_MID) //GW_MID上升沿
{
if(flag_turn) //右转
{
now_degree=-10;
}
else //左转
{
now_degree=10;
}
}
else if(t_gw_mid&&(!GW_MID)) //GW_MID下降沿
{
if(flag_turn) //右转
{
now_degree=10;
}
else //左转
{
now_degree=-10;
}
}
t_gw_mid=GW_MID;
if(now_degree==degree) //若已经转到指定角度则关闭转向电机
{
GW_CE=1;
}
else if(now_degree<degree) //需要右转
{
GW_CE=0; //打开转向电机
step_right(); //右转一步
flag_turn=1; //置右转标志
if(kongcheng<N_KC) //若有空程
{
kongcheng++;
}
else //若无空程
{
now_degree++;
}
}
else //需要左转
{
GW_CE=0; //打开转向电机
step_left(); //左转一步
flag_turn=0; //置左转标志
if(kongcheng>0) //若有空程
{
kongcheng--;
}
else //若无空程
{
now_degree--;
}
}
}
///////////////////////////////////////////////////////////////////////
//设置前轮转动角度
void setdegree(char dg)
{
EA=0;
degree=dg;
if(degree>10)LED_YZ=1;
else LED_YZ=0;
if(degree<(-10))LED_ZZ=1;
else LED_ZZ=0;
EA=1;
}
//////////////////////////////////////////////////////////////////
//前轮左转
void turnleft(void)
{
setdegree(-40);
while(getnowdegree()>(-30));
delay_ms(500);
}
//////////////////////////////////////////////////////////////////
//前轮右转
void turnright(void)
{
setdegree(40);
while(getnowdegree()<30);
delay_ms(500);
}
//////////////////////////////////////////////////////////////////
//前轮转到正中
void turnmid(void)
{
setdegree(0);
while(getnowdegree());
delay_ms(500);
}
////////////////////////////////////////////////////////////////////
//获得前轮当前的角度
char getnowdegree(void)
{
return now_degree;
}
//////////////////////////////////////////////////////////////////////
//拐弯步进电机的初始化
//并将前轮调整至0度位置
void gw_init(void)
{
GW_MID=1; //初始化输入口
t_gw_mid=GW_MID;
if(GW_MID) //红外对管被遮挡,即前轮在正中位置附近
{
now_degree=0;
degree=20;
flag_turn=1;
while(now_degree!=20);
delay_ms(200);
degree=0;
while(now_degree!=0);
}
else //前轮已转了一定角度
{
now_degree=40;
degree=-40;
flag_turn=0;
while((now_degree!=(-40))&&(!GW_MID));
if(GW_MID)degree=0;
else
{
delay_ms(200);
now_degree=-80;
degree=0;
while(now_degree!=0);
}
}
delay_ms(200);
}
////////////////////////////////////////////////////////////////////
//设置速度
void setspeed(char sp)
{
speed=sp;
if(speed<0)LED_DC=1; //倒车灯开关控制
else LED_DC=0;
}
/////////////////////////////////////////////////////////////////////
//获得速度值
char getspeed(void)
{
return speed;
}
///////////////////////////////////////////////////////////////////
//紧急刹车函数
void imstop(void)
{
if(getspeed()>0) //前进时,电机反转刹车
{
setspeed(-1);
delay_ms(50);
setspeed(0);
}
else if(getspeed()<0) //后退时,电机反转刹车
{
setspeed(1);
delay_ms(50);
setspeed(0);
}
}
/////////////////////////////////////////////////////////////////////
//里程检测函数,并置全局变量li_cheng
static bit lc_flag;
void licheng(void)
{
if(lc_flag!=LC_IN)
{
li_cheng++;
//li_cheng_limi=2.095*li_cheng
li_cheng_limi=(2*li_cheng)+(li_cheng/10)-(li_cheng/200);
lc_flag=LC_IN;
}
}
///////////////////////////////////////////////////////////////////////
//里程初始化函数
void init_lc(void)
{
lc_flag=LC_IN;
}
///////////////////////////////////////////////////////////////
//取得里程值,单位1/8圈
uint getlicheng(void)
{
uint temp;
temp=li_cheng;
return temp;
}
///////////////////////////////////////////////////////////////////
//取得里程值,单位厘米
uint getlichenglimi(void)
{
uint temp;
temp=li_cheng_limi;
return li_cheng_limi;
}
//////////////////////////////////////////////////////////////////////
//设置里程值,单位1/8圈
void setlicheng(uint lc)
{
li_cheng=lc;
//li_cheng_limi=2.095*li_cheng
li_cheng_limi=(2*li_cheng)+(li_cheng/10)-(li_cheng/200);
}
//////////////////////////////////////////////////////////////////////
//前轮右转一步函数
static uchar temp_t=0;
void step_right(void)
{
switch(temp_t)
{
case 0:
GW_A=0;
GW_B=0;
break;
case 1:
GW_A=1;
GW_B=0;
break;
case 2:
GW_A=1;
GW_B=1;
break;
case 3:
GW_A=0;
GW_B=1;
break;
}
temp_t++;
temp_t&=0x03;
}
////////////////////////////////////////////////////////////////////
//前轮左转一步函数
void step_left(void)
{
switch(temp_t)
{
case 0:
GW_A=0;
GW_B=0;
break;
case 1:
GW_A=0;
GW_B=1;
break;
case 2:
GW_A=1;
GW_B=1;
break;
case 3:
GW_A=1;
GW_B=0;
break;
}
temp_t++;
temp_t&=0x03;
}
//////////////////////////////////////////////////////////////
//漏粉控制
void loufen(uchar flag)
{
if(flag)
{
FEN=0;
LED_FEN=1;
}
else
{
FEN=1;
LED_FEN=0;
}
}
//////////////////////////////////////////////////////////////
//获取当前是否在漏粉
uchar getloufen(void)
{
if(FEN)return 0;
else return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -