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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

【0.96寸 OLED屏实现1500Fps的帧率】STM32 软件、硬件SPI、I2C驱动总结

發布時間:2023/12/9 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【0.96寸 OLED屏实现1500Fps的帧率】STM32 软件、硬件SPI、I2C驱动总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • SPI版
    • OLED SPI 端口定義
      • 七針OLED引腳定義
      • 六針OLED引腳定義
    • 軟件SPI
    • 硬件SPI
      • 啟用DMA
        • 幀率測試
  • I2C 版
    • 軟件I2C
    • 硬件I2C
      • DMA

STM32F103VET6
STM32 Cube IDE


SPI版

OLED SPI 端口定義

本節引自STM32驅動0.96寸OLED液晶屏(12864液晶屏) —— 小牧同學

兩種屏幕的引腳數不一樣,左邊的有7個引腳,而右邊的只有6個。其次,端口的標號也不完全一樣,第一個分別標為GND,VCC,D0,D1,RES,DC和CS第二個分別標為GND,VCC,SCL,SDA,RST,D/C。

七針OLED引腳定義

GND — 接地端口
VCC — 接3.3V電源端口
D0 — CLK時鐘信號(等同于上面的SCL)
D1 — 數據端口(等同于上面的SDA)
RES — 復位端口(等同于上面的RST)
DC — 數據/命令選擇引腳(等同于上面的D/C)
CS — 片選引腳(低電平有效,也就是所需要接低電平,我實際試驗過不接該引腳也是可以正常使用的)

六針OLED引腳定義

GND — 接地端口
VCC — 接3.3V電源端口
SCL — CLK時鐘信號端口
SDA — MOSI數據端口
RST — 復位端口
D/C — 數據/命令選擇引腳

軟件SPI

???????指令解讀見【51單片機快速入門指南】4.2: SSD1306 OLED屏(0.96寸、1.3寸)的I2C控制詳解

???????各引腳初始化如下,均為推挽輸出:

???????從【51單片機快速入門指南】5:軟件SPI獲取軟件SPI程序。

修改控制電平的函數:

GPIOx->BSRR = GPIO_Pin;GPIOx->BSRR = (uint32_t)GPIO_Pin << 16u;

由于我們需要的只是單向的、半雙工的SPI,只需修改部分函數即可

???????從SPI驅動0.96/1.3寸 OLED屏幕,易修改為DMA控制獲取SPI版驅動程序。
將51特色的code改為const

修改對應引腳

修改延時函數


在主函數中添加測試程序:

如圖,屏幕已輕松點亮。

幀率為180(見后文)

使用虛擬顯存是時為46幀

硬件SPI

如圖,使用硬件SPI

移除軟件SPI的程序,修改OLED_WR_Byte函數

extern SPI_HandleTypeDef hspi1; void OLED_WR_Byte(uint8_t dat, uint8_t cmd) {OLED_CS_L();if (cmd)OLED_DC_H();elseOLED_DC_L(); // SOFT_SPI_RW_MODE2(dat);HAL_SPI_Transmit(&hspi1, &dat, 1, 10);OLED_DC_H();OLED_CS_H(); }

再次測試:

成功點亮

幀率為410

在oled.h中啟用虛擬顯存

修改OLED_Refresh_Gram函數,實現1024 Byte 顯存連續寫入

extern SPI_HandleTypeDef hspi1; void OLED_Refresh_Gram(void) { #if OLED_BUFFER_MODE // uint16_t i;OLED_Set_Pos(0, 128); // for (i = 0; i < Max_Row / 8 * Max_Column; i++) // { // OLED_WR_Byte(OLED_GRAM[0][i], OLED_DATA); // }OLED_CS_L();OLED_DC_H();HAL_SPI_Transmit(&hspi1, OLED_GRAM[0], Max_Row / 8 * Max_Column, 10);OLED_DC_H();OLED_CS_H(); #endif }

再次測試,仍能成功點亮,幀率為969。

啟用DMA

再次修改OLED_Refresh_Gram函數

extern SPI_HandleTypeDef hspi1; void OLED_Refresh_Gram(void) { #if OLED_BUFFER_MODE // uint16_t i;OLED_Set_Pos(0, 128); // for (i = 0; i < Max_Row / 8 * Max_Column; i++) // { // OLED_WR_Byte(OLED_GRAM[0][i], OLED_DATA); // }OLED_CS_L();OLED_DC_H(); // HAL_SPI_Transmit(&hspi1, OLED_GRAM[0], Max_Row / 8 * Max_Column, 10);HAL_SPI_Transmit_DMA(&hspi1, OLED_GRAM[0], Max_Row / 8 * Max_Column);while(hspi1.State != HAL_SPI_STATE_READY);OLED_DC_H();OLED_CS_H(); #endif }

幀率測試

幀率的顯示:

在1ms中斷中統計1s內的幀數

在每次更新屏幕內容時FPS_Count自加1

這個幀率已經遠遠超過屏幕本身所能提供的刷新率了。

I2C 版

軟件I2C

將SCL設為推挽輸出,SDA設為開漏上拉輸出

從【51單片機快速入門指南】4.2: SSD1306 OLED屏(0.96寸、1.3寸)的I2C控制詳解和【51單片機快速入門指南】4: 軟件 I2C獲取控制程序。

修改對應引腳,其他部分同SPI的步驟。

//SCL拉高 移植時需修改 void I2C_SCL_H(void) {OLED_SCL_GPIO_Port->BSRR = OLED_SCL_Pin; }//SCL拉低 移植時需修改 void I2C_SCL_L(void) {OLED_SCL_GPIO_Port->BSRR = (uint32_t)OLED_SCL_Pin << 16u; }//SDA拉高 移植時需修改 void I2C_SDA_H(void) {OLED_SDA_GPIO_Port->BSRR = OLED_SDA_Pin; }//SDA拉低 移植時需修改 void I2C_SDA_L(void) {OLED_SDA_GPIO_Port->BSRR = (uint32_t)OLED_SDA_Pin << 16u; }//讀取SDA 移植時需修改 uint8_t I2C_SDA_Read(void) {OLED_SDA_GPIO_Port->BSRR = (uint32_t)OLED_SDA_Pin << 16u;i2c_delay();return ((OLED_SDA_GPIO_Port->IDR & OLED_SDA_Pin) == 0?0:1); }

測試:

幀率約為60幀

硬件I2C


修改OLED_WR_Byte函數

extern I2C_HandleTypeDef hi2c1; void OLED_WR_Byte(uint8_t dat, uint8_t cmd) {if (cmd)HAL_I2C_Mem_Write(&hi2c1, OLED_ADDRESS << 1, OLED_WriteData_Addr, I2C_MEMADD_SIZE_8BIT, &dat, 1, 10);elseHAL_I2C_Mem_Write(&hi2c1, OLED_ADDRESS << 1, OLED_WriteCom_Addr, I2C_MEMADD_SIZE_8BIT, &dat, 1, 10); }

此時幀率為49


開虛擬顯存模式,修改OLED_Refresh_Gram函數

extern I2C_HandleTypeDef hi2c1; void OLED_Refresh_Gram(void) { #if OLED_BUFFER_MODE // uint16_t i;OLED_Set_Pos(0, 128); // for (i = 0; i < Max_Row / 8 * Max_Column; i++) // { // OLED_WR_Byte(OLED_GRAM[0][i], OLED_DATA); // }HAL_I2C_Mem_Write(&hi2c1, OLED_ADDRESS << 1, OLED_WriteData_Addr, I2C_MEMADD_SIZE_8BIT, OLED_GRAM[0], Max_Row / 8 * Max_Column, 1000); #endif }

發現會更慢

DMA


開中斷

再次修改OLED_Refresh_Gram函數

extern I2C_HandleTypeDef hi2c1; void OLED_Refresh_Gram(void) { #if OLED_BUFFER_MODE // uint16_t i;OLED_Set_Pos(0, 128); // for (i = 0; i < Max_Row / 8 * Max_Column; i++) // { // OLED_WR_Byte(OLED_GRAM[0][i], OLED_DATA); // } // HAL_I2C_Mem_Write(&hi2c1, OLED_ADDRESS << 1, OLED_WriteData_Addr, I2C_MEMADD_SIZE_8BIT, OLED_GRAM[0], Max_Row / 8 * Max_Column, 1000);while(hi2c1.State != HAL_I2C_STATE_READY);HAL_I2C_Mem_Write_DMA(&hi2c1, OLED_ADDRESS << 1, OLED_WriteData_Addr, I2C_MEMADD_SIZE_8BIT, OLED_GRAM[0], Max_Row / 8 * Max_Column); #endif }

如圖,瓶頸應為400kHz的I2C速度

總結

以上是生活随笔為你收集整理的【0.96寸 OLED屏实现1500Fps的帧率】STM32 软件、硬件SPI、I2C驱动总结的全部內容,希望文章能夠幫你解決所遇到的問題。

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