電子產(chǎn)業(yè)一站式賦能平臺

PCB聯(lián)盟網(wǎng)

搜索
查看: 1136|回復(fù): 0
收起左側(cè)

【HarmonyOS HiSpark Wi-Fi IoT 套件試用連連載】我和鴻蒙的親密接觸----點亮OLED

[復(fù)制鏈接]

2607

主題

2607

帖子

7472

積分

高級會員

Rank: 5Rank: 5

積分
7472
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2020-12-23 09:56:32 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
【HarmonyOS HiSpark Wi-Fi IoT 套件試用連連載】我和鴻蒙的親密接觸----點亮OLED,   
本帖最后由 1073865331 于 2020-12-22 20:58 編輯





首先,科普一下OLED的知識:      OLED,即有機發(fā)光二極管 ( O r gan i c Ligh t - Em itti ng D i ode ) ,又稱為有機電激光顯示 ( O r gan i c El e c t r o l u mi ne s ence    D i sp l a y , O E L D ) 。 O L E D 由于同時具備自發(fā)光,不需背光源、對比度高、 厚度薄、視角廣、反應(yīng)速度快、可用于撓曲性面板、使用溫度范圍廣、構(gòu)造及制程較簡單等優(yōu)異之特性,被認為是下一代的平面顯示器新興應(yīng)用技術(shù)。      LCD 都需要背光,而OLED 不需要,因為它是自發(fā)光的。這樣同樣的顯示,OLED 效果要來得好一些。以目前的技術(shù),OLED 的尺寸還難以大型化,但是分辨率確可以做到很高。在本章中,我們使用的是ALINETEK 的OLED 顯示模塊,該模塊有以下特點: 1) 模塊有單色和雙色兩種可選,單色為純藍色,而雙色則為黃藍雙色。 2) 尺寸小,顯示尺寸為 0.96 寸,而模塊的尺寸僅為 27mm*26mm 大小。 3) 高分辨率,該模塊的分辨率為 128*64。 4) 多種接口方式,該模塊提供了總共 4 種接口包括:6800、8080 兩種并行接口方式、4 線 SPI 接口方式以及 IIC 接口方式(只需要 2 根線就可以控制 OLED 了!)。      wifiiot套件上的顯示模塊使用的是IIC方式,通過SCL和SDA就可以跟MCU進行通信,進而顯示信息到oled屏幕上。       在這里,我們先看一下原理圖:

原理圖.png (98.29 KB, 下載次數(shù): 0)

下載附件  保存到相冊  

昨天 20:15 上傳 從原理可以獲知 OLED模塊使用的是GPIO13和GPIO14。 那么現(xiàn)在就要開始操作了。首先還是在app目錄下新建一個文件夾oled_example,還有新建oled.c和BUILD.gn,具體如下:

目錄結(jié)構(gòu).png (19.72 KB, 下載次數(shù): 0)

下載附件  保存到相冊  

昨天 20:22 上傳 由于這里的端口是屬于端口復(fù)用狀態(tài),所以需要修改原來的代碼,將IIC屬性復(fù)用到GPIO13和GPIO14。這里就是需要來到vendor\hisi\hi3861\hi3861\app\wifiiot_app\init\app_io_init.c 文件中,把初始化IIC引腳的代碼修改如下:

  • #ifdef CONFIG_I2C_SUPPORT
      

  •   
  •     /* I2C IO復(fù)用也可以選擇3/4; 9/10,根據(jù)產(chǎn)品設(shè)計選擇 */
      

  •   
  •     hi_io_set_func(HI_IO_NAME_GPIO_13, HI_IO_FUNC_GPIO_13_I2C0_SDA);
      

  •   
  •     hi_io_set_func(HI_IO_NAME_GPIO_14, HI_IO_FUNC_GPIO_14_I2C0_SCL);
      

  •   
  • #endif

復(fù)制代碼 接下來還需要開啟IIC功能,具體需要修改文件vendor\hisi\hi3861\hi3861\build\config\usr_config.mk 增加CONFIG_I2C_SUPPORT = y



通過以上的準備工作,就可以編寫我們的函數(shù)了。

在這里是借鑒連志安老師的帖子和代碼,在這里謝謝連老師。

其實我們最主要是調(diào)用海思寫好的接口函數(shù),所以這里把關(guān)鍵的函數(shù)列出來即可。



  • hi_u32 my_i2c_write(hi_i2c_idx id, hi_u16 device_addr, hi_u32 send_len)
      
  • {
      
  •     hi_u32 status;
      
  •     hi_i2c_data es8311_i2c_data = { 0 };
      

  •   
  •     es8311_i2c_data.send_buf = g_send_data;
      
  •     es8311_i2c_data.send_len = send_len;
      
  •     status = hi_i2c_write(id, device_addr, &es8311_i2c_data);
      
  •     if (status != HI_ERR_SUCCESS) {
      
  •         printf(“===== Error: I2C write status = 0x%x! =====\r\n“, status);
      
  •         return status;
      
  •     }
      

  •   
  •     return HI_ERR_SUCCESS;
      
  • }

復(fù)制代碼 這里就是調(diào)用海思芯片的hi_i2c_write函數(shù)進行實現(xiàn),我們只需要基于這個基礎(chǔ)上進行打包方便我們調(diào)用即可了。

OLED模板需要寫命令和寫數(shù)據(jù)操作,所以這里我們需要分別定義這兩個函數(shù),函數(shù)如下:



  • **********************************************/

復(fù)制代碼 便于兼容性,這里我們通過定義一個OLED_WR_Byte函數(shù)改變形參來選擇寫數(shù)據(jù)還是寫命令,代碼如下:



  • void OLED_WR_Byte(unsigned dat,unsigned cmd)
      
  • {
      
  •         if (cmd)
      
  •         {
      
  •         Write_IIC_Data(dat);
      
  •         }
      
  •         else {
      
  •         Write_IIC_Command(dat);
      
  •         }
      
  • }

復(fù)制代碼 在這時,我們通過寫命令來驅(qū)動OLED了。具體寫什么命令,這得看數(shù)據(jù)手冊了。我把OLED模塊的數(shù)據(jù)手冊放在附件中去,有興趣的可以下載看看。這里直接列出:



  • void oled_init(void)
      
  • {
      
  •     OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
      
  •         OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
      
  •         OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
      
  •         OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM display Start Line (0x00~0x3F)
      
  •         OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
      
  •         OLED_WR_Byte(0xCF,OLED_CMD);// Set SEG Output Current Brightness
      
  •         OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
      
  •         OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
      
  •         OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
      
  •         OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
      
  •         OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
      
  •         OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset        Shift Mapping RAM Counter (0x00~0x3F)
      
  •         OLED_WR_Byte(0x00,OLED_CMD);//-not offset
      
  •         OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
      
  •         OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
      
  •         OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
      
  •         OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
      
  •         OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
      
  •         OLED_WR_Byte(0x12,OLED_CMD);
      
  •         OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
      
  •         OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
      
  •         OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
      
  •         OLED_WR_Byte(0x02,OLED_CMD);//
      
  •         OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
      
  •         OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
      
  •         OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
      
  •         OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
      
  •         OLED_WR_Byte(0xAF,OLED_CMD);
      
  • }

復(fù)制代碼 跟著操作就好了,發(fā)送這些命令就相當(dāng)于讓OLED模塊準備好了。下面你就得通過寫命令和寫數(shù)據(jù)的形式結(jié)合,編寫功能函數(shù),例如OLED的畫點函數(shù),這里的畫點函數(shù)我們是通過一個BUF進行緩存的,每次都是通過把這個大數(shù)組進行寫入實現(xiàn)頁面刷新,具體如下:



  • u8 OLED_GRAM[144][8];

復(fù)制代碼 void OLED_Refresh(void)

{

     u8 i,n;

     for(i=0;i<8;i++)

     {

        OLED_WR_Byte(0xb0+i,OLED_CMD); //設(shè)置行起始地址

        OLED_WR_Byte(0x00,OLED_CMD);   //設(shè)置低列起始地址

        OLED_WR_Byte(0x10,OLED_CMD);   //設(shè)置高列起始地址

        for(n=0;n<128;n++)

          OLED_WR_Byte(OLED_GRAM[n]
,OLED_DATA);
   }
}

//畫點
//x:0~127
//y:0~63
void OLED_DrawPoint(u8 x,u8 y)
{
         u8 i,m,n;
         i=y/8;
         m=y%8;
         n=1<<m;
         OLED_GRAM[x]|=n;
}在這個畫點函數(shù)的基礎(chǔ)上,我們就可以干很多事情了。例如,顯示字符函數(shù)OLED_ShowChar,先列出函數(shù):


  

       
  • //在指定位置顯示一個字符,包括部分字符
      
       
  • //x:0~127
      
       
  • //y:0~63
      
       
  • //size:選擇字體 12/16/24
      
       
  • //取模方式 逐列式
      
       
  • void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1)
      
       
  • {
      
       
  •         u8 i,m,temp,size2,chr1;
      
       
  •         u8 y0=y;
      
       
  •         size2=(size1/8+((size1%8)?1:0))*(size1/2);  //得到字體一個字符對應(yīng)點陣集所占的字節(jié)數(shù)
      
       
  •         chr1=chr-\“ \“;  //計算偏移后的值
      
       
  •         for(i=0;i<size2;i++)
      
       
  •         {
      
       
  •                 //temp=asc2_1206[chr1];
      
       
  •                 if(size1==12)
      
       
  •         {temp=asc2_1206[chr1];} //調(diào)用1206字體
      
       
  •                 else if(size1==16)
      
       
  •         {temp=asc2_1608[chr1];} //調(diào)用1608字體
      
       
  •                 else return;
      
       

  •   
       
  •         for(m=0;m<8;m++)           //寫入數(shù)據(jù)
      
       
  •         {
      
       
  •             if(temp&0x80)OLED_DrawPoint(x,y);
      
       
  •             else OLED_ClearPoint(x,y);
      
       
  •             temp<<=1;
      
       
  •             y++;
      
       
  •             if((y-y0)==size1)
      
       
  •             {
      
       
  •                 y=y0;
      
       
  •                 x++;
      
       
  •                 break;
      
       
  •             }
      
       
  •                 }
      
       
  •   }
      
       
  • }
      
復(fù)制代碼 在這里就有一個漢字取模的知識,由于字符型數(shù)據(jù)已經(jīng)是很常見的了,可以通過下載正點原子的OLED顯示實驗獲得ASCII碼表,但是這里也簡單列一下如何得到?
這里我們介紹一個款很好的字符提取軟件:
PCtoLCD2002 完美版。該軟件可以提供各種字符,包括漢字 ( 字體和大小都可以自己設(shè)置 ) 陣 提取,且取模方式可以設(shè)置好幾種,常用的取模方式,該軟件都支持。該軟件還支持圖形模式, 也就是用戶可以自己定義圖片的大小,然后畫圖,根據(jù)所畫的圖形再生成點陣數(shù)據(jù),這功能在 制作圖標或圖片的時候很有用。 該軟件的界面如圖 所示:

軟件.png (41.67 KB, 下載次數(shù): 0)
下載附件  保存到相冊  
昨天 20:53 上傳
PCtoLCD2002 軟件界面
然后我們選擇設(shè)置,在設(shè)置里面設(shè)置取模方式如圖 所示:

取模.png (25.81 KB, 下載次數(shù): 0)
下載附件  保存到相冊  
昨天 20:54 上傳
設(shè)置取模方式 上圖設(shè)置的取模方式,在右上角的取模說明里面有,即:從第一列開始向下每取 8 個點作 為一 個 字 節(jié) , 如 果 最 后 不 足 8 個 點 就補 滿 8 位 。 取模 順序 是 從 高 到 低 , 即 第 一個 點作 為 最 高 位。如*        取為 10000000 。 其實 就 是 按如 圖 所 示的 這 種 方 式:

過程.png (14.46 KB, 下載次數(shù): 0)
下載附件  保存到相冊  
昨天 20:54 上傳
取模方式圖解 從上到下,從左到右,高位在前。我們按這樣的取模方式,然后把 ASCII 字符集按 12*6 大小、16*8 和 24*12 大小取模出來 ( 對應(yīng)漢字大小為 12*12 、16*16 和 24*24 ,字符的只有漢字 的一半大! ) ,保存在 oledfont.h 里面,每個 12*6 的字符占用 12 個字節(jié),每個 16*8 的字符占用 16 個字節(jié),每個 24*12 的字符占用 36 個字節(jié)。
以上操作需要自行完成。然后我們回到oled.c中

  

       
  • void my_oled_demo(void)
      
       
  • {
      
       
  •     //初始化
      
       
  •     hi_i2c_init(HI_I2C_IDX_0, 100000); /* baudrate: 100000 */
      
       

  •   
       
  • oled_init();
      
復(fù)制代碼 接下來看一下同級目錄下的BUILD.gn

  

       
  • static_library(“oled_demo“) {
      
       
  •     sources = [
      
       
  •         “oled.c“
      
       
  •     ]
      
       

  •   
       
  •     include_dirs = [
      
       
  •         “//utils/native/lite/include“,
      
       
  •         “//kernel/liteos_m/components/cmsis/2.0“,
      
       
  •     ]
      
       
  • }
      
復(fù)制代碼 到這里就完成了。
編譯燒錄就不多說了;乜次业奶印


回復(fù)

使用道具 舉報

發(fā)表回復(fù)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則


聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表