天天看點

SSD1306驅動的OLED實驗 - vi_cc

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部分代碼(該部分我們不再這裡列出來了,請大家參考CD光牒裡面的代碼)。

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

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子產品的使用,在調試代碼的時候,又多了一種顯示資訊的途徑,在以後的程式編寫中,大家可以好好利用。