目录
须知
大小级菜单
各级页面
按键初始化与按键扫描
最后
我使用的是四个按键操作,2寸的IPS显示。
大小级菜单就是在一个页面跳到另一个页面。类似于老年机的操作逻辑,在每个页面可以设置自己想要的东西,通过IPS、TFT或者OLED来显示,按键用来调参或者跳转页面。Dispay_Codename做为每个页面的编号。在每个页面中扫描按键可以更改Dispay_Codename页面编号,在函数外边使用while就可以因为Dispay_Codename页面编号的改变而改变页面。结束菜单系统的话,我选择按键4,当扫描按键4按下就结束菜单系统,进入跑车的环节。
//-------------------------------------------------------------------------------------------------------------------
// @brief 菜单目录
// @param Dispay_Codename 页面编号
// @param
// @param
// @param
// @return void
// @note 启用while来显示目标页面 在每个页面按键按键后都会改变到对应页面,此函数用于更新屏幕显示
//-------------------------------------------------------------------------------------------------------------------
void Keystroke_Menu(void)
{
switch(Dispay_Codename)
{
case 0:
Keystroke_Menu_HOME();
break;
case 1:
Keystroke_Menu_ONE();
break;
case 11:
Keystroke_Menu_ONE_One();
break;
case 12:
Keystroke_Menu_ONE_Two();
break;
case 2:
Keystroke_Menu_TWO();
break;
case 21:
Keystroke_Menu_TWO_One();
break;
case 22:
Keystroke_Menu_TWO_Two();
break;
case 3:
Keystroke_Menu_THREE();
break;
case 31:
Keystroke_Menu_THREE_One();
break;
case 32:
Keystroke_Menu_THREE_Two();
break;
}
}
int mian(void)
{
DIP_Switch_Init(); //先扫描拨码开关
Keystroke_Init(); //初始化按键
Display_Init(); //初始化IPS
Beep_Init(); //初始化蜂鸣器
while(1) //菜单系统
{
DIP_Switch_Contorl(); //拨码开关选择模式 模式0开启菜单系统
switch(MODE)
{
case 0:
Keystroke_Menu();
break;
case 1:
RUN_STAR = 1;
break;
case 2:
RUN_STAR = 1;
break;
case 3:
RUN_STAR = 1;
break;
}
if(RUN_STAR == 1) //菜单系统中按下按键4,RUN_STAR=1,就可以退出菜单系统
{
ips200_clear(WHITE);
EEPROM_FLASH();
if(MODE == 2)
{
Run_Voltage = 10.7;
}
else if(MODE == 3)
{
Run_Voltage = 11;
}
break;
}
}
All_Config_CPU0(); //各个模块初始化
}
一级主页面:用于去到二级页面。我因为不需要使用太多的页面,所以我选择按键直接进入:按键1、2、3用于进入对应页面,按键4用于结束菜单系统开始跑车,我的二级菜单也是两个或者一个小页面。如果需要分得较多的话可以使用小光标的方式,在每个页面标题前边跳动一个小光标,当光标对应到标题前边时,可以选择是否进入页面。
二级页面:用于去到三级页面或者调参。用于去到三级页面:按键1、2用于去到对应页面,按键3用于返回上一页面。用于调参:按键1用于+,按键2用于-,按键3用于返回上一页面。按键4始终作为结束菜单系统的按键。
void Keystroke_Menu_HOME(void) //页面编号0
{
ips200_showstr(0,0,"Parameter"); //参数页面 按键 1
ips200_showstr(0,6,"Encoder"); //编码计数页面 按键 2
ips200_showstr(0,12,"Control"); //控制策略页面 按键 3
ips200_showstr(0,18,"Run"); //运行开关 按键 4
Keystroke_Scan(); //按键扫描函数,用于确定按下哪个按键
switch(KeystrokeLabel)
{
case 0 :
Dispay_Codename = 0;
break;
case KeystrokeONE :
Dispay_Codename = 1;
ips200_clear(WHITE);
break;
case KeystrokeTWO :
Dispay_Codename = 2;
ips200_clear(WHITE);
break;
case KeystrokeTHREE :
Dispay_Codename = 3;
ips200_clear(WHITE);
break;
case KeystrokeFOUR :
RUN_STAR = 1;
ips200_clear(WHITE);
break;
}
}
//-------------------------------------------------------------------------------------------------------------------
// @brief 控制菜单目录
// @param
// @param
// @param
// @param
// @return void
// @note 此页面为编号为2
//-------------------------------------------------------------------------------------------------------------------
void Keystroke_Menu_TWO(void) //2
{
EEPROM_GarageDistance = flash_read(EEPROM_DistanceG,0,uint16);
EEPROM_ChBat = flash_read(EEPROM_DistanceC,0,float);
ips200_showstr(0,0,"GarageDistance");
ips200_showuint16(120,0,EEPROM_GarageDistance);
ips200_showstr(0,6,"CHBAT");
ips200_showfloat(120,6,EEPROM_ChBat,2,1);
Keystroke_Scan();
switch(KeystrokeLabel)
{
case 0 :
Dispay_Codename = 2;
break;
case KeystrokeONE : //按键1 进入下一页面
Dispay_Codename = 21;
ips200_clear(WHITE);
break;
case KeystrokeTWO :
Dispay_Codename = 22; //按键2 进入下一页面
ips200_clear(WHITE);
break;
case KeystrokeTHREE : //按键3 返回上一页面
Dispay_Codename = 0;
ips200_clear(WHITE);
break;
case KeystrokeFOUR : //按键4 结束菜单系统
RUN_STAR = 1;
break;
}
}
//-------------------------------------------------------------------------------------------------------------------
// @brief 控制菜单中的出库编码器计步菜单
// @param
// @param
// @param
// @param
// @return void
// @note 此页面为编号为21
//-------------------------------------------------------------------------------------------------------------------
void Keystroke_Menu_TWO_One(void) //21
{
EEPROM_GarageDistance = flash_read(EEPROM_DistanceG,0,uint16);
ips200_showstr(0,0,"GarageDistance");
ips200_showuint16(120,0,EEPROM_GarageDistance);
Keystroke_Scan();
switch(KeystrokeLabel)
{
case 0 :
Dispay_Codename = 21;
break;
case KeystrokeONE : //按键1 目标编码值+100 使用flash
EEPROM_GarageDistance = flash_read(EEPROM_DistanceG,0,uint16);
EEPROM_GarageDistance += 100;
if(flash_check(EEPROM_DistanceG,0) == 1)
{
eeprom_erase_sector(EEPROM_DistanceG);
}
Write_Date = (uint32)EEPROM_GarageDistance;
eeprom_page_program(EEPROM_DistanceG,0,&Write_Date);
Dispay_Codename = 21;
ips200_clear(WHITE);
break;
case KeystrokeTWO : //按键2 目标编码值-100 使用flash
EEPROM_GarageDistance = flash_read(EEPROM_DistanceG,0,uint16);
EEPROM_GarageDistance = EEPROM_GarageDistance - 100;
if(flash_check(EEPROM_DistanceG,0) == 1)
{
eeprom_erase_sector(EEPROM_DistanceG);
}
Write_Date = (uint32)EEPROM_GarageDistance;
eeprom_page_program(EEPROM_DistanceG,0,&Write_Date);
Dispay_Codename = 21;
ips200_clear(WHITE);
break;
case KeystrokeTHREE : //按键3 返回上一页面
Dispay_Codename = 2;
ips200_clear(WHITE);
break;
case KeystrokeFOUR : //按键4 结束菜单页面
RUN_STAR = 1;
break;
}
}
const PIN_enum ButtonPins[ButtonCnt] =
{
P15_6,
P15_8,
P14_0,
P15_7
};
//-------------------------------------------------------------------------------------------------------------------
// @brief 按键初始化
// @param
// @param
// @param
// @param
// @return void
// @note
//-------------------------------------------------------------------------------------------------------------------
void Keystroke_Init(void)
{
for(uint8 Cnt=0;Cnt
按键扫描应该出现在各个页面显示中。
菜单系统可以各种花里胡哨,但是核心思路是如何能显示各个页面,如何达到目的。本文章写的非常粗糙,详情源代码:「菜单系统」https://www.aliyundrive.com/s/uZ1YRMLhrbS 。智能车的代码已经全部开源,开源地址:GitHub - StingeMoZGD/17th-SmartCar: 17届智能车竞赛,无线充电组
在B站上有演示视频:【智能车菜单系统-极其简单的按键系统】 https://www.bilibili.com/video/BV1n14y1s7c1?share_source=copy_web&vd_source=dcee5db3a992452fdf8223dc0bb853e2
如果有什么不理解的地方可以评论或私信我,欢迎各位多多交流。