基於事件型表驅動法選單框架之小熊派簡易氣體探測器實戰專案開發(中)

2020-10-21 17:01:14

上次我們分享了事件驅動型的選單框架,也實現了一個基本的小專案,如下:

基於事件型表驅動法選單框架之小熊派簡易氣體探測器實戰專案開發(上)

但是怎麼看怎麼都覺得介面不爽,單純顯示文字的方式實在是太單調了,如果想要顯示顏色豐富的圖片,MCU資源受限又很難直接在程式中直接定義圖片大陣列。

於是,我選擇在SD卡中放圖片,通過Fatfs去讀取SD卡中的圖片來進行顯示,圖片都是我自己在阿里相簿上找的開源素材,然後用PS自己P的:

廢話不多說,來看看實際效果吧!演示視訊如下:

這樣看起來效果就舒服一點啦。

1、新增功能項

本節分享的內容相較於上篇文章修改/增加了如下功能:

底層設定

  • 修改LCD暫存器,提升LCD刷屏速度

  • 增加Fatfs、SD卡讀寫功能

應用邏輯

  • 增加模擬長按開機識別

  • 增加開機LOGO以及其它UI的顯示

  • 增加選單(閾值設定、設定、偵錯模式、儀器資訊)

1.1、關於底層設定

1.1.1、提升屏重新整理速度

由於要刷圖,所以只能想辦法儘量提升屏的重新整理速度,於是在LCD手冊裡有這麼一個暫存器,可以提升屏的重新整理速度:

在LCD驅動初始化程式碼裡,這個暫存器預設設定的是60Hz,也就是0x0F這個值

/* Frame Rate Control in Normal Mode */
LCD_Write_Cmd(0xC6);
// LCD_Write_Data(0x0F); //60HZ
LCD_Write_Data(0x01);  //111Hz 提升屏的重新整理速度

本來設定為0x00為119Hz,但是設定完LCD就黑畫面了,改為0x01就不會,目前沒找到具體原因,將就著用吧。

1.1.2、增加Fatfs、SD卡讀寫功能

之前也分享了設定方法,詳情可以看以下文章:

基於小熊派SD卡+Fatfs+移植開源iniparse解析庫並使用

1.2、關於應用邏輯

1.2.1、增加模擬長按開機識別

由於開機前需要載入整幅圖片,會存在重新整理慢的問題,我們可以先關掉LCD背光,然後等圖刷完了再開背光,這樣看到就是一張完整的圖,這個過程可以用長按一個按鍵開機的方式來代替,程式碼實現如下:

void PowerOn(void)
{
    static uint32_t power_press_count = 0;
    HAL_Delay(500);
    while(1)
    {
        if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 0)
        {
            power_press_count ++;
      
            if(power_press_count >= 100)
            {
                //開指示燈
                HAL_GPIO_WritePin(GPIOC, LED_Pin, GPIO_PIN_SET);
                while(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 0)
                {
                    HAL_Delay(10);
                }
                break;
            }
        }
        else
        {
            power_press_count = 0;
        }

        HAL_Delay(10);
    }
}

然後在顯示開機LOGO前呼叫即可,顯示開機LOGO呼叫完畢後開啟背光顯示。

1.2.2、增加開機LOGO以及其它UI的顯示

圖片資源採用的是24位元bmp圖,這些圖片都存放在SD卡根目錄下的LOGO資料夾的子資料夾中:

(1)開機LOGO

(2)主頁面UI

(3)檢測頁面動畫LOGO

顯示介面移植了硬石科技提供的bsp_bmp.c,他們用的是320*480的RGB屏,小熊派用的是240*240的屏,根據現有的屏我做了一些修改:

uint8_t pColorData[960];     /* 一行真彩色資料快取 320 * 3 = 960 */
//uint8_t pColorData[720];     /* 一行真彩色資料快取 240 * 3 = 720 */

顯示bmp函數:

/**
  * 函數功能: 顯示bmp圖片, 24位元真彩色
  * 輸入引數: x:顯示圖片左上角x軸座標
  *           y:顯示圖片左上角y軸座標
  *           pic_name:顯示圖片檔名稱
  * 返 回 值: 無
  * 說    明:圖片寬度和高度根據圖片大小而定
  */
void Lcd_show_bmp(uint16_t x, uint16_t y,char *pic_name)
{
 uint16_t i, j, k;
 int width, height, l_width;
  
 BMP_FileHeader FileHeader;
 BMP_InfoHeader InfoHeader;
  
/*-------------------------------------------------------------------------------------------------------*/
 f_res=f_open(&file,pic_name, FA_OPEN_EXISTING|FA_READ); 
 if(f_res == FR_OK)
 {
  BMP_DEBUG_PRINTF("Open file success\r\n");

  /* 讀取檔案頭資訊  兩個位元組*/         
  f_res=f_read(&file,&FileHeader,sizeof(BMP_FileHeader),&f_num);     
    
  /* 判斷是不是bmp檔案 "BM"*/
  if(FileHeader.bfType!=0x4d42)
  {
   BMP_DEBUG_PRINTF("file is not .bmp file!\r\n");
   return;
  }
  else
  {
   BMP_DEBUG_PRINTF("Ok this is .bmp file\r\n"); 
  }
  /* 讀取BMP檔案頭資訊*/      
  showBmpHeader(&FileHeader);
   
  /* 讀取點陣圖資訊頭資訊 */
  f_res=f_read(&file,&InfoHeader,sizeof(BMP_InfoHeader),&f_num);      
  showBmpInforHeader(&InfoHeader);
 }    
 else
 {
  BMP_DEBUG_PRINTF("file open fail!\r\n");
  return;
 }  
/*-------------------------------------------------------------------------------------------------------*/
 width  = InfoHeader.biWidth;
 height = InfoHeader.biHeight; 
  
 /* 計算點陣圖的實際寬度並確保它為32的倍數 */
 l_width = WIDTHBYTES(width* InfoHeader.biBitCount);
  
 if((l_width>960)||(InfoHeader.biBitCount!=24))
 {
  BMP_DEBUG_PRINTF("\n SORRY, PIC IS TOO BIG (X<=320 and bit!=16)\n");
  return;
  }
  f_lseek(&file,FileHeader.bfOffBits);
   
  if(InfoHeader.biBitCount == 24)
  {
    for(i=0;i<height;++i)
    {
      /* 開一個圖片大小的視窗*/
      LCD_OpenWindow(x, y+height-i-1, width, 1);
   LCD_Write_Cmd(0x2C);
      /* 讀取一行bmp的資料到陣列pColorData裡面 */
      f_read(&file,pColorData,l_width,&f_num);      
      for(j=0;j<width;j++)               //一行有效資訊
      {        
        k = j*3;                  //一行中第K個畫素的起點        
        //LCD_WRITE_DATA(RGB24TORGB16(pColorData[k+2],pColorData[k+1],pColorData[k])); //寫入LCD-GRAM
        //這裡呼叫的是寫一次寫兩個位元組的函數
        LCD_Write_2Byte(RGB24TORGB16(pColorData[k+2],pColorData[k+1],pColorData[k]));
      }
    }
  }
 f_close(&file);    
}

修改完後在如果需要圖片顯示則呼叫如下介面:

#define START_LOGO "0:/UI/start_logo/start_logo.bmp"

//最開始的時候呼叫掛載,只掛載一次就好了
//在序列FLASH掛載檔案系統,檔案系統掛載時會對序列FLASH初始化
f_res = f_mount(&fs, (TCHAR const*)SDPath, 1);
if(f_res == FR_OK)
  printf("》SD卡檔案系統掛載成功\n");


//以後只需要呼叫顯示即可
Lcd_show_bmp(0,0,START_LOGO);

注意:圖片的路徑是SD卡下存放的路徑,一定要選對。

1.2.2、增加選單(閾值設定、設定、偵錯模式、儀器資訊)

在主頁面長按右鍵進入選單:

此時按左鍵可以切換選項,短按右鍵進入某一選單項,長按右鍵退出回到主頁面,這裡只實現了儀器資訊,其它專案還沒有實現,但要新增也非常簡單,期待後期分享。

選單的實現也很簡單,選單項切換的邏輯和主頁面的切換邏輯是一樣的:

其餘功能:後續還可以做報警記錄儲存、資料上傳到OneNet或者華為雲等平臺、引數設定等等,總之這個專案可拓展性非常強,這些功能將在本專案開發的下一章節持續進行拓展並分享,歡迎及時關注我的碼雲倉庫與微信公眾號文章更新。

本節程式碼已同步到碼雲的程式碼倉庫中:

獲取方法如下:

1、新建一個資料夾

2、使用git clone遠端獲取小熊派所有案例程式碼

我還將之前做的一些專案以及練習例程在近期內全部上傳完畢,與大家一起分享交流:

公眾號粉絲福利時刻

這裡我給大家申請到了福利,本公眾號讀者購買小熊派開發板可享受9折優惠,有需要購買小熊派以及騰訊物聯網開發板的朋友,淘寶搜尋即可,跟客服說你是公眾號:嵌入式雲IOT技術圈 的粉絲,立享9折優惠!

往期精彩

STM32系統bootloader應用

【C進階】拿著"sizeof這些用法和坑"去吹牛吧!

基於事件型表驅動法選單框架之小熊派簡易氣體探測器實戰專案開發(上)

上海出差之行--領略外灘美景、RT-Thread總部之旅、嵌友面基、返程記錄

覺得本次分享的文章對您有幫助,隨手點[在看]並轉發分享,也是對我的支援。

Engineer-Bruce_Yang CSDN認證部落格專家 嵌入式硬體 微控制器 arm開發
本科畢業於華南理工大學,現美國卡羅爾工商管理碩士研究生在讀,曾就職於世界名企偉易達、聯發科技等,多年嵌入式產品開發經驗,在智慧玩具、安防產品、平板電腦、手機開發有豐富的實戰開發經驗,現任深圳市雲之手科技有限公司副總經理、研發總工程師。