打印
[DemoCode下载]

使用链表构建多级菜单

[复制链接]
2070|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
734774645|  楼主 | 2017-1-26 19:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/********************************下面是主函数代码****************************************************/

#include<reg52.H>
#include"lcd5110.h"
#include"fun.h"

sbit BUZZ = P0^4;   

void main(void)
{
unsigned char ft=10;    //功能函数扫描时间变量

P2M0 = 0x7;          //P2.0-P2.2设置为推挽输出
P1   = 0xff;         //P1口做按键输入
TMOD = 0x12;                    //定时器1工作于16位模式,定时65536us
EA      = 1;
ET0    = 1;
TR1  = 1;            //启动定时器1

LCD_Init();          //显示器初始化
fun = HomePage;            //显示主页面

while(1)
{
  if(TF1)
    {
     TF1 = 0;
     if(!ft)ft=5;
        KeyScan();                        //按键扫描
     if(key_value||--ft==0)
      fun();                                 //功能函数                           
     }
}
}

void Timer0Interrupt(void) interrupt 1
{
static bit a;
a = ~a;
BUZZ = a;
}



沙发
734774645|  楼主 | 2017-1-26 19:26 | 只看该作者
/*********************************下面是功能函数的代码***************************************************/

#include"fun.h"
#include"lcd5110.h"

/************全局变量定义***********************/
void (*fun)() = NULL;                    //定义一个功能函数指针,用于外部调用函数
unsigned char key_value = 0;  //按键值变量
extern code unsigned char gImage_1[];         //声明图像数据

/****************功能函数***********************/

/***************************************************************
-函数功能:显示主页面
-参数说明:无
-返回说明:无
-备注:无
****************************************************************/
void HomePage(void)
{
if(key_value==KEY_OK)                                     //判断键值
  fun = MenuDisplay;                                            //显示菜单
else                                                                         //没有键按下则显示
{
  LCD_Clear();
    LCD_WriteChinese(4,2,"多级菜单测试",0);
}
}

/***************************************************************
-函数功能:图片显示
-参数说明:无
-返回说明:无
-备注:无
****************************************************************/
void PictureDisplay(void)
{
if(key_value==KEY_OK)                                     //判断键值
  fun = HomePage;                                                 //返回主页面
else
{                                                                          //没有键按下则显示
  LCD_Clear();
  LCD_DrawPicture(0,0,gImage_1,52,48);    //输出图片
}
}

/***************************************************************
-函数功能:输出声音
-参数说明:无
-返回说明:无
-备注:无
****************************************************************/
void Buzzing(void)
{
   TR0 = ~TR0;
   fun = HomePage;                                                 //返回主页面
}

/***************************************************************
-函数功能:开启背光
-参数说明:无
-返回说明:无
-备注:无
****************************************************************/
void LightON(void)
{
LCD_BL = 1;
fun = HomePage;                                                 //返回主页面
}

/***************************************************************
-函数功能:关闭背光
-参数说明:无
-返回说明:无
-备注:无
****************************************************************/
void LightOFF(void)
{
LCD_BL = 0;
fun = HomePage;                                                 //返回主页面
}

/******************************************************************
-函数功能:扫描按键
-参数说明:无
-返回说明:无
-备注:扫描时间由T1溢出标志位控制
******************************************************************/
void KeyScan(void)
{
  static unsigned char cont=0;
    unsigned char read = ~P1;

    key_value = read&(read^cont);
    cont = read;            
}

/******************************************************************
-函数功能:菜单显示
-参数说明:无
-返回说明:无
-备注:
******************************************************************/
void MenuDisplay(void)
{

#define MENU_ST  struct menu_st code

MENU_ST    sys_set={2,{"开启背光","关闭背光","返回主页"},{NULL,NULL,NULL},\
{LightON,LightOFF,HomePage}};

MENU_ST home={3,{"图片显示","输出声音","系统设置","返回主页"},{NULL,NULL,&sys_set,NULL},\
{PictureDisplay,Buzzing,NULL,HomePage}};

#undef MENU_ST

static struct menu_st *p = &home;             //结构体指针用于指向下一个任务
static unsigned char opt;                                    //选中的条目
unsigned char opt_max = p->opt_max;                //最大菜单条目数
unsigned char pg,i;                                        //显示页面条目控制变量

switch (key_value)                                                  //按键值处理
{
  case KEY_UP:if(opt)opt--;break;                        
    case KEY_DOWN:if(opt!=opt_max)opt++;break;
    case KEY_OK:if(p->pnext[opt]!=NULL)p=p->pnext[opt];        //指向下一级菜单
                           else {fun=p->fp[opt];p = &home;}
                            opt=0;                                                                     //选择条目清零
                            break;
    }

LCD_Clear();                                                        
for(pg=opt/3,i=0;i<3&&pg*3+i<=opt_max;i++)    //每页显示三条,选中的反相
    {
     LCD_WriteChar(0,i*2,pg*3+i+'1');
     LCD_WriteChinese(6,i*2,p->str[pg*3+i],pg*3+i==opt);
    }
}

使用特权

评论回复
板凳
734774645|  楼主 | 2017-1-26 19:28 | 只看该作者
过程中千万注意不要使用递归的函数,因为单片机的堆栈深度有限。

使用特权

评论回复
地板
dongnanxibei| | 2017-1-26 19:54 | 只看该作者
使用链表构建菜单非常不错,不过如果能不用最好别,增加的系统复杂度。

使用特权

评论回复
5
heisexingqisi| | 2017-1-26 20:02 | 只看该作者
使用链表实现真是节约内存的方法。

使用特权

评论回复
6
gejigeji521| | 2017-1-26 20:18 | 只看该作者
通过指针跳转到不同的菜单显示。

使用特权

评论回复
7
huangcunxiake| | 2017-1-26 20:34 | 只看该作者
if(key_value==KEY_OK)                                     //判断键值
  fun = MenuDisplay;                                            //显示菜单

使用特权

评论回复
8
zhuomuniao110| | 2017-1-26 20:35 | 只看该作者
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

使用特权

评论回复
9
zhuotuzi| | 2017-1-27 12:40 | 只看该作者
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。

使用特权

评论回复
10
zhuotuzi| | 2017-1-27 12:41 | 只看该作者
链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在**体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换

使用特权

评论回复
11
zhuotuzi| | 2017-1-27 12:41 | 只看该作者
链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。链表可以在多种编程语言中实现。

使用特权

评论回复
12
zhuotuzi| | 2017-1-27 12:43 | 只看该作者
像Lisp和Scheme这样的语言的内建数据类型中就包含了链表的存取和操作。程序语言或面向对象语言,如C,C++和Java依靠易变工具来生成链表。

使用特权

评论回复
13
zhuotuzi| | 2017-1-27 12:44 | 只看该作者
线性表的链式存储表示的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。因此,为了表示每个数据元素 与其直接后继数据元素 之间的逻辑关系,对数据元素 来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。由这两部分信息组成一个"结点",表示线性表中一个数据元素。线性表的链式存储表示,有一个缺点就是要找一个数,必须要从头开始找起,十分麻烦。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

197

主题

3445

帖子

14

粉丝