OLED的波形曲線、進度條、圖片顯示(STM32 HAL庫 模擬SPI通訊 5線OLED螢幕)詳細篇

東小東發表於2021-01-25

少廢話,先上效果圖

螢幕顯示效果

       

全家福

 

觀看演示效果:

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個點,最下面的點為最高位

其它相關逐條分析內容,可加本人微信獲取,見文末

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

需要資料可加本人微信,見文末

 


 

 

觀看演示效果:https://www.bilibili.com/video/BV13V411b78V

 

原文連結:https://www.cnblogs.com/dongxiaodong/p/14321569.html

 

如需資料可加本人微信

 

微訊號:dongxiaodongwx

 

相關文章