ESP32使用4针I2C驱动SSD1306OLED显示屏实现多级菜单
首先我先声明一下,代码参考了B站UP主的ESP32入门教程,这里是对4针OLED实现同样效果并做出一定优化的补充,请各位读者放心食用,这里附上效果图:
接线图
连接方式:
VCC–VIN
GND–GND
SDA—D21
SCL—D22
两个按键开关,一个接单片机的D12,一个接D14,分别用作向下和向上移动箭头
注意按键开关的连接方式,这里附上原理图
注意到较长距离的两个引脚之间是互相连通的,较短距离的两个引脚并不相通,如果不知道如何连接,我们直接外接斜对角即可,这样不管怎么接都是正确的,
如果知道原理接较短的两脚之间也无所谓,但是注意在洞洞板上可以这么接,在面包板上,由于竖排相通,我们将较长两端的按键开关顺着插入才能正常使用,否则会使四角全通,全部短接,失去作用,如果实在看不懂,按上图的接线图接即可。
部分代码亮点预讲解
1.代码中没有采用外部中断用来检测12,14引脚电平的变化从而使OLED菜单的指针发生移动,而是采用简单的if语句执行相应的操作。可能导致切换并不灵敏,于是需要软件消抖。
2.使用字符数组存多级菜单信息。
3.使用4针OLED屏幕对应的类,屏幕不旋转,无重置引脚
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
4.D12,D14引脚默认输出高电平,要从该两个引脚接地输入低电平信号,刺激(bushi)单片机做出改变菜单内容的动作,应使该引脚设为上拉输入模式。
5.按键在按下和松开的瞬间会产生一定的抖动,可能没有正确触底,第一次检测按键被按下时,我们先做延时,第二次再次检测按键是否完全被按下,并做出相应动作,最后松手检测,当检测到低电平时,低电平信号输入单片机引脚,松开按键瞬间退出引脚为高电平,用while语句判断是否结束,最后执行相应操作。
6.代码烧录进单片机后,OLED 屏幕不亮,只有按下按键方可触发显示。
B站原教程:【2023年最新 ESP32 Arduino 教程(持续更新中)-哔哩哔哩】 https://b23.tv/wYrjB63
这里附上代码
#include<U8g2lib.h>
#include<Arduino.h>
#include<Wire.h>
#define SCL_PIN 22
#define SDA_PIN 21
#define button_up 12
#define button_down 14
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
char*menu[4]={"Item1","Item2","Item3","Item4"};
unsigned int order=0;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Wire.begin(SDA_PIN,SCL_PIN);
u8g2.begin();
u8g2.setFont(u8g2_font_ncenB08_tr);
pinMode(button_up,INPUT_PULLUP);
pinMode(button_down,INPUT_PULLUP);
}
void loop() {
// put your main code here, to run repeatedly:
// if(!digitalRead(button_down)){
// display_Menu(order++);
// if(order==4)
// order==0;}
// if(!digitalRead(button_up)) {
// display_Menu(order--);
// if(order==-1)
// order=3;}
// 或采用如下写法
if(!digitalRead(button_down)){
delay(10);//软件消抖
if(!digitalRead(button_down)){
order=(order+1)%4;//循环0,1,2,3
while(digitalRead(button_down));}
display_Menu(order);
}
if(!digitalRead(button_up)){
delay(10);
if(!digitalRead(button_up)){
order=(order-1+4)%4;
while(digitalRead(button_up));}
display_Menu(order);}
}
void display_Menu(unsigned int index){
u8g2.firstPage();//显示第一页
do{
u8g2.clearBuffer();
u8g2.drawStr(0,12,"Menu");
u8g2.drawHLine(0,14,128);
for(int i=0;i<4;i++){
if(i==index){
u8g2.drawStr(5,(i+2)*12+2,"->");
u8g2.drawStr(20,(i+2)*12+2,menu[i]);}
else
u8g2.drawStr(5,(i+2)*12+2,menu[i]);
}
u8g2.sendBuffer();
delay(1000);}
while(u8g2.nextPage());
}