标题:
OLED四行多级菜单STM32程序
[打印本页]
作者:
fgth5s
时间:
2017-7-20 15:56
标题:
OLED四行多级菜单STM32程序
单片机源程序如下:
/***
*****************************************************************************
* @file menu.c
* @author 原作:张子墨
* @version V1.0
* @brief OLED四行多级菜单
*****************************************************************************
***/
#include "menu.h"
#include "oled.h"
#include "key.h"
#include "delay.h"
#include "text.h"
#include "fontupd.h"
/*菜单结构定义*/
struct Option
{
unsigned char KeyLevel; //菜单选项所属菜单表号
unsigned char EnterIndex; //选项进入索引号
unsigned char CancelIndex; //选项退出索引号
unsigned char *KeyWord; //菜单选项文字描述指针
unsigned char WordMete; //菜单选项描述文字字节数
};
/**
* 具体菜单选项定义,定义一个结构数组
* 存储在编码区,节省内存RAM
**/
struct Option sOption[OPTIONMETE] =
{
/*菜单表号 进入索引 退出索引 菜单选项文字 菜单选项文字字节数*/
{0, OPTIONMETE - 1, 0, "1.亮度调节", 10},//0
{0, 6, 1, "2.时间设置", 10},//1
{0, OPTIONMETE - 1, 2, "3.系统检测", 10},//2
{0, OPTIONMETE - 1, 3, "4.修改密码", 10},//3
{0, OPTIONMETE - 1, 4, "5.帮助说明", 10},//4
{0, OPTIONMETE - 1, 5, "6.系统信息", 12},//5
{1, OPTIONMETE - 1, 1, "1.时钟设置", 10},//6
{1, OPTIONMETE - 1, 1, "2.日期设置", 10},//7
};
/*菜单表分类数组*/
unsigned char Level[MENULEVEL][3] =
{
/*每层表单对应的开始索引 结束索引 选项数目*/
{0, 5, 6},
{6, 7, 2},
};
/*菜单索引定义*/
unsigned char FirstLineDisIndex = 0; //屏幕第一行显示的索引号
unsigned char SelectLine_L = 1; //原来选中行
unsigned char SelectLine = 1; //当前选择的行
unsigned char SelectIndex = 0; //当前选定行对应的索引号
unsigned char LastIndex = 0; //进入功能函数前的索引号,判断具体功能使用
/**
* @name void Select_Line(unsigned char line, unsigned char clear)
* @brief 选中行反白显示
* @param line:选中行 clear:1,选中行清除反白 0,选中行反白显示
* @retval none
*/
void Select_Line(unsigned char line, unsigned char clear)
{
switch (line) //选择行
{
case 1:
OLED_Fill(0, 0, 127, 15, 0); //清除原来的显示
Show_Str(0, 0, sOption[FirstLineDisIndex].WordMete*8, 16, \
sOption[FirstLineDisIndex].KeyWord, 16, clear);
break;
case 2:
OLED_Fill(0, 16, 127, 31, 0); //清除原来的显示
Show_Str(0, 16, sOption[FirstLineDisIndex+1].WordMete*8, 16, \
sOption[FirstLineDisIndex+1].KeyWord, 16, clear);
break;
case 3:
OLED_Fill(0, 32, 127, 47, 0); //清除原来的显示
Show_Str(0, 32, sOption[FirstLineDisIndex+2].WordMete*8, 16, \
sOption[FirstLineDisIndex+2].KeyWord, 16, clear);
break;
case 4:
OLED_Fill(0, 48, 127, 63, 0); //清除原来的显示
Show_Str(0, 48, sOption[FirstLineDisIndex+3].WordMete*8, 16, \
sOption[FirstLineDisIndex+3].KeyWord, 16, clear);
break;
default :
break;
}
delay_ms(10);
}
/**
* @name void Display_OLEDMenu (void)
* @brief 刷新菜单功能函数
* @param none
* @retval none
*/
void Display_OLEDMenu (void)
{
unsigned char LineMete = Level[sOption[SelectIndex].KeyLevel][2]; //循环量,显示行数
OLED_Fill(0, 0, 128, 64, 0); //清屏,否则会出现一些乱码
delay_ms(10);
do //分别显示各行菜单项
{
OLED_Fill(0, 0, 127, 15, 0);
Show_Str(0, 0, sOption[FirstLineDisIndex].WordMete*8, 16, \
sOption[FirstLineDisIndex].KeyWord, 16, 1);
if(--LineMete == 0) break;
OLED_Fill(0, 16, 127, 31, 0);
Show_Str(0, 16, sOption[FirstLineDisIndex+1].WordMete*8, 16, \
sOption[FirstLineDisIndex+1].KeyWord, 16, 1);
if(--LineMete == 0) break;
OLED_Fill(0, 32, 127, 47, 0);
Show_Str(0, 32, sOption[FirstLineDisIndex+2].WordMete*8, 16, \
sOption[FirstLineDisIndex+2].KeyWord, 16, 1);
if(--LineMete == 0) break;
OLED_Fill(0, 48, 127, 63, 0);
Show_Str(0, 48, sOption[FirstLineDisIndex+3].WordMete*8, 16, \
sOption[FirstLineDisIndex+3].KeyWord, 16, 1);
}
while(0);
Select_Line(SelectLine_L, 1); //消除上一行反白
Select_Line(SelectLine, 0); //填充所需反白
}
/**
* @name bool MenuLevelStart (void)
* @brief 判断当前索引是否是表单第一项功能函数
* @param none
* @retval 返回Bit标志,是第一项返回TURE,不是返回FALSE
*/
bool MenuLevelStart (void)
{
unsigned char i = MENULEVEL;
do
{
i--;
if(SelectIndex == Level[i][0])
return TURE;
}
while(i);
return FALSE;
}
/**
* @name bool MenuLevelEnd (void)
* @brief 判断当前索引是否是表单最后一项功能函数
* @param none
* @retval 返回Bit标志,是最后一项返回TURE,不是返回FALSE
*/
bool MenuLevelEnd (void)
{
unsigned char i = MENULEVEL;
do
{
i--;
if(SelectIndex == Level[i][1])
return TURE;
}
while(i);
return FALSE;
}
/**
* @name void MenuUpOneOption (void)
* @brief 菜单上移一项函数
* @param none
* @retval none
*/
void MenuUpOneOption (void)
{
if(MenuLevelStart ()) //如果当前为表单第一项
{
if(Level[sOption[SelectIndex].KeyLevel][2] >= 4) //并且表单中选项数目大于等于4个
{
FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][1] - 3; //第一行显示索引号为倒数第四项
SelectIndex = Level[sOption[SelectIndex].KeyLevel][1]; //选择索引为表单最后一项
SelectLine_L = SelectLine; //记录原来行
SelectLine = 4; //标记选择行为第四行
}
else //如果选项数目并不大于四个
{
SelectIndex = Level[sOption[SelectIndex].KeyLevel][1]; //选择索引为当前表单最后一个
SelectLine_L = SelectLine; //记录原来行
SelectLine = Level[sOption[SelectIndex].KeyLevel][2]; //显示行表单数目(最后一个)
}
}
else //如果当前不是开始索引
{
if(SelectLine == 1) //并且已经在屏幕最上边一行
{
FirstLineDisIndex--; //显示索引上移
SelectIndex--; //选择索引自减
SelectLine_L = SelectLine; //记录原来行
SelectLine = 1; //选择行还是第一行
}
else //如果不是第一行
{
SelectLine_L = SelectLine; //记录原来行
SelectLine--; //选择行自减
SelectIndex--; //选择索引自减
}
}
Display_OLEDMenu(); //刷新屏幕显示
}
/**
* @name void MenuDownOneOption (void)
* @brief 菜单下移一项函数
* @param none
* @retval none
*/
void MenuDownOneOption (void)
{
if(MenuLevelEnd ()) //如果当前是表单最后一个索引
{
FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][0]; //第一行显示索引为表单第一个选项
SelectIndex = Level[sOption[SelectIndex].KeyLevel][0]; //选择索引为表单第一个选项索引
SelectLine_L = SelectLine; //记录原来行
SelectLine = 1; //选择行为第一行
}
else //如果不是最后的索引
{
if(SelectLine != 4) //如果当前不是屏幕最底行
{
SelectIndex++; //选择索引自加
SelectLine_L = SelectLine; //记录原来行
SelectLine++; //选择行下移
}
else //如果是屏幕最低行
{
FirstLineDisIndex++; //第一行显示下移
SelectIndex++; //选择索引自加
}
}
Display_OLEDMenu(); //刷新屏幕显示
}
/**
* @name void MenuEnterOption (void)
* @brief 进入某项功能函数
* @param none
* @retval none
*/
void MenuEnterOption (void)
{
LastIndex = SelectIndex; //标记进入前的索引号(以便判断具体功能)
SelectIndex = sOption[SelectIndex].EnterIndex; //更新选择索引为之前索引号对应进入索引
if(SelectIndex != OPTIONMETE - 1) //如果当前索引不是功能选择索引
{
FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][0]; //第一行显示为进入表单第一项
SelectLine_L = SelectLine;
SelectLine = 1; //设定第一行为选择行
Display_OLEDMenu (); //刷新菜单
}
else
{
FunctionAction (); //如果是功能选择项,进入功能分支判断函数
}
}
/**
* @name void MenuCancelOption (void)
* @brief 菜单退出功能函数
* @param none
* @retval none
*/
void MenuCancelOption (void)
{
if(SelectIndex != OPTIONMETE - 1) //如果不是从功能返回
{
SelectIndex = sOption[SelectIndex].CancelIndex; //选择索引为选项返回索引
}
else //如果是从功能返回
{
SelectIndex = LastIndex; //索引等于进入前保存索引
}
if(Level[sOption[SelectIndex].KeyLevel][2] >= 4) //如果返回表单选项数目大于4个
{
if(SelectIndex > Level[sOption[SelectIndex].KeyLevel][1] - 3) //根据返回选项确定显示首项
{
FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][1] - 3;
SelectLine_L = SelectLine;
SelectLine = 4 - (Level[sOption[SelectIndex].KeyLevel][1] - SelectIndex);
}
else //一般显示方式
{
FirstLineDisIndex = SelectIndex; //第一行显示索引
SelectLine_L = SelectLine;
SelectLine = 1; //选择第一行
}
}
else //如果返回表单选项数目不足4个
{
FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][0]; //第一行显示索引为表单第一项
SelectLine_L = SelectLine;
SelectLine = SelectIndex - Level[sOption[SelectIndex].KeyLevel][0] + 1; //选择行标志为当前选择索引对应行
}
Display_OLEDMenu (); //刷新菜单
}
/**
* @name void ShutDown (void)
* @brief 某一项功能函数 实际应该改为实际功能函数
* @param none
* @retval none
*/
void SystemState (void)
{
OLED_Clear(); //清屏
delay_ms(1);
Show_Str(16, 29, 128, 16, "系统版本V1.0", 16, 1);
}
void System_Help (void)
{
OLED_Clear(); //清屏
delay_ms(1);
Show_Str(0, 0, 128, 16, "1.上下键选择", 16, 1);
Show_Str(0, 16, 128, 16, "2.左键确定", 16, 1);
Show_Str(0, 32, 128, 16, "3.右键退出", 16, 1);
}
void SystemTest (void)
{
OLED_Clear(); //清屏
delay_ms(1);
if (font_init())
{
OLED_Fill(0, 16, 128, 31, 0);
Show_Str(32, 16, 128, 16, "字库错误", 16, 1);
}
else
{
OLED_Fill(0, 16, 128, 31, 0);
Show_Str(32, 16, 128, 16, "字库正常", 16, 1);
}
}
u16 radio = 0x7F;
void OLED_Light (void)
{
u8 flag = 1;
OLED_Clear(); //清屏
delay_ms(1);
Show_Str(32, 0, 128, 16, "亮度调节", 16, 1);
OLED_DrawRectangle(0, 16, 93, 31, 1); //画进度条的边框
while (1)
{
/*限制进度条的范围*/
if (radio <= 2)
{
radio = 2;
}
else if (radio >= 255)
{
radio = 255;
}
OLED_Write_Com(0x81); //对比度设置
OLED_Write_Com(radio); //1~255;默认0X7F (亮度设置,越大越亮)
if (flag == 1)
{
flag = 0;
OLED_Fill(1+(92 * radio / 255), 17, 93, 31, 0); //消除进度条的多余部分
OLED_Fill(1, 17, 1+(92 * radio / 255), 31, 1); //填充进度条
OLED_ShowNum(94, 16, (100 * radio / 255), 3, 16, 1); //显示进度百分比
OLED_ShowChar(120, 16, '%', 16, 1);
}
delay_ms(10);
switch (KEY_Scan(1)) //按键扫描
{
case KEY_UP : //按上键增加亮度
flag = 1;
radio += 2;
break;
case KEY_DOWN : //按下键减小亮度
flag = 1;
radio -= 2;
break;
case KEY_RIGHT : //按右键退出
MenuCancelOption();
return;
default :
break;
}
}
}
void NoThisFunction (void)
{
unsigned char Font[] = {"没有这个功能"};
OLED_Clear(); //清屏
delay_ms(1);
Show_Str(16, 16, 128, 16, Font, 16, 1);
delay_ms(500);
MenuCancelOption();
}
/**
* @name void FunctionAction (void)
* @brief 具体功能散转函数
* @param none
* @retval none
*/
void FunctionAction (void)
{
switch (LastIndex) //根据进入前的索引判断具体函数
{
case 0:
OLED_Light();
break;
// case 1:
// break;
// case 2:
// break;
case 2:
SystemTest();
break;
// case 4:
// break;
case 4:
System_Help();
break;
case 5:
复制代码
这个是Keil4的工程,用Keil5编译有错误:
OLED菜单程序.rar
(1.09 MB, 下载次数: 750)
2017-7-21 02:40 上传
点击文件名下载附件
仅供参考
作者:
rodderliu
时间:
2017-11-26 00:47
GOOD 非常好
作者:
szb0321
时间:
2017-11-30 09:12
oled屏幕操作正在学习中,不知道楼主屏幕水平滚动、垂直滚动有没有尝试过
作者:
micheal_wang
时间:
2017-11-30 14:20
下载下来看看看
作者:
後輪追前輪
时间:
2017-12-31 00:49
再再进入菜单怎么就老是乱跳了呢
作者:
120542121
时间:
2018-1-3 21:52
谢谢分享,先下载,然后在试试
作者:
小时候可花
时间:
2018-1-13 21:57
oled屏幕操作正在学习
作者:
dyc1229
时间:
2018-3-28 16:39
正需要呢,十分感谢你的分享,谢谢了
作者:
bennyqian
时间:
2018-4-25 17:05
很好,真好需要!
作者:
he33504898
时间:
2018-5-6 22:16
下了 编译不过,楼主解释一下
作者:
lh6774
时间:
2018-5-9 16:53
好东西 正需要
作者:
TIGER520169
时间:
2018-5-31 15:47
谢谢分享!
作者:
mhktzy
时间:
2018-6-16 21:20
谢谢分享!
作者:
mrliangg
时间:
2018-6-21 11:49
谢谢分享!
作者:
y12345678
时间:
2018-6-24 16:17
请问ssd1306驱动的四脚显示屏能用这个吗?
作者:
y12345678
时间:
2018-6-24 16:23
请问是ssd306驱动的显示屏用的吗?几脚的?
作者:
owlandauk
时间:
2018-7-27 17:01
谢谢分享
作者:
kanwoe
时间:
2018-8-17 12:03
感谢分享!!
作者:
icefish
时间:
2018-9-12 17:40
学习了!感谢分享!
作者:
346500452
时间:
2018-9-19 17:23
下载看看可不可以用
作者:
xuming123
时间:
2018-12-17 13:49
谢谢分享
作者:
yjwpm
时间:
2018-12-17 17:44
正需要呢,十分感谢你的分享,谢谢了
作者:
tonyhy1975
时间:
2018-12-20 12:33
感谢分享,值得学习
作者:
hilam
时间:
2019-8-4 16:08
没人交流学习心得吗?我觉得做一个KEY FUNC处理结构体程序框架好,这样更完美
作者:
那个谁和谁
时间:
2019-8-22 09:51
很好,谢谢分享。
作者:
wsxujn
时间:
2019-8-29 23:47
下来看看,怎么样
作者:
wyy19970316
时间:
2019-12-15 22:02
正在学习,非常感谢楼主
作者:
wsxujn
时间:
2020-1-20 11:41
stm32f4的,看看怎样
作者:
bignobeach
时间:
2020-5-12 22:52
mark 一下
作者:
布莱克先生
时间:
2020-9-7 15:43
感谢楼主,最近正在学习这部分
作者:
蛋黄派@SZPT
时间:
2020-9-12 18:16
MARK 一下
作者:
沉云儿
时间:
2021-7-28 16:40
?57个error有点夸张了吧
作者:
sr861126
时间:
2023-12-1 08:35
没有103的吗、
作者:
fhq1087
时间:
2024-1-23 18:57
这个真是太友好了,瞌睡了送来枕头
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1