本教程將詳細(xì)介紹如何在零知增強(qiáng)板上使用3.5寸ILI9486顯示屏實(shí)現(xiàn)電子書(shū)閱讀器功能。我們將使用LVGL庫(kù)構(gòu)建用戶(hù)界面,并實(shí)現(xiàn)翻頁(yè)、進(jìn)度顯示等核心功能。
一、硬件連接
1.1 硬件組件清單
| 組件名稱(chēng) | 規(guī)格參數(shù) | 備注 | 
|---|---|---|
| 零知開(kāi)發(fā)板 | STM32F407VGT6 | 主控制器 | 
| ILI9486顯示屏 | 3.5英寸TFT LCD (480×320) | 電阻觸摸屏 | 
| SD卡模塊 | SPI接口,支持FAT32 | 存儲(chǔ)電子書(shū)文件 | 
| XPT2046觸摸控制器 | SPI接口 | 集成在顯示屏模塊上 | 
| W25Q128 Flash芯片 | 128M-bit (16MB) | 存儲(chǔ)字體和系統(tǒng)文件 | 
| USB數(shù)據(jù)線 | 直流供電 | 系統(tǒng)電源 | 
1.2 連接方式
零知增強(qiáng)板設(shè)計(jì)有專(zhuān)門(mén)的顯示屏接口,3.5寸ILI9486顯示屏可直接插入增強(qiáng)板,無(wú)需額外連線
	
電子書(shū)閱讀器界面效果圖:
	

二、軟件UI組件實(shí)現(xiàn)
2.1 核心數(shù)據(jù)結(jié)構(gòu)
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]); // 電子書(shū)翻頁(yè)事件回調(diào) 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; // 觸摸起始點(diǎn) 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. 完全兼容的觸摸事件處理(替代手勢(shì)事件)
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);
                
                // 計(jì)算滑動(dòng)距離和時(shí)間
                lv_coord_t dx = touch_end.x - touch_start.x;
                uint32_t duration = lv_tick_elaps(touch_time);
                
                // 判斷有效滑動(dòng) (水平移動(dòng)>30像素且時(shí)間300ms)
                if(abs(dx) > 30 && duration < 300) {
                    if(dx > 0) {
                        // 向右滑動(dòng):上一頁(yè)
                        if(ebook_state.current_page > 0) {
                            ebook_prev_event_cb(NULL, LV_EVENT_SHORT_CLICKED);
                        }
                    } else {
                        // 向左滑動(dòng):下一頁(yè)
                        if(ebook_state.current_page < ebook_state.total_pages - 1) {
                            ebook_next_event_cb(NULL, LV_EVENT_SHORT_CLICKED);
                        }
                    }
                }
            }
            break;
        }
    }
}
// 更新電子書(shū)顯示
static void update_ebook_display() {
    // 重置位置避免動(dòng)畫(huà)殘留
    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);
    
    // 初始化電子書(shū)狀態(tài)
    ebook_state.current_page = 0;
    ebook_state.total_pages = ebook_page_count;
    ebook_state.is_english = true; // 默認(rèn)英文
    ebook_state.touch_start.x = 0;
    ebook_state.touch_start.y = 0;
    
    // 創(chuàng)建內(nèi)容容器(支持觸摸檢測(cè))
    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);
    
    // 創(chuàng)建頁(yè)面標(biāo)簽
    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);
    
    // 創(chuàng)建進(jìn)度標(biāo)簽
    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 翻頁(yè)功能實(shí)現(xiàn)
// 翻頁(yè)動(dòng)畫(huà)函數(shù) (兼容舊版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:設(shè)置持續(xù)時(shí)間和延遲
    lv_anim_set_exec_cb(&a, label, (lv_anim_exec_xcb_t)lv_obj_set_x);  // 兼容舊版API
    lv_anim_create(&a);
}
// 上一頁(yè)事件
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) {
            // 先設(shè)置新內(nèi)容再動(dòng)畫(huà)
            ebook_state.current_page--;
            update_ebook_display();
            
            // 從左側(cè)滑入動(dòng)畫(huà)
            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);
        }
    }
}
// 下一頁(yè)事件
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();
            
            // 從右側(cè)滑入動(dòng)畫(huà)
            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功能說(shuō)明
支持左右滑動(dòng)翻頁(yè),滑動(dòng)距離大于30像素且時(shí)間小于300ms時(shí)觸發(fā)
屏幕兩側(cè)的箭頭按鈕提供物理翻頁(yè)功能
使用LVGL動(dòng)畫(huà)實(shí)現(xiàn)平滑的翻頁(yè)效果
底部顯示當(dāng)前頁(yè)碼和總頁(yè)數(shù)
使用英文字體內(nèi)容顯示(中文字體需要進(jìn)一步優(yōu)化取模)
三、零知IDE配置
3.1 項(xiàng)目設(shè)置
打開(kāi)零知IDE,創(chuàng)建新項(xiàng)目
選擇正確的開(kāi)發(fā)板型號(hào)(零知增強(qiáng)板)
添加以下庫(kù)依賴(lài):
LVGL
ILI9486驅(qū)動(dòng)
XPT2046觸摸驅(qū)動(dòng)
3.2LCD屏幕驅(qū)動(dòng)和初始化
/* 與LCD驅(qū)動(dòng)關(guān)聯(lián) */
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);           //設(shè)置光標(biāo)位置
                LCD_WriteRAM_Prepare();     //開(kāi)始寫(xiě)入GRAM
                for(j=0;jLCD_RAM=color_p->full;//寫(xiě)入數(shù)據(jù)
                        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 功能演示
打開(kāi)電子書(shū)應(yīng)用,顯示第一頁(yè)內(nèi)容
向右滑動(dòng):切換到上一頁(yè)內(nèi)容
向左滑動(dòng):切換到下一頁(yè)內(nèi)容
進(jìn)度更新:底部頁(yè)碼隨翻頁(yè)自動(dòng)更新
4.2 視頻演示
https://www.bilibili.com/video/BV19DKgzSEir/?spm_id_from=333.1387.homepage.video_card.click&vd_source=a31e3d8d8ce008260eee442534c2f63d
4.3 性能指標(biāo)
| 項(xiàng)目 | 數(shù)值 | 說(shuō)明 | 
|---|---|---|
| 翻頁(yè)響應(yīng)時(shí)間 | < 100ms | 從觸摸到頁(yè)面開(kāi)始動(dòng)畫(huà)的時(shí)間 | 
| 動(dòng)畫(huà)幀率 | 30 FPS | 翻頁(yè)動(dòng)畫(huà)流暢度 | 
| 內(nèi)存占用 | 42KB | 包括LVGL和電子書(shū)數(shù)據(jù) | 
| 刷新率 | 30Hz | 顯示屏刷新頻率 | 
五、常見(jiàn)問(wèn)題解決
5.1觸摸不靈敏
解決方案
檢查觸摸屏校準(zhǔn)數(shù)據(jù)
增加觸摸檢測(cè)閾值
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翻頁(yè)卡頓
優(yōu)化建議
減少頁(yè)面內(nèi)容長(zhǎng)度
使用LVGL的局部刷新功能
優(yōu)化動(dòng)畫(huà)參數(shù)
lv_anim_set_time(&a, 300, 0); // 兼容舊版API:設(shè)置持續(xù)時(shí)間和延遲
六、總結(jié)與擴(kuò)展
6.1 實(shí)現(xiàn)總結(jié)
本教程實(shí)現(xiàn)了電子書(shū)閱讀器的核心功能:中文內(nèi)容顯示、觸摸翻頁(yè)、翻頁(yè)動(dòng)畫(huà)效果、閱讀進(jìn)度顯示
6.2 擴(kuò)展建議
添加書(shū)簽保存和跳轉(zhuǎn)功能
實(shí)現(xiàn)字體大小切換
添加暗色主題保護(hù)視力
從SD卡加載電子書(shū)文件
6.3 下一步
在下一個(gè)系列教程中,我們將實(shí)現(xiàn)日歷顯示及切換
	?零知開(kāi)源是一個(gè)真正屬于國(guó)人自己的開(kāi)源軟硬件平臺(tái),在開(kāi)發(fā)效率上超越了Arduino平臺(tái)并且更加容易上手,大大降低了開(kāi)發(fā)難度。
	?零知開(kāi)源在軟件方面提供了完整的學(xué)習(xí)教程和豐富示例代碼,讓不懂程序的工程師也能非常輕而易舉的搭建電路來(lái)創(chuàng)作產(chǎn)品,測(cè)試產(chǎn)品。快來(lái)動(dòng)手試試吧!
	?訪問(wèn)零知開(kāi)源平臺(tái),獲取更多實(shí)戰(zhàn)項(xiàng)目和教程資源吧!
	www.lingzhilab.com
	審核編輯 黃宇
- 
                                顯示屏
                                +關(guān)注
關(guān)注
30文章
4658瀏覽量
78338 - 
                                STM32F4
                                +關(guān)注
關(guān)注
3文章
204瀏覽量
29739 
發(fā)布評(píng)論請(qǐng)先 登錄
零知開(kāi)源——STM32F4結(jié)合BMP581氣壓傳感器實(shí)現(xiàn)ST7789中文顯示教程
    
零知開(kāi)源——STM32F4結(jié)合BMP581氣壓傳感器實(shí)現(xiàn)ST7789中文顯示教程
零知開(kāi)源——STM32F1驅(qū)動(dòng)BMP581壓強(qiáng)傳感器使用SPI實(shí)現(xiàn)ST7789顯示的環(huán)境監(jiān)測(cè)系統(tǒng)
零知開(kāi)源——基于STM32F407VET6零知增強(qiáng)板的四路獨(dú)立計(jì)時(shí)器
零知開(kāi)源——基于STM32F407VET6零知增強(qiáng)板的四路獨(dú)立計(jì)時(shí)器
    
零知開(kāi)源——STM32F4實(shí)現(xiàn)ILI9486顯示屏UI界面系列教程(四):相冊(cè)預(yù)覽和大圖功能
零知開(kāi)源——STM32F4實(shí)現(xiàn)ILI9486顯示屏UI界面系列教程(四):相冊(cè)預(yù)覽和大圖功能
    
零知開(kāi)源——STM32F4實(shí)現(xiàn)ILI9486顯示屏UI界面系列教程(三):記事本功能實(shí)現(xiàn)
零知開(kāi)源——STM32F4實(shí)現(xiàn)ILI9486顯示屏UI界面系列教程(二):日歷功能實(shí)現(xiàn)
零知開(kāi)源——STM32F4實(shí)現(xiàn)ILI9486顯示屏UI界面系列教程(二):日歷功能實(shí)現(xiàn)
    
零知開(kāi)源——STM32F4實(shí)現(xiàn)ILI9486顯示屏UI界面系列教程(一):電子書(shū)閱讀器功能
STM32F3系列、STM32F4系列、STM32L4系列和STM32L4+系列Cortex-M4編程手冊(cè)
零知開(kāi)源——STM32F4驅(qū)動(dòng)MAX31865實(shí)現(xiàn)PT100高精度測(cè)溫
    
零知開(kāi)源——STM32F4驅(qū)動(dòng)MAX31865實(shí)現(xiàn)PT100高精度測(cè)溫
    
          
        
        
零知開(kāi)源——STM32F4實(shí)現(xiàn)ILI9486顯示屏UI界面系列教程(一):電子書(shū)閱讀器功能
                
 
           
            
            
                
            
評(píng)論