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

📄 menu.c

📁 本菜单程序基于单片机8051和液晶1602
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <reg52.h>
#include <intrins.h>
#include <absacc.h>
#include <MATH.H>
#include "D12Config.h"
#include "Descriptor.h"
#include "Chap_9.h"
#include "D12Driver.h"


unsigned char tmp;    //暂存接收到的串口数据 
unsigned char advl,advh; //接收采样的高低字节



unsigned char   zd = 0;
sbit ckey	 	= P3^4; 





//LCD部分宏定义
#define wc 0xa000   //写命令
#define wd 0xa200   //写数据
#define rc 0xa100   //读忙状态


//当bz=1时,485处于接收状态,bz=0时,485处于发送状态
sbit bz=P3^4;   



//第一级菜单
#define FIRSTSUM 3   //第一级菜单包含2个菜单项
#define CONVERTERNUM   1  //第一项
#define COMMUNICATION  2  //第二项
#define ADDRESS485     3  //第三项
unsigned char code CONVERLAB[] = {"Local Operation"};   //显示标题 
unsigned char code COMLAB[] = {"Communication"};   //显示标题 
unsigned char code ADDRESSLAB[] = {"Address485"};   //显示标题 

//第二级菜单Local Operation下
#define SECOND1SUM 1   //第二级菜单Local Operation下包含1个菜单项
#define ADconverter  1  //第一项
//#define DAconverter  2  //第二项
//#define DI           3  //第三项
//#define DO           4  //第四项
unsigned char code 	 ADLAB[]={ "AD converter" };  //显示标题
unsigned char code	 DALAB[]={ "   "};   //显示标题
//unsigned char code   DILAB[]={ "DI " };           //显示标题
//unsigned char code   DOLAB[]={ "DO " };           //显示标题

//第二级菜单communication下
#define SECOND2SUM 3   //第二级菜单communication下包含2个菜单项
#define RS232  1  //第一项
#define RS485  2  //第二项
#define USB    3  //第三项
unsigned char code RS232LAB[] = {" RS232 "};   //显示标题
unsigned char code RS485LAB[] = {" RS485 "} ;  //显示标题
unsigned char code USBLAB[] = { "USB COM"} ;  //显示标题

//第三级菜单AD converter下
#define THIRD1SUN  4   //第三级菜单AD converter下包含4个菜单项
#define AD590  1      //第一项AD590
#define FCV    2      //第二项F/V转换
#define PT100  3      //第三项PT100温度感测
#define Other  4      //第四项其他 直接测量显示电阻值
unsigned char code OTHERLAB[] ={"Other"}; //显示标题
unsigned char code AD590LAB[] = {"AD590"};   //显示标题
unsigned char code FCVLAB[] = {"F/V"};   //显示标题
unsigned char code PT100LAB[] = {"PT100"};   //显示标题



//第一级菜单操作函数
void firstturn();   //在同级菜单中翻转
void firstenter();  //进入下一级菜单
void firstesc();    //返回上一级菜单

//第二级菜单CONVERTER下操作函数
void second1turn();   //在同级菜单中翻转
void second1enter();  //进入下一级菜单
void second1esc();    //返回上一级菜单

//第二级菜单COMMUNICATION下操作函数
void second2turn();   //在同级菜单中翻转
void second2enter();  //进入下一级菜单
void second2esc();    //返回上一级菜单

//第三级菜单ADCONVERTER下操作函数
void third1turn();   //在同级菜单中翻转
void third1enter();  //进入下一级菜单
void third1esc();    //返回上一级菜单


	


//检测是否按下ESC或PAUSE键
void  keyprocess1();


//初始化菜单
void menuini();


//键盘操作函数声明
void keyprocess();            // 初始化
void keyprocess1();         //检测是否按下ESC 或PAUSE键
unsigned char GetKeyStatus();    //读取键的状态
unsigned char GetKeyCode();      // 获取键值
void delayms(unsigned char ms);  //延时
void zero();
void one();
void changeV();  //改变采样的速率  用定时器控制
void turn();   //同级菜单翻滚
void enter();  //进入下级菜单或启动具体功能
void esc();    //返回上一级菜单
void pause();  //结束具体功能    
void delete(); //数字删除


//LCD部分操作函数声明
bit lcd_busy();               //检测忙状态
void lcd_wcmd(unsigned char cmd);     //写命令
void lcd_pos(unsigned char pos);      //设定显示位置
void lcd_wdat(unsigned char dat);     //写数据
void lcd_init();	          //LCD初始化
void lcddisplay(unsigned char code menuitem1[],unsigned char code menuitem2[]); //LCD显示函数
//void delay(unsigned char ms);


//延时函数1
void  delay(unsigned int k)
{
  unsigned int xdata j;
  for (j=1;j<k;j++) ;
}



//延时函数2
void  delay2(unsigned char changev)
{
  unsigned int xdata j;
 if(changev == 0)
{
 for (j=1;j<20000;j++) ;
}
else if (changev == 1)
{
 for (j=1;j<40000;j++) ;
 }   
else if(changev == 2)
{
 for (j=1;j<5000;j++) ;
}
}




// 传送一个字符   串口通信
void send_char(unsigned char txd)

{
	SBUF = txd;
	while(!TI);				// 等特数据传送
	TI = 0;					// 清除数据传送标志
}


// 键盘部分宏定义    采用行扫描   列读取方式
#define key		XBYTE[0x8000]        //键盘(新加)
#define mHorizontalNumber 4 // 总行数
#define mVerticalNumber 4  // 总列数
#define mH_InitValue 0xfe  //逐行扫描初值  先扫KB1
#define mReadVertical(c) { key = ucH_Value ; _nop_(); _nop_(); c = key; c = c|0xf0 ;}   // 某一行为低电平,读键值
#define mJugeVertical(c) { c = key; c = c|0xf0; }   // 判断列值是否全为高电平,即是否有按键
#define mHorizontalAllLow { key = 0xf0;_nop_(); _nop_();}  // 高四位行线输出全零
#define mKeyOff 0xff    //表示没按键




//定义菜单
xdata struct menu  
{
  void (*turn)();
  void (*enter)();
  void (*esc)();

}M_FIRST,M_SECOND1,M_SECOND2,M_THIRD1;




//全局指针指向结构体
struct menu *ptrstru;

//全局变量,标记当前菜单中的当前项
unsigned char item_num;

//改变LCD屏的显示速率
unsigned char chanV = 0;


//全局变量  定义一组位变量  用来打开或关闭各键  为0时打开  为1时关闭
unsigned char  bdata lock; 
sbit esclock = lock^0;
sbit enterlock = lock^1;
sbit turnlock = lock^2;
sbit pauselock = lock^3;
sbit samplelock = lock^4;   //采样速率调整
sbit reback  = lock^5;     //从具体功能中返回   0表示返回  1表示进入
sbit volrange = lock^6;     //标记采样电压范围  0表示0到10V  1表示-10到0
sbit adready =  lock^7;     //标记外中断1是否响应   0表示未到   1表示收到


//复位
sbit comrst		= P1^4; 


//485
sbit ctrl485 =  P1^6;


//将AD采样的12位数转换为10进制数输出
unsigned int  AD12to10(unsigned char adl,unsigned char adh )

{
   unsigned char  idata i1,cc;
   unsigned int   idata bj;
   bj = 0;     
  
     for(i1 = 0;i1<4;i1++)
   {
     cc = adl&0x01;
   if(cc != 0)
   {
     bj = bj + x[i1];

    }
	 adl = adl>>1;
   }
    
  
     for(i1 = 0;i1<7;i1++)    //只算到11位  最高位做判断
   {
     cc = adh&0x01;
   if(cc!= 0)
   {
     bj = bj + x[i1+4];

    }
	 adh = adh>>1;
   }
    adh = adh&0x01;
   if(adh == 0x01) 
   {
   volrange = 0;    //0到10伏
   }
   else 
   {
   volrange = 1;     //-10到0伏
   bj = 2048-bj;
   }

   return bj;

} 


void main()
{

spk = 0;
delay(20000);
spk = 1;
comrst=1;
delay(20);
comrst=0;


//系统启动后进入第一级菜单
menuini();           //菜单初始化 
ptrstru = &M_FIRST;  //使全局指针指向第一级菜单
item_num = CONVERTERNUM;  // 全局变量指向第一级菜单第一项


//////////////////////////

lcddisplay(CONVERLAB,COMLAB);  //LCD同步显示第一级菜单2项内容
lcd_wcmd(0x02);                //光标停在第一项
///////////////////////////
esclock = 0;            //打开 ESC ENTER TURN   关闭PAUSE SAMPLE
enterlock = 0;
turnlock = 0;
pauselock = 1;
samplelock = 1;
reback = 0;
adready = 0;
///////////////////////////

//串行口设置
SCON=0x50;  //10位异步收发   由定时器控制
PCON=0;    //波特率无倍增
TMOD=0x20;   //定时器模式控制   方式2  自动装入8位
ES = 0;    // 串行中断允许
TL1=TH1=0xf3;
TR1=1;    // 定时器由软件控制位启动  //串口工作在模式3,波特率2400(12M)

//外中断设置
IT1 = 1;            // 设置中断触发方式为下降沿触发
EX1 = 0;              // 禁止外中断1

//中断总允许
EA=1;

//
 

while(1)
{

  keyprocess();     //进入键扫描

}

}






//初始化菜单
void menuini()
{
//
M_FIRST.turn=firstturn;
M_FIRST.enter=firstenter;
M_FIRST.esc=firstesc;

//
M_SECOND1.turn=second1turn;
M_SECOND1.enter=second1enter;
M_SECOND1.esc=second1esc;

//
M_SECOND2.turn=second2turn;
M_SECOND2.enter=second2enter;
M_SECOND2.esc=second2esc;

//
M_THIRD1.turn=third1turn;
M_THIRD1.enter=third1enter;
M_THIRD1.esc=third1esc;

}




//第一级菜单操作函数
void firstesc()
{

}

void firstturn()    //在同级菜单中翻转
{
  item_num = (item_num)%FIRSTSUM+1;
  switch(item_num)
  {
 case  CONVERTERNUM:
      lcddisplay(CONVERLAB,COMLAB);
      lcd_wcmd(0x02);                       //光标指向CONVERTERNUM项       
	  break;
 case COMMUNICATION: 
      lcddisplay(COMLAB,ADDRESSLAB); 
      lcd_wcmd(0x02); 
	  break;

 case  ADDRESS485:
      lcddisplay(ADDRESSLAB,CONVERLAB); 
      lcd_wcmd(0x02); 
 default:
         
	  break;
  }

}



void firstenter()  //进入下一级菜单
{
 switch(item_num)
 {
case CONVERTERNUM: 
     ptrstru = &M_SECOND1;
     item_num = ADconverter;
     lcddisplay(ADLAB,DALAB); 
     lcd_wcmd(0x02); 
     break;
case COMMUNICATION: 
     ptrstru = &M_SECOND2;
     item_num = RS232;
     lcddisplay(RS232LAB,RS485LAB); 
     lcd_wcmd(0x02); 
     break;

case ADDRESS485:
     lcd_init();	 
     lcd_wcmd(0x02); 
     lcd_wdat(0x31); 
     delay(50000);
     delay(50000);
     lcddisplay(ADDRESSLAB,CONVERLAB); 
     lcd_wcmd(0x02); 
	 break;

default: 
     item_num = CONVERTERNUM;
     break;
}


}


//第二级菜单CONVERTER下操作函数

void second1turn()   //在同级菜单中翻转
{

}

void second1enter()  //进入下一级菜单
{
     ptrstru = &M_THIRD1;
	 item_num = AD590;
     lcddisplay(AD590LAB,FCVLAB); 
	 lcd_wcmd(0x02); 
}

void second1esc()   //返回上一级菜单
{
    ptrstru = &M_FIRST;
	item_num = CONVERTERNUM;
    lcddisplay(CONVERLAB,COMLAB);  
    lcd_wcmd(0x02);    
}



//第二级菜单COMMUNICATION下操作函数
void second2turn()   //在同级菜单中翻转
{
  item_num = (item_num)%SECOND2SUM+1;
  switch(item_num)
  {
 case  RS232:
	   lcddisplay(RS232LAB,RS485LAB);
       lcd_wcmd(0x02); 
	  break;
 case  RS485: 
       lcddisplay(RS485LAB,USBLAB); 
       lcd_wcmd(0x02);
	  break;
 case  USB:
	   lcddisplay(USBLAB,RS232LAB); 
       lcd_wcmd(0x02);
	    break;
 default: 
      item_num=0;
	  break;
  }  


}



//进入下一级菜单
void second2enter()  
{

switch(item_num)
 {
case RS232:
     EX1 = 0;            //关外中断1
     esclock = 0;
 	 enterlock = 1;      //0为打开  1为关闭
	 turnlock = 1;
	 pauselock = 0;
     samplelock = 1;
     reback = 1;
	 ///////////
	 lcd_init();  
	 lcd_wcmd(0x02);
	 lcd_wdat(0x32);
     lcd_wdat(0x33);
     lcd_wdat(0x32);
     lcd_wdat(0x2e);
     lcd_wdat(0x2e);
	 lcd_wdat(0x2e);
	 //////////////

     //rs232通信的处理程序
	 while(reback)
	 {            ////////
	    
     	if(RI)						// 是否有数据到来
		{         ///////
			RI = 0;
			tmp = SBUF;				// 暂存接收到的数据
			if(tmp =='F')           //收到验证位第一位
			{        //////
			 while(!RI);
			 RI = 0 ;
			 tmp = SBUF ;
			 if(tmp == 'S')         //收到验证位第二位
			 {          /////
			   RI = 0;        //发送循环
			          ////
                 advl = xdadl;
                 advh = xdadh;
                 advl = advl & 0x0f;  //使5到8位为0
				 if(advh >= 0x80)
				 {
				  advh = advh & 0x7f;
                  send_char('F'); send_char(advl);send_char(advh);send_char('P');send_char('M');     //发送高低字节  电压为正
				 }
				 else
				 {
			     send_char('F'); send_char(advl);send_char(advh);send_char('N');send_char('M');     //发送高低字节   电压为负
			     
				 }

			     keyprocess1();   //检测是否有ESC PAUSE     

			        ////
			 
			 }       /////
			 
			}     //////
		
		}		  ///////

		//返回函数
     keyprocess1();    //检测是否有ESC PAUSE    
	
     }         ////////
     break;
case RS485 :
     //RS485通信的处理程序 
   
     EX1 = 0;            //关外中断1
     esclock = 0;
 	 enterlock = 1;      //0为打开  1为关闭
	 turnlock = 1;
	 pauselock = 0;
     samplelock = 1;
     reback = 1;
	 lcd_init();
	 ///////////////
	 lcd_wcmd(0x02);
	 lcd_wdat(0x34);
     lcd_wdat(0x38);
     lcd_wdat(0x35);
     lcd_wdat(0x2e);
     lcd_wdat(0x2e);
	 lcd_wdat(0x2e);
	 /////////////////
     //rs485通信的处理程序
	 while(reback)
	 {            ////////
	    
     	if(RI)						// 是否有数据到来
		{         ///////
			RI = 0;
			tmp = SBUF;				// 暂存接收到的数据
			if(tmp =='F')           //收到验证位第一位
			{        //////
			 while(!RI);
			 RI = 0 ;
			 tmp = SBUF ;
			 if(tmp == 'S')         //收到验证位第二位
			 {          /////
                 while(!RI);
                 RI = 0;
                 tmp = SBUF ;
               if(tmp == '1')        //确认是否是发送给本机的传送命令   1为本机从机号
                 {            ////
			     RI = 0;                
			     ctrl485 = 0;            // 处于发送状态
                 advl = xdadl;
                 advh = xdadh;
                 advl = advl & 0x0f;  //使5到8位为0
				 if(advh >= 0x80)
				 {
				  advh = advh & 0x7f;
                  send_char('F'); send_char(advl);send_char(advh);send_char('P');send_char('M');     //发送高低字节  电压为正
				 }
				 else
				 {
			     send_char('F'); send_char(advl);send_char(advh);send_char('N');send_char('M');     //发送高低字节   电压为负
			     
				 }
                 ctrl485 = 1;  //485处于接收状态
			     keyprocess1();   //检测是否有ESC PAUSE     

               }			        ////
			 
			 }       /////
			 
			}     //////
		
		}		  ///////

		//返回函数
     keyprocess1();    //检测是否有ESC PAUSE    
	
     }         ////////
     break;
case USB:
	 //USB方式的处理程序
      //USB方式的处理程序
     EX1 = 0;            //关外中断1
     esclock = 0;
 	 enterlock = 1;      //0为打开  1为关闭
	 turnlock = 1;
	 pauselock = 0;
     samplelock = 1;
     reback = 1;
     EA = 1;	
	 lcd_init();
	 ///////////////
	 lcd_wcmd(0x02);
	 lcd_wdat(0x55);
     lcd_wdat(0x53);
     lcd_wdat(0x42);
     lcd_wdat(0x2e);
     lcd_wdat(0x2e);
	 lcd_wdat(0x2e);
	 /////////////////

 	if (Init_D12()!=0)					
		return;


	EX0 = 1;							
	PX0 = 0;							
	EA = 1;	

⌨️ 快捷键说明

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