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

📄 mcu2_main.c

📁 单片机实现的遥控小汽车的设计研究论文与程序
💻 C
字号:
////////////////////////////////////////////////////////////////////
//文件名:mcu2_main.c
//功能描述:从单片机上主任务文件,负责寻找光源的方向
////////////////////////////////////////////////////////////////////
#include "reg52.h"
#include "comm_s.h"
#include "timer0_s.h"
#include "dianji_s.h"
#include "chaoshengceju.h"

sbit LIANGDU=P3^3;  //亮度信号输入端INT1
//////////////////////////////////////////////////////////////////
uchar jiance(void); //光源亮度检测
void find(void);    //寻找光源任务
void find360(void); //旋转一圈寻找一次光源
void genzong(void); //跟踪光源

/////////////////////////////////////////////////////////////////
//主函数负责各部件的初始化工作
//然后调用寻找光源模块
main()
{
        initcomm();    //初始化串口通信
        init_timer0(); //初始化定时器
        EA=1;          //开中断
        initdianji();  //初始化步进电机驱动

        find();        //开始执行寻找光源背景任务

        while(1);
}

//////////////////////////////////////////////////////////////////
//寻找光源函数
void find(void)
{
        uchar msg;
        while(1)
        {
                msg=getmsg();  //取得主控单片机发来的命令
                switch(msg)
                {
                        case MSG_BEGINFIND://寻找一圈
                             find360();
                             break;
                        case MSG_GENZONG:  //跟踪光源
                             genzong();
                             break;
                        case MSG_ENDFIND:  //停止工作
                             break;
                        default:
                             break;
                 }
        }
}

data int sourcedegree=0;  //光源的方位
data uchar liangdu=0;     //光源的亮度
data uchar aver;          //四周环境的平均亮度

////////////////////////////////////////////////////////////////////
//旋转一圈,寻找一次光源的方位
//光源的亮度必须比四周平均亮度大50%
void find360(void)
{
        data int dg1;   //其始角度
        data int dg2;   //终止角度
        data int dg;    //暂存最亮处角度
        data char flag1;//旋转方向标识
        data uchar temp;//暂存亮度值
        data uchar max; //暂存最亮的亮度值
        data uint temp_aver; //暂存各方向亮度值之和

        //就近转到最右或最左边
        if(getnowdegree()>0)
        {
                dg1=260;
                dg2=-260;
                flag1=-1;
        }
        else
        {
                dg1=-260;
                dg2=260;
                flag1=1;
        }
        temp_aver=0;
        max=0;
        for(;dg1!=dg2;dg1+=flag1)
        {
               if(getmsg()!=MSG_BEGINFIND)return;  //若主机发送来其他命令则立即结束寻找光源
                roundto(dg1);
                temp=jiance();
                if(temp>max)   //若该方向的亮度比先前检测的各方向都亮
                {
                        max=temp;
                        dg=dg1;
                }
                temp_aver+=(temp>>1); //累加各方向亮度值的一半,防止溢出
        }
        aver=(uchar)(temp_aver/260); //求四周亮度的平均值
        if(max>(aver*3/2))  //最亮处比四周平均亮度大50%则认为是光源
        {
                sourcedegree=dg;      //保存光源方位值
                liangdu=max;          //保存光源的亮度
                dg/=2;                //角度压缩成8位然后发送给主控单片机
                if(dg<(-128))dg=-128;  //将-260~260压缩到-128~127
                else if(dg>127)dg=127;
                sendmsg(MSG_FOUND,(char)dg);
        }
        else        //未找到光源
        {
                sendmsg(MSG_NOTFOUND,0);
        }
        while(getmsg()==MSG_BEGINFIND); //等待主机发送其他命令

}
/////////////////////////////////////////////////////////////////////
//跟踪光源,即在已经找到的光源附近小角度范围内查找光源
//此处查找的光源;亮度也必须比四周平均亮度大50%
void genzong(void)
{
        data int dg1;
        data int dg2;
        data int dg;
        data uchar max;
        data uchar temp;
        data char flag;

        //先就近转到先前检测到的光源附近
        if(getnowdegree()>sourcedegree)
        {
                dg1=sourcedegree+30;
                dg2=sourcedegree-30;
                flag=-1;
        }
        else
        {
                dg1=sourcedegree-30;
                dg2=sourcedegree+30;
                flag=1;
        }
        dg=dg1;
        max=0;

        for(;dg1!=dg2;dg1+=flag)
        {
                if(getmsg()!=MSG_GENZONG)return;
                 roundto(dg1);
                temp=jiance();
                if(temp>max)
                {
                        max=temp;
                        dg=dg1;
                }
        }
        if(max>aver*3/2)  //比四周平均亮度大50%的方位认为是光源的方位
        {
                sourcedegree=dg;
                liangdu=max;
                dg/=2;                //角度压缩成8位然后发送给主控单片机
                if(dg<(-128))dg=-128;  //将-260~260压缩到-128~127
                else if(dg>127)dg=127;
                sendmsg(MSG_FOUND,(char)dg);
        }
        else             //否则认为没有找到光源
        {
                sendmsg(MSG_NOTFOUND,0);
        }
}


//////////////////////////////////////////////////////////////////////
//亮度检测函数
//使用定时器1来检测正脉冲宽度,工作在门控方式下,配合软件查询提高检测精度
uchar jiance(void)
{
        uchar i;

        EA=0;       //关中断
        TH1=0;
        TL1=0;
        TMOD&=0x0f; //T/C1作为定时器,GATA=1,M1M0=01
        TMOD|=0x90;
        ET1=0;      //关定时器1中断
        i=0;
        while(LIANGDU)  //等到低电平
        {
                if(!(++i))goto RET;//若超时则跳到RET做处理
        }
        TR1=1;  //打开定时器1,开始计时
        i=0;
        while(!LIANGDU) //等到高电平
        {
                if(!(++i))goto RET; //若超时则跳到RET做处理
        }
        while(LIANGDU)  //等到低电平
        {
                if(!(++i))goto RET; //若超时则跳到RET做处理
        }
        TR1=0;          //停止计时
        i=240-TL1; //光源越亮,脉冲越窄,返回的数越大
RET:
        EA=1;      //开中断
        return i;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -