节省RAM在Flash空间实现的菜单方法
这个是AVR单片机实现的菜单方法,尽量使用Flash空间,少使用RAM。本来这个程序在两年前就做了,但是由于某种协议的关系只能在今天才能透出一点,虽然协议到期但由于这是个商业产品,我也不想惹出事端,删除了一此细节的东西,并做了大量的更改,改变了本来的面目(有点面目全非:)),现在列出来的程序也比较隐晦,希望大家见谅。我只是提出了一种方法,如果大家要做菜单时再看这个程序应该就不难了。
欢迎大家讨论这个方法。
近段时间把C++也学习完了:),现在是用VC++还是用BCB不能确定,从实际情况来看用BCB要好些(我的程序较简单,界面多些),但实示我也要考虑口袋的银子问题。
写程序我是被逼的,我喜欢做电路设计,也是我学的专业,实际上我的电路设计比程序设计要好,而且要多些:)
说明:
fo为函数的标记头。
这个菜单是在LCD1602显示屏上实现的
#ifndef __MENU_LAYOUT_H__
#define __MENU_LAYOUT_H__
struct menu
{
const structmenu * parent; // 父指针
const structmenu * child; // 子指针
unsigned char pos; // 位置
unsigned char MenuLenght; // 本菜单中的子菜单长度
void (*CurrentOperate)(void); // 调用函数用,以fo为头
unsigned char str_len; // 显示文字长度
unsigned char name; // 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;
extern const struct menu sub_setting; //设置
extern const struct menu sub_view; //查看
extern const struct menu sub_info; //信息
extern const struct menu sub_set;
extern const struct menu sub_view;
/*****************顶层菜单*********************/
const struct menu main_menu=
{
{NULL, &sub_setting, 0, 3, NullSubs,7,"Setting"},
{NULL, &sub_view, 1, 3, NullSubs,4,"View"},
{NULL, &sub_info, 2, 3, NullSubs,4,"Help"},
};
/******************第二层**********************/
const struct menu sub_setting =
{
{&main_menu, NULL, 0, 4, foSetting0, 8, "Setting0"},
{&main_menu, NULL, 1, 4, foSetting1, 8, "Setting1"},
{&main_menu, &sub_set, 2, 4, foSetting2, 8,"Setting2"},
{&main_menu, NULL, 3, 4, fosetting3, 8, "Setting3"},
};
const struct menu sub_view =
{
{&main_menu, &sub_view, 0, 3, foView0,5, "View0"},
{&main_menu, NULL, 1, 3, foView1, 5, "View1"},
{&main_menu, NULL, 2, 3, foView2, 5,"View2"},
};
const struct menu sub_info=
{
{&main_menu, NULL, 0, 2, foInfo0, 5,"Help0"},
{&main_menu, NULL, 1, 2, foInfo1, 5, "Help1"},
};
/*******************第三层**********************/
const struct menu sub_set =
{
{&sub_setting, NULL, 0,2, foSubSetting0, 15, "SubSetting0"},
{&sub_setting, NULL, 1,2, foSubSetting1, 13, "SubSetting1"},
};
const struct menu sub_view =
{
{&sub_view, NULL,0, 4, foSubView0, 8, "SubView0"},
{&sub_view, NULL,1, 4, foSubView1, 8, "SubView1"},
{&sub_view, NULL,2, 4, foSubView2, 8, "SubView2"},
{&sub_view, 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;
} 本来我一直用的是GCC,但是GCC好象对flash存储器,flash指针支持不是很好,要通过API来实现,而且我没找到存储在flash内指向flash的指针在GCC AVR是怎样实现的;(,只能用ICC来实现了。 在编写菜单程序时,我也由于GCC对flash存储器操作不太好而改用其他C语言来替代GCC. 顶下 自己还菜 标记下 存储在flash内指向flash的指针在GCC AVR是怎样实现的.
实际上就是存储在FLASH里面的指针,至于指针是指向RAM,还是FLASH,由程序控制. 发觉怎么很多人写出的菜单结构都是这种...可以思考下其他的方法,这种方法在深度深时恐怕比较麻烦,结构化程度还不是很高...当然我没仔细看,也许说的不对 menu mark mark mark 。。。。。。。。。。。。 看看,很实用的样子 这种模式适合菜单固定的,而且转向确定的场合,比如这种就相对难实现
菜单A 可以跳转到 菜单C
菜单B 也可以跳转到 菜单C
当在菜单C处理完后分别退回到 菜单A 菜单B
谢谢分享
页:
[1]