/**
* 基于FreeRTOS,可以多个任务并行处理.
* ESP32有两个Tenants Xtensa LX6 微处理器
* 用arduino进行编程时中使用第一个核心,第0核心没有使用
* 多线程可以指定在那个核心运行
*/
#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
//配置IIC引脚 与SPI引脚
#define scl 22 //时钟引脚IIC SPI
#define sda 21 //数据引脚IIC SPI
#define cs 0 //片选引脚 SPI
#define dc 0 //发送命令引脚 SPI
#define reset 0 //重置引脚 SPI
/*
#define U8g2_MULTCORE
0.软件I2c 一次刷新为500ms
1.硬件I2c 一次刷新为22ms
2.软件SPI 一次刷新为40ms
3.硬件SPI 一次刷新为5ms
*/
/*
旋转方式
U8G2_R0:不旋转 U8G2_R1:顺时针旋转90度
U8G2_R1:顺时针旋转180度
U8G2_R3:顺时针旋转270度
U8G2_MIRROR:镜像显示但不旋转
*/
#define U8g2_MULTCORE 1
#if U8g2_MULTCORE == 0 //软件I2c 一次刷新为500ms
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0,scl,sda,U8X8_PIN_NONE);
#elif U8g2_MULTCORE == 1 //硬件I2c 一次刷新为22ms
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0,scl,sda,U8X8_PIN_NONE);
#elif U8g2_MULTCORE == 2 //软件SPI 一次刷新为40ms
U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0,scl,sda,cs,dc,reset);
#elif U8g2_MULTCORE == 3 //硬件SPI 一次刷新为4ms 要设置时钟为9M
U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0,cs,dc,reset);
#endif
//u8g2初始化
void U8g2_init()
{
u8g2.setBusClock(80000);//设置时钟频率
//屏幕初始化
u8g2.begin();
// 开启中文字符集支持
u8g2.enableUTF8Print();
//关闭中文字符集
//u8g2.disableUTF8Print();
//设置屏幕亮度
u8g2.setContrast(200);
/*设置字体 字号12,13,14,15,16
u8g2_font_wqy12_t_gb2312
u8g2_font_wqy12_t_gb2312a
u8g2_font_wqy12_t_gb2312b
u8g2_font_wqy12_t_chinese1
u8g2_font_wqy12_t_chinese2
u8g2_font_wqy12_t_chinese3
*/
u8g2.setFont(u8g2_font_wqy12_t_gb2312);
//打印时钟频率
Serial.println(u8g2.getBusClock());
}
/********************************************************************************************8 */
//菜单输入按键初始化
#define key_OK_pin 25
#define key_UP_pin 26
#define key_DOWN_pin 27
#define key_OK digitalRead(key_OK_pin) //引脚宏定义
#define key_UP digitalRead(key_UP_pin) //引脚宏定义
#define key_DOWN digitalRead(key_DOWN_pin) //引脚宏定义
void KYE_init()
{
//INPUT_PULLUP 上拉模式 INPUT_PULLDOWN 下拉模式
pinMode(key_OK_pin, INPUT_PULLUP);
pinMode(key_UP_pin, INPUT_PULLUP);
pinMode(key_DOWN_pin, INPUT_PULLUP);
}
//主菜单页面
int menu_one()
{
int flag = 1; //记录选择菜单
while(1)
{
if(key_UP == 0) //下一项
{
delay(10);
while (key_UP == 0);
delay(10);
flag++;
if(flag==5) flag=1;
}
if(key_OK == 0)
{
delay(10);
while (key_OK == 0);
delay(10);
u8g2.clearBuffer(); //清除缓冲区内容
return(flag) ;
}
switch (flag)
{
case 1:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16,"->设置1") ;
u8g2.drawUTF8(0,32," 设置2") ;
u8g2.drawUTF8(0,48," 设置3") ;
u8g2.drawUTF8(0,64," 设置4") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
case 2:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16," 设置1") ;
u8g2.drawUTF8(0,32,"->设置2") ;
u8g2.drawUTF8(0,48," 设置3") ;
u8g2.drawUTF8(0,64," 设置4") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
case 3:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16," 设置1") ;
u8g2.drawUTF8(0,32," 设置2") ;
u8g2.drawUTF8(0,48,"->设置3") ;
u8g2.drawUTF8(0,64," 设置4") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
case 4:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16," 设置1") ;
u8g2.drawUTF8(0,32," 设置2") ;
u8g2.drawUTF8(0,48," 设置3") ;
u8g2.drawUTF8(0,64,"->设置4") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
}
}
}
//子菜单设置1
int menu_TWo()
{
int flag = 1; //记录选择菜单
while(1)
{
if(key_UP == 0) //下一项
{
delay(10);
while (key_UP == 0);
delay(10);
flag++;
if(flag==5) flag=1;
}
if(key_OK == 0)
{
delay(10);
while (key_OK == 0);
delay(10);
u8g2.clearBuffer(); //清除缓冲区内容
return 0; //结束函数 这里可以添加变量函数
}
switch (flag)
{
case 1:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16,"->子菜单1") ;
u8g2.drawUTF8(0,32," 子菜单12") ;
u8g2.drawUTF8(0,48," 子菜单13") ;
u8g2.drawUTF8(0,64," 子菜单14") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
case 2:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16," 子菜单11") ;
u8g2.drawUTF8(0,32,"->子菜单12") ;
u8g2.drawUTF8(0,48," 子菜单13") ;
u8g2.drawUTF8(0,64," 子菜单14") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
case 3:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16," 子菜单11") ;
u8g2.drawUTF8(0,32," 子菜单12") ;
u8g2.drawUTF8(0,48,"->子菜单13") ;
u8g2.drawUTF8(0,64," 子菜单14") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
case 4:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16," 子菜单11") ;
u8g2.drawUTF8(0,32," 子菜单12") ;
u8g2.drawUTF8(0,48," 子菜单13") ;
u8g2.drawUTF8(0,64,"->子菜单14") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
}
}
}
//子菜单设置2
int menu_Three()
{
int flag = 1; //记录选择菜单
while(1)
{
if(key_UP == 0) //下一项
{
delay(10);
while (key_UP == 0);
delay(10);
flag++;
if(flag==5) flag=1;
}
if(key_OK == 0)
{
delay(10);
while (key_OK == 0);
delay(10);
u8g2.clearBuffer(); //清除缓冲区内容
return 0; //结束函数 这里可以添加变量函数
}
switch (flag)
{
case 1:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16,"->子菜单2") ;
u8g2.drawUTF8(0,32," 子菜单22") ;
u8g2.drawUTF8(0,48," 子菜单23") ;
u8g2.drawUTF8(0,64," 子菜单24") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
case 2:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16," 子菜单21") ;
u8g2.drawUTF8(0,32,"->子菜单22") ;
u8g2.drawUTF8(0,48," 子菜单23") ;
u8g2.drawUTF8(0,64," 子菜单24") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
case 3:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16," 子菜单21") ;
u8g2.drawUTF8(0,32," 子菜单22") ;
u8g2.drawUTF8(0,48,"->子菜单23") ;
u8g2.drawUTF8(0,64," 子菜单24") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
case 4:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16," 子菜单21") ;
u8g2.drawUTF8(0,32," 子菜单22") ;
u8g2.drawUTF8(0,48," 子菜单23") ;
u8g2.drawUTF8(0,64,"->子菜单24") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
}
}
}
//子菜单设置3
int menu_Four()
{
int flag = 1; //记录选择菜单
while(1)
{
if(key_UP == 0) //下一项
{
delay(10);
while (key_UP == 0);
delay(10);
flag++;
if(flag==5) flag=1;
}
if(key_OK == 0)
{
delay(10);
while (key_OK == 0);
delay(10);
u8g2.clearBuffer(); //清除缓冲区内容
return 0; //结束函数 这里可以添加变量函数
}
switch (flag)
{
case 1:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16,"->子菜单32") ;
u8g2.drawUTF8(0,32," 子菜单3") ;
u8g2.drawUTF8(0,48," 子菜单33") ;
u8g2.drawUTF8(0,64," 子菜单34") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
case 2:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16," 子菜单31") ;
u8g2.drawUTF8(0,32,"->子菜单32") ;
u8g2.drawUTF8(0,48," 子菜单33") ;
u8g2.drawUTF8(0,64," 子菜单34") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
case 3:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16," 子菜单31") ;
u8g2.drawUTF8(0,32," 子菜单32") ;
u8g2.drawUTF8(0,48,"->子菜单33") ;
u8g2.drawUTF8(0,64," 子菜单34") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
case 4:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16," 子菜单31") ;
u8g2.drawUTF8(0,32," 子菜单32") ;
u8g2.drawUTF8(0,48," 子菜单33") ;
u8g2.drawUTF8(0,64,"->子菜单34") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
}
}
}
//子菜单设置4
int menu_Fivw()
{
int flag = 1; //记录选择菜单
while(1)
{
if(key_UP == 0) //下一项
{
delay(10);
while (key_UP == 0);
delay(10);
flag++;
if(flag==5) flag=1;
}
if(key_OK == 0)
{
delay(10);
while (key_OK == 0);
delay(10);
u8g2.clearBuffer(); //清除缓冲区内容
return 0; //结束函数 这里可以添加变量函数
}
switch (flag)
{
case 1:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16,"->子菜单42") ;
u8g2.drawUTF8(0,32," 子菜单43") ;
u8g2.drawUTF8(0,48," 子菜单43") ;
u8g2.drawUTF8(0,64," 子菜单44") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
case 2:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16," 子菜单4") ;
u8g2.drawUTF8(0,32,"->子菜单4") ;
u8g2.drawUTF8(0,48," 子菜单4") ;
u8g2.drawUTF8(0,64," 子菜单4") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
case 3:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16," 子菜单4") ;
u8g2.drawUTF8(0,32," 子菜单4") ;
u8g2.drawUTF8(0,48,"->子菜单4") ;
u8g2.drawUTF8(0,64," 子菜单34") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
case 4:
{
u8g2.clearBuffer(); //清除缓冲区内容
u8g2.drawUTF8(0,16," 子菜单4") ;
u8g2.drawUTF8(0,32," 子菜单4") ;
u8g2.drawUTF8(0,48," 子菜单34") ;
u8g2.drawUTF8(0,64,"->子菜单4") ;
u8g2.sendBuffer(); //显示缓冲区内容
}break;
}
}
}
/*****************************************************************************************8 */
/******************************************************************************* */
#define USE_MULTCORE 0 //定义利用那个核心 0选择用ESP32第0个核心 1不选择核心
//任务1
void xTaskOne(void *xTask1)
{
while(1)
{
Serial.printf("//任务1task1\r\n");
delay(1000);
}
}
//任务2
void xTaskTwo(void *xTask2)
{
while(1)
{
Serial.printf("//任务1task2\r\n");
delay(2000);
}
}
//任务3
void xTaskThree(void *xTask3)
{
while(1)
{
Serial.printf("//任务1task3\r\n");
delay(3000);
}
}
/******************************************************************************* */
//函数初始化
void setup() {
Serial.begin(9600);
delay(10);
U8g2_init();
//FreeRTOS
#if !USE_MULTCORE
xTaskCreate(
xTaskOne, // 任务函数
"TaskOne", // 任务名称
4096, // 堆栈大小(以字为单位)
NULL, // 传递给任务的参数
1, // 任务的优先级
NULL) ; // 指向任务句柄的指针
xTaskCreate(
xTaskTwo,
"TaskTwo",
4096, //分配内存大小
NULL,
2, //优先级
NULL);
xTaskCreate(
xTaskThree, //任务名称
"TaskThree",
4096, //分配内存大小
NULL,
3, //优先级
NULL);
#else
//最后一个参数决定在那个核心运行
xTaskCreatePinnedToCore(xTaskOne,"TaskOne", 4096,NULL,1,NULL,0);
xTaskCreatePinnedToCore(xTaskTwo,"TaskTwo", 4096,NULL,2,NULL,1);
xTaskCreatePinnedToCore(xTaskThree,"TaskThree", 4096,NULL,3,NULL,0);
#endif
KYE_init(); //按键初始化
}
//图片数组
PROGMEM const uint8_t logo1[] = {
0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x3F,0x00,0x00,0x00,
0x00,0x00,0xF0,0xFF,0xFF,0x03,0x00,0x00,0x00,0x00,0xFC,0xFF,0xFF,0x0F,0x00,0x00,
0x00,0x00,0xFF,0xFF,0xFF,0x3F,0x00,0x00,0x00,0x80,0xFF,0xFF,0xFF,0xFF,0x00,0x00,
0x00,0xE0,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xFF,0x03,0x00,
0x00,0xF8,0xFF,0xFF,0xFF,0xFF,0x0F,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0xFF,0x0F,0x00,
0x00,0xFE,0xFF,0xFF,0xFF,0xFF,0x3F,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x00,
0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00,0xC0,0xFF,0xFF,0x0F,0xFC,0xFF,0xFF,0x00,
0xE0,0xFF,0xFF,0x03,0xF0,0xFF,0xFF,0x01,0xE0,0xFF,0xFF,0x01,0xC0,0xFF,0xFF,0x01,
0xF0,0xFF,0x7F,0xF8,0x87,0xFF,0xFF,0x03,0xF0,0xFF,0x7F,0xFC,0x0F,0xFF,0xFF,0x03,
0xF8,0xFF,0x3F,0xFE,0x1F,0xFF,0xFF,0x07,0xF8,0xFF,0x3F,0xFF,0x3F,0xFF,0xFF,0x07,
0xFC,0xFF,0x3F,0xFF,0x3F,0xFE,0xFF,0x0F,0xFC,0xFF,0x1F,0xFF,0x3F,0xFE,0xFF,0x0F,
0xFC,0xFF,0x1F,0xFF,0x3F,0xFE,0xFF,0x0F,0xFE,0xFF,0x1F,0xFF,0x3F,0xFE,0xFF,0x1F,
0xFE,0xFF,0x1F,0xFF,0x3F,0xFE,0xFF,0x1F,0xFE,0xFF,0x3F,0xFF,0x3F,0xFE,0xFF,0x1F,
0xFE,0xFF,0x3F,0xFE,0x3F,0xFF,0xFF,0x1F,0xFE,0xFF,0x3F,0xFE,0x1F,0xFF,0xFF,0x1F,
0xFF,0xFF,0x7F,0xFC,0x8F,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0xF0,0xC3,0xFF,0xFF,0x1F,
0xFF,0xFF,0xFF,0x01,0xE0,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x07,0xF0,0xFF,0xFF,0x1F,
0xFF,0xFF,0xFF,0x1F,0xFE,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x03,0xF0,0xFF,0xFF,0x1F,
0xFF,0xFF,0xFF,0x00,0xC0,0xFF,0xFF,0x1F,0xFE,0xFF,0x3F,0xF0,0x03,0xFF,0xFF,0x1F,
0xFE,0xFF,0x1F,0xFC,0x0F,0xFE,0xFF,0x1F,0xFE,0xFF,0x0F,0xFF,0x3F,0xFC,0xFF,0x1F,
0xFE,0xFF,0x8F,0xFF,0x7F,0xF8,0xFF,0x1F,0xFC,0xFF,0xC7,0xFF,0xFF,0xF8,0xFF,0x1F,
0xFC,0xFF,0xE3,0xFF,0xFF,0xF1,0xFF,0x0F,0xFC,0xFF,0xF3,0xFF,0xFF,0xE3,0xFF,0x0F,
0xFC,0xFF,0xF1,0xFF,0xFF,0xE3,0xFF,0x0F,0xF8,0xFF,0xF1,0xFF,0xFF,0xE7,0xFF,0x07,
0xF8,0xFF,0xF9,0xFF,0xFF,0xE7,0xFF,0x07,0xF0,0xFF,0xF8,0xFF,0xFF,0xC7,0xFF,0x03,
0xF0,0xFF,0xF8,0xFF,0xFF,0xC7,0xFF,0x03,0xE0,0xFF,0xF8,0xFF,0xFF,0xC7,0xFF,0x01,
0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,
0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x00,
0x00,0xFE,0xFF,0xFF,0xFF,0xFF,0x1F,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0xFF,0x0F,0x00,
0x00,0xF8,0xFF,0xFF,0xFF,0xFF,0x07,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xFF,0x03,0x00,
0x00,0xE0,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x00,0xC0,0xFF,0xFF,0xFF,0xFF,0x00,0x00,
0x00,0x00,0xFF,0xFF,0xFF,0x3F,0x00,0x00,0x00,0x00,0xFC,0xFF,0xFF,0x0F,0x00,0x00,
0x00,0x00,0xE0,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0xFF,0x3F,0x00,0x00,0x00
};
//主函数运行
void loop() {
int value=0;
while(1)
{
/*****方法1***** */
// u8g2.clearBuffer(); //清除缓冲区内容
/***输出文字图像*** */
// u8g2.drawStr(0,16,"Hallo") ;
// u8g2.drawUTF8(0,32,"你好哈");
//u8g2.setCursor(0,48); //设置光标
//u8g2.printf("温度数值:%d",value);
//u8g2.drawXBMP(0,0,62,62,logo1);
/****************** */
// u8g2.sendBuffer(); //显示缓冲区内容
//delay(10);
//value++;
/********方法2******* */
/*
u8g2.firstPage();
do{
u8g2.drawXBMP(0,0,41,62,logo);
}while (u8g2.nextPage());
*/
value = menu_one();
if(value == 1) //子菜单1
{
menu_TWo();
}else if (value == 2)
{
menu_Three();
}else if (value == 3)
{
menu_Four();
}else if (value == 4)
{
menu_Fivw();
}
}
}
文档参考视频https://www.bilibili.com/video/BV1ij411676D/?spm_id_from=333.788.top_right_bar_window_history.content.click&vd_source=00217da3dd521fe6dc49ba32c87b19e8