#include <U8g2lib.h>
#include <Wire.h>
#define buttun_1 2 //按钮1 的引脚号
#define buttun_2 3 //按钮2 的引脚号
//U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);//该驱动是1.3寸的OLED屏幕。---------
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ SCL, /* data=*/ SDA); //0.9寸的OLED显示器的驱动使用硬件I2C
short x, x_trg; //x当前x坐标值,x_trg 目标x坐标值
short y = 10, y_trg = 10; //y坐标,目标y坐标
int state; //状态
typedef struct //定义别名为CAIDAN_LIEBIAO的结构
{
char *str; //指针变量用于指向菜单列表成员的地址
} CD_LIEBIAO;
CD_LIEBIAO LieBiao[] = { //定义结构体数组来存放菜单列表
{"a"}, {"ab"}, {"abc"}, {"abcd"}, {"abcde"}
};
typedef struct
{
byte val; //按钮键值
byte last_val; //上一次的按钮键值
} KEY_T;
KEY_T key[2] = {0}; //置0
typedef struct
{
byte id; //按钮id
byte press; //按钮状态
byte update_flag; //更新状态
byte res; //预留位
} KEY_MSG; //按钮消息
KEY_MSG key_msg = {0}; //初始化变量值
/***------------获取按钮键值------***/
byte get_io_val (byte ch)
{
if (ch == 0)
{
return digitalRead(buttun_1);
}
else
{
return digitalRead(buttun_2);
}
}
/***===================================================***/
/***------------按钮初始化函数------***/
void key_init(void) //按钮初始化
{
for (int i = 0; i < 2; i++)
{
key[i].val = key[i].last_val = get_io_val(i);
}
}
/***===================================================***/
/***---------------------------按钮扫描函数----------------------***/
void key_scan (void) //扫描按钮状态
{
for (int i = 0; i < 2; i++)
{
key[i].val = get_io_val(i); //获取当前按钮键值
if (key[i].val != key[i].last_val) //如果当前键值与上一次的键值不相等
{
key[i].last_val = key[i].val; //将当前键值保存为上一次键值
if (key[i].val == 0) //如果按钮被按下,更新按钮消息
{
key_msg.id = i;
key_msg.press = 1;
key_msg.update_flag = 1;
}
}
}
}
/***===================================================***/
/***---------------------------菜单执行函数----------------------***/
void ui_proc (void)
{
if (key_msg.press && key_msg.update_flag) //如果按钮被按下且已更新键值
{
key_msg.update_flag = 0; //将更新键值状态置为0 (未更新键值)
if (key_msg.id) //判断被按下的是哪个按钮,buttun_1向上移,buttun_2向下移
{
y_trg += 10;
}
else
{
y_trg -= 10;
}
}
cd_show();
}
/***------------菜单移动(从当前坐标向目标坐标靠近)------***/
int cd_run(short *a, short *a_trg) //两个指针变量分别指向代入坐标的地址
{
if (*a < *a_trg) //取出两个地址中的数据(坐标值)进行比较,如果当前坐标小于目标坐标
{
*a += 1; //加大当前坐标值,向目标坐标靠近
if (*a >= 60) //如果大于等于60,就从10重新开始
{
*a = *a_trg = 10;
}
}
else if ( *a > *a_trg)
{
*a -= 1;
if (*a <= 0) //如果小于等于0,就从50重新开始,要和上面的60错开
{
*a = *a_trg = 50;
}
}
else
{
return 0; //如果两坐标相等,返回0
}
return 1; //不相等,返回1
}
/***===================================================***/
/***-------------------------菜单显示--------------------------***/
void cd_show(void)
{
u8g2.clearBuffer(); // 清除内部缓冲区
int CD_ChangDu = sizeof(LieBiao) / sizeof(CD_LIEBIAO);//计算菜单列表的成员数量
for (int i = 0; i < CD_ChangDu ; i++) //遍历列表成员
{
//Serial.println(y);
u8g2.drawStr(x + 10, y + i * 10, LieBiao[i].str); // 输出列表成员
if ((y + i * 10) > 49)
{
u8g2.drawStr(x + 10, y + i * 10 - 50, LieBiao[i].str); // 输出列表成员
}
if ((y + i * 10) < 11)
{
u8g2.drawStr(x + 10, y + i * 10 + 50, LieBiao[i].str); // 输出列表成员
}
}
cd_run(&y, &y_trg);
u8g2.sendBuffer(); // 将内存数据传输到显示器
}
/***===================================================***/
void setup(void)
{
pinMode(buttun_1, INPUT_PULLUP);
pinMode(buttun_2, INPUT_PULLUP);
key_init(); //按钮初始化
Serial.begin(115200);
u8g2.begin(); //U8G2初始化
u8g2.setFont(u8g2_font_ncenB08_tr); //设置字体
}
void loop(void)
{
key_scan();
ui_proc();
}