搜索
bottom↓
回复: 12

节省RAM在Flash空间实现的菜单方法

[复制链接]

出0入0汤圆

发表于 2008-3-29 10:59:29 | 显示全部楼层 |阅读模式
这个是AVR单片机实现的菜单方法,尽量使用Flash空间,少使用RAM。
本来这个程序在两年前就做了,但是由于某种协议的关系只能在今天才能透出一点,虽然协议到期但由于这是个商业产品,我也不想惹出事端,删除了一此细节的东西,并做了大量的更改,改变了本来的面目(有点面目全非:)),现在列出来的程序也比较隐晦,希望大家见谅。我只是提出了一种方法,如果大家要做菜单时再看这个程序应该就不难了。

欢迎大家讨论这个方法。

近段时间把C++也学习完了:),现在是用VC++还是用BCB不能确定,从实际情况来看用BCB要好些(我的程序较简单,界面多些),但实示我也要考虑口袋的银子问题。
写程序我是被逼的,我喜欢做电路设计,也是我学的专业,实际上我的电路设计比程序设计要好,而且要多些:)
说明:
fo为函数的标记头。

这个菜单是在LCD1602显示屏上实现的

#ifndef __MENU_LAYOUT_H__
#define __MENU_LAYOUT_H__

struct menu
{
    const struct  menu * parent;              // 父指针
    const struct  menu * child;               // 子指针
    unsigned char pos;                        // 位置
    unsigned char MenuLenght;                 // 本菜单中的子菜单长度
    void          (*CurrentOperate)(void);    // 调用函数用,以fo为头
    unsigned char str_len;                    // 显示文字长度
    unsigned char name[16];                   // point to display name of menu item
};

#define NULL (struct menu const *)0

void NullSubs(void)
{
}

#pragma data:code
extern const struct menu main_menu[3];
extern const struct menu sub_setting[4];     //设置
extern const struct menu sub_view[3];        //查看
extern const struct menu sub_info[2];        //信息
extern const struct menu sub_set[2];             
extern const struct menu sub_view[4];         
/*****************顶层菜单*********************/
const struct menu main_menu[3]  =      
{
        {NULL, &sub_setting[0], 0, 3, NullSubs,  7,  "Setting"},
        {NULL, &sub_view[0],    1, 3, NullSubs,  4,  "View"},
        {NULL, &sub_info[0],    2, 3, NullSubs,  4,  "Help"},
};
/******************第二层**********************/
const struct menu sub_setting[4] =      
{
        {&main_menu[0], NULL,           0, 4, foSetting0, 8, "Setting0"},                
        {&main_menu[0], NULL,           1, 4, foSetting1, 8, "Setting1"},
        {&main_menu[0], &sub_set[0],    2, 4, foSetting2, 8,"Setting2"},
        {&main_menu[0], NULL,           3, 4, fosetting3, 8, "Setting3"},
};
const struct menu sub_view[3] =   
{
        {&main_menu[1], &sub_view[0], 0, 3, foView0,  5, "View0"},
        {&main_menu[1], NULL,          1, 3, foView1, 5, "View1"},
        {&main_menu[1], NULL,          2, 3, foView2, 5,  "View2"},
};
const struct menu sub_info[2]  =     
{
        {&main_menu[2], NULL,         0, 2, foInfo0,    5,  "Help0"},
        {&main_menu[2], NULL,         1, 2, foInfo1,     5, "Help1"},
};
/*******************第三层**********************/
const struct menu sub_set[2] =
{
        {&sub_setting[2], NULL, 0,  2, foSubSetting0,   15, "SubSetting0"},
        {&sub_setting[2], NULL, 1,  2, foSubSetting1,   13, "SubSetting1"},
};
const struct menu sub_view[4] =
{
        {&sub_view[0], NULL,  0, 4, foSubView0, 8, "SubView0"},
        {&sub_view[0], NULL,  1, 4, foSubView1, 8, "SubView1"},
        {&sub_view[0], NULL,  2, 4, foSubView2, 8, "SubView2"},
        {&sub_view[0], NULL,  3, 4, foSubView3, 8, "SubView3"},
};
#pragma data:data
#endif

/**********************************/
/*   菜单操作函数                 */
/**********************************/
unsigned char menu_exe(void)       //函数调用,如果返回值为0xFF则中止
{
        const struct menu   * mp;  
        const unsigned char * str;
        unsigned char menu_len, position;
        unsigned char len;
        unsigned char key_val;
        void (*KeyFuncPtr)(void);
       
        mp = main_menu;
        position = 0;
       
        while(1)
        {
                WDR();
                menu_len = mp->MenuLenght;
                str = mp->name;
                len = mp->str_len;
                delay_ms(300);   
                LCD_clr();                   //清屏
                delay_ms(3);                 //保证按键人性化
                LCD_write_string_P(0,0,4,str_menu);
                if(menu_len < 10)
                {
                        LCD_write_data(12,0,menu_len+0x30);
                }
                else
                {
                        LCD_write_data(11,0,0x31);
                        LCD_write_data(12,0,menu_len+0x26);
                }
                LCD_write_data(13,0,'-');
                if( position < 9)
                {
                        LCD_write_data(14,0,position+0x31);
                }
                else
                {
                        LCD_write_data(14,0,0x31);
                        LCD_write_data(15,0,position+0x27);
                }
                do
                {
                        FlashStr(str,0x20,0,1);
                        delay_ms(2);
                        key_val = GetKey();
                        if(lighttimer < 8000)
                        {
                                return 0xFF;                                 //超时退出
                        }
                }
                while(!key_val);                                     //wait the key press
                switch (key_val)
                {
                        case DOWN_KEY:
                                if (position == (menu_len - 1))
                                {
                                        position = 0;
                                        mp -= menu_len -1;
                                }
                                else
                                {
                                        mp++;
                                        position++;
                                }
                                break;
                        case UP_KEY:
                                if (position == 0)
                                {
                                        position = menu_len - 1;
                                        mp += menu_len - 1;
                                }
                                else
                                {
                                        mp--;
                                        position--;
                                }
                                break;
                        case ENTER_KEY:
                                if(mp->child == NULL)
                                {
                                        LCD_clr();                              //清屏
                                        delay_ms(10);                           //保证按键人性化
                                        KeyFuncPtr = mp->CurrentOperate;
                                        (*KeyFuncPtr)();       
                                        //mp = mp->parent;
                                }
                                else
                                {
                                        mp = mp->child;
                                        position = 0;
                                }
                                break;
                        case ESC_KEY:
                                if(mp->parent == NULL)
                                return 0xFF;
                                mp = mp->parent;
                                position = mp->pos;
                                break;
                }
        }
        return 0;
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2008-3-29 11:05:46 | 显示全部楼层
本来我一直用的是GCC,但是GCC好象对flash存储器,flash指针支持不是很好,要通过API来实现,而且我没找到存储在flash内指向flash的指针在GCC AVR是怎样实现的;(,只能用ICC来实现了。

出0入0汤圆

发表于 2008-5-18 22:44:37 | 显示全部楼层
在编写菜单程序时,我也由于GCC对flash存储器操作不太好而改用其他C语言来替代GCC.

出0入0汤圆

发表于 2008-5-19 00:38:02 | 显示全部楼层
顶下    自己还菜   标记下

出0入0汤圆

发表于 2008-5-19 08:10:15 | 显示全部楼层
存储在flash内指向flash的指针在GCC AVR是怎样实现的.

实际上就是存储在FLASH里面的指针,至于指针是指向RAM,还是FLASH,由程序控制.

出0入0汤圆

发表于 2008-5-19 10:53:43 | 显示全部楼层
发觉怎么很多人写出的菜单结构都是这种...可以思考下其他的方法,这种方法在深度深时恐怕比较麻烦,结构化程度还不是很高...当然我没仔细看,也许说的不对

出0入0汤圆

发表于 2008-8-1 18:21:11 | 显示全部楼层
menu   mark

出0入0汤圆

发表于 2010-3-24 21:30:08 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-24 22:27:12 | 显示全部楼层
mark

出0入0汤圆

发表于 2013-12-31 08:58:54 | 显示全部楼层
。。。。。。。。。。。。

出0入0汤圆

发表于 2013-12-31 18:17:00 | 显示全部楼层
看看,很实用的样子

出100入85汤圆

发表于 2013-12-31 20:37:12 | 显示全部楼层
这种模式适合菜单固定的,而且转向确定的场合,比如这种就相对难实现

菜单A    可以跳转到   菜单C
菜单B   也可以跳转到 菜单C

当在菜单C处理完后  分别退回到 菜单A   菜单B

出0入0汤圆

发表于 2014-1-1 20:13:39 来自手机 | 显示全部楼层
谢谢分享
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 22:10

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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