📄 main.c
字号:
/*---------------------------------
本系统只采用一个中断,串口中断,所有外部中断全部不采用,I/O口工作于查询方式
所有的静态变量处于初值0
-----------------------------------*/
#include <general.h> //定义外部的函数
volatile unsigned char bdata bflag=0; //通用位变量
sbit bflag_0=bflag^0;
sbit bflag_1=bflag^1;
sbit bflag_2=bflag^2;
sbit bflag_3=bflag^3;
sbit bflag_4=bflag^4;
sbit bflag_5=bflag^5;
sbit bflag_6=bflag^6;
sbit bflag_7=bflag^7;
volatile unsigned char bdata bflag1=0; //通用位变量
sbit bflag1_0=bflag1^0;
sbit bflag1_1=bflag1^1;
sbit bflag1_2=bflag1^2;
sbit bflag1_3=bflag1^3;
sbit bflag1_4=bflag1^4;
sbit bflag1_5=bflag1^5;
sbit bflag1_6=bflag1^6;
sbit bflag1_7=bflag1^7;
/*-----------------------------------------------
明景的键盘PELCO-P球机ID为实际球机ID少1,程序要进行处理
PELCO-D上下两代码颠倒了,UP为000 DOWN 为00108 与公布的相反
------------------------------------------------*/
volatile unsigned char cProtocol;
volatile unsigned char bdata id=0; //通用位变量
sbit id_0=id^0;
sbit id_1=id^1;
sbit id_2=id^2;
sbit id_3=id^3;
sbit id_4=id^4;
sbit id_5=id^5;
sbit id_6=id^6;
sbit id_7=id^7;
unsigned char idata sKeyCode[20]={""}; //目前只用一组来表示,并且为0值 接收键盘码用
unsigned char idata cKeyCodeReceiveState=0 ; //初值处于无串口码接收到状态有值用1表示
unsigned char idata cKeyCodeReceive=0;
unsigned char idata *pKeyCode;
unsigned char ProtocalSelect()
{ unsigned char x;
bflag1=0;
DIP_4=1; //写1
DIP_3=1;
DIP_2=1;
DIP_1=1;
do
{
bflag1_0=!DIP_4; //选择通讯协议 取反
bflag1_1=!DIP_3;
bflag1_2=!DIP_2;
bflag1_3=!DIP_1;
x= bflag1;
bflag1_0=!DIP_4; //选择通讯协议 取反
bflag1_1=!DIP_3;
bflag1_2=!DIP_2;
bflag1_3=!DIP_1;
}while(bflag1!=x);
return(x);
}
void BaudSelect() //波特率选择 子程序
{
unsigned char x; //开关取反才是正确的
bflag1=0;
DIP_6=1; //先给1
DIP_5=1;
do
{
bflag1_0=!DIP_6; //选择波特率
bflag1_1=!DIP_5;
x=bflag1;
bflag1_0=!DIP_6; //选择波特率
bflag1_1=!DIP_5;
}while(bflag1!=x);
/*------------------------------------------------------------------调试用 */
bflag1=x; //正式有上面的,没有此项
/*------------------------------------------------------------------调试用 */
switch(bflag1) //与说明手册上控制位一致
{
case 0:
baud_2400();
break;
case 2:
baud_4800();
break;
case 1:
baud_9600();
break;
case 3:
baud_19200();
break;
}
}
void IdSelect() //球机ID选择子程序
{
unsigned char x;
P0_7=1; // 先给1 按从左到右的BCD方式
P1_7=1;
P1_6=1;
P1_5=1;
P1_4=1;
P1_3=1;
P1_2=1;
P1_1=1;
do
{
id_0=!P0_7; //10位拨码开关的右8 位按BCD排列
id_1=!P1_7;
id_2=!P1_6; //可选择256位
id_3=!P1_5;
id_4=!P1_4; //P0-6 P1-0两位可作它用 ,如果有相机选择可减少ID位数
id_5=!P1_3;
id_6=!P1_2;
id_7=!P1_1;
x=id;
id_0=!P0_7; //10位拨码开关的右8 位按BCD排列
id_1=!P1_7;
id_2=!P1_6; //可选择256位
id_3=!P1_5;
id_4=!P1_4; //P0-6 P1-0两位可作它用 ,如果有相机选择可减少ID位数
id_5=!P1_3;
id_6=!P1_2;
id_7=!P1_1;
}while(id!=x);
/*------------------------------------------------------------------调试用 */
//SBUF=x;
id=x; // 正式有上面的,没有此项
/*------------------------------------------------------------------调试用 */
}
void LeftRight_out(char x) //左右方向的位输出
{
bflag=x; //水平方向电机输出
P2_3=bflag_3;
P2_2=bflag_2;
P2_1=bflag_1;
P2_0=bflag_0;
}
void UpDown_out(char x) //上下方向的位输出
{
bflag=x; //竖直方向电机输出
P2_7=bflag_0;
P2_6=bflag_1;
P2_5=bflag_2;
P2_4=bflag_3;
}
/*----------------------------------------------------------------------------
水平方向电机用T0来控制
竖直方向用T1来控制
波特用T2来控制
------------------------------------------------------------------------------*/
void T0_load()
{ //水平方向
int x;
x=T0_interval;
TH0=(char)(x>>8); //复位时的时间常数
TL0=(char)x;
}
void T1_load()
{
int x;
x=T1_interval; //竖直方向
TH1=(char)(x>>8); //复位时的时间常数
TL1=(char)x;
}
void AutoTest(void) //自检程序,加电前拨第9位开关于“on”位
{
while(!P1_0) //自检过程中拨回“off“位进入正常运行
{
WDT_CONTR=0xff; //0xff; 启动看门狗看门狗清零
if(!cDirectHorizon)
cDirectHorizon=1;
cAutoScan=1;
T0_start();
if(!cDirectVertical)
cDirectVertical=1 ;
cAutoTestVertical=1 ;
T1_start();
}
cAutoScan=0;
cAutoTestVertical=0;
T1_stop();
T0_stop();
CameraStop();
/*---------------------------
因为串口数据易丢失所以在执行串口的程序前不能加别的程序,可能引起数据丢失
所以自检程序放在起始段了
---------------------------*/
}
void main()
{
unsigned int x;
unsigned long y;
ERRor:
WDT_cls();
GlobalSet();
INT_disable();
T0_stop();
T1_stop();
T2_stop();
port_init();
INT_set();
timer_set();
SCI_set();
T0_load();
T1_load();
T2_start();
INT_enable();
BaudSelect(); //波特选择 程序波特及ID可随时选
IdSelect(); //ID选择
pKeyCode=sKeyCode; //接收码清零程序
for(x=0;x<20;x++) //预设20个字符
{
*pKeyCode =0;
++pKeyCode ;
}
pKeyCode=sKeyCode; //重新指向代码
cProtocal= ProtocalSelect();
/*----------------------------------------------------------------------
下面是复位监测程序取消 cDirectHorizon cAutoScan初始化
---------------------------------------------------------------------- */
if((cAutoScan==1)&&( P1_0==1 )) //自动扫描标志存在就进行左开始及水平定时器开始,后面就进入
{
cDirectHorizon=1; //取消方向,由复位RAM保留决定
T0_start();
}
else
{
AutoTest();
} //自检程序
cKeyCodeReceiveState=0;
switch(cProtocal) //与说明手册上控制位一致
{
default: break;
case 1: //三星协议
while(1)
{
WDT_cls();
if(1!=cProtocal) // 利用协议出错处理
{
goto ERRor;
}
if(cKeyCodeReceiveState)
{
switch((unsigned char)cKeyCodeReceive)
{
case 0xa0: //防误码先接收一个FF后接下来进行 判断是否下个码
cKeyCodeReceiveState=0; //取走第一个码
while(!cKeyCodeReceiveState) //对于键盘发出的选择球机也是七位FF开始的码
{
_nop_();
}
if(0xa0==(unsigned char)cKeyCodeReceive) //判断是否是误码,FF说明是误码
{
break; //
}
else //上一个取发送地址码但无用舍去
cKeyCodeReceiveState=0;
while(!cKeyCodeReceiveState)
{
_nop_();
}
if( (unsigned char)cKeyCodeReceive==id) //说明是正确的键盘码转入处理程序
{
x=3;
pKeyCode=sKeyCode;
*pKeyCode=0xa0; //起始同步码
++pKeyCode; //跳过发送地址
++pKeyCode;
*pKeyCode=id; //ID码
cKeyCodeReceiveState=0;//已取走第3个码
do
{
// x=x+*pKeyCode ; //从第二个开始累加校验
while(!cKeyCodeReceiveState) //读码等待
{
_nop_();
}
++pKeyCode;
*pKeyCode=cKeyCodeReceive;
cKeyCodeReceiveState=0; //取走键盘码
++x;
}while(x!=9); //读码结束标志
y= (((unsigned long)sKeyCode[3])<<16)+(((unsigned long)sKeyCode[4])<<8)+(unsigned long)sKeyCode[5];
//构造一译码关键字
WDT_cls();
switch(y)
{
case 0x010800: //光圈开
if(cAutoScan==1)
{
T0_stop();
cAutoScan=0; //自动扫描标志
}
CameraStop();
IrisOpen();
break;
case 0x011000: //光圈关
if(cAutoScan==1)
{
T0_stop();
cAutoScan=0; //自动扫描标志
}
CameraStop();
IrisClose();
break;
case 0x010200: //焦距拉近 因电路接线 必须单操作
if(cAutoScan==1)
{
T0_stop();
cAutoScan=0; //自动扫描标志
}
CameraStop();
Focus_near();
break;
case 0x010100: //焦距拉远
if(cAutoScan==1)
{
T0_stop();
cAutoScan=0; //自动扫描标志
}
CameraStop();
Focus_far() ;
break;
case 0x014000: //视角宽
if(cAutoScan==1)
{
T0_stop();
cAutoScan=0; //自动扫描标志
}
CameraStop();
Zoom_wide();
break;
case 0x012000: //视角窄
if(cAutoScan==1)
{
T0_stop();
cAutoScan=0; //自动扫描标志
}
CameraStop();
Zoom_tele();
break;
case 0x010004: //向上 上下由T1控制
if(cAutoScan==1)
{
T0_stop();
cAutoScan=0; //自动扫描标志
}
cDirectVertical=1 ;
T0_stop();
if(cDirectVerticalLim==1 )
break;
cDirectVerticalLim=0;
T1_start();
break;
case 0x010008: //向下
if(cAutoScan==1)
{
T0_stop();
cAutoScan=0; //自动扫描标志
}
cDirectVertical=-1 ;
T0_stop();
if(cDirectVerticalLim==-1 )
break;
cDirectVerticalLim=0;
T1_start();
break;
case 0x010001: //向左 左右由T0控制
if(cAutoScan==1)
{
T0_stop();
cAutoScan=0; //自动扫描标志
}
cDirectHorizon=1;
T1_stop();
if(cDirectHorizonLim ==1 )
break;
cDirectHorizonLim =0; //可以运动则复位
T0_start();
break;
case 0x010002: //向右
if(cAutoScan==1)
{
T0_stop();
cAutoScan=0; //自动扫描标志
}
cDirectHorizon=-1;
T1_stop();
if(cDirectHorizonLim ==-1 )
break;
cDirectHorizonLim =0; //可以运动则复位
T0_start();
break;
case 0x031301: //自动扫描
cAutoScan=1; //自动扫描标志
cDirectHorizon=1;
T0_start();
break;
case 0x031a01: //自动扫描
cAutoScan=1; //自动扫描标志
cDirectHorizon=1;
T0_start();
break;
case 0x031b01: //自动扫描
cAutoScan=1; //自动扫描标志
cDirectHorizon=1;
T0_start();
break;
case 0x010000: //结束所有运动 2 明景工控
T1_stop();
T0_stop();
CameraStop();
break;
default :break;
}
break; //处理程序后的分枝完成
}
else
{ //不是本球机的接收码ID不正确或者是一误码都必须会结束
cKeyCodeReceiveState=0;
break; //处理并且清除接收标志
}
default: break;
} //结束协议一次接收
} //结束 if有数
} //结束协议的while
break; //结束协议的case事件
case 2: //PELCO-P协议
while(1)
{
WDT_cls();
if(2!=cProtocal) // 利用协议出错处理
{
goto ERRor;
}
if(cKeyCodeReceiveState)
{
cKeyCodeReceiveState=0; //取走第一个码
switch(cKeyCodeReceive)
{
case 0xa0: //防误码先接收一个FF后接下来进行 判断是否下个码
while(!cKeyCodeReceiveState) //对于键盘发出的选择球机也是七位FF开始的码
{
_nop_();
}
// cKeyCodeReceiveState=0;
if(cKeyCodeReceive==0xa0) //判断是否是误码,FF说明是误码
{ //不进行处理转入从头开始的循环
//不清标志
break;
}
else if( cKeyCodeReceive==id) //说明是正确的键盘码转入处理程序
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -