日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STM32 HAL 硬件IIC+DMA+简单图形库控制OLED

發布時間:2023/12/9 编程问答 59 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STM32 HAL 硬件IIC+DMA+简单图形库控制OLED 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 前言
  • 一、建立工程
  • 二、編寫和移植
    • 前期準備
    • 驅動部分修改
  • 三、使用和驗證
  • 結論


(2022年1月22日重制)本文主要是移植帶簡單圖形庫的程序,如果只是實現DMA控制,建議看【0.96寸 OLED屏實現1500Fps的幀率】STM32 軟件、硬件SPI、I2C驅動總結

本文參考例程
提取碼: sch3

前言

本文將介紹在STM32 HAL庫下實現硬件IIC+DMA控制0.96寸 OLED屏,以及OLED圖形庫的移植。


一、建立工程

平臺:野火指南者STM32F103VET6 + STM32Cube MX + Keil MDK 5

(示例)
1.選擇所用MCU。

2.選擇啟用晶振
3.選擇Debug方式
4.設置時鐘樹

5.選擇合適的引腳開啟I2C
6.加入I2Cx_TX的DMA
7.開啟12Cx_event_interrupt
8.配置完后建立工程

二、編寫和移植

本節主要介紹移植標準庫編寫的oledlib圖形庫過程。
oledlib庫原作者:MjGame
原作例程開源地址:MjGame 的例程
本文使用的oledlib庫修訂者:一只程序緣
本文所要移植庫的開源地址:一只程序緣 的例程

git clone https://gitee.com/jiezhuonew/oledlib.git (示例):

前期準備

1.先導入所需的文件
所用Delay文件參考《無需另配定時器在STM32 HAL下實現微秒級延時(兼容FreeRTOS)》



2.將delay.h改為我們所用的Delay.h文件


修改u16為unsigned short或uint16_t

驅動部分修改

  • 在oled_config.h中添加#include “main.h”,并修改TRANSFER_METHOD

  • 在oled_driver.h和oled_driver.c中注釋掉標準庫相關的東西:

    此時編譯不再彈出錯誤。

  • 在oled_driver.c修改I2C_WriteByte函數

  • /**@brief I2C_WriteByte,向OLED寄存器地址寫一個byte的數據@param addr:寄存器地址data:要寫入的數據@retval 無*/void I2C_WriteByte(uint8_t addr, uint8_t data){ // while (I2C_GetFlagStatus(I2CX, I2C_FLAG_BUSY));// I2C_GenerateSTART(I2CX, ENABLE);//開啟I2C1 // while (!I2C_CheckEvent(I2CX, I2C_EVENT_MASTER_MODE_SELECT)); /*EV5,主模式*/// I2C_Send7bitAddress(I2CX, OLED_ADDRESS, I2C_Direction_Transmitter);//器件地址 -- 默認0x78 // while (!I2C_CheckEvent(I2CX, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));// I2C_SendData(I2CX, addr);//寄存器地址 // while (!I2C_CheckEvent(I2CX, I2C_EVENT_MASTER_BYTE_TRANSMITTED));// I2C_SendData(I2CX, data);//發送數據 // while (!I2C_CheckEvent(I2CX, I2C_EVENT_MASTER_BYTE_TRANSMITTED));// I2C_GenerateSTOP(I2CX, ENABLE);//關閉I2C1總線extern I2C_HandleTypeDef hi2c1;HAL_I2C_Mem_Write(&hi2c1, OLED_ADDRESS, addr, I2C_MEMADD_SIZE_8BIT, &data, 1, 10);}
  • 在oled_driver.c修改OLED_CLS函數
  • void OLED_CLS(void)//清屏 { // unsigned char m, n; // for (m = 0; m < 8; m++) // { // WriteCmd(0xb0 + m); //page0-page1 // WriteCmd(0x00); //low column start address // WriteCmd(0x10); //high column start address // for (n = 0; n < 128; n++) // { // WriteDat(0x00); // } // }extern unsigned char ScreenBuffer[SCREEN_PAGE_NUM][SCREEN_COLUMN];uint16_t i;for (i = 0; i < SCREEN_PAGE_NUM * SCREEN_COLUMN; ++i){ScreenBuffer[0][i] = 0;}OLED_FILL(ScreenBuffer[0]); }
  • 在oled_driver.c修改OLED_FILL函數
  • void OLED_FILL(unsigned char BMP[]) { // uint8_t i, j;unsigned char *p;p = BMP;// for (i = 0; i < 8; i++) // { // WriteCmd(0xb0 + i); //page0-page1 // WriteCmd(0x00); //low column start address // WriteCmd(0x10);// for (j = 0; j < 128; j++) // { // WriteDat(*p++); // } // }extern I2C_HandleTypeDef hi2c1;while(hi2c1.State != HAL_I2C_STATE_READY);HAL_I2C_Mem_Write_DMA(&hi2c1, OLED_ADDRESS, 0x40, I2C_MEMADD_SIZE_8BIT, p, SCREEN_PAGE_NUM * SCREEN_PAGEDATA_NUM); }
  • 注意到
  • //請將此函數放入1ms中斷里,為圖形提供時基 //系統時間基準主要用于FrameRateUpdateScreen()中固定幀率刷新屏幕 void OledTimeMsFunc(void) {if(OledTimeMs != 0x00){ OledTimeMs--;} }

    故到stm32f1xx_it.c中聲明并添加此函數
    若未使用FreeRTOS則在滴答定時器中斷中添加,反之在對應定時器中斷中添加:

    /*** @brief This function handles System tick timer.*/ void SysTick_Handler(void) {/* USER CODE BEGIN SysTick_IRQn 0 *//* USER CODE END SysTick_IRQn 0 */HAL_IncTick();/* USER CODE BEGIN SysTick_IRQn 1 */OledTimeMsFunc();/* USER CODE END SysTick_IRQn 1 */ }
  • 修改OLED_Init函數
  • void OLED_Init(void) {WriteCmd(0xAE); //display offWriteCmd(0x20); //Set Memory Addressing Mode // WriteCmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,InvalidWriteCmd(0x00); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,InvalidWriteCmd(0xb0); //Set Page Start Address for Page Addressing Mode,0-7WriteCmd(0xc8); //Set COM Output Scan DirectionWriteCmd(0x00); //---set low column addressWriteCmd(0x10); //---set high column addressWriteCmd(0x40); //--set start line addressWriteCmd(0x81); //--set contrast control registerWriteCmd(0xff); //亮度調節 0x00~0xffWriteCmd(0xa1); //--set segment re-map 0 to 127WriteCmd(0xa6); //--set normal displayWriteCmd(0xa8); //--set multiplex ratio(1 to 64)WriteCmd(0x3F); //WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM contentWriteCmd(0xd3); //-set display offsetWriteCmd(0x00); //-not offsetWriteCmd(0xd5); //--set display clock divide ratio/oscillator frequencyWriteCmd(0xf0); //--set divide ratioWriteCmd(0xd9); //--set pre-charge periodWriteCmd(0x22); //WriteCmd(0xda); //--set com pins hardware configurationWriteCmd(0x12);WriteCmd(0xdb); //--set vcomhWriteCmd(0x20); //0x20,0.77xVccWriteCmd(0x8d); //--set DC-DC enableWriteCmd(0x14); //WriteCmd(0xaf); //--turn on oled panelOLED_CLS(); }

    其中 WriteCmd(0x20); WriteCmd(0x00); 兩句函數將SSD1306的尋址方式修改為了水平尋址,能夠一次性對OLED內部Graphic Display Data RAM (GDDRAM)整體更新。
    見firestaradmin大佬的
    《STM32 DMA-IIC刷新OLED屏(理論可達42+幀率)》
    和Coder_BCM大佬的
    《基于STM32F407的 中景園0.96寸OLED(IIC)的程序升級(DMA+IIC + 顯存Buffer)》)
    若發現行錯位,則修改

    WriteCmd(0xd3); //-set display offsetWriteCmd(0x00 加或減 8的倍數);

    三、使用和驗證

    添加test.c,該文件源自原例程,有修改。
    需要注意的是調用OLED_ShowCHinese函數的文件和oled_font.c文件的編碼格式需一致:GBK。當一個為UTF-8,一個為GBK時會顯示不出漢字。

    /*Copyright (c) [2019] [一只程序緣 jiezhuo][https://gitee.com/jiezhuonew/oledlib] is licensed under the Mulan PSL v1.You can use this software according to the terms and conditions of the Mulan PSL v1.You may obtain a copy of Mulan PSL v1 at:http://license.coscl.org.cn/MulanPSLTHIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULARPURPOSE.See the Mulan PSL v1 for more details.==========此函數是oledlib圖形庫的綜合測試函數 基本上使用到了里面的所有內容==================目前接線說明:僅僅使用到0.96寸7引腳oled 使用SPI通信方式(具體見oled_drive.c)D0 = SCK -> PA4 (屏幕批次不同絲印可能不同)D1 = SDA -> PA5RES = RES -> PA6DC = DC -> PA7CS = SCS -> PA8軟件模塊:oled spi驅動beep 蜂鳴器 提示或作為led表示運行狀態timer3 中斷1ms 可為圖形庫提供時間基準uart 可作為串口連接電腦打印調試xinxidelay 系統自帶的時間設置與提供延時函數視頻演示信息:單片機 --- STM32F103oled --- 采用4線SPI的7引腳0.96寸黑白雙色oled圖形庫功能:在oledlib文件夾下作出多個c文件的分類 每個c文件的開頭都有對該文件的簡要說明包括打點 畫線 矩形 三角形 圓 橢圓 圓角矩形 的邊緣與填充還包括 字符顯示 漢字顯示 位圖顯示最后還有 oled模擬串口printf的debug字符顯示:針對于字符有4種大小0-1-2-3 具體參見SetFontSize()基于大家的使用習慣0是一般大家習慣用的 此時y只能為0-7對應顯示的7大行 注意:此時x為地基大行 y為第幾列2 3都是基于1的等比例放大 此時y能為0-6x對應顯示的每一小行 此時為正常坐標系 x為第幾小行 y為第幾列中文漢字顯示:中文漢字的大小為16x16 此時y也只能為0-7對應顯示的7大行 注意:此時x為地基大行 y為第幾列取模說明:取模軟件采用PCtoLCD2002字符 漢字 和 位圖的取模方式和設置都在font.c和bmp.c中有注釋用戶調用函數:在draw_api.h中提供了所有函數的接口 可在其中查看所有函數的簡要功能移植說明:1.移植圖形庫僅需要準備好底層驅動 在oled_driver.c中作出修改即可 在該c文件開頭有說明2.若需要對test.c中的動畫效果進行測試 還需要為函數OledTimeMsFunc()提供時間基準3.庫函數使用的延時函數是DelayMs() 移植后由單片機型號補充調整DelayMs()圖形庫本質:該圖形庫本質為對一數組進行操作 然后刷新整個數組到屏幕中實現效果因此相似點陣屏(oled/TFT/大小尺寸/點陣/液晶)也可以使用 根據像素可參見oled_config.h詳細的注釋:如果是使用為用途 了解test.c和draw_api.c即可 做出花里胡哨的UI界面在本人閱讀代碼和注釋的過程中 發現很多結構和函數都值得學習 仔細理解理解GUI和本圖形庫的關系:gui是一個以圖形界面來進行人機交互的系統 gui是擁有窗口、菜單、控件、對話框等交互的圖形接口這個只是一個圖形庫 類似于c++上的easyx圖形庫 是沒有圖形接口的 只提供繪圖和顯示的功能圖形庫可以算是gui的一部分,也可以自己以圖形庫繼續封裝為gui庫代碼容量:除去位圖 Code=26254 RO-data=3754 RW-data=100 ZI-data=4108原作的話:為了做這個繪制圖形庫,我參考了很多其他的算法,花了大量時間去做移植優化,其中參考最多的是github中的arduboy游戲機,大部分圖形是移植它的,現在是最初的初稿版本,還有很多地方需要優化改進。我想要將這個圖形庫做大,后續會加入更多有趣的東西,和模塊,代碼都是用最簡單的方式編寫的,都是開源的。后續也會加上注釋說明,讓更多人以單片機和oled屏來入門硬件編程,如果你使用了該庫,請標明出處。b站關注oximeterg,可獲取該庫的最新版本和消息。注意:繪制填充或實心的圖形,影響刷新效率(待優化中) */// #include "test.h" #include "draw_api.h" #include "../Delay/Delay.h" #include "stdlib.h" #include "stdio.h" #include "math.h"void ShowStars(void); void ShowWatch(void); void ShowPolygon(void); void ShowSnow(void);void demo(void) {int i,j;//demo演示ClearScreen();DrawBitmap(0,0,Panda,128,64);UpdateScreen();DelayMs(1000);//字符ClearScreen();SetFontSize(1);DrawString(0,0,"test");UpdateScreen();DelayMs(1000);SetFontSize(2);DrawString(0,8,"test");UpdateScreen();DelayMs(1000);SetFontSize(3);DrawString(0,24,"test");UpdateScreen();DelayMs(1000);//漢字測試ClearScreen();OLED_ShowCHinese(0,0,"一只程序緣");UpdateScreen();DelayMs(1000);OLED_ShowCHinese(2,0,"一只程序緣一只程序緣一只程序緣一只程序緣");UpdateScreen();DelayMs(1000);//數字測試ClearScreen();for(i=0; i<300; i++){SetFontSize(0);DrawNum(0,96,i,4);SetFontSize(1);DrawNum(0,16,i,4);SetFontSize(2);DrawNum(0,24,i,4);SetFontSize(3);DrawNum(0,40,i,4);UpdateScreen();}//串口debugDelayMs(100);ClearScreen();for(i=0; i<256; i++){OledPrintf("num:%d cha:%c hex:%x\r\n",i,i,i);}DelayMs(100);//劃線ClearScreen();for(i=0; i<20; i++){DrawLine(0,0,i*10,63);UpdateScreen();}for(i=0; i<20; i++){DrawLine(128,0,128-i*10,63);UpdateScreen();}DelayMs(100);//矩形for(j=0; j<2; j++){if(j==0)ClearScreen();for(i=0; i<31; i+=2){DrawRect2(i*2,i,128-i*4,64-2*i);//畫矩形外框UpdateScreen();}if(j==0)ClearScreen();DelayMs(100);for(i=31; i>0; i-=2){DrawFillRect2(i*2,i,128-i*4,64-2*i);//畫實心矩形UpdateScreen();}SetDrawColor(pix_black);//劃線顏色SetFillcolor(pix_black);//填充顏色}SetDrawColor(pix_white);SetFillcolor(pix_white);//圓角矩形for(j=0; j<2; j++){if(j==0)ClearScreen();for(i=0; i<25; i+=2){DrawRoundRect(i*2,i,128-i*4,64-2*i,8);UpdateScreen();}if(j==0)ClearScreen();DelayMs(100);for(i=25; i>2; i-=2){DrawfillRoundRect(i*2,i,128-i*4,64-2*i,8);UpdateScreen();}SetDrawColor(pix_black);SetFillcolor(pix_black);}SetDrawColor(pix_white);SetFillcolor(pix_white);DelayMs(100);//橢圓ClearScreen();DrawEllipse(63,31,63,31);UpdateScreen();DelayMs(500);ClearScreen();DrawEllipse(63,31,16,31);UpdateScreen();DelayMs(500);ClearScreen();DrawFillEllipse(63,31,63,31);UpdateScreen();DelayMs(500);ClearScreen();DrawFillEllipse(63,31,16,31);UpdateScreen();DelayMs(500);//圓ClearScreen();DrawCircle(63,31,30);UpdateScreen();DelayMs(500);ClearScreen();DrawFillCircle(63,31,30);UpdateScreen();DelayMs(500);//三角形ClearScreen();DrawTriangle(5,10,100,30,60,50);UpdateScreen();DelayMs(500);ClearScreen();DrawFillTriangle(5,10,100,30,60,50);UpdateScreen();DelayMs(500);//繪制圖形圖片 位圖ClearScreen();DrawBitmap(0,0,BmpTest1,16,16);UpdateScreen();DelayMs(500);DrawBitmap(16,0,BmpTest2,32,32);UpdateScreen();DelayMs(500);DrawBitmap(48,0,BmpTest3,64,64);UpdateScreen();DelayMs(500);//圓弧ClearScreen();for(i=0; i<360; i++){DrawArc(63,31,30,0,i); //畫圓弧UpdateScreen();DelayMs(25);ClearScreen();}DrawCircle(63,31,30); //畫圓UpdateScreen();DelayMs(100);for(i=0; i<10; i++){DrawFillCircle(63,31,i); //在中心填充圓DrawCircle(63,31,30);UpdateScreen();DelayMs(25);ClearScreen();}//繞點for(i=0; i<720; i++) //轉720度2圈{TypeXY temp;SetAngle(i); //設置角度SetRotateCenter(63,31); //設置圓心temp=GetRotateXY(63,31+30); //講已知坐標旋轉角度DrawFillCircle(temp.x,temp.y,5);//畫出算出的位置DrawCircle(63,31,30); //畫出軌跡DrawFillCircle(63,31,10); //填充中心UpdateScreen(); //更新屏幕ClearScreen();}//向右邊平移for(i=0; i<95; i++){TypeXY temp; //其實就是上面繼續旋轉SetAngle(720+i); //畫圖的時候x+偏移量SetRotateCenter(63+i,31);temp=GetRotateXY(63+i,31+30);DrawFillCircle(temp.x,temp.y,5);DrawCircle(63+i,31,30);DrawFillCircle(63+i,31,10);UpdateScreen();ClearScreen();}//動畫ShowStars(); //星空動畫ShowWatch(); //時鐘動畫ShowPolygon(); //多邊形動畫 // ShowSnow(); //下雪動畫DelayMs(100);//結束ClearScreen();SetFontSize(2);DrawString(8,16," Show End "); //顯示字符串UpdateScreen();DelayMs(1000);ClearScreen();DrawBitmap(0,10,Like,128,40); //三連圖片UpdateScreen();DelayMs(1000); }/ //星空動畫 void ShowStars(void) {int i;int count=0;int fps=60;typedef struct START{short x;short y;short speed;unsigned char speedcount;unsigned char isexist;} Star;Star star[128]= {0};srand(2);for(i=0; i<128; i++){if(star[i].isexist==0){//設置128個()星星的初始信息star[i].x=rand()%127; //隨機生成初始x坐標star[i].y=rand()%64; //隨機生成y的坐標star[i].speedcount=0;star[i].speed=rand()%8+1; //1-8的數star[i].isexist=1;}}while(1){if(FrameRateUpdateScreen(fps)==1) //在此函數中定時刷新屏{count++;if(count>=fps*10) //10秒鐘時間到達之后跳出循環結束動畫return;}//此段函數一直在運行//依次畫出128個星星for(i=0; i<128; i++){//如果這一個星星已經移動到退出屏幕界面//則在最左側重新生成一顆新星星if(star[i].isexist==0){star[i].x=0;star[i].y=rand()%64;star[i].speed=rand()%6+1;star[i].speedcount=0;star[i].isexist=1;}else{star[i].speedcount++;if(star[i].x>=124) //標記已經退出屏幕star[i].isexist=0;//清除上一個時刻畫的星星(的尾巴) 不管有沒有操作 都進行清除操作SetDrawColor(pix_black);DrawLine(star[i].x,star[i].y,star[i].x,star[i].y);SetDrawColor(pix_white);if(star[i].speedcount==star[i].speed) //運行時間到了一定的長度{star[i].speedcount=0; //復位運行時間并向右移一格star[i].x+=1; //總之星星的結束需要在這經歷124次} //只不過有的更快 就能移動更快//從頭到尾畫出整條星星 不管星星是否已經變化DrawLine(star[i].x, star[i].y, star[i].x+(6/star[i].speed)-1, star[i].y);}}} } //時鐘動畫 //鐘 小時 分鐘 秒, void RoundClock(int hours,int minute,int sec) {unsigned char i=0;TypeXY hourspoint,minutepoint,secpoint,tmp1,tmp2;//時針SetRotateValue(63,31,hours*30+(minute*30)/60,1);hourspoint=GetRotateXY(63-14,31);DrawLine(63,31,hourspoint.x,hourspoint.y);//分針SetRotateValue(63,31,minute*6+(sec*6)/60,1);minutepoint=GetRotateXY(63-21,31);DrawLine(63,31,minutepoint.x,minutepoint.y);//秒針SetRotateValue(63,31,sec*6,1);secpoint=GetRotateXY(63-28,31);DrawLine(63,31,secpoint.x,secpoint.y);//表盤for(i=0; i<12; i++){SetRotateValue(63,31,i*30,1);tmp1=GetRotateXY(63-29,31);tmp2=GetRotateXY(63-24,31);DrawLine(tmp1.x,tmp1.y,tmp2.x,tmp2.y);}DrawFillCircle(63,31,2);DrawCircle(63,31,30);UpdateScreen();DelayMs(25);ClearScreen(); }void ShowWatch(void) {int i,j,z;int count=0;for(i=0; i<12; i++)for(j=0; j<60; j++)for(z=0; z<60; z++){RoundClock(i,j,z);count++;if(count>=800)return;} }/ //多邊形動畫 void ShowPolygon(void) {int x0=63,y0=31; //正多邊形的外接圓的圓心unsigned char i =0,j;int n=1,r=31; //畫正n邊形 大小半徑31int v=1,count=0; //每個相鄰的多邊形隔1 畫count次后退出int x[30],y[30];while(1){ClearScreen();for(i=0; i<n; i++){x[i]=r*cos(2*3.1415926*i/n)+x0;y[i]=r*sin(2*3.1415926*i/n)+y0;}for(i=0; i<=n-2; i++){for(j=i+1; j<=n-1; j++)DrawLine(x[i],y[i],x[j],y[j]);}n+=v;if(n==20||n==0)v=-v;UpdateScreen();DelayMs(25); //延時停頓100msif(++count==90){count=0;return ;}} }//下雪的函數 和星空類似 void ShowSnow(void) {int a[66],i,num=0;int count=0;int fps=60;struct Snow{short x;short y;short speed;} snow[100];srand(1);for(i=0; i<66; i++)a[i]=(i-2)*10;ClearScreen();while(1){if(FrameRateUpdateScreen(fps)==1) //在此函數中定時刷新屏{count++;if(count>=fps*10) //10秒鐘時間到達之后跳出循環結束動畫return;}if(num!=100){snow[num].speed=1+rand()%4;i=rand()%66;snow[num].x=a[i];snow[num].y=0;num++;}for(i=0; i<num; i++){snow[i].y+=snow[i].speed;DrawPixel(snow[i].x,snow[i].y+1);DrawPixel(snow[i].x+1,snow[i].y);DrawPixel(snow[i].x,snow[i].y);DrawPixel(snow[i].x-1,snow[i].y);DrawPixel(snow[i].x,snow[i].y-1);if(snow[i].y>63){snow[i].y=0;}}UpdateScreen();DelayMs(25);ClearScreen();} }

    在main.c文件中包含必要的頭文件

    //... #include "main.h"/* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "../Delay/Delay.h" #include "../oledlib/draw_api.h" /* USER CODE END Includes */ //...

    添加初始化函數并測試demo

    //.../* USER CODE BEGIN 2 */delay_init();InitGraph();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */void demo(void);demo();}/* USER CODE END 3 */ //...

    效果如下



    結論

    相比于普通的硬件IIC控制屏幕,改用DMA驅動后,刷新率得到了很大提升。其速度提升的原理為《STM32 DMA-IIC刷新OLED屏(理論可達42+幀率)》

    總結

    以上是生活随笔為你收集整理的STM32 HAL 硬件IIC+DMA+简单图形库控制OLED的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。