SSD1306驅動的OLED實驗


【轉】http://bbs.21ic.com/icview-434543-1-1.html

 

前面幾章的實例,均沒涉及到液晶顯示,這一章,我們將向大家介紹OLED的使用。在本章中,我們將使用戰艦STM32開發板上的OLED模塊接口(與攝像頭共用的這個),來點亮OLED,並實現ASCII字符的顯示。本章分為如下幾個部分:

17.1 OLED簡介

17.2 硬件設計

17.3 軟件設計

17.4 下載驗證

17.1 OLED簡介

OLED,即有機發光二極管(Organic Light-Emitting Diode),又稱為有機電激光顯示(Organic Electroluminesence Display, OELD)。OLED由於同時具備自發光,不需背光源、對比度高、厚度薄、視角廣、反應速度快、可用於撓曲性面板、使用溫度范圍廣、構造及制程較簡單等優異之特性,被認為是下一代的平面顯示器新興應用技術。

LCD都需要背光,而OLED不需要,因為它是自發光的。這樣同樣的顯示,OLED效果要來得好一些。以目前的技術,OLED的尺寸還難以大型化,但是分辨率確可以做到很高。在本章中,我們使用的是ALINETEK的OLED顯示模塊,該模塊有以下特點:

1)模塊有單色和雙色兩種可選,單色為純藍色,而雙色則為黃藍雙色。

2)尺寸小,顯示尺寸為0.96寸,而模塊的尺寸僅為27mm*26mm大小。

3)高分辨率,該模塊的分辨率為128*64。

4)多種接口方式,該模塊提供了總共5種接口包括:6800、8080兩種並行接口方式、3線或4線的穿行SPI接口方式,、IIC接口方式(只需要2根線就可以控制OLED了!)。

5)不需要高壓,直接接3.3V就可以工作了。

這里要提醒大家的是,該模塊不和5.0V接口兼容,所以請大家在使用的時候一定要小心,別直接接到5V的系統上去,否則可能燒壞模塊。以上5種模式通過模塊的BS0~2設置,BS0~2的設置與模塊接口模式的關系如表17.1.1所示:


                       表17.1.1 OLED模塊接口方式設置表

表17.1.1中:“1”代表接VCC,而“0”代表接GND。

該模塊的外觀圖如圖17.1.1所示:



圖17.1.1 ALIENTEK OLED模塊外觀圖

ALIENTEK OLED模塊默認設置的是BS0接GND,BS1和BS2接VCC ,即使用8080並口方式,如果你想要設置為其他模式,則需要在OLED的背面,用烙鐵修改BS0~2的設置。

模塊的原理圖如圖17.1.2所示:

圖17.1.2 ALIENTEK OLED模塊原理圖

該模塊采用8*2的2.54排針與外部連接,總共有16個管腳,在16條線中,我們只用了15條,有一個是懸空的。15條線中,電源和地線占了2條,還剩下13條信號線。在不同模式下,我們需要的信號線數量是不同的,在8080模式下,需要全部13條,而在IIC模式下,僅需要2條線就夠了!這其中有一條是共同的,那就是復位線RST(RES),RST上的低電平,將導致OLED復位,在每次初始化之前,都應該復位一下OLED模塊。

ALIENTEK OLED模塊的控制器是SSD1306,本章,我們將學習如何通過STM32來控制該模塊顯示字符和數字,本章的實例代碼將可以支持2種方式與OLED模塊連接,一種是8080的並口方式,另外一種是4線SPI方式。

首先我們介紹一下模塊的8080並行接口,8080並行接口的發明者是INTEL,該總線也被廣泛應用於各類液晶顯示器,ALIENTEK OLED模塊也提供了這種接口,使得MCU可以快速的訪問OLED。ALIENTEK OLED模塊的8080接口方式需要如下一些信號線:

       CS:OLED片選信號。

       WR:向OLED寫入數據。

       RD:從OLED讀取數據。

       D[7:0]:8位雙向數據線。

       RST(RES):硬復位OLED。

       DC:命令/數據標志(0,讀寫命令;1,讀寫數據)。

模塊的8080並口讀/寫的過程為:先根據要寫入/讀取的數據的類型,設置DC為高(數據)/低(命令),然后拉低片選,選中SSD1306,接着我們根據是讀數據,還是要寫數據置RD/WR為低,然后:

在RD的上升沿, 使數據鎖存到數據線(D[7:0])上;

在WR的上升沿,使數據寫入到SSD1306里面;

SSD1306的8080並口寫時序圖如圖17.1.3所示:



圖17.1.3  8080並口寫時序圖

SSD1306的8080並口讀時序圖如圖17.1.4所示:



圖17.1.4  8080並口讀時序圖

SSD1306的8080接口方式下,控制腳的信號狀態所對應的功能如表17.1.2:

功能

RD

WR

CS

DC

寫命令

H

L

L

讀狀態

H

L

L

寫數據

H

L

H

讀數據

H

L

H


                             表17.1.2  控制腳信號狀態功能表

在8080方式下讀數據操作的時候,我們有時候(例如讀顯存的時候)需要一個假讀命(Dummy Read),以使得微控制器的操作頻率和顯存的操作頻率相匹配。在讀取真正的數據之前,由一個的假讀的過程。這里的假讀,其實就是第一個讀到的字節丟棄不要,從第二個開始,才是我們真正要讀的數據。

一個典型的讀顯存的時序圖,如圖17.1.5所示:


圖17.1.5  讀顯存時序圖

可以看到,在發送了列地址之后,開始讀數據,第一個是Dummy Read,也就是假讀,我們從第二個開始,才算是真正有效的數據。

並行接口模式就介紹到這里,我們接下來介紹一下4線串行(SPI)方式,4先串口模式使用的信號線有如下幾條:

CS:OLED片選信號。

RST(RES):硬復位OLED。

DC:命令/數據標志(0,讀寫命令;1,讀寫數據)。

SCLK:串行時鍾線。在4線串行模式下,D0信號線作為串行時鍾線SCLK。

SDIN:串行數據線。在4線串行模式下,D1信號線作為串行數據線SDIN。

模塊的D2需要懸空,其他引腳可以接到GND。在4線串行模式下,只能往模塊寫數據而不能讀數據。

在4線SPI模式下,每個數據長度均為8位,在SCLK的上升沿,數據從SDIN移入到SSD1306,並且是高位在前的。DC線還是用作命令/數據的標志線。在4線SPI模式下,寫操作的時序如圖17.1.6所示:

圖17.1.6 4線SPI寫操作時序圖

4線串行模式就為大家介紹到這里。其他還有幾種模式,在SSD1306的數據手冊上都有詳細的介紹,如果要使用這些方式,請大家參考該手冊。

接下來,我們介紹一下模塊的顯存,SSD1306的顯存總共為128*64bit大小,SSD1306將這些顯存分為了8頁,其對應關系如表17.1.3所示:

表17.1.3  SSD1306顯存與屏幕對應關系表

可以看出,SSD1306的每頁包含了128個字節,總共8頁,這樣剛好是128*64的點陣大小。因為每次寫入都是按字節寫入的,這就存在一個問題,如果我們使用只寫方式操作模塊,那么,每次要寫8個點,這樣,我們在畫點的時候,就必須把要設置的點所在的字節的每個位都搞清楚當前的狀態(0/1?),否則寫入的數據就會覆蓋掉之前的狀態,結果就是有些不需要顯示的點,顯示出來了,或者該顯示的沒有顯示了。這個問題在能讀的模式下,我們可以先讀出來要寫入的那個字節,得到當前狀況,在修改了要改寫的位之后再寫進GRAM,這樣就不會影響到之前的狀況了。但是這樣需要能讀GRAM,對於3線或4線SPI模式,模塊是不支持讀的,而且讀->改->寫的方式速度也比較慢。

所以我們采用的辦法是在STM32的內部建立一個OLED的GRAM(共128*8個字節),在每次修改的時候,只是修改STM32上的GRAM(實際上就是SRAM),在修改完了之后,一次性把STM32上的GRAM寫入到OLED的GRAM。當然這個方法也有壞處,就是對於那些SRAM很小的單片機(比如51系列)就比較麻煩了。

SSD1306的命令比較多,這里我們僅介紹幾個比較常用的命令,這些命令如表17.1.4所示:

表17.1.4  SSD1306常用命令表

第一個命令為0X81,用於設置對比度的,這個命令包含了兩個字節,第一個0X81為命令,隨后發送的一個字節為要設置的對比度的值。這個值設置得越大屏幕就越亮。

第二個命令為0XAE/0XAF。0XAE為關閉顯示命令;0XAF為開啟顯示命令。

第三個命令為0X8D,該指令也包含2個字節,第一個為命令字,第二個為設置值,第二個字節的BIT2表示電荷泵的開關狀態,該位為1,則開啟電荷泵,為0則關閉。在模塊初始化的時候,這個必須要開啟,否則是看不到屏幕顯示的。

第四個命令為0XB0~B7,該命令用於設置頁地址,其低三位的值對應着GRAM的頁地址。

第五個指令為0X00~0X0F,該指令用於設置顯示時的起始列地址低四位。

第六個指令為0X10~0X1F,該指令用於設置顯示時的起始列地址高四位。

其他命令,我們就不在這里一一介紹了,大家可以參考SSD1306 datasheet的第28頁。從這頁開始,對SSD1306的指令有詳細的介紹。

最后,我們再來介紹一下OLED模塊的初始化過程,SSD1306的典型初始化框圖如圖17.1.7所示:

圖17.1.7  SSD1306初始化框圖

驅動IC的初始化代碼,我們直接使用廠家推薦的設置就可以了,只要對細節部分進行一些修改,使其滿足我們自己的要求即可,其他不需要變動。

OLED的介紹就到此為止,我們重點向大家介紹了ALIENTEK OLED模塊的相關知識,接下來我們將使用這個模塊來顯示字符和數字。通過以上介紹,我們可以得出OLED顯示需要的相關設置步驟如下:

1)設置STM32與OLED模塊相連接的IO。

這一步,先將我們與OLED模塊相連的IO口設置為輸出,具體使用哪些IO口,這里需要根據連接電路以及OLED模塊所設置的通訊模式來確定。這些將在硬件設計部分向大家介紹。

2)初始化OLED模塊。

其實這里就是上面的初始化框圖的內容,通過對OLED相關寄存器的初始化,來啟動OLED的顯示。為后續顯示字符和數字做准備。

3)通過函數將字符和數字顯示到OLED模塊上。

這里就是通過我們設計的程序,將要顯示的字符送到OLED模塊就可以了,這些函數將在軟件設計部分向大家介紹。

通過以上三步,我們就可以使用ALIENTEK OLED模塊來顯示字符和數字了,在后面我們還將會給大家介紹顯示漢字的方法。這一部分就先介紹到這里。


17.2 硬件設計

本實驗用到的硬件資源有:

1)  指示燈DS0

2)  OLED模塊

OLED模塊的電路在17.1節已有詳細說明了,這里我們介紹OLED模塊與ALIETEK 戰艦STM32開發板的連接,戰艦STM32開發板有兩個地方可以接OLED模塊,第一個是左下角的攝像頭模塊/OLED模塊共用接口,第二個是LCD模塊和OLED模塊的共用接口,不論哪個共用接口,OLED都是靠左插的。這里我們選擇攝像頭模塊/OLED模塊共用接口來接OLED模塊,OLED模塊同戰艦STM32開發板的連接圖如圖17.2.1所示:



圖17.2.1 OLED模塊與開發板連接示意圖

圖中圈出來的部分就是連接OLED的接口,這里在硬件上,OLED與戰艦STM32開發板的IO口對應關系如下:

       OLED_CS對應PD6;

OLED_RST對應PG15;

       OLED_RS對應PD3;

       OLED_WR對應PG14;

       OLED_RD對應PG13;

       OLED_D[7:0]對應PC[7:0];

這些線的連接,戰艦STM32的內部已經連接好了,我們只需要將OLED模塊插上去就好了。實物連接如圖17.2.2所示:

圖17.2.2 OLED模塊與開發板連接實物圖





 
 
 
 
 
 

 

   
 
 
 


17.3 軟件設計

軟件設計我們依舊在之前的工程上面增加,首先在HARDWARE文件夾下新建一個OLED的文件夾。然后打開USER文件夾下的工程,新建一個oled.c的文件和oled.h的頭文件,保存在OLED文件夾下,並將OLED文件夾加入頭文件包含路徑。

oled.c的代碼,由於比較長,這里我們就不貼出來了,僅介紹幾個比較重要的函數。首先是OLED_Init函數,該函數的結構比較簡單,開始是對IO口的初始化,這里我們用了宏定義OLED_MODE來決定要設置的IO口,其他就是一些初始化序列了,我們按照廠家提供的資料來做就可以。最后要說明一點的是,因為OLED是無背光的,在初始化之后,我們把顯存都清空了,所以我們在屏幕上是看不到任何內容的,跟沒通電一個樣,不要以為這就是初始化失敗,要寫入數據模塊才會顯示的。OLED_Init函數代碼如下:  

//初始化SSD1306                                

void OLED_Init(void)

{                                                                  

       RCC->APB2ENR|=1<<4;    //使能PORTC時鍾

       RCC->APB2ENR|=1<<5;    //使能PORTD時鍾

       RCC->APB2ENR|=1<<8;    //使能PORTG時鍾

      GPIOD->CRL&=0XF0FF0FFF;//PD3,6推挽輸出

      GPIOD->CRL|=0X03003000;      

      GPIOD->ODR|=1<<3;

      GPIOD->ODR|=1<<6;      

#if OLED_MODE==1   

       GPIOC->CRL=0X33333333; //PC0~7 OUT

       GPIOC->ODR|=0X00FF;            

      GPIOG->CRH&=0X000FFFFF;//PG13,14,15 OUT

      GPIOG->CRH|=0X33300000;      

       GPIOG->ODR|=7<<13;

#else

       GPIOC->CRL&=0XFFFFFF00; //PC0,1 OUT

       GPIOC->CRL|=0X00000033;         

      GPIOC->ODR|=3<<0;

      GPIOG->CRH&=0X0FFFFFFF;//RST   

      GPIOG->CRH|=0X30000000;      

       GPIOG->ODR|=1<<15;

#endif                                                               

       OLED_RST=0;                                 //復位

       delay_ms(100);

       OLED_RST=1;                                   

       OLED_WR_Byte(0xAE,OLED_CMD);//關閉顯示

       OLED_WR_Byte(0xD5,OLED_CMD);//設置時鍾分頻因子,震盪頻率

       OLED_WR_Byte(80,OLED_CMD);  //[3:0],分頻因子;[7:4],震盪頻率

       OLED_WR_Byte(0xA8,OLED_CMD);//設置驅動路數

       OLED_WR_Byte(0X3F,OLED_CMD);//默認0X3F(1/64)

       OLED_WR_Byte(0xD3,OLED_CMD);//設置顯示偏移

       OLED_WR_Byte(0X00,OLED_CMD);//默認為0

       OLED_WR_Byte(0x40,OLED_CMD);//設置顯示開始行 [5:0],行數.                              

       OLED_WR_Byte(0x8D,OLED_CMD);//電荷泵設置

       OLED_WR_Byte(0x14,OLED_CMD);//bit2,開啟/關閉

       OLED_WR_Byte(0x20,OLED_CMD);//設置內存地址模式

       OLED_WR_Byte(0x02,OLED_CMD);

//[1:0],00,列地址模式;01,行地址模式;10,頁地址模式;默認10;

       OLED_WR_Byte(0xA1,OLED_CMD);//段重定義設置,bit0:0,0->0;1,0->127;

       OLED_WR_Byte(0xC0,OLED_CMD);

//設置COM掃描方向;bit3:0,普通模式;1,重定義模式 COM[N-1]->COM0;N:驅動路數

       OLED_WR_Byte(0xDA,OLED_CMD);//設置COM硬件引腳配置

       OLED_WR_Byte(0x12,OLED_CMD);//[5:4]配置            

       OLED_WR_Byte(0x81,OLED_CMD);//對比度設置

       OLED_WR_Byte(0xEF,OLED_CMD);//1~255;默認0X7F (亮度設置,越大越亮)

       OLED_WR_Byte(0xD9,OLED_CMD);//設置預充電周期

       OLED_WR_Byte(0xf1,OLED_CMD);//[3:0],PHASE 1;[7:4],PHASE 2;

       OLED_WR_Byte(0xDB,OLED_CMD);//設置VCOMH 電壓倍率

       OLED_WR_Byte(0x30,OLED_CMD);//[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;

       OLED_WR_Byte(0xA4,OLED_CMD);//全局顯示開啟;bit0:1,開啟;0,關閉;(白屏/黑屏)

       OLED_WR_Byte(0xA6,OLED_CMD);//設置顯示方式;bit0:1,反相顯示;0,正常顯示        

       OLED_WR_Byte(0xAF,OLED_CMD);//開啟顯示     

       OLED_Clear();

}  

接着,要介紹的是OLED_Refresh_Gram函數。我們在STM32內部定義了一個塊GRAM:u8 OLED_GRAM[128][8];此部分GRAM對應OLED模塊上的GRAM。在操作的時候,我們只要修改STM32內部的GRAM就可以了,然后通過OLED_Refresh_Gram函數把GRAM一次刷新到OLED 的GRAM上。該函數代碼如下:

//更新顯存到LCD        

void OLED_Refresh_Gram(void)

{

       u8 i,n;               

       for(i=0;i<8;i++)  

       {  

              OLED_WR_Byte (0xb0+i,OLED_CMD);    //設置頁地址(0~7)

              OLED_WR_Byte (0x00,OLED_CMD);      //設置顯示位置—列低地址

              OLED_WR_Byte (0x10,OLED_CMD);      //設置顯示位置—列高地址   

              for(n=0;n<128;n++)OLED_WR_Byte(OLED_GRAM[n],OLED_DATA);

       }   

}

OLED_Refresh_Gram函數先設置頁地址,然后寫入列地址(也就是縱坐標),然后從0開始寫入128個字節,寫滿該頁,最后循環把8頁的內容都寫入,就實現了整個從STM32顯存到OLED顯存的拷貝。

OLED_Refresh_Gram函數還用到了一個外部函數,也就是我們接着要介紹的函數:OLED_WR_Byte,該函數直接和硬件相關,函數代碼如下:

#if OLED_MODE==1

//向SSD1306寫入一個字節。

//dat:要寫入的數據/命令

//cmd:數據/命令標志 0,表示命令;1,表示數據;

void OLED_WR_Byte(u8 dat,u8 cmd)

{

       DATAOUT(dat);         

      OLED_RS=cmd;

       OLED_CS=0;   

       OLED_WR=0;      

       OLED_WR=1;

       OLED_CS=1;   

       OLED_RS=1;

}                    

#else

//向SSD1306寫入一個字節。

//dat:要寫入的數據/命令

//cmd:數據/命令標志 0,表示命令;1,表示數據;

void OLED_WR_Byte(u8 dat,u8 cmd)

{     

       u8 i;               

       OLED_RS=cmd; //寫命令

       OLED_CS=0;         

       for(i=0;i<8;i++)

       {                     

              OLED_SCLK=0;

              if(dat&0x80)OLED_SDIN=1;

              else OLED_SDIN=0;

              OLED_SCLK=1;

              dat<<=1;   

       }                          

       OLED_CS=1;         

       OLED_RS=1;        

}

#endif

這里有2個一樣的函數,通過宏定義OLED_MODE來決定使用哪一個。如果OLED_MODE=1,就定義為並口模式,選擇第一個函數,而如果為0,則為4線串口模式,選擇第二個函數。這兩個函數輸入參數均為2個:dat和cmd,dat為要寫入的數據,cmd則表明該數據是命令還是數據。這兩個函數的時序操作就是根據上面我們對8080接口以及4線SPI接口的時序來編寫的。

OLED_GRAM[128][8]中的128代表列數(x坐標),而8代表的是頁,每頁又包含8行,總共64行(y坐標)。從高到低對應行數從小到大。比如,我們要在x=100,y=29這個點寫入1,則可以用這個句子實現:

                                          OLED_GRAM[100][4]|=1<<2;

一個通用的在點(x,y)置1表達式為:

                                          OLED_GRAM[x][7-y/8]|=1<<(7-y%8);

其中x的范圍為:0~127;y的范圍為:0~63。

因此,我們可以得出下一個將要介紹的函數:畫點函數,void OLED_DrawPoint(u8 x,u8 y,u8 t);函數代碼如下:

void OLED_DrawPoint(u8 x,u8 y,u8 t)

{

       u8 pos,bx,temp=0;

       if(x>127||y>63)return;//超出范圍了.

       pos=7-y/8;

       bx=y%8;

       temp=1<<(7-bx);

       if(t)OLED_GRAM[x][pos]|=temp;

       else OLED_GRAM[x][pos]&=~temp;      

}

該函數有3個參數,前兩個是坐標,第三個t為要寫入1還是0。該函數實現了我們在OLED模塊上任意位置畫點的功能。      

在介紹完畫點函數之后,我們介紹一下顯示字符函數,OLED_ShowChar,在介紹之前,我們來介紹一下字符(ASCII字符集)是怎么顯示在OLED模塊上去的。要顯示字符,我們先要有字符的點陣數據,ASCII常用的字符集總共有95個,從空格符開始,分別為: !"#$%&'()*+,-0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~.

我們先要得到這個字符集的點陣數據,這里我們介紹一個款很好的字符提取軟件:PCtoLCD2002完美版。該軟件可以提供各種字符,包括漢字(字體和大小都可以自己設置)陣提取,且取模方式可以設置好幾種,常用的取模方式,該軟件都支持。該軟件還支持圖形模式,也就是用戶可以自己定義圖片的大小,然后畫圖,根據所畫的圖形再生成點陣數據,這功能在制作圖標或圖片的時候很有用。

該軟件的界面如圖17.3.1所示:

圖17.3.1 PCtoLCD2002軟件界面

然后我們選擇設置,在設置里面設置取模方式如圖17.3.2所示:

圖17.3.2 設置取模方式

上圖設置的取模方式,在右上角的取模說明里面有,即:從第一列開始向下每取8個點作為一個字節,如果最后不足8個點就補滿8位。取模順序是從高到低,即第一個點作為最高位。如*-------取為10000000。其實就是按如圖17.3.3所示的這種方式:

圖17.3.3 取模方式圖解

從上到下,從左到右,高位在前。我們按這樣的取模方式,然后把ASCII字符集按12*6大小和16*0大小取模出來(對應漢字大小為12*12和16*16,字符的只有漢字的一半大!),保存在oledfont.h里面,每個12*6的字符占用12個字節,每個16*8的字符占用16個字節。具體見oledfont.h部分代碼(該部分我們不再這里列出來了,請大家參考光盤里面的代碼)。

在知道了取模方式之后,我們就可以根據取模的方式來編寫顯示字符的代碼了,這里我們針對以上取模方式的顯示字符代碼如下:

void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)

{                          

       u8 temp,t,t1;

       u8 y0=y;

       chr=chr-' ';//得到偏移后的值                              

   for(t=0;t<size;t++)

    {   

              if(size==12)temp=oled_asc2_1206[chr][t];  //調用1206字體

              else temp=oled_asc2_1608[chr][t];              //調用1608字體                                 

       for(t1=0;t1<8;t1++)

              {

                     if(temp&0x80)OLED_DrawPoint(x,y,mode);

                     else OLED_DrawPoint(x,y,!mode);

                     temp<<=1;

                     y++;

                     if((y-y0)==size)

                     {

                            y=y0;

                            x++;

                            break;

                     }

              }     

    }         

}

該函數為字符以及字符串顯示的核心部分,函數中chr=chr-' ';這句是要得到在字符點陣數據里面的實際地址,因為我們的取模是從空格鍵開始的,例如oled_asc2_1206[0][0],代表的是空格符開始的點陣碼。在接下來的代碼,我們也是按照從上到小,從左到右的取模方式來編寫的,先得到最高位,然后判斷是寫1還是0,畫點;接着讀第二位,如此循環,直到一個字符的點陣全部取完為止。這其中涉及到列地址和行地址的自增,根據取模方式來理解,就不難了。

oled.c的內容就為大家介紹到這里,將oled.c保存,然后加入到HARDWARE組下。接下來我們在oled.h中輸入如下代碼:

#ifndef __OLED_H

#define __OLED_H                           

#include "sys.h"

#include "stdlib.h"      

//OLED模式設置

//0:4線串行模式

//1:並行8080模式

#define OLED_MODE      1     

//---------------------------OLED端口定義--------------------------                                   

#define OLED_CS PDout(6)

#define OLED_RST PGout(15)   

#define OLED_RS PDout(3)

#define OLED_WR PGout(14)            

#define OLED_RD PGout(13)      

//PC0~7,作為數據線

#define DATAOUT(x) GPIOC->ODR=(GPIOC->ODR&0xff00)|(x&0x00FF); //輸出  

//使用4線串行接口時使用

#define OLED_SCLK PCout(0)

#define OLED_SDIN PCout(1)               

#define OLED_CMD 0       //寫命令

#define OLED_DATA 1 //寫數據

//OLED控制用函數

void OLED_WR_Byte(u8 dat,u8 cmd);         

void OLED_Display_On(void);

void OLED_Display_Off(void);

void OLED_Refresh_Gram(void);                                                                  

void OLED_Init(void);

void OLED_Clear(void);

void OLED_DrawPoint(u8 x,u8 y,u8 t);

void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot);

void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode);

void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size);

void OLED_ShowString(u8 x,u8 y,const u8 *p);

#endif  

該部分比較簡單,OLED_MODE的定義也在這個文件里面,我們必須根據自己OLED模塊BS0~2的設置(目前代碼僅支持8080和4線SPI)來確定OLED_MODE的值。

保存好oled.h之后,我們就可以在主程序里面編寫我們的應用層代碼了,該部分代碼如下:

int main(void)

{

      u8 t;

      Stm32_Clock_Init(9);    //系統時鍾設置

       uart_init(72,9600);      //串口初始化為9600

       delay_init(72);                  //延時初始化

       LED_Init();                //初始化與LED連接的硬件接口

      OLED_Init();                //初始化液晶      

      OLED_ShowString(0,0, "0.96' OLED TEST");  

      OLED_ShowString(0,16,"ATOM@ALIENTEK");  

      OLED_ShowString(0,32,"2010/06/3");  

      OLED_ShowString(0,48,"ASCII:");  

      OLED_ShowString(63,48,"CODE:");  

       OLED_Refresh_Gram();      

       t=' ';

       while(1)

       {            

              OLED_ShowChar(48,48,t,16,1);//顯示ASCII字符      

              OLED_Refresh_Gram();

              t++;

              if(t>'~')t=' ';

              OLED_ShowNum(103,48,t,3,16);//顯示ASCII字符的碼值

              delay_ms(300);

              LED0=!LED0;

       }      

}

該部分代碼用於在OLED上顯示一些字符,然后從空格鍵開始不停的循環顯示ASCII字符集,並顯示該字符的ASCII值。注意在test.c文件里面包含oled.h頭文件,同時把oled.c文件加入到HARDWARE組下,然后我們編譯此工程,直到編譯成功為止。

17.4 下載驗證

將代碼下載到戰艦STM32后,可以看到DS0不停的閃爍,提示程序已經在運行了。同時可以看到OLED模塊顯示如圖17.4.1所示:


圖17.4.1 OLED顯示效果

最后一行不停的顯示ASCII字符以及其碼值。通過這一章的學習,我們學會了ALIENTEK OLED模塊的使用,在調試代碼的時候,又多了一種顯示信息的途徑,在以后的程序編寫中,大家可以好好利用。


免責聲明!

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



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