0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

STM32移植U8g2圖形庫的方法 實現OLED圖形顯示

碼農愛學習 ? 來源:碼農愛學習 ? 作者:碼農愛學習 ? 2022-06-07 08:29 ? 次閱讀

之前的文章,介紹過ESP8266Arduino IDE環(huán)境中使用U8g2庫,實現OLED上的各種圖形顯示。

本篇,介紹一下U8g2庫如何移植到STM32上,進行OLED的圖形顯示。

本次的實驗硬件為:

STM32:型號為最常見的STM32F103C8T6

OLED:0.96寸OLED,IIC接口(如果是SPI接口,文中也有對應的修改介紹)

1 U8g2簡介

U8g2 是一個用于嵌入式設備的單色圖形庫。U8g2支持單色OLED和LCD,并支持如SSD1306等多種類型的OLED驅動。

U8g2源碼的開源庫地址:https://github.com/olikraus/u8g2

pYYBAGKeIkWAbyNYAADKIaGINn0614.png

2 移植步驟

首先下載U8g2的源碼,因為STM32主要是使用C語言編程,所以只需關注源碼中的C源碼部分,即csrc文件夾下的文件。

2.1 精簡c源碼

U8g2支持多種顯示驅動的屏幕,因為源碼中也包含了各個驅動對應的文件,為了減小整個工程的代碼體積,在移植U8g2時,可以刪除一些無用的文件。

2.1.1 去掉無用的驅動文件

這些驅動文件通常是u8x8_d_xxx.c,xxx包括驅動的型號和屏幕分辨率。ssd1306驅動芯片的OLED,使用u8x8_ssd1306_128x64_noname.c這個文件,其它的屏幕驅動和分辨率的文件可以刪掉。

pYYBAGKeIk6Afkk8AAEKVfzfGYc168.png

2.1.2 精簡u8g2_d_setup.c

由于我的OLED是IIC接口,只留一個本次要用到的u8g2_Setup_ssd1306_i2c_128x64_noname_f就好(如果是SPI接口,需要使用u8g2_Setup_ssd1306_128x64_noname_f這個函數),其它的可以刪掉或注釋掉。

#include "u8g2.h"

/* ssd1306 f */
void u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb)
{
  uint8_t tile_buf_height;
  uint8_t *buf;
  u8g2_SetupDisplay(u8g2, u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_fast_i2c, byte_cb, gpio_and_delay_cb);
  buf = u8g2_m_16_8_f(&tile_buf_height);
  u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation);
}

注意,與這個函數看起來十分相似的函數的有:

u8g2_Setup_ssd1306_128x64_noname_1

u8g2_Setup_ssd1306_128x64_noname_2

u8g2_Setup_ssd1306_128x64_noname_f

u8g2_Setup_ssd1306_i2c_128x64_noname_1

u8g2_Setup_ssd1306_i2c_128x64_noname_2

u8g2_Setup_ssd1306_i2c_128x64_noname_f

其中,前面3個,是給SPI接口的OLED用的,函數最后的數字或字母,代表顯示時的buf大小:

1:128字節(jié)

2:256字節(jié)

f1024字節(jié)

2.1.3 精簡u8g2_d_memory.c

由于用到的u8g2_Setup_ssd1306_i2c_128x64_noname_f函數中,只調用了u8g2_m_16_8_f這個函數,所以留下這個函數,其它的函數一定要刪掉或注釋掉,否則編譯時很可能會提示內存不足?。?!

#include "u8g2.h"

uint8_t *u8g2_m_16_8_f(uint8_t *page_cnt)
{
  #ifdef U8G2_USE_DYNAMIC_ALLOC
  *page_cnt = 8;
  return 0;
  #else
  static uint8_t buf[1024];
  *page_cnt = 8;
  return buf;
  #endif
}

2.2 編寫移植函數

精簡源碼之后,還需要編寫如下的配置函數。

2.2.1 GPIO初始化

對OLED用到的IIC接口進行GPIO的初始化配置:

#define SCL_Pin GPIO_Pin_6
#define SDA_Pin GPIO_Pin_7
#define IIC_GPIO_Port GPIOB
void IIC_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	
	   
	GPIO_InitStructure.GPIO_Pin = SCL_Pin|SDA_Pin;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽輸出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(IIC_GPIO_Port, &GPIO_InitStructure);
}

如果是SPI接口,則初始化對應的SPI接口即可。

2.2.2 u8x8_gpio_and_delay

這個函數也需要自己寫,主要的修改包括:

賦予U8g2相應的延時函數,比如下面的delay_ms和delay_us

為U8g2提供IIC接口的高低電平調用:

U8X8_MSG_GPIO_I2C_CLOCK:IIC的SCL

U8X8_MSG_GPIO_I2C_DATA:IIC的SDA

uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
    switch (msg)
    {
    case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
        __NOP();
        break;
    case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
        for (uint16_t n = 0; n < 320; n++)
        {
            __NOP();
        }
        break;
    case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
        delay_ms(1);
        break;
    case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
        delay_us(5);
        break;                    // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
    case U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pin
		if(arg_int == 1) 
		{
			GPIO_SetBits(IIC_GPIO_Port, SCL_Pin);
		}
		else if(arg_int == 0)
		{
			GPIO_ResetBits(IIC_GPIO_Port, SCL_Pin);  
		}  
        break;                    // arg_int=1: Input dir with pullup high for I2C clock pin
    case U8X8_MSG_GPIO_I2C_DATA:  // arg_int=0: Output low at I2C data pin
        if(arg_int == 1) 
		{
			GPIO_SetBits(IIC_GPIO_Port, SDA_Pin);
		}
		else if(arg_int == 0)
		{
			GPIO_ResetBits(IIC_GPIO_Port, SDA_Pin);  
		} 
        break;                    // arg_int=1: Input dir with pullup high for I2C data pin
    case U8X8_MSG_GPIO_MENU_SELECT:
        u8x8_SetGPIOResult(u8x8, /* get menu select pin state */ 0);
        break;
    case U8X8_MSG_GPIO_MENU_NEXT:
        u8x8_SetGPIOResult(u8x8, /* get menu next pin state */ 0);
        break;
    case U8X8_MSG_GPIO_MENU_PREV:
        u8x8_SetGPIOResult(u8x8, /* get menu prev pin state */ 0);
        break;
    case U8X8_MSG_GPIO_MENU_HOME:
        u8x8_SetGPIOResult(u8x8, /* get menu home pin state */ 0);
        break;
    default:
        u8x8_SetGPIOResult(u8x8, 1); // default return value
        break;
    }
    return 1;
}

如果是SPI接口,可以參考如下寫法:

uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
    switch (msg)
    {
        case U8X8_MSG_GPIO_SPI_DATA:
            lcd_sdin((uint8_t)arg_int); //SPI - MOSI
            break;
        case U8X8_MSG_GPIO_SPI_CLOCK: //SPI - CLK
            lcd_sclk(arg_int);
            break;
        case U8X8_MSG_GPIO_AND_DELAY_INIT:
            oled_init(); //OLED初始化
            Delay(1);
            break;
        case U8X8_MSG_DELAY_MILLI:
            Delay(arg_int); //延時
            break;
        case U8X8_MSG_GPIO_CS: //SPI - CS
            lcd_cs((uint8_t)arg_int);
        case U8X8_MSG_GPIO_DC:
            lcd_dc((uint8_t)arg_int); //SPI - MISO
            break;
        case U8X8_MSG_GPIO_RESET:
            break;
    }
    return 1;
}

可以看出,對于IIC與SPI接口,只有分別進行對應的配置即可。

2.2.3 u8g2Init

U8g2的初始化,需要調用下面這個u8g2_Setup_ssd1306_128x64_noname_f函數,該函數的4個參數含義:

u8g2:傳入的U8g2結構體

U8G2_R0:默認使用U8G2_R0即可(用于配置屏幕是否要旋轉)

u8x8_byte_sw_i2c:使用軟件IIC驅動,該函數由U8g2源碼提供

u8x8_gpio_and_delay:就是上面我們寫的配置函數

void u8g2Init(u8g2_t *u8g2)
{
	u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay);  // 初始化 u8g2 結構體
	u8g2_InitDisplay(u8g2); // 根據所選的芯片進行初始化工作,初始化完成后,顯示器處于關閉狀態(tài)
	u8g2_SetPowerSave(u8g2, 0); // 打開顯示器
	u8g2_ClearBuffer(u8g2);
}

2.2.4 顯示測試函數

使用U8g2提供的測試函數,用于查看顯示效果

void draw(u8g2_t *u8g2)
{
    u8g2_SetFontMode(u8g2, 1); /*字體模式選擇*/
    u8g2_SetFontDirection(u8g2, 0); /*字體方向選擇*/
    u8g2_SetFont(u8g2, u8g2_font_inb24_mf); /*字庫選擇*/
    u8g2_DrawStr(u8g2, 0, 20, "U");
    
    u8g2_SetFontDirection(u8g2, 1);
    u8g2_SetFont(u8g2, u8g2_font_inb30_mn);
    u8g2_DrawStr(u8g2, 21,8,"8");
        
    u8g2_SetFontDirection(u8g2, 0);
    u8g2_SetFont(u8g2, u8g2_font_inb24_mf);
    u8g2_DrawStr(u8g2, 51,30,"g");
    u8g2_DrawStr(u8g2, 67,30,"xb2");
    
    u8g2_DrawHLine(u8g2, 2, 35, 47);
    u8g2_DrawHLine(u8g2, 3, 36, 47);
    u8g2_DrawVLine(u8g2, 45, 32, 12);
    u8g2_DrawVLine(u8g2, 46, 33, 12);
  
    u8g2_SetFont(u8g2, u8g2_font_4x6_tr);
    u8g2_DrawStr(u8g2, 1,54,"github.com/olikraus/u8g2");
}

2.3 源碼加入到MDK編譯

在一個STM32的基礎例程上進行修改。

2.3.1添加u8g2源碼到工程

左側工程目錄添加U8g2源碼,然后再添加U8g2的頭文件搜尋目錄,如下:

pYYBAGKeIlqAS42_AAG_sD-BLpY254.png

2.3.2 主函數

主函數中,首先是IIC的初始化和U8g2的初始化,然后就可以測試U8g2的圖形顯示功能了:

#include "delay.h"
#include "sys.h"
#include "u8g2.h"

int main(void)
{	
	delay_init();
	IIC_Init();
	 
    u8g2_t u8g2;
	u8g2Init(&u8g2);

	while(1)
	{
       u8g2_FirstPage(&u8g2);
       do
       {
			draw(&u8g2);
       } while (u8g2_NextPage(&u8g2));
    }
}

3 測試效果

pYYBAGKeImaAbklYAAES8Ep9QH8703.png

4 總結

本篇介紹了如何將U8g2圖形庫移植到STM32中,其中主要的修改包括:

精簡源碼中的u8g2_d_setup.c和u8g2_d_memory.c

OLED所用IIC接口的GPIO初始化

編寫u8x8_gpio_and_delay和u8g2Init

其中,u8g2_d_memory.c文件一定要去掉無用的函數,否則編譯時會提示內存不足;對于SPI接口的OLED,參考IIC接口進行類似的修改即可。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯系本站處理。 舉報投訴
  • 單片機
    +關注

    關注

    6026

    文章

    44452

    瀏覽量

    630834
  • 嵌入式
    +關注

    關注

    5052

    文章

    18909

    瀏覽量

    300740
  • OLED
    +關注

    關注

    119

    文章

    6158

    瀏覽量

    223495
  • STM32
    +關注

    關注

    2263

    文章

    10846

    瀏覽量

    353701
  • u8g2
    +關注

    關注

    0

    文章

    13

    瀏覽量

    1828
收藏 人收藏

    評論

    相關推薦

    使用MSP430圖形時的設計注意事項

    電子發(fā)燒友網站提供《使用MSP430圖形時的設計注意事項.pdf》資料免費下載
    發(fā)表于 09-03 10:49 ?0次下載
    使用MSP430<b class='flag-5'>圖形</b><b class='flag-5'>庫</b>時的設計注意事項

    【CH32V208開發(fā)板】圖形u8g2oled顯示

    靈活配置),基于 32 位 RISC-V 指令集及架構設計,芯片內部集成了ETH-10M(+PHY)以太網和藍牙。 本篇講述使用u8g2圖形驅動oled
    發(fā)表于 07-29 23:11

    求助,請問ESP32-S2-DevKitM-1開發(fā)板的IIC引腳是哪些?

    購買的ESP32-S2-DevKitM-1,說是有兩路IIC,可是到處找的資料,都沒說是哪些引腳,使用Arduino里的Adafruit_SSD1306或者U8g2對0.96吋OLED
    發(fā)表于 07-01 07:03

    【Vision Board創(chuàng)客營連載體驗】RA8D1-Vision Board 移植LVGL8.3驅動和觸摸屏驅動代碼

    先說結論:移植LVGL的過程挺順利的,觸摸屏也能正常移植運行,但是目前無法通過觸摸與LVGL界面聯動,原因未知。 移植LVGL8.3.10圖形
    發(fā)表于 05-13 19:53

    使用STM32F429移植STemwin后,能正常顯示字符串及2D圖形,但是不能顯示控件,為什么?

    使用STM32F429移植STemwin后,能正常顯示字符串及2D圖形,但是不能顯示控件,使用W
    發(fā)表于 05-10 06:24

    鴻蒙OS元服務開發(fā):【WebGL網頁圖形開發(fā)概述】

    WebGL的全稱為Web Graphic Library(網頁圖形),主要用于交互式渲染2D圖形和3D圖形。目前HarmonyOS中使用的
    的頭像 發(fā)表于 04-02 17:26 ?367次閱讀
    鴻蒙OS元服務開發(fā):【WebGL網頁<b class='flag-5'>圖形</b><b class='flag-5'>庫</b>開發(fā)概述】

    Minitab 中包括哪些圖形

    于分析的圖形(如控制圖)。Minitab 還有作為許多統(tǒng)計分析的一部分的內置圖形。 檢查變量對之間的關系 使用這些圖形研究一對或多對變量之間的關系。例如,您可以評估以下內容: · 1)土壤 pH 值與植物生長之間的關系 ·
    的頭像 發(fā)表于 01-29 10:28 ?385次閱讀

    u8g2應用程序無法在moduStoolBox中構建是為什么?

    一些幫助。 u8g2 應用說明書 Step2 問題:它說把這個添加到應用程序中。 這是管理器中的 SSD1306 OLED 控制器
    發(fā)表于 01-24 07:03

    基于LL實現STM32U5 LPTIM功能

    有人打算使用STM32U5系列片內LPTIM做低功耗模式喚醒。基于STM32 LL組織代碼,折騰幾天后似乎連中斷都進不了,想找找是否有現存LL例程可以參考。
    的頭像 發(fā)表于 01-07 14:12 ?1343次閱讀
    基于LL<b class='flag-5'>庫</b><b class='flag-5'>實現</b><b class='flag-5'>STM32U</b>5 LPTIM功能

    英飛凌推出TRAVEO T2G-C系列圖形MCU,以MCU的成本為汽車圖形應用提供堪比MPU的性能

    【 2023 年 12 月 8 日, 德國慕尼黑訊】 英飛凌科技股份公司(FSE代碼:IFX / OTCQX代碼:IFNNY)近日推出搭載新型圖形引擎的全新TRAVEO? T2G-C系列車用微控制器
    發(fā)表于 12-26 11:44 ?998次閱讀
    英飛凌推出TRAVEO T<b class='flag-5'>2G</b>-C系列<b class='flag-5'>圖形</b>MCU,以MCU的成本為汽車<b class='flag-5'>圖形</b>應用提供堪比MPU的性能

    實戰(zhàn)經驗 | 移植 SBSFU 到 STM32G070 的過程

    關鍵詞:SBSFU,移植 目錄預覽 1、前言 2、基于STM32G070和STM32G071的SBSFU 實現差異 3、開始
    的頭像 發(fā)表于 12-08 18:20 ?790次閱讀

    誰說單片機不能圖形編程,介紹MCU的TOP 5圖形GUI!

    LittlevGL(LVGL) 是一款開源的嵌入式圖形用戶界面(GUI),專為嵌入式系統(tǒng)設計。LVGL以其輕量級、靈活性和強大的功能而備受開發(fā)者青睞,資源夠的情況下可移植到所有MCU。
    的頭像 發(fā)表于 12-07 10:42 ?6929次閱讀
    誰說單片機不能<b class='flag-5'>圖形</b>編程,介紹MCU的TOP 5<b class='flag-5'>圖形</b>GUI<b class='flag-5'>庫</b>!

    ProTool組態(tài)圖形顯示用戶手冊

    電子發(fā)燒友網站提供《ProTool組態(tài)圖形顯示用戶手冊.pdf》資料免費下載
    發(fā)表于 11-22 17:14 ?0次下載

    【LuckFox Pico Plus開發(fā)板免費試用】交叉編譯U8G2點亮OLED

    看到已經可以掃描的到屏幕了。 第五步:執(zhí)行./u8g2_hw_i2c 可以看到,屏幕已經點亮并顯示了。
    發(fā)表于 10-29 20:48

    STM32GUI_使用 STLINK+stm32gui-pydfb 工具來實時查看圖形緩存的圖片

    STM32GUI_使用 STLINK+stm32gui-pydfb 工具來實時查看圖形緩存的圖片
    的頭像 發(fā)表于 10-27 10:28 ?831次閱讀
    <b class='flag-5'>STM32</b>GUI_使用 STLINK+<b class='flag-5'>stm32</b>gui-pydfb 工具來實時查看<b class='flag-5'>圖形</b>緩存的圖片