本教程將詳細介紹如何在零知增強板上使用3.5寸ILI9486顯示屏實現電子書閱讀器功能。我們將使用LVGL庫構建用戶界面,并實現翻頁、進度顯示等核心功能。
一、硬件連接
1.1 硬件組件清單
組件名稱 | 規格參數 | 備注 |
---|---|---|
零知開發板 | STM32F407VGT6 | 主控制器 |
ILI9486顯示屏 | 3.5英寸TFT LCD (480×320) | 電阻觸摸屏 |
SD卡模塊 | SPI接口,支持FAT32 | 存儲電子書文件 |
XPT2046觸摸控制器 | SPI接口 | 集成在顯示屏模塊上 |
W25Q128 Flash芯片 | 128M-bit (16MB) | 存儲字體和系統文件 |
USB數據線 | 直流供電 | 系統電源 |
1.2 連接方式
零知增強板設計有專門的顯示屏接口,3.5寸ILI9486顯示屏可直接插入增強板,無需額外連線
電子書閱讀器界面效果圖:
二、軟件UI組件實現
2.1 核心數據結構
static const char* ebook_content[] = { "Embedded Systems Fundamentalsnn" "Embedded systems are specialized computing systems that perform dedicated functions.", "Microcontroller Architecturenn" "Microcontrollers (MCUs) contain a processor core, memory, and programmable I/O peripherals.", "Real-Time Operating Systemsnn" "RTOS provides deterministic timing behavior for embedded applications.", "Communication Protocolsnn" "Wired: UART, SPI, I2C, CANnWireless: BLE, Wi-Fi, LoRaWAN", "Development Lifecyclenn" "Stages: Requirements, Design, Implementation, Testing, Deployment" }; static const uint8_t ebook_page_count = sizeof(ebook_content) / sizeof(ebook_content[0]); // 電子書翻頁事件回調 static void ebook_prev_event_cb(lv_obj_t* btn, lv_event_t event); static void ebook_next_event_cb(lv_obj_t* btn, lv_event_t event); typedef struct { uint8_t current_page; uint8_t total_pages; bool is_english; lv_point_t touch_start; // 觸摸起始點 lv_obj_t* page_label; lv_obj_t* progress_label; lv_obj_t* btn_translate; } EBookState;
2.2 觸摸事件處理
// 聲明全局ebook_state變量 static EBookState ebook_state; // 3. 完全兼容的觸摸事件處理(替代手勢事件) static void ebook_touch_event_cb(lv_obj_t* obj, lv_event_t event) { static lv_point_t touch_start; static uint32_t touch_time; switch(event) { case LV_EVENT_PRESSED: { lv_indev_t* indev = lv_indev_get_act(); if(indev) { lv_indev_get_point(indev, &touch_start); touch_time = lv_tick_get(); } break; } case LV_EVENT_RELEASED: { lv_indev_t* indev = lv_indev_get_act(); lv_point_t touch_end; if(indev) { lv_indev_get_point(indev, &touch_end); // 計算滑動距離和時間 lv_coord_t dx = touch_end.x - touch_start.x; uint32_t duration = lv_tick_elaps(touch_time); // 判斷有效滑動 (水平移動>30像素且時間300ms) if(abs(dx) > 30 && duration < 300) { if(dx > 0) { // 向右滑動:上一頁 if(ebook_state.current_page > 0) { ebook_prev_event_cb(NULL, LV_EVENT_SHORT_CLICKED); } } else { // 向左滑動:下一頁 if(ebook_state.current_page < ebook_state.total_pages - 1) { ebook_next_event_cb(NULL, LV_EVENT_SHORT_CLICKED); } } } } break; } } } // 更新電子書顯示 static void update_ebook_display() { // 重置位置避免動畫殘留 lv_obj_set_x(ebook_state.page_label, 0); lv_label_set_text(ebook_state.page_label, ebook_content[ebook_state.current_page]); char progress[16]; snprintf(progress, sizeof(progress), "%d/%d", ebook_state.current_page + 1, ebook_state.total_pages); lv_label_set_text(ebook_state.progress_label, progress); }
2.3初始化界面
void show_app_book() { lv_obj_t* win = create_app_win("EBook Reader"); lv_coord_t hres = lv_disp_get_hor_res(NULL); lv_coord_t vres = lv_disp_get_ver_res(NULL); // 初始化電子書狀態 ebook_state.current_page = 0; ebook_state.total_pages = ebook_page_count; ebook_state.is_english = true; // 默認英文 ebook_state.touch_start.x = 0; ebook_state.touch_start.y = 0; // 創建內容容器(支持觸摸檢測) lv_obj_t* content_cont = lv_cont_create(win, NULL); lv_obj_set_size(content_cont, hres - 40, vres - 100); lv_obj_align(content_cont, NULL, LV_ALIGN_IN_TOP_MID, 0, 20); // lv_obj_set_gesture_parent(content_cont, true); lv_obj_set_event_cb(content_cont, ebook_touch_event_cb); // 創建頁面標簽 ebook_state.page_label = lv_label_create(content_cont, NULL); lv_obj_set_width(ebook_state.page_label, lv_obj_get_width(content_cont) - 20); lv_label_set_long_mode(ebook_state.page_label, LV_LABEL_LONG_EXPAND); lv_label_set_align(ebook_state.page_label, LV_LABEL_ALIGN_LEFT); lv_obj_set_width(ebook_state.page_label, lv_obj_get_width(content_cont) - 40); // 增加一些邊距 lv_label_set_text(ebook_state.page_label, ""); lv_obj_align(ebook_state.page_label, NULL, LV_ALIGN_CENTER, 0, 0); // 創建進度標簽 ebook_state.progress_label = lv_label_create(win, NULL); lv_obj_align(ebook_state.progress_label, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, -30); lv_label_set_text(ebook_state.progress_label, "0/0"); // 初始顯示 update_ebook_display(); }
2.4 翻頁功能實現
// 翻頁動畫函數 (兼容舊版LVGL) static void ebook_page_anim(lv_obj_t* label, lv_coord_t start, lv_coord_t end) { lv_anim_t a; lv_anim_init(&a); // lv_anim_set_var(&a, label); lv_anim_set_values(&a, start, end); lv_anim_set_time(&a, 300, 0); // 兼容舊版API:設置持續時間和延遲 lv_anim_set_exec_cb(&a, label, (lv_anim_exec_xcb_t)lv_obj_set_x); // 兼容舊版API lv_anim_create(&a); } // 上一頁事件 static void ebook_prev_event_cb(lv_obj_t* btn, lv_event_t event) { if(event == LV_EVENT_SHORT_CLICKED) { if(ebook_state.current_page > 0) { // 先設置新內容再動畫 ebook_state.current_page--; update_ebook_display(); // 從左側滑入動畫 lv_obj_set_x(ebook_state.page_label, -lv_obj_get_width(lv_obj_get_parent(ebook_state.page_label))); ebook_page_anim(ebook_state.page_label, -lv_obj_get_width(lv_obj_get_parent(ebook_state.page_label)), 0); } } } // 下一頁事件 static void ebook_next_event_cb(lv_obj_t* btn, lv_event_t event) { if(event == LV_EVENT_SHORT_CLICKED) { if(ebook_state.current_page < ebook_state.total_pages - 1) { ebook_state.current_page++; update_ebook_display(); // 從右側滑入動畫 lv_obj_set_x(ebook_state.page_label, lv_obj_get_width(lv_obj_get_parent(ebook_state.page_label))); ebook_page_anim(ebook_state.page_label, lv_obj_get_width(lv_obj_get_parent(ebook_state.page_label)), 0); } } }
2.5功能說明
支持左右滑動翻頁,滑動距離大于30像素且時間小于300ms時觸發
屏幕兩側的箭頭按鈕提供物理翻頁功能
使用LVGL動畫實現平滑的翻頁效果
底部顯示當前頁碼和總頁數
使用英文字體內容顯示(中文字體需要進一步優化取模)
三、零知IDE配置
3.1 項目設置
打開零知IDE,創建新項目
選擇正確的開發板型號(零知增強板)
添加以下庫依賴:
LVGL
ILI9486驅動
XPT2046觸摸驅動
3.2LCD屏幕驅動和初始化
/* 與LCD驅動關聯 */ void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) { u16 height,width; u16 i,j; width=area->x2 - area->x1+1; //得到填充的寬度 height=area->y2 - area->y1+1; //高度 for(i=0;ix1,area->y1+i); //設置光標位置 LCD_WriteRAM_Prepare(); //開始寫入GRAM for(j=0;jLCD_RAM=color_p->full;//寫入數據 color_p++; } } lv_disp_flush_ready(disp); } /* 中斷 ms */ static void lv_tick_handler(HardwareTimer*) { lv_tick_inc(LVGL_TICK_PERIOD); } void lvgl_setup() { lv_init(); lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10); lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.hor_res = LV_HOR_RES_MAX; disp_drv.ver_res = LV_VER_RES_MAX; disp_drv.flush_cb = my_disp_flush; disp_drv.buffer = &disp_buf; lv_disp_drv_register(&disp_drv); lv_indev_drv_t indev_drv; lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_POINTER; indev_drv.read_cb = my_touchpad_read; lv_indev_drv_register(&indev_drv); MyTim = new HardwareTimer(TIM2); MyTim->setMode(2, TIMER_OUTPUT_COMPARE); MyTim->setOverflow(1000/LVGL_TICK_PERIOD, HERTZ_FORMAT); MyTim->attachInterrupt(lv_tick_handler); MyTim->resume(); }
四、演示效果
4.1 功能演示
打開電子書應用,顯示第一頁內容
向右滑動:切換到上一頁內容
向左滑動:切換到下一頁內容
進度更新:底部頁碼隨翻頁自動更新
4.2 視頻演示
https://www.bilibili.com/video/BV19DKgzSEir/?spm_id_from=333.1387.homepage.video_card.click&vd_source=a31e3d8d8ce008260eee442534c2f63d
4.3 性能指標
項目 | 數值 | 說明 |
---|---|---|
翻頁響應時間 | < 100ms | 從觸摸到頁面開始動畫的時間 |
動畫幀率 | 30 FPS | 翻頁動畫流暢度 |
內存占用 | 42KB | 包括LVGL和電子書數據 |
刷新率 | 30Hz | 顯示屏刷新頻率 |
五、常見問題解決
5.1觸摸不靈敏
解決方案
檢查觸摸屏校準數據
增加觸摸檢測閾值
bool my_touchpad_read(lv_indev_drv_t * indev, lv_indev_data_t * data) { static lv_coord_t last_x = 0; static lv_coord_t last_y = 0; data->state = ts.touched() ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL; if(data->state == LV_INDEV_STATE_PR){ TS_Point p = ts.getPoint(); last_x = LV_HOR_RES-(p.y *LV_HOR_RES)/4095; last_y = (p.x *LV_VER_RES)/4095; Serial.print("touched:"); Serial.print(last_x);Serial.print(",");Serial.println(last_y); } data->point.x = last_x; data->point.y = last_y; return false; }
5.2翻頁卡頓
優化建議
減少頁面內容長度
使用LVGL的局部刷新功能
優化動畫參數
lv_anim_set_time(&a, 300, 0); // 兼容舊版API:設置持續時間和延遲
六、總結與擴展
6.1 實現總結
本教程實現了電子書閱讀器的核心功能:中文內容顯示、觸摸翻頁、翻頁動畫效果、閱讀進度顯示
6.2 擴展建議
添加書簽保存和跳轉功能
實現字體大小切換
添加暗色主題保護視力
從SD卡加載電子書文件
6.3 下一步
在下一個系列教程中,我們將實現日歷顯示及切換
?零知開源是一個真正屬于國人自己的開源軟硬件平臺,在開發效率上超越了Arduino平臺并且更加容易上手,大大降低了開發難度。
?零知開源在軟件方面提供了完整的學習教程和豐富示例代碼,讓不懂程序的工程師也能非常輕而易舉的搭建電路來創作產品,測試產品。快來動手試試吧!
?訪問零知開源平臺,獲取更多實戰項目和教程資源吧!
www.lingzhilab.com
審核編輯 黃宇
-
顯示屏
+關注
關注
28文章
4604瀏覽量
76375 -
STM32F4
+關注
關注
3文章
203瀏覽量
29039
發布評論請先 登錄
零知開源——STM32F1驅動BMP581壓強傳感器使用SPI實現ST7789顯示的環境監測系統
零知開源——基于STM32F407VET6零知增強板的四路獨立計時器
零知開源——STM32F4實現ILI9486顯示屏UI界面系列教程(四):相冊預覽和大圖功能
零知開源——STM32F4實現ILI9486顯示屏UI界面系列教程(四):相冊預覽和大圖功能

零知開源——STM32F4實現ILI9486顯示屏UI界面系列教程(三):記事本功能實現
零知開源——STM32F4實現ILI9486顯示屏UI界面系列教程(一):電子書閱讀器功能
STM32F3系列、STM32F4系列、STM32L4系列和STM32L4+系列Cortex-M4編程手冊
零知開源——STM32F4驅動MAX31865實現PT100高精度測溫
STM32項目實戰:基于STM32F4的智能大棚溫控系統(LVGL),附項目教程/源碼

評論