📄 mcu2_main.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 + -