#include <U8g2lib.h>
#include <Wire.h>
#include <math.h>
//!!!!!UNO板默认A4为SDA,A5为SCL
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, SCL, SDA, /* reset=*/ U8X8_PIN_NONE); //这是比较常用的0.9寸的OLED显示器的驱动
/************结构体定义********************/
/*****************************************/
/*******菜单变量******/
typedef struct
{
char* str;
byte len;
}SETTING_LIST; //给一个默认的字符长度,是因为中文无法strlen得到长度值
SETTING_LIST list[] =
{
{"list_a", 6},
{"add", 3},
{"lisc", 4},
{"lixv_1", 6},
{"lixfdd_2", 8},
};
/******按键扫描值记录********/
typedef struct
{
byte val;
byte last_val;
}KEY_T;
KEY_T key[2] = {0};
/********按键状态判断*******/
typedef struct
{
byte id;
byte press;
byte update_flag;
byte res;
}KEY_MSG;
KEY_MSG key_msg = {0};
/***********变量配置************/
short x, x_trg; //x当前位置数值,x_trg 目标坐标值
short y, y_trg;
int state;
short frame_len, frame_len_trg; //选中框的宽度
short frame_y, frame_y_trg; //选中框的高度
char ui_select = 0; //表示当前选中第几行菜单
/**************函数定义*************/
byte get_io_val(byte ch)
{
if(ch == 0)
{
return digitalRead(2);
}
else
{
return digitalRead(3);
}
}
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;
}
}
}
}
/***********UI移动函数***********/
int ui_run(short *a,short *a_trg, u8 step, u8 slow_cnt)
{
u8 temp;
temp = abs(*a_trg - *a) > slow_cnt ? step : 1;
if(*a < *a_trg)
{
*a += temp;
}
else if( *a > *a_trg)
{
*a -= temp;
}
else
{
return 0; //如果到达目标值,返回0
}
return 1; //未到达目标值,返回1
}
/**************配置函数*****************/
void setup(void)
{
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
key_init();
u8g2.begin();
u8g2.setFont(u8g2_font_ncenB08_tr); //设置字体
x = 0;
y = 10;
//x_trg = 64;
y_trg = 10;
frame_len = frame_len_trg = list[ui_select].len*6;
}
/**************UI显示函数*****************/
void ui_show(void)
{
int list_len = sizeof(list) / sizeof(SETTING_LIST);
u8g2.clearBuffer(); // 清除内部缓冲区
for(int i = 0; i < list_len; i++)
{
u8g2.drawStr(x+2, y+i*10, list[i].str); // 第一段输出位置,为了防止显示内容与框框重合,所以x往右偏移2个像素
}
// ui_run(&x, &x_trg);
u8g2.drawRFrame(x, frame_y, frame_len, 12 ,3 );
/**
* 绘制圆角空心方形,左上角坐标为(x,y),宽度为w,高度为h,圆角半径为r
* @param x 左上角的x坐标
* @param y 左上角的y坐标
* @param w 方形的宽度
* @param h 方形的高度
* @param r 圆角半径
*/
//void U8G2::drawRFrame(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, u8g2_uint_t r)
// ui_run(&y, &y_trg) //这里实现,框不动,字动
ui_run(&frame_y, &frame_y_trg, 4, 2); //这里实现框动,字不动
ui_run(&frame_len, &frame_len_trg, 6, 3);
u8g2.sendBuffer(); // transfer internal memory to the display
}
/***************UI运动处理****************/
void ui_proc(void)
{
int list_len = sizeof(list) / sizeof(SETTING_LIST);
if(key_msg.update_flag && key_msg.press)
{
key_msg.update_flag = 0;
if(key_msg.id)
{
ui_select ++;
//frame_y += 10;
if(ui_select >= list_len)
{
ui_select = list_len - 1;
}
}
else{
ui_select --;
//frame_y -= 10;
if(ui_select < 0)
{
ui_select = 0;
}
}
frame_y_trg = ui_select*10;
frame_len_trg = list[ui_select].len*6;
}
ui_show();
}
void loop()
{
// put your main code here, to run repeatedly:
key_scan();
ui_proc();
}