⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dianji.c

📁 单片机实现的遥控小汽车的设计研究论文与程序
💻 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 + -