[低端局][cx32L003] 移植U8G2

文章目錄

  • 一、簡介
    • (1)U8g2
    • (2)U8x8
  • 二、配置要求
  • 三、移植步驟
    • (1)文件準備和添加
    • (2)實現回調接口(I2C的讀寫函數)
      • ①軟件I2C
      • ②硬件I2C
    • (3)功能裁剪
      • ① u8g2_d_setup.c
      • ② u8g2_d_memory.c
      • ③ 關于字庫

在低端芯片上使用U8G2

一、簡介

U8g2:單色顯示庫,版本2

U8g2是一個用于嵌入式設備的單色圖形庫。U8g2支持單色oled和lcd,其中包括以下控制器:Ssd1305、ssd1306、ssd1309、ssd1312、ssd1316、ssd1318、ssd1320、ssd1322、ssd1325、ssd1327、ssd1327、ssd1327、ssd1327、ssd1327、ssd1327、ssd1106、sh1107、sh1108、ssd1607、hx1230、uc1601、uc1604、uc1608、pcd8544、pcf8812、hx1230、uc1601、uc1611、uc1617、uc1638、uc1701、st7511、st7528、st7565、st7567、st7586、st7588、st75160、st75256、st75320、nt7534、st7920、ist3020、ist3088、ist7920、ld7032、ks0108、ks0713、hd44102、t7932、sed1520、sbn1661、il3820、max7219、gp1287、gp1247、GU800(查看完整列表)。

Arduino庫U8g2可以從Arduino IDE的庫管理器中安裝。U8g2還包括U8x8庫:

(1)U8g2

  1. 包括所有圖形程序(線/框/圓繪制)。

  2. 支持多種字體。(幾乎)對字體高度沒有限制。

  3. 在微控制器中需要一些內存來呈現顯示。

(2)U8x8

  1. 僅文本輸出(字符)設備。

  2. 只允許適合8x8像素網格的字體。

  3. 直接寫入顯示。在微控制器中不需要緩沖區。

二、配置要求

最少要求:
ROM:122+354+12+56+304+723+312+72+134+280+12+28+502+412+288+101+192+10+72=3986byte
RAM:0x80+0x01=0x81=129byte

在這里插入圖片描述

在這里插入圖片描述

RAM范圍[128,1024],越大刷新越快。

Demo工程整體大小:NOS+IIC+GPIO+U8G2

  • Total RO Size (Code + RO Data) 9472 ( 9.25kB)
  • Total RW Size (RW Data + ZI Data) 880 ( 0.86kB)
  • Total ROM Size (Code + RO Data + RW Data) 9492 ( 9.27kB)

三、移植步驟

(1)文件準備和添加

  1. 下載文件(Gitee)
  2. 解壓csrc到工程根目錄在這里插入圖片描述
  3. keil添加目錄文件
    在這里插入圖片描述

注意:帶_d_是用戶自定義文件,可以移動到工程中修改。

  1. keil添加頭文件 [csrc的目錄]
    在這里插入圖片描述
  2. 添加驅動文件
    u8g2里面支持多種驅動芯片,以u8x8_d_xxx.c命名的就是驅動文件,本文使用的是0.96吋oled,芯片是ssd1306,因此只需將u8x8_d_ssd1312_128x64_noname.c這個驅動文件添加到工程中:
    在這里插入圖片描述

(2)實現回調接口(I2C的讀寫函數)

void u8g2_Setup_ssd1306_i2c_128x64_noname_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb)

byte_cb:是通信相關的函數,比如i2c寫數據,
gpio_and_delay_cb:是延時相關的函數。

①軟件I2C

u8g2_Setup_ssd1306_i2c_128x64_noname_1(&u8g2, U8G2_R0, u8x8_byte_sw_i2c, gpio_and_delay); // init u8g2 structure

  1. u8x8_byte_sw_i2c官方已經實現 <–u8x8_byte.c
  2. 我們需要實現gpio_and_delay函數
uint8_t gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {//printf("%s:msg = %d,arg_int = %d\r\n",__FUNCTION__,msg,arg_int);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 secondsfor (uint16_t n = 0; n < 320; n++) {__NOP();}     break;case U8X8_MSG_DELAY_MILLI:			// delay arg_int * 1 milli secondHAL_Delay(1);break;case U8X8_MSG_DELAY_I2C:		    // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz//delay 5usdelay_us(5);						// arg_int=1: delay by 5us, arg_int = 4: delay by 1.25uscase U8X8_MSG_GPIO_I2C_CLOCK:		// arg_int=0: Output low at I2C clock pinif(arg_int == 1) {HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);} else if(arg_int == 0) {HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  }          break;							// arg_int=1: Input dir with pullup high for I2C clock pincase U8X8_MSG_GPIO_I2C_DATA:		// arg_int=0: Output low at I2C data pin//  printf("U8X8_MSG_GPIO_I2C_DATA:%d\r\n",arg_int);if(arg_int == 1)  {HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);} else if(arg_int == 0) {HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);  }         break;							// arg_int=1: Input dir with pullup high for I2C data pincase 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 valuebreak;}return 1;
}

②硬件I2C

跟軟件實現方式類似

u8g2_Setup_ssd1306_i2c_128x64_noname_1(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, gpio_and_delay); // init u8g2 structure

#define I2C_SPEED_RATE	100   //uint khz
I2C_HandleTypeDef i2c_test = {0};
FlagStatus i2c_int = RESET;main:
{__HAL_RCC_I2C_CLK_ENABLE();gpioi2c.Pin    = GPIO_PIN_5;gpioi2c.Mode = GPIO_MODE_AF; // GPIO端口復用功能 gpioi2c.Alternate = GPIO_AF4_I2C_SDA;gpioi2c.OpenDrain = GPIO_OPENDRAIN; // 開漏輸出gpioi2c.Debounce.Enable = GPIO_DEBOUNCE_DISABLE; // 禁止輸入去抖動gpioi2c.SlewRate = GPIO_SLEW_RATE_HIGH; // 電壓轉換速率gpioi2c.DrvStrength = GPIO_DRV_STRENGTH_HIGH; // 驅動強度gpioi2c.Pull = GPIO_PULLUP;			// 上拉HAL_GPIO_Init(GPIOB, &gpioi2c);gpioi2c.Pin = GPIO_PIN_4;gpioi2c.Mode = GPIO_MODE_AF;gpioi2c.Alternate = GPIO_AF4_I2C_SCL;gpioi2c.OpenDrain = GPIO_OPENDRAIN; gpioi2c.Debounce.Enable = GPIO_DEBOUNCE_DISABLE;gpioi2c.SlewRate = GPIO_SLEW_RATE_HIGH;gpioi2c.DrvStrength = GPIO_DRV_STRENGTH_HIGH;gpioi2c.Pull = GPIO_PULLUP;	HAL_GPIO_Init(GPIOB, &gpioi2c);i2c_test.Instance = I2C;i2c_test.Init.master = I2C_MASTER_MODE_ENABLE; // 主機模式使能i2c_test.Init.slave = I2C_SLAVE_MODE_DISABLE; // 從機模式禁止i2c_test.Mode = HAL_I2C_MODE_MASTER; // 主機模式i2c_test.Init.broadack = I2C_BROAD_ACK_DISABLE; // 廣播地址應答禁止i2c_test.Init.speedclock = I2C_SPEED_RATE; // I2C傳輸速率  i2c_test.State = HAL_I2C_STATE_RESET; //HAL_I2C_Init(&i2c_test);
}uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {static uint8_t buffer[32];		/* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */static uint8_t buf_idx;uint8_t *data;switch(msg){case U8X8_MSG_BYTE_SEND:data = (uint8_t *)arg_ptr;      while( arg_int > 0 ){buffer[buf_idx++] = *data;data++;arg_int--;}      break;case U8X8_MSG_BYTE_INIT:/* add your custom code to init i2c subsystem */break;case U8X8_MSG_BYTE_START_TRANSFER:buf_idx = 0;break;case U8X8_MSG_BYTE_END_TRANSFER:HAL_I2C_Master_Transmit(&i2c_test, buffer[0], &buffer[1], buf_idx - 1);break;default:return 0;}return 1;
}uint8_t gpio_and_delay(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
{switch(msg){case U8X8_MSG_GPIO_AND_DELAY_INIT:break;case U8X8_MSG_DELAY_MILLI:HAL_Delay(arg_int);break;case U8X8_MSG_GPIO_I2C_CLOCK:		break;							case U8X8_MSG_GPIO_I2C_DATA:			break;default:	return 0;}return 1; // command processed successfully.
}

到此,移植完畢,但是編譯失敗,空間不足!

(3)功能裁剪

① u8g2_d_setup.c

  1. 注釋全部函數
  2. 找到u8g2_Setup_ssd1306_i2c_128x64_noname_1函數,解除注釋。
    在這里插入圖片描述
    注:用緩存128舉例。有條件的可以使用256,1024.
    u8g2_Setup_ssd1306_i2c_128x64_noname_1() --緩存128byte
    u8g2_Setup_ssd1306_i2c_128x64_noname_2() --緩存256byte
    u8g2_Setup_ssd1306_i2c_128x64_noname_f() --緩存1024byte

② u8g2_d_memory.c

  1. 注釋全部函數
  2. 找到u8g2_m_16_8_1函數,解除注釋。
    在這里插入圖片描述

注:用緩存128舉例。有條件的可以使用256,1024.
u8g2_Setup_ssd1306_i2c_128x64_noname_1() --緩存128byte
u8g2_Setup_ssd1306_i2c_128x64_noname_2() --緩存256byte
u8g2_Setup_ssd1306_i2c_128x64_noname_f() --緩存1024byte

u8g2_Setup_ssd1306_128x64_noname_1、
u8g2_Setup_ssd1306_128x64_noname_2、
u8g2_Setup_ssd1306_128x64_noname_f,
這些都是spi接口的;
u8g2_Setup_ssd1306_i2c_128x64_noname_1、
u8g2_Setup_ssd1306_i2c_128x64_noname_2、
u8g2_Setup_ssd1306_i2c_128x64_noname_f,
這些都是i2c接口的;
后綴1、2、f代表緩沖區大小的不同:
1代表128字節,
2代表256字節,
f代表1024字節;
根據單片機空間的大小選擇合適的接口,緩沖區小的,刷新lcd/oled的時候就比較耗時,反之。

③ 關于字庫

“u8g2_fonts.c”文件中定義了各種字庫,這些字庫比較占用空間,根據使用情況屏蔽掉沒有使用的。

demo工程gitee

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/36992.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/36992.shtml
英文地址,請注明出處:http://en.pswp.cn/news/36992.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Gof23設計模式之模板方法模式

1.定義 定義一個操作中的算法骨架&#xff0c;而將算法的一些步驟延遲到子類中&#xff0c;使得子類可以不改變該算法結構的情況下重定義該算法的某些特定步驟。 2.結構 模板方法&#xff08;Template Method&#xff09;模式包含以下主要角色&#xff1a; 抽象類&#xff0…

Kerberos 重新認識 From Oracle安全

參考 https://docs.oracle.com/cd/E24847_01/html/819-7061/seamtm-1.html#scrolltoc Kerberos服務 Kerberos服務是一種網絡身份認證協議&#xff0c;由麻省理工學院&#xff08;MIT&#xff09;開發。它提供了強大的身份驗證功能&#xff0c;用于在計算機網絡中驗證用戶和服務…

買愛心氣球(nim博弈)

鏈接&#xff1a;登錄—專業IT筆試面試備考平臺_牛客網 來源&#xff1a;牛客網 Alice 和 Bob 是一對競技編程選手&#xff0c;他們路過了一家氣球店&#xff0c;發現有 m 個大愛心氣球和 n個小愛心氣球。他們決定玩一個游戲&#xff0c;游戲規則如下&#xff1a; Alice先手拿…

Python Selenium 設置帶賬號密碼的socks5代理,啟動瀏覽器

selenium添加帶有賬密的socks5代理 我們都知道在使用selenium開發爬蟲的時候不可避免的會使用socks5高匿名代理。一般情況下我們使用方法如下(開發語言為python)&#xff1a; from selenium import webdriver chrome_options webdriver.ChromeOptions() chrome_options.add_…

Java并發之ReentrantLock

AQS AQS&#xff08;AbstractQueuedSynchronizer&#xff09;&#xff1a;抽象隊列同步器&#xff0c;是一種用來構建鎖和同步器的框架。在是JUC下一個重要的并發類&#xff0c;例如&#xff1a;ReentrantLock、Semaphore、CountDownLatch、LimitLatch等并發都是由AQS衍生出來…

React Native Expo項目,復制文本到剪切板

裝包&#xff1a; npx expo install expo-clipboard import * as Clipboard from expo-clipboardconst handleCopy async (text) > {await Clipboard.setStringAsync(text)Toast.show(復制成功, {duration: 3000,position: Toast.positions.CENTER,})} 參考鏈接&#xff1a…

3.文件目錄

第四章 文件管理 3.文件目錄 ? ??對于D盤這個根目錄來說它對應的目錄文件就是圖中的樣子&#xff0c;其實就是用一個所謂的目錄表來表示這個目錄下面存放了哪些東西。在D盤中的每一個文件&#xff0c;每一個文件夾都會對應這個目錄表中的一個表項&#xff0c;所以其實這些一…

如何寫簡歷?

寫程序員簡歷時&#xff0c;可以從以下幾個方面入手&#xff1a; 1. 個人信息&#xff1a;在簡歷的開頭&#xff0c;包含個人基本信息如姓名、聯系方式、地址等。 2. 求職目標/職業目標&#xff1a;明確自己希望得到的職位或行業&#xff0c;并簡要描述為什么適合該職位。 3…

Autoware感知02—歐氏聚類(lidar_euclidean_cluster_detect)源碼解析

文章目錄 引言一、點云回調函數&#xff1a;二、預處理&#xff08;1&#xff09;裁剪距離雷達過于近的點云&#xff0c;消除車身的影響&#xff08;2&#xff09;點云降采樣&#xff08;體素濾波&#xff0c;默認也是不需要的&#xff09;&#xff08;3&#xff09;裁剪雷達高…

【概念篇】文件概述

?作者簡介&#xff1a;大家好&#xff0c;我是小楊 &#x1f4c3;個人主頁&#xff1a;「小楊」的csdn博客 &#x1f433;希望大家多多支持&#x1f970;一起進步呀&#xff01; 文件概述 1&#xff0c;文件的概念 狹義上的文件是計算機系統中用于存儲和組織數據的一種數據存…

React源碼解析18(5)------ 實現函數組件【修改beginWork和completeWork】

摘要 經過之前的幾篇文章&#xff0c;我們實現了基本的jsx&#xff0c;在頁面渲染的過程。但是如果是通過函數組件寫出來的組件&#xff0c;還是不能渲染到頁面上的。 所以這一篇&#xff0c;主要是對之前寫得方法進行修改&#xff0c;從而能夠顯示函數組件&#xff0c;所以現…

【深度學習】NLP中的對抗訓練

在NLP中&#xff0c;對抗訓練往往都是針對嵌入層&#xff08;包括詞嵌入&#xff0c;位置嵌入&#xff0c;segment嵌入等等&#xff09;開展的&#xff0c;思想很簡單&#xff0c;即針對嵌入層添加干擾&#xff0c;從而提高模型的魯棒性和泛化能力&#xff0c;下面結合具體代碼…

Spark 學習記錄

基礎 SparkContext是什么&#xff1f;有什么作用&#xff1f; https://blog.csdn.net/Shockang/article/details/118344357 SparkContext 是什么&#xff1f; SparkContext 是通往 Spark 集群的唯一入口&#xff0c;可以用來在 Spark 集群中創建 RDDs 、累加和廣播變量( Br…

【數據庫基礎】Mysql下載安裝及配置

下載 下載地址&#xff1a;https://downloads.mysql.com/archives/community/ 當前最新版本為 8.0版本&#xff0c;可以在Product Version中選擇指定版本&#xff0c;在Operating System中選擇安裝平臺&#xff0c;如下 安裝 MySQL安裝文件分兩種 .msi和.zip [外鏈圖片轉存失…

C++11時間日期庫chrono的使用

chrono是C11中新加入的時間日期操作庫&#xff0c;可以方便地進行時間日期操作&#xff0c;主要包含了&#xff1a;duration, time_point, clock。 時鐘與時間點 chrono中用time_point模板類表示時間點&#xff0c;其支持基本算術操作&#xff1b;不同時鐘clock分別返回其對應…

vue中router路由的原理?兩種路由模式如何實現?(vue2) -(上)

平時我們編寫路由時&#xff0c;通常直接下載插件使用&#xff0c;在main.js文件中引入直接通過引入vue-router中的Router通過Vue.use使用以后定義一個routeMap數組&#xff0c;里邊是我們編寫路由的地方&#xff0c;最后通過實例化一個 Router實例 將routes我們定義的routeMao…

Docker中部署Nginx

1.Nginx部署需求 2.操作教程 3.實際步驟 把配置粘過來。

客戶端遠程啟動服務器腳本文件

目錄 軟件需求 實現 方法1 方法2 方法3 軟件需求 有兩臺計算機&#xff0c;一臺是linux客戶端&#xff0c;另一臺是linux服務器。要求操作員可以在客戶端遠程啟動服務器上的腳本文件&#xff0c;控制服務器。 實現 方法1 客戶端通過ssh登錄服務器&#xff0c;然后通過…

Cookie、Session、Token的區別

有人或許還停留在它們只是驗證身份信息的機制&#xff0c;但是它們之間的關系你真的弄懂了么&#xff1f; 發展史&#xff1a; Coolie: Netscape Communications 公司引入了 Cookie 概念&#xff0c;作為在客戶端存儲狀態信息的一種方法。初始目的是為了解決 HTTP 的無狀態性…

Python爬蟲:單線程、多線程、多進程

前言 在使用爬蟲爬取數據的時候&#xff0c;當需要爬取的數據量比較大&#xff0c;且急需很快獲取到數據的時候&#xff0c;可以考慮將單線程的爬蟲寫成多線程的爬蟲。下面來學習一些它的基礎知識和代碼編寫方法。 一、進程和線程 進程可以理解為是正在運行的程序的實例。進…