📄 menu.c
字号:
#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 + -