适合初学者看看
串口通信 有加注释,完整代码下载:
菜单程序.zip
(2.65 KB, 下载次数: 62)
预览:
- #include <reg52.h>
- #include <intrins.h>
- #define uchar unsigned char
- sbit LCD_RS = P2^6;
- sbit LCD_RW = P2^5;
- sbit LCD_EN = P2^7;
- sbit PSB= P2^1; //串并口选择端 并高串低
- //按键
- sbit KEY_PgDn=P3^0;
- sbit KEY_PgUp=P3^1;
- sbit KEY_Enter=P3^2;
- sbit KEY_Esc=P3^3;
- bit Menu1,Menu2,Menu3,Menu4,Menu5,Menu6,Enter_Menu,Menu0;
- unsigned char curr=1,currold;//全局变量,当前箭头位置
- unsigned char code user16x16[]={ //箭头图片
- 0x00,0x00,0x20,0x00,0x30,0x00,0x38,0x00,0x3C,0x00,0x3E,0x00,0x3F,0x00,0x3F,0x80,
- 0x3F,0xC0,0x3F,0x80,0x3F,0x00,0x3E,0x00,0x3C,0x00,0x38,0x00,0x30,0x00,0x20,0x00,
- };
- unsigned char code *MainMenu[]=
- {
- {" 功能菜单"},
- {" 温度显示"},
- {" 自制万年历"},
- {" 我的设置"},
- {" 5.设置5"},
- {" 6.设置6"},
- {" 7.设置7"},
- {" 8.设置8"},
- {" 9.设置9"},
- {" 0.设置0"},
- };
- /***********************************************
- 延时函数
- ***********************************************/
- void DelayUs2x(unsigned char t)
- {
- while(--t);
- }
- void DelayMs(unsigned char t)
- {
-
- while(t--)
- {
- DelayUs2x(245);
- DelayUs2x(245);
- }
- }
- /*********************************************
- 数据读写端口
- *********************************************/
- void Lcd_Send_Date(uchar date)
- {
- uchar i;
- LCD_RS=1;
- for(i=0;i<8;i++)
- {
- if((date<<i)&0x80)
- LCD_RW=1;
- else
- LCD_RW=0;
- LCD_EN=0;
- LCD_EN=1;
- }
- }
- /***********************************************
- 写入命令
- ***********************************************/
- void Write_Cmd(uchar com)
- {
- Lcd_Send_Date(0xf8);
- Lcd_Send_Date(0xf0&com);
- Lcd_Send_Date(com<<4);
- DelayMs(1);
- }
- /***********************************************
- 写入数据
- ***********************************************/
- void Write_Data(uchar dat)
- {
- Lcd_Send_Date(0xfa);
- Lcd_Send_Date(dat&0xf0);
- Lcd_Send_Date(dat<<4);
- DelayMs(1);
- }
- /***********************************************
- 液晶屏初始化
- ***********************************************/
- void Init_ST7920()
- {
- DelayMs(40); //大于40MS的延时程序
- DelayMs(1); //延时
- Write_Cmd(0x30); //选择基本指令集
- DelayUs2x(50); //延时大于100us
- Write_Cmd(0x30); //选择8bit数据流
- DelayUs2x(20); //延时大于37us
- Write_Cmd(0x0c); //开显示(无游标、不反白)
- DelayUs2x(50); //延时大于100us
- Write_Cmd(0x01); //清除显示,并且设定地址指针为00H
- DelayMs(15); //延时大于10ms
- Write_Cmd(0x06); //指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位,光标从右向左加1位移动
- DelayUs2x(50); //延时大于100us
- }
- /***********************************************
- 用户自定义字符
- ***********************************************/
- void CGRAM()
- {
- int i;
- Write_Cmd(0x30);
- Write_Cmd(0x40); //对CGRAM第一个自定义字符操作,
- for(i=0;i<16;i++)
- {
- Write_Data(user16x16[i*2]);
- Write_Data(user16x16[i*2+1]);
- }
- }
- /***********************************************
- 显示用户自定义字符
- ***********************************************/
- void DisplayCGRAM(unsigned char x,unsigned char y)
- {
- switch(y)
- {
- case 1: Write_Cmd(0x80+x);break;
- case 2: Write_Cmd(0x90+x);break;
- case 3: Write_Cmd(0x88+x);break;
- case 4: Write_Cmd(0x98+x);break;
- default:break;
- }
- Write_Data(00); //上面有一个字符操作0x04了 所以直接写
- Write_Data(00); //写字符 Write_Data(user16x16[i*2]);
- // Write_Data(user16x16[i*2+1]);
- }
- /***********************************************
- 显示字符串
- x:横坐标值,范围0~8
- y:纵坐标值,范围1~4
- ***********************************************/
- void LCD_PutString(unsigned char x,unsigned char y,unsigned char code *s)
- {
- switch(y)
- {
- case 1: Write_Cmd(0x80+x);break;
- case 2: Write_Cmd(0x90+x);break;
- case 3: Write_Cmd(0x88+x);break;
- case 4: Write_Cmd(0x98+x);break;
- default:break;
- }
- while(*s>0)
- {
- Write_Data(*s);
- s++;
- DelayUs2x(50);
- }
- }
- /***********************************************
- 清屏
- ***********************************************/
- void ClrScreen()
- {
- Write_Cmd(0x01);
- DelayMs(15);
- }
-
- /***********************************************
- 调用显示更新
- ***********************************************/
- void DisplayUpdata(void)
- {
- unsigned char num; //输入的CURR为1 执行完 DisplayUpdata后又变为0
- ClrScreen();
- num=sizeof(MainMenu)/sizeof(MainMenu[0]);//判断数组中数值个数
- //num为此数组的语速的个数
- //代表数组中元素的个数,size(a)表示整个数组的字节数,size(a[0])表示一个元素的字节数,他们相除之后就表示这个数组中元素的个数
- if((0+(curr/4)*4)<num)
- LCD_PutString(0,1,MainMenu[0+(curr/4)*4]);
- else //如果超出数组最大元素,则写空信息,不判断此信息可能会出现乱码 0是字节 1是行数
- LCD_PutString(0,1,"");
- // 2
- if((1+(curr/4)*4)<num)
- LCD_PutString(0,2,MainMenu[1+(curr/4)*4]); //num是字节数 1or2or3/4=0
- // <0curr<3 3<curr<8
- else // 0+(curr/4)*4=0 4
- LCD_PutString(0,2,""); // 1+(curr/4)*4=1 5
- //3 // 2+(curr/4)*4=2 6
- if((2+(curr/4)*4)<num) // 3+(curr/4)*4=3 7
- LCD_PutString(0,3,MainMenu[2+(curr/4)*4]);
- else
- LCD_PutString(0,3,"");
- //4
- if((3+(curr/4)*4)<num) //判断行数
- LCD_PutString(0,4,MainMenu[3+(curr/4)*4]);
- else
- LCD_PutString(0,4,"");
- DisplayCGRAM(0,curr%4+1); //显示字符串的函数 0%4+1=1 1%4+1=2 /2+1=3 /3+1=4
- }
- /*------------------------------------
- 主界面处理
- ------------------------------------*/
- void MainMenu_Pro()
- {
- if(curr!=currold) //光标位置变化,则更新显示 按键按下去 字符串就变更位置了 CURR也就变了
- {
- DisplayUpdata();
- currold=curr; //把CURR的值赋给CURROLD 判断下加一个一
- }
-
- if(!KEY_PgUp)
- {
- DelayMs(10);
- if(!KEY_PgUp)
- {
- while(!KEY_PgUp);
- {
- if(curr<sizeof(MainMenu)/sizeof(MainMenu[0])-1) //sizeof 求字节数
- //判断数组中数值个数
- { curr++; }
- }
- }
- }
- else
- if(!KEY_PgDn)
- {
- DelayMs(10);
- if(!KEY_PgDn)
- {
- while(!KEY_PgDn);
- {
- if(curr>0)
- { curr--; }
- }
- }
- }
- else if(!KEY_Enter)
- {
- DelayMs(10);
- if(!KEY_Enter)
- {
- while(!KEY_Enter);
- switch(curr)
- {
- // case 0: Menu0=1;Enter_Menu=1;break;
- case 1: Menu1=1;Enter_Menu=1;ClrScreen();break;
- case 2: Menu2=1;Enter_Menu=1;ClrScreen();break;
- case 3: Menu3=1;Enter_Menu=1;ClrScreen();break;
- // case 4: Menu4=1;Enter_Menu=1;break;
- // case 5: Menu5=1;Enter_Menu=1;break;
- // case 6: FanHui1=1;Menu_Flag=0;guide=0;
- // Write_Cmd(0x01);break; //轮询到有enter键,当guide指向返回时候直接去掉FanHui1控制的父菜单循环
- default:return;
- }
- TR1=0;
- }
- }
-
- }
- /*************************************************************
- 按键返回函数
- *************************************************************/
- void ESC()
- {
- DelayMs(10);
- if(!KEY_Esc)
- {
- while(!KEY_Esc);
- Menu1=0;
- Menu2=0;
- Menu3=0;
- Enter_Menu=0;
- DisplayUpdata();
- }
- }
- /*------------------------------------
- Menu1设置时间子菜单处理
- ------------------------------------*/
- void Menu1_Pro()
- {
- LCD_PutString(0,2,MainMenu[9]);
- if(!KEY_Esc)
- {
- ESC();
- }
- }
- /*------------------------------------
- Menu2设置时间子菜单处理
- ------------------------------------*/
- void Menu2_Pro()
- {
- LCD_PutString(0,2,MainMenu[1]);
- if(!KEY_Esc)
- {
- ESC();
- }
- }
- /*------------------------------------
- Menu3设置时间子菜单处理
- ------------------------------------*/
- void Menu3_Pro()
- {
- LCD_PutString(0,2,MainMenu[5]);
- if(!KEY_Esc)
- {
- ESC();
- }
- }
- /***********************************************
- MAIN
- ***********************************************/
- void main()
- {
- Init_ST7920();
- CGRAM(); //写入自定义字符
- DisplayUpdata();
- while(1)
- {
- MainMenu_Pro();
- while(Enter_Menu) //进入子菜单标签
- {
- // if(Menu0) Menu0_Pro(); //子菜单0处理函数
- // else
- if(Menu1) Menu1_Pro();
- else if(Menu2) Menu2_Pro();
- else if(Menu3) Menu3_Pro();
- // else if(Menu4) Menu4_Pro();
- // else if(Menu5) Menu5_Pro();
- }
- }
- }
复制代码
|