好的,作为一名高级嵌入式软件开发工程师,我将针对这款0.97寸墨水屏U盘产品,详细阐述一个可靠、高效、可扩展的系统平台架构,并提供相应的C代码示例。考虑到实际嵌入式开发的复杂性,以下代码并非完全可编译运行,但足以体现设计思路和关键技术点。关注微信公众号,提前获取相关推文 1. 系统需求分析
首先,我们需要明确这款墨水屏U盘的功能需求:
基本功能:
U盘存储:作为标准的USB存储设备,提供数据存储功能。
墨水屏显示:能够显示U盘状态信息、文件列表、个性化内容等。
按键交互:至少3个按键,用于菜单导航、选择、确认等操作。
低功耗设计:墨水屏特性决定低功耗,但整体系统需考虑功耗优化。
扩展功能:
RTC:实时时钟,用于显示时间信息。
文件系统:支持FAT32等常见文件系统。
升级功能:支持通过USB或其它方式进行固件升级。
用户自定义:提供配置文件的修改功能。
电池管理:如果有内置电池,需要进行电量监控和管理。
2. 系统架构设计
我将采用分层架构来设计这个嵌入式系统,这样可以提高代码的可维护性、可复用性和可扩展性。架构分为以下几层:
硬件抽象层 (HAL): 封装底层硬件操作,提供统一的接口给上层使用。
包括GPIO驱动、SPI驱动 (墨水屏)、USB驱动、RTC驱动等。
设备驱动层 (Device Driver): 在HAL基础上,实现具体设备的驱动逻辑。
包括墨水屏驱动、按键驱动、USB存储驱动、RTC驱动等。
系统服务层 (System Service): 提供系统级的服务。
应用层 (Application): 实现具体的功能逻辑。
3. 软件设计细节
3.1. 硬件抽象层 (HAL)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 #ifndef HAL_H #define HAL_H #include <stdint.h> typedef enum { GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_MAX } gpio_pin_t ; typedef enum { GPIO_MODE_INPUT, GPIO_MODE_OUTPUT } gpio_mode_t ; typedef enum { GPIO_STATE_LOW, GPIO_STATE_HIGH } gpio_state_t ; void hal_gpio_init (gpio_pin_t pin, gpio_mode_t mode) ;void hal_gpio_set (gpio_pin_t pin, gpio_state_t state) ;gpio_state_t hal_gpio_get (gpio_pin_t pin) ;typedef enum { SPI_MODE_0, SPI_MODE_1, SPI_MODE_MAX } spi_mode_t ; void hal_spi_init (spi_mode_t mode, uint32_t speed) ;void hal_spi_transfer (uint8_t *tx_data, uint8_t *rx_data, uint32_t len) ;void hal_usb_init () ;void hal_usb_send_data (uint8_t *data, uint32_t len) ;uint32_t hal_usb_receive_data (uint8_t *data, uint32_t max_len) ;typedef struct { uint8_t second; uint8_t minute; uint8_t hour; uint8_t day; uint8_t month; uint16_t year; } rtc_time_t ; void hal_rtc_init () ;void hal_rtc_get_time (rtc_time_t *time) ;void hal_rtc_set_time (rtc_time_t *time) ;#endif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 #include "hal.h" #include "stm32f4xx.h" void hal_gpio_init (gpio_pin_t pin, gpio_mode_t mode) { GPIO_InitTypeDef GPIO_InitStruct; if (pin == GPIO_PIN_0) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; } else if (pin == GPIO_PIN_1) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1; } if (mode == GPIO_MODE_OUTPUT) { GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; } else { GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; } GPIO_Init(GPIOA, &GPIO_InitStruct); } void hal_gpio_set (gpio_pin_t pin, gpio_state_t state) { if (pin == GPIO_PIN_0) { GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)state); }else if (pin == GPIO_PIN_1){ GPIO_WriteBit(GPIOA, GPIO_Pin_1, (BitAction)state); } } gpio_state_t hal_gpio_get (gpio_pin_t pin) { if (pin == GPIO_PIN_0) { return (gpio_state_t )GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0); }else if (pin == GPIO_PIN_1){ return (gpio_state_t )GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1); } return GPIO_STATE_LOW; } void hal_spi_init (spi_mode_t mode, uint32_t speed) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); SPI_InitTypeDef SPI_InitStruct; SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStruct.SPI_Mode = SPI_Mode_Master; SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low; SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStruct.SPI_NSS = SPI_NSS_Soft; SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStruct.SPI_CRCPolynomial = 7 ; SPI_Init(SPI1, &SPI_InitStruct); SPI_Cmd(SPI1, ENABLE); } void hal_spi_transfer (uint8_t *tx_data, uint8_t *rx_data, uint32_t len) { for (int i = 0 ; i < len; i++) { while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI1, tx_data[i]); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); rx_data[i] = SPI_I2S_ReceiveData(SPI1); } } void hal_usb_init () { return ; } void hal_usb_send_data (uint8_t *data, uint32_t len) { return ; } uint32_t hal_usb_receive_data (uint8_t *data, uint32_t max_len) { return 0 ; } void hal_rtc_init () { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); PWR_BackupAccessCmd(ENABLE); RCC_LSEConfig(RCC_LSE_ON); while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET); RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); RCC_RTCCLKCmd(ENABLE); RTC_InitTypeDef RTC_InitStructure; RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24; RTC_InitStructure.RTC_AsynchPrediv = 127 ; RTC_InitStructure.RTC_SynchPrediv = 255 ; RTC_Init(&RTC_InitStructure); } void hal_rtc_get_time (rtc_time_t *time) { RTC_TimeTypeDef RTC_TimeStruct; RTC_DateTypeDef RTC_DateStruct; RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct); RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct); time->second = RTC_TimeStruct.RTC_Seconds; time->minute = RTC_TimeStruct.RTC_Minutes; time->hour = RTC_TimeStruct.RTC_Hours; time->day = RTC_DateStruct.RTC_Date; time->month = RTC_DateStruct.RTC_Month; time->year = RTC_DateStruct.RTC_Year; } void hal_rtc_set_time (rtc_time_t *time) { RTC_TimeTypeDef RTC_TimeStruct; RTC_DateTypeDef RTC_DateStruct; RTC_TimeStruct.RTC_Seconds = time->second; RTC_TimeStruct.RTC_Minutes = time->minute; RTC_TimeStruct.RTC_Hours = time->hour; RTC_DateStruct.RTC_Date = time->day; RTC_DateStruct.RTC_Month = time->month; RTC_DateStruct.RTC_Year = time->year; RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct); RTC_SetDate(RTC_Format_BIN, &RTC_DateStruct); }
3.2. 设备驱动层 (Device Driver)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #ifndef DEVICE_H #define DEVICE_H #include "hal.h" #define EINK_WIDTH 128 #define EINK_HEIGHT 32 void eink_init () ;void eink_clear_screen () ;void eink_draw_pixel (uint16_t x, uint16_t y, uint8_t color) ;void eink_display_buffer (uint8_t *buffer) ;void eink_draw_text (uint16_t x, uint16_t y, const char *text) ;typedef enum { KEY_NONE, KEY_UP, KEY_DOWN, KEY_OK } key_event_t ; key_event_t keypad_get_event () ;void usb_storage_init () ;void usb_storage_read (uint32_t sector, uint8_t *buffer, uint32_t count) ;void usb_storage_write (uint32_t sector, uint8_t *buffer, uint32_t count) ;void rtc_get_time (rtc_time_t *time) ;void rtc_set_time (rtc_time_t *time) ;#endif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 #include "device.h" #include "font.h" #define EINK_DC_PIN GPIO_PIN_0 #define EINK_CS_PIN GPIO_PIN_1 #define EINK_RST_PIN GPIO_PIN_2 uint8_t eink_buffer[EINK_WIDTH * EINK_HEIGHT / 8 ];void eink_init () { hal_gpio_init(EINK_DC_PIN, GPIO_MODE_OUTPUT); hal_gpio_init(EINK_CS_PIN, GPIO_MODE_OUTPUT); hal_gpio_init(EINK_RST_PIN, GPIO_MODE_OUTPUT); hal_spi_init(SPI_MODE_0, 1000000 ); hal_gpio_set(EINK_RST_PIN, GPIO_STATE_LOW); for (int i = 0 ; i < 1000 ; i++); hal_gpio_set(EINK_RST_PIN, GPIO_STATE_HIGH); for (int i = 0 ; i < 1000 ; i++); eink_send_command(0x12 ); eink_send_command(0x74 ); eink_send_data(0x54 ); eink_send_command(0x7e ); eink_send_data(0x3b ); eink_send_command(0x2b ); eink_send_data(0x02 ); eink_clear_screen(); } void eink_send_command (uint8_t command) { hal_gpio_set(EINK_CS_PIN, GPIO_STATE_LOW); hal_gpio_set(EINK_DC_PIN, GPIO_STATE_LOW); hal_spi_transfer(&command, NULL , 1 ); hal_gpio_set(EINK_CS_PIN, GPIO_STATE_HIGH); } void eink_send_data (uint8_t data) { hal_gpio_set(EINK_CS_PIN, GPIO_STATE_LOW); hal_gpio_set(EINK_DC_PIN, GPIO_STATE_HIGH); hal_spi_transfer(&data, NULL , 1 ); hal_gpio_set(EINK_CS_PIN, GPIO_STATE_HIGH); } void eink_clear_screen () { for (int i=0 ;i<EINK_WIDTH * EINK_HEIGHT / 8 ;i++){ eink_buffer[i]=0xFF ; } eink_display_buffer(eink_buffer); } void eink_draw_pixel (uint16_t x, uint16_t y, uint8_t color) { if (x >= EINK_WIDTH || y >= EINK_HEIGHT) return ; uint16_t index = y * EINK_WIDTH / 8 + x / 8 ; uint8_t bit = 7 - (x % 8 ); if (color) { eink_buffer[index] |= (1 << bit); } else { eink_buffer[index] &= ~(1 << bit); } } void eink_display_buffer (uint8_t *buffer) { eink_send_command(0x24 ); hal_gpio_set(EINK_CS_PIN, GPIO_STATE_LOW); hal_gpio_set(EINK_DC_PIN, GPIO_STATE_HIGH); hal_spi_transfer(buffer, NULL , EINK_WIDTH * EINK_HEIGHT / 8 ); hal_gpio_set(EINK_CS_PIN, GPIO_STATE_HIGH); eink_send_command(0x22 ); eink_send_data(0xC7 ); eink_send_command(0x20 ); hal_gpio_set(EINK_CS_PIN, GPIO_STATE_LOW); } void eink_draw_char (uint16_t x, uint16_t y, char c, uint8_t color) { if (c>=' ' && c<='~' ) { uint8_t i,j; for (i=0 ;i<16 ;i++) { for (j=0 ;j<8 ;j++) { if ((Font8x16[c-0x20 ][i] & (0x80 >>j))) { eink_draw_pixel(x+j,y+i,color); } } } } } void eink_draw_text (uint16_t x, uint16_t y, const char *text) { uint16_t cursor_x = x; while (*text) { eink_draw_char(cursor_x, y, *text, 0 ); cursor_x += 8 ; text++; } eink_display_buffer(eink_buffer); } key_event_t keypad_get_event () { if (hal_gpio_get(GPIO_PIN_3) == GPIO_STATE_LOW) { for (int i = 0 ; i < 100000 ; i++); if (hal_gpio_get(GPIO_PIN_3) == GPIO_STATE_LOW) return KEY_UP; }else if (hal_gpio_get(GPIO_PIN_4) == GPIO_STATE_LOW) { for (int i = 0 ; i < 100000 ; i++); if (hal_gpio_get(GPIO_PIN_4) == GPIO_STATE_LOW) return KEY_DOWN; }else if (hal_gpio_get(GPIO_PIN_5) == GPIO_STATE_LOW) { for (int i = 0 ; i < 100000 ; i++); if (hal_gpio_get(GPIO_PIN_5) == GPIO_STATE_LOW) return KEY_OK; } return KEY_NONE; } void usb_storage_init () { return ; } void usb_storage_read (uint32_t sector, uint8_t *buffer, uint32_t count) { return ; } void usb_storage_write (uint32_t sector, uint8_t *buffer, uint32_t count) { return ; } void rtc_get_time (rtc_time_t *time) { hal_rtc_get_time(time); } void rtc_set_time (rtc_time_t *time) { hal_rtc_set_time(time); }
3.3. 系统服务层 (System Service)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #ifndef SERVICE_H #define SERVICE_H #include <stdint.h> #include "device.h" typedef struct { char filename[32 ]; uint32_t size; uint32_t address; } file_info_t ; uint32_t fs_get_file_count () ;file_info_t * fs_get_file_info (uint32_t index) ;uint32_t fs_read_file (uint32_t index, uint8_t * buffer, uint32_t max_len) ;uint32_t fs_write_file (const char * filename, uint8_t * buffer, uint32_t len) ;uint32_t fs_delete_file (uint32_t index) ;void power_enter_lowpower () ;void config_load () ;void config_save () ;uint32_t config_get_value (const char * key) ;void config_set_value (const char * key, uint32_t value) ;#endif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 #include "service.h" #include "string.h" #include "stdio.h" #include "stdlib.h" #define MAX_FILES 10 file_info_t files[MAX_FILES];uint32_t file_count = 0 ;#define SECTOR_SIZE 512 uint32_t fs_get_file_count () { return file_count; } file_info_t * fs_get_file_info (uint32_t index) { if (index < file_count) { return &files[index]; } return NULL ; } uint32_t fs_read_file (uint32_t index, uint8_t * buffer, uint32_t max_len) { if (index >= file_count) return 0 ; uint32_t read_size = files[index].size > max_len ? max_len : files[index].size; usb_storage_read(files[index].address / SECTOR_SIZE, buffer, read_size); return read_size; } uint32_t fs_write_file (const char * filename, uint8_t * buffer, uint32_t len) { if (file_count >= MAX_FILES) { return 0 ; } strncpy (files[file_count].filename, filename, 31 ); files[file_count].filename[31 ]=0 ; files[file_count].size = len; files[file_count].address = file_count * 1024 * 10 ; usb_storage_write(files[file_count].address/SECTOR_SIZE, buffer, len); file_count++; return len; } uint32_t fs_delete_file (uint32_t index) { if (index >= file_count){ return 0 ; } for (int i=index;i<file_count-1 ;i++){ files[i] = files[i+1 ]; } file_count--; return 1 ; } void power_enter_lowpower () { } #define MAX_CONFIG_ENTRIES 10 typedef struct { char key[32 ]; uint32_t value; } config_entry_t ; config_entry_t config_entries[MAX_CONFIG_ENTRIES];uint32_t config_count = 0 ;void config_load () { config_count = 0 ; strcpy (config_entries[0 ].key, "brightness" ); config_entries[0 ].value = 100 ; strcpy (config_entries[1 ].key, "volume" ); config_entries[1 ].value = 50 ; config_count = 2 ; } void config_save () { } uint32_t config_get_value (const char * key) { for (uint32_t i = 0 ; i < config_count; i++) { if (strcmp (config_entries[i].key, key) == 0 ) { return config_entries[i].value; } } return 0 ; } void config_set_value (const char * key, uint32_t value) { for (uint32_t i = 0 ; i < config_count; i++) { if (strcmp (config_entries[i].key, key) == 0 ) { config_entries[i].value = value; return ; } } if (config_count < MAX_CONFIG_ENTRIES) { strcpy (config_entries[config_count].key,key); config_entries[config_count].value = value; config_count++; } }
3.4. 应用层 (Application)
1 2 3 4 5 6 7 8 #ifndef APP_H #define APP_H void app_init () ;void app_run () ;#endif
// app.c
#include "app.h"
#include "device.h"
#include "service.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define MAX_MENU_ITEMS 10
typedef enum {
MENU_MAIN,
MENU_FILE,
MENU_SETTINGS,
MENU_TIME
} menu_state_t;
typedef struct {
const char *text;
menu_state_t next_menu;
} menu_item_t;
void show_menu(menu_item_t *menu, int item_count, int current_item);
void main_menu_loop();
void file_menu_loop();
void settings_menu_loop();
void time_menu_loop();
static menu_state_t current_menu = MENU_MAIN;
void app_init() {
// 系统初始化
hal_usb_init();
usb_storage_init();
eink_init();
hal_gpio_init(GPIO_PIN_3, GPIO_MODE_INPUT); //按键1 上
hal_gpio_init(GPIO_PIN_4, GPIO_MODE_INPUT); //按键2 下
hal_gpio_init(GPIO_PIN_5, GPIO_MODE_INPUT); //按键3 确认
hal_rtc_init();
config_load();
}
void app_run() {
// 主循环
while (1) {
switch (current_menu) {
case MENU_MAIN:
main_menu_loop();
break;
case MENU_FILE:
file_menu_loop();
break;
case MENU_SETTINGS:
settings_menu_loop();
break;
case MENU_TIME:
time_menu_loop();
break;
default:
current_menu = MENU_MAIN;
break;
}
}
}
void main_menu_loop() {
static int current_item = 0;
menu_item_t main_menu[] = {
{"File", MENU_FILE},
{"Settings", MENU_SETTINGS},
{"Time", MENU_TIME},
};
int item_count = sizeof(main_menu) / sizeof(main_menu[0]);
show_menu(main_menu,item_count,current_item);
while (1) {
key_event_t event = keypad_get_event();
if (event == KEY_UP) {
current_item = (current_item - 1 + item_count) % item_count;
show_menu(main_menu,item_count,current_item);
} else if (event == KEY_DOWN) {
current_item = (current_item + 1) % item_count;
show_menu(main_menu,item_count,current_item);
} else if (event == KEY_OK) {
current_menu = main_menu[current_item].next_menu;
current_item = 0; //重置子菜单选项
break;
}
}
}
void file_menu_loop() {
static int current_item = 0;
uint32_t file_count = fs_get_file_count();
if(file_count==0){
eink_clear_screen();
eink_draw_text(0, 10, "No Files!");
while (1) {
key_event_t event = keypad_get_event();
if (event == KEY_OK){
current_menu = MENU_MAIN;
break;
}
}
return;
}
menu_item_t file_menu[MAX_MENU_ITEMS];
for (int i = 0; i < file_count; i++) {
file_info_t *file_info = fs_get_file_info(i);
file_menu[i].text = file_info->filename;
file_menu[i].next_menu = MENU_FILE; //可以扩展成具体的文件操作
}
show_menu(file_menu,file_count,current_item);
while (1) {
key_event_t event = keypad_get_event();
if (event == KEY_UP) {
current_item = (current_item - 1 + file_count) % file_count;
show_menu(file_menu,file_count,current_item);
} else if (event == KEY_DOWN) {
current_item = (current_item + 1) % file_count;
show_menu(file_menu,file_count,current_item);
} else if (event == KEY_OK) {
eink_clear_screen();
uint8_t buffer[200];
fs_read_file(current_item, buffer, 200);
eink_draw_text(0, 10, (char *)buffer);
while (1) {
key_event_t event = keypad_get_event();
if (event == KEY_OK){
current_menu = MENU_MAIN;
break;
}
}
break;
}
}
}
void settings_menu_loop() {
static int current_item = 0;
menu_item_t settings_menu[] = {
{"Brightness", MENU_SETTINGS},
{"Volume", MENU_SETTINGS},
};
int item_count = sizeof(settings_menu) / sizeof(settings_menu[0]);
show_menu(settings_menu,item_count,current_item);
while (1) {
key_event_t event = keypad_get_event();
if (event == KEY_UP) {
current_item = (current_item - 1 + item_count) % item_count;
show_menu(settings_menu,item_count,current_item);
} else if (event == KEY_DOWN) {
current_item = (current_item + 1) % item_count;
show_menu(settings_menu,item_count,current_item);
} else if (event == KEY_OK) {
if(current_item==0){
uint32_t brightness = config_get_value("brightness");
eink_clear_screen();
char display_str[20];
sprintf(display_str,"Brightness:%d",brightness);
eink_draw_text(0, 10, display_str);
while(1){
key_event_t event = keypad_get_event();
if (event == KEY_UP) {
if(brightness <100){
brightness +=10;
char display_str[20];
sprintf(display_str,"Brightness:%d",brightness);
eink_clear_screen();
eink_draw_text(0, 10, display_str);
}
} else if (event == KEY_DOWN) {
if(brightness >0){
brightness -=10;
char display_str[20];
sprintf(display_str,"Brightness:%d",brightness);
eink_clear_screen();
eink_draw_text(0, 10, display_str);
}
}else if (event == KEY_OK) {
config_set_value("brightness",brightness);
current_menu = MENU_MAIN;
break;
}
}
}else if(current_item == 1){
uint32_t volume = config_get_value("volume");
eink_clear_screen();
char display_str[20];
sprintf(display_str,"Volume:%d",volume);
eink_draw_text(0, 10, display_str);
while(1){
key_event_t event = keypad_get_event();
if (event == KEY_UP) {
if(volume<100){
volume += 10;
char display_str[20];
sprintf(display_str,"Volume:%d",volume);
eink_clear_screen();
eink_draw_text(0, 10, display_str);
}
} else if (event == KEY_DOWN) {
if(volume>0){
volume -= 10;
char display_str[20];
sprintf(display_str,"Volume:%d",volume);
eink_clear_screen();
eink_draw_text(0, 10, display_str);