STM32 OLED屏顯示詳解


不多廢話,先看效果

       

全家福

 

觀看演示效果:

https://www.bilibili.com/video/BV13V411b78V

一、基礎認識及引腳介紹

屏幕參數:

尺寸:0.96英寸

分辨率:128*64

驅動芯片:SSD1306

驅動接口協議:SPI

引腳說明:

二、 SSD1306芯片介紹

SSD1306是一款帶控制器的用於OLED點陣圖形顯示系統的單片CMOS OLED/PLED驅動器。它由128個SEG(列輸出)和64個COM(行輸出)組成。 

SSD1306嵌入了對比度控制器、顯示RAM和振盪器,從而減少了外部組件的數量和功耗。它有256級亮度控制。數據/命令可以通用硬件選擇3種通信方式:6800/8000串口、IIC接口和SPI接口。適用於手機子顯示器、MP3播放器、計算器等多種便攜應用。

模塊有多種通信方式,包括串口、IIC、SPI,其選擇通過硬件固化,如果使用IIC通信方式時可以選擇兩個IIC地址,其分別為0x78和0x7A。

三、 通信方式(4線SPI)

所謂的4線SPI並非是收發一體的標准4線SPI協議,標准的4線SPI為SCLK、CS、MOSI、MISO,模塊所述大的4線SPI是單向的,即MISO(主入從出)變成了D/C(數據命令選擇腳)。

該4線串行接口由串行時鍾SCLK、串行數據SDIN、數據命令選擇線D/C#、片選信號CS#組成.在四線SPI模式下,D0為SCLK,D1為SDIN。

其真實使用的是標准的3線SPI,也就是省略了MISO(主入從出)數據線。

數據命令選擇:DC為高時表示數據,DC為低時表示寫命令

片選:CS腳為低電平是選中,如果不通信時將腳輸出高電平

數據通信:在SCLK的每一個上升邊上,SDIN按D7,D6,…D0,高位先寫出

通信時序圖

四、編程(CubeMX部分)

(一)   CubeMX基礎配置

選擇芯片(STM32F103C8T6)

打開外部的高速和低速晶振

所占用的引腳

 

開啟SWD調試

所占用的引腳

時鍾樹設置

設置系統時鍾為最高速度,72MHZ

(二)  GPIO初始化

初始化電平分析

D0:SCLK,時鍾線,上升沿有效,所以默認輸出高電平

D1:SDIN,數據線,默認輸出電平隨意

RST:復位腳,低電平復位,默認電平為低

DC:數據/命令選擇腳,默認輸出電平隨意

CS:片選引腳,默認輸出高電平

引腳選擇

使用單片機是STM32F103C8T6

考慮到已經使用的IO和硬件上的布局,最好是將一個模塊的相關線放在一起,所以選擇如下接線方式:

D0   ---->  B5

D1   ---->  B6

RST  ---->  B7

DC   ---->  B8

CS   ---->  B9

(三)  CubeMX GPIO配置

所使用的IO

(四) 整體配置圖

五、 編程(程序部分)

(一)    分析原理

有IIC通信方式為什么要有SPI,我看可以簡單對比一下:

IIC通信方式:兩條數據線,通信數據較慢

SPI通信方式:四條數據線,通信數據腳快

這就看項目需要,如果需要刷屏速度的話當然選用SPI方式優秀

在此之前要知道,OLED SPI通信中不需要單片機讀取OLED模塊的任何數據,所以單片機按照一定的規則向SPI線上寫數據就可以了。在通信中單片機充當SPI的主機,OLED模塊為SPI的從機。因為主機不需要接收從機數據,所以標准的四線SPI中MISO線就沒必要存在了。通信使用的是標准的三線SPI,即CS、CLK、MOSI。

根據這個時序圖就可以了解如何變成,在CS為低電平時就是芯片通信啟動;D/C是數據或者命令的選擇,也就是主機拉高拉低可以控制寫的數據是指令還是數據;SCLK(D0)是時鍾引腳,MOSI (D1 SDIN)為數據已經。當SCLK上升沿的瞬間,從機將會讀取MOSI上的電平。發送一個字節時,是高位在前低位在后的。

所以發送一個字節大的函數,這實現了單向的數據傳輸SPI

實現步驟:

l  先保證時鍾線默認為低電平

l  循環發送8位數據,發送最高位數據:

|  設置時鍾線為低電平

|   判斷發送的數據是1還是0,1則發送高電平,0則低低電平

|   設置時鍾線為高電平(此時有上升沿)

l  數據左移一位,讓次高位在最高位上

l  循環發送8位數據,發送次高位數據:

|   設置時鍾線為低電平

|   判斷發送的數據是1還是0,1則發送高電平,0則低低電平

|   設置時鍾線為高電平(此時有上升沿)

l  數據左移一位,……

l  ……

l  保證時鍾線最終為高電平

代碼,需要交流可加本人微信,見文章結尾

數據和命令分發:

OLED SPI方式為了更快的數據交互,有一個專門的引腳作為數據和命令選擇腳,而IIC還要靠發送數據去做判斷,可想而知他們的速率會有相差。

D/C引腳就是數據/命令選擇,低電平寫命令,高電平寫數據

設計思路:

l  如果是命令,則拉高DC引腳

l  如果不是命令,則拉低DC引腳

l  CS引腳拉低表示選中從機,開啟通信

l  發送一個數據,則調用了前面的標准3線SPI通信函數

l  拉高DC引腳

l  拉高CS引腳,關閉通信

代碼,需要交流可加本人微信,見文章結尾

六、OLED進階版及曲線顯示

(一)驅動分析

想要了解OLED顯示曲線就必須了解其顯示本質,更加底層細致的分析寄存器及顯示原理。

0.96寸的12864 OLED屏幕由128*64個發光二極管組成。

這是數據手冊的截圖

注意圖總的黑色和綠色,它只是告訴你可以反向,也就是0編號的位置可以換成127編號而已。

由此可見屏幕總共分為8頁(page),每頁占用Y軸的8行發光二極管和X軸的128個發光二極管,所以一頁總共占用8*128=1024個發光二極管。

所以在真實的圖中表示:

這是數據手冊中其中一頁的表示

這是基於沒有做反轉時的介紹,如果反轉了就不是這樣了。反轉是在程序初始化是調用的,后面分析的初始化函數有介紹

其中“Each lattice represents one bit of image data”的翻譯是“每個格子代表一個圖像數據位”,因為一頁剛好8個Y方向的各種,對應的剛好是U8類型,所以我們通常用一個U8表示一頁里的一個列的顯示,一頁中共有128個列,所以一頁總共需要1*128=128個U8類型數據。並且從圖中可以看出,最下面的是最高位。

舉個栗子:

假如我們拿第二頁的第一列來說,其值的二進制為11110000,其實點亮的是如下圖的紅色部分。

這也就說明高位點亮的是下面的位置。

(二)初始化函數及逐條分析

復制代碼
 1 void my_oled_init(){
 2   my_oled_rst();
 3     my_oled_write_byte(0xAE,OLED_CMD);//關閉顯示
 4     
 5     my_oled_write_byte(0x00,OLED_CMD);//X軸低位,起始X軸為0
 6     my_oled_write_byte(0x10,OLED_CMD);//X軸高位
 7     my_oled_write_byte(0x40,OLED_CMD);//Y軸,可設區間[0x40,0x7F],設置為0了
 8     
 9 
10     my_oled_write_byte(0xA1,OLED_CMD);//設置X軸掃描方向,0xa0左右反置 ,0xa1正常(左邊為0列)
11     my_oled_write_byte(0xC8,OLED_CMD);//設置Y軸掃描方向,0xc0上下反置 ,0xc8正常(上邊為0行)
12     my_oled_write_byte(0xA6,OLED_CMD);//位值表示的意義,0xa6表示正常,1為點亮,0為關閉,0xa7顯示效果相反
13     
14 
15     my_oled_write_byte(0x81,OLED_CMD);//命令頭,調節亮度,對比度,變化很小,但是仔細可以觀察出來
16     my_oled_write_byte(0xFF,OLED_CMD);//可設置區間[0x00,0xFF]
17     
18     my_oled_write_byte(0xA8,OLED_CMD);//命令頭,設置多路復用率(1 to 64)
19     my_oled_write_byte(0x3f,OLED_CMD);//--1/64 duty
20     
21     my_oled_write_byte(0xD3,OLED_CMD);//命令頭,設置顯示偏移移位映射RAM計數器(0x00~0x3F)
22     my_oled_write_byte(0x00,OLED_CMD);//不偏移
23     
24     my_oled_write_byte(0xd5,OLED_CMD);//命令頭,設置顯示時鍾分頻比/振盪器頻率
25     my_oled_write_byte(0x80,OLED_CMD);//設置分割比率,設置時鍾為100幀/秒
26     
27     my_oled_write_byte(0xD9,OLED_CMD);//命令頭,--set pre-charge period
28     my_oled_write_byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
29     
30     my_oled_write_byte(0xDA,OLED_CMD);//命令頭,--set com pins hardware configuration
31     my_oled_write_byte(0x12,OLED_CMD);
32     
33     my_oled_write_byte(0xDB,OLED_CMD);//命令頭,--set vcomh
34     my_oled_write_byte(0x40,OLED_CMD);//Set VCOM Deselect Level
35     
36     my_oled_write_byte(0x20,OLED_CMD);//命令頭,設置尋址模式
37     my_oled_write_byte(0x10,OLED_CMD);//頁面尋址模式(重置) (0x00/0x01/0x02)
38     
39     my_oled_write_byte(0x8D,OLED_CMD);//命令頭,--set Charge Pump enable/disable
40     my_oled_write_byte(0x14,OLED_CMD);//--set(0x10) disable
41     
42     my_oled_write_byte(0xA4,OLED_CMD);//恢復到RAM內容顯示(重置)
43 
44     my_oled_clear();//清屏
45     
46     my_oled_write_byte(0xAF,OLED_CMD); //開啟顯示
47 
48 }
復制代碼

局部分析:

設置尋址模式

A[1:0] = 00b,水平尋址模式

A[1:0] = 01b,垂直尋址模式

A[1:0] = 10b,頁面尋址模式(重置)

A[1:0] = 11b,無效

00b,水平尋址模式

01b,垂直尋址模式

10b,頁面尋址模式

尋址模式對應着我們的取模:

我們取模軟件設置的刷新方式:

從左到右從上到下:對應了頁面尋址模式

縱向8點下高位:縱向右8個點,最下面的點為最高位

...

  (三)  寄存器配置補充(詳細)

...


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM