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

📄 main.c

📁 通过89s51实现的模拟键盘代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*---------------------------------
本系统只采用一个中断,串口中断,所有外部中断全部不采用,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 + -