找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2966|回复: 1
打印 上一主题 下一主题
收起左侧

12864简易菜单框架单片机源程序 串口通信 带注释

[复制链接]
跳转到指定楼层
楼主
ID:152913 发表于 2016-12-9 23:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
适合初学者看看  
串口通信  有加注释,完整代码下载: 菜单程序.zip (2.65 KB, 下载次数: 61)

预览:
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char

  4. sbit LCD_RS = P2^6;
  5. sbit LCD_RW = P2^5;
  6. sbit LCD_EN  = P2^7;

  7. sbit PSB= P2^1; //串并口选择端  并高串低

  8. //按键
  9. sbit KEY_PgDn=P3^0;
  10. sbit KEY_PgUp=P3^1;
  11. sbit KEY_Enter=P3^2;
  12. sbit KEY_Esc=P3^3;

  13. bit Menu1,Menu2,Menu3,Menu4,Menu5,Menu6,Enter_Menu,Menu0;

  14. unsigned char curr=1,currold;//全局变量,当前箭头位置

  15. unsigned char code user16x16[]={ //箭头图片
  16. 0x00,0x00,0x20,0x00,0x30,0x00,0x38,0x00,0x3C,0x00,0x3E,0x00,0x3F,0x00,0x3F,0x80,
  17. 0x3F,0xC0,0x3F,0x80,0x3F,0x00,0x3E,0x00,0x3C,0x00,0x38,0x00,0x30,0x00,0x20,0x00,
  18. };

  19. unsigned char code *MainMenu[]=
  20. {
  21. {"    功能菜单"},
  22. {"  温度显示"},
  23. {"  自制万年历"},
  24. {"  我的设置"},
  25. {"  5.设置5"},
  26. {"  6.设置6"},
  27. {"  7.设置7"},
  28. {"  8.设置8"},
  29. {"  9.设置9"},
  30. {"  0.设置0"},
  31. };

  32. /***********************************************
  33.                   延时函数
  34. ***********************************************/
  35. void DelayUs2x(unsigned char t)
  36. {   
  37. while(--t);
  38. }

  39. void DelayMs(unsigned char t)
  40. {
  41.      
  42. while(t--)
  43. {
  44.      DelayUs2x(245);
  45.   DelayUs2x(245);
  46. }
  47. }
  48. /*********************************************
  49.              数据读写端口
  50. *********************************************/

  51. void Lcd_Send_Date(uchar date)
  52. {
  53.         uchar i;
  54.         LCD_RS=1;
  55.         for(i=0;i<8;i++)
  56.         {
  57.                 if((date<<i)&0x80)
  58.                 LCD_RW=1;
  59.                 else
  60.                 LCD_RW=0;
  61.                 LCD_EN=0;
  62.                 LCD_EN=1;
  63.         }
  64. }
  65. /***********************************************
  66.                 写入命令
  67. ***********************************************/
  68. void Write_Cmd(uchar com)
  69. {
  70.         Lcd_Send_Date(0xf8);       
  71.         Lcd_Send_Date(0xf0&com);
  72.         Lcd_Send_Date(com<<4);
  73.         DelayMs(1);
  74. }
  75. /***********************************************
  76.                  写入数据
  77. ***********************************************/
  78. void Write_Data(uchar dat)
  79. {
  80.         Lcd_Send_Date(0xfa);
  81.         Lcd_Send_Date(dat&0xf0);
  82.         Lcd_Send_Date(dat<<4);
  83.         DelayMs(1);
  84. }
  85. /***********************************************
  86.                液晶屏初始化
  87. ***********************************************/
  88. void Init_ST7920()
  89. {  
  90.    DelayMs(40);           //大于40MS的延时程序
  91.    DelayMs(1);            //延时
  92.    Write_Cmd(0x30);       //选择基本指令集
  93.    DelayUs2x(50);         //延时大于100us
  94.    Write_Cmd(0x30);       //选择8bit数据流
  95.    DelayUs2x(20);         //延时大于37us
  96.    Write_Cmd(0x0c);       //开显示(无游标、不反白)
  97.    DelayUs2x(50);         //延时大于100us
  98.    Write_Cmd(0x01);       //清除显示,并且设定地址指针为00H
  99.    DelayMs(15);           //延时大于10ms
  100.    Write_Cmd(0x06);       //指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位,光标从右向左加1位移动
  101.    DelayUs2x(50);         //延时大于100us
  102. }

  103. /***********************************************
  104.                 用户自定义字符
  105. ***********************************************/
  106. void CGRAM()
  107. {
  108.      int i;
  109.      Write_Cmd(0x30);
  110.      Write_Cmd(0x40);          //对CGRAM第一个自定义字符操作,
  111.      for(i=0;i<16;i++)
  112.        {
  113.         Write_Data(user16x16[i*2]);
  114.         Write_Data(user16x16[i*2+1]);
  115.       }
  116. }   

  117. /***********************************************
  118.                显示用户自定义字符
  119. ***********************************************/
  120. void DisplayCGRAM(unsigned char x,unsigned char y)
  121. {
  122. switch(y)
  123.      {
  124.    case 1: Write_Cmd(0x80+x);break;
  125.    case 2: Write_Cmd(0x90+x);break;
  126.    case 3: Write_Cmd(0x88+x);break;
  127.    case 4: Write_Cmd(0x98+x);break;
  128.       default:break;
  129.   }
  130.     Write_Data(00);                                          //上面有一个字符操作0x04了  所以直接写
  131.     Write_Data(00);                 //写字符          Write_Data(user16x16[i*2]);
  132.                         //            Write_Data(user16x16[i*2+1]);
  133. }         

  134. /***********************************************
  135.                   显示字符串
  136.             x:横坐标值,范围0~8
  137.             y:纵坐标值,范围1~4
  138. ***********************************************/
  139. void LCD_PutString(unsigned char x,unsigned char y,unsigned char code *s)
  140. {
  141. switch(y)
  142.      {
  143.    case 1: Write_Cmd(0x80+x);break;
  144.    case 2: Write_Cmd(0x90+x);break;
  145.    case 3: Write_Cmd(0x88+x);break;
  146.    case 4: Write_Cmd(0x98+x);break;
  147.       default:break;
  148.   }
  149. while(*s>0)
  150.    {
  151.       Write_Data(*s);
  152.       s++;
  153.       DelayUs2x(50);
  154.    }
  155. }

  156. /***********************************************
  157.                      清屏
  158. ***********************************************/
  159. void ClrScreen()
  160. {
  161.    Write_Cmd(0x01);
  162.    DelayMs(15);
  163. }
  164.    
  165. /***********************************************
  166.                调用显示更新
  167. ***********************************************/
  168. void DisplayUpdata(void)
  169. {   
  170.     unsigned char num;                   //输入的CURR为1 执行完 DisplayUpdata后又变为0
  171.     ClrScreen();                  
  172. num=sizeof(MainMenu)/sizeof(MainMenu[0]);//判断数组中数值个数
  173. //num为此数组的语速的个数
  174. //代表数组中元素的个数,size(a)表示整个数组的字节数,size(a[0])表示一个元素的字节数,他们相除之后就表示这个数组中元素的个数
  175. if((0+(curr/4)*4)<num)
  176.    LCD_PutString(0,1,MainMenu[0+(curr/4)*4]);
  177. else //如果超出数组最大元素,则写空信息,不判断此信息可能会出现乱码          0是字节 1是行数
  178.    LCD_PutString(0,1,"");
  179.                 //  2
  180. if((1+(curr/4)*4)<num)                         
  181.    LCD_PutString(0,2,MainMenu[1+(curr/4)*4]);                                                          //num是字节数                 1or2or3/4=0
  182.                                                                                                                                                 //                                         <0curr<3                         3<curr<8
  183. else                                                                                                                                        //                                         0+(curr/4)*4=0                  4
  184.    LCD_PutString(0,2,"");                                                                                                //                                         1+(curr/4)*4=1                  5
  185.            //3                                                                                                                                //                                         2+(curr/4)*4=2                  6
  186. if((2+(curr/4)*4)<num)                                                                                                        //                                         3+(curr/4)*4=3                  7
  187.    LCD_PutString(0,3,MainMenu[2+(curr/4)*4]);
  188. else
  189.    LCD_PutString(0,3,"");
  190.                 //4
  191. if((3+(curr/4)*4)<num)                //判断行数
  192.    LCD_PutString(0,4,MainMenu[3+(curr/4)*4]);
  193. else
  194.    LCD_PutString(0,4,"");

  195. DisplayCGRAM(0,curr%4+1); //显示字符串的函数 0%4+1=1  1%4+1=2 /2+1=3 /3+1=4
  196. }

  197. /*------------------------------------
  198.                         主界面处理
  199. ------------------------------------*/
  200. void MainMenu_Pro()
  201. {
  202.   if(curr!=currold) //光标位置变化,则更新显示                  按键按下去  字符串就变更位置了  CURR也就变了
  203.       {
  204.        DisplayUpdata();
  205.        currold=curr;   //把CURR的值赋给CURROLD  判断下加一个一
  206.       }

  207.    if(!KEY_PgUp)  
  208.     {
  209.      DelayMs(10);
  210.      if(!KEY_PgUp)     
  211.        {
  212.         while(!KEY_PgUp);
  213.           {
  214.     if(curr<sizeof(MainMenu)/sizeof(MainMenu[0])-1)                //sizeof 求字节数
  215.      //判断数组中数值个数
  216.      { curr++; }
  217.           }
  218.        }
  219.     }
  220.   else
  221.   if(!KEY_PgDn)
  222.     {
  223.      DelayMs(10);
  224.      if(!KEY_PgDn)     
  225.         {
  226.         while(!KEY_PgDn);
  227.           {
  228.        if(curr>0)
  229.      { curr--; }
  230.           }
  231.         }
  232.     }
  233.                         else if(!KEY_Enter)
  234.                                 {
  235.                                 DelayMs(10);
  236.                                         if(!KEY_Enter)
  237.                                         {
  238.                                         while(!KEY_Enter);
  239.                                                 switch(curr)
  240.                                                 {
  241. //                                                case 0: Menu0=1;Enter_Menu=1;break;
  242.                                                 case 1: Menu1=1;Enter_Menu=1;ClrScreen();break;
  243.                                                 case 2: Menu2=1;Enter_Menu=1;ClrScreen();break;
  244.                                                 case 3: Menu3=1;Enter_Menu=1;ClrScreen();break;
  245. //                                                case 4: Menu4=1;Enter_Menu=1;break;
  246. //                                                case 5: Menu5=1;Enter_Menu=1;break;
  247. //                                                case 6: FanHui1=1;Menu_Flag=0;guide=0;
  248. //                                                                Write_Cmd(0x01);break;                //轮询到有enter键,当guide指向返回时候直接去掉FanHui1控制的父菜单循环
  249.                                                 default:return;
  250.                                                 }
  251.                                         TR1=0;
  252.                                         }
  253.                                 }
  254.                        

  255. }
  256. /*************************************************************
  257.                     按键返回函数         
  258. *************************************************************/
  259. void ESC()
  260. {
  261.                 DelayMs(10);
  262.                         if(!KEY_Esc)
  263.                         {
  264.                         while(!KEY_Esc);
  265.                         Menu1=0;
  266.                         Menu2=0;
  267.                         Menu3=0;
  268.                         Enter_Menu=0;
  269.                         DisplayUpdata();
  270.                         }
  271. }

  272. /*------------------------------------
  273.                 Menu1设置时间子菜单处理
  274. ------------------------------------*/
  275. void Menu1_Pro()
  276. {
  277. LCD_PutString(0,2,MainMenu[9]);
  278. if(!KEY_Esc)
  279.                 {
  280.                 ESC();
  281.                         }
  282. }

  283. /*------------------------------------
  284.                 Menu2设置时间子菜单处理
  285. ------------------------------------*/
  286. void Menu2_Pro()
  287. {
  288. LCD_PutString(0,2,MainMenu[1]);
  289. if(!KEY_Esc)
  290.                         {
  291.                 ESC();
  292.                         }
  293. }

  294. /*------------------------------------
  295.                 Menu3设置时间子菜单处理
  296. ------------------------------------*/
  297. void Menu3_Pro()
  298. {
  299. LCD_PutString(0,2,MainMenu[5]);
  300. if(!KEY_Esc)
  301.                         {
  302.                         ESC();
  303.                         }
  304. }

  305. /***********************************************
  306.                  MAIN
  307. ***********************************************/
  308. void main()
  309. {
  310.    Init_ST7920();
  311.    CGRAM(); //写入自定义字符
  312.    DisplayUpdata();
  313. while(1)
  314. {
  315.                 MainMenu_Pro();

  316. while(Enter_Menu)        //进入子菜单标签
  317.                 {
  318. //                                     if(Menu0) Menu0_Pro();                //子菜单0处理函数
  319. //                                else
  320.                                 if(Menu1) Menu1_Pro();       
  321.                                 else if(Menu2) Menu2_Pro();
  322.                                 else if(Menu3) Menu3_Pro();
  323. //                                else if(Menu4) Menu4_Pro();
  324. //                                else if(Menu5) Menu5_Pro();
  325.                 }
  326. }
  327. }
复制代码


评分

参与人数 2黑币 +55 收起 理由
mcxq + 5 赞一个!
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:402077 发表于 2018-11-10 08:54 | 只看该作者
我要我要我要
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表