1、學習 SSD1306 型OLED的使用,區別8088與080 接口以及 4 線 SPI接口的寫數據與命令的區別。
2、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 並口寫時序圖如圖:
實現代碼爲:
//向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;
}
SPI 模式:
SPI的通信原理很簡單,它以主從方式工作,這種模式通常有一個主設備和一個或多個從設備,需要至少4根線,事實上3根也可以(單向傳輸時)。也是所有基於SPI的設備共有的,它們是SDI(數據輸入)、SDO(數據輸出)、SCLK(時鐘)、CS(片選)。
(1)SDO – 主設備數據輸出,從設備數據輸入;
(2)SDI – 主設備數據輸入,從設備數據輸出;
(3)SCLK – 時鐘信號,由主設備產生;
(4)CS – 從設備使能信號,由主設備控制。
其數據寫入方式:
實現代碼:基本思路是在8個時鐘週期內,將數據的最高位與0x80進行比較,如果爲真,寄存器將記錄下數值。
//向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;
}
3、字符集點陣的製作,可以參考以下鏈接:
http://blog.csdn.net/exbob/article/details/6532772
http://wenku.baidu.com/link?url=F6tJTZcH6AYxGOaX_-YqFx0-OsPmUd7zxPTZRGiVK0AwHxrtAvX0I11dDP6zMKOqDlAjC2GxnmdKx6i7v-lBf94kvA0H2mXrsQQCidYT-JS
同時我們可以用以下的代碼實現字符點陣的顯示,思路就是首先判斷字體一個字符對應點陣集所需要佔的字節數,然後在確定所要顯示的字符與空格符的相差數值,因爲我們所
編寫的字符點陣是從空格符開始,兩者相減得到的數值就是該字符在字符點陣中的行數。一個字節又有8個位,我們在每一個字節數中都對每一位進行一次判斷,(通過數據
的左移,最高位與0x80進行與運算)。
//在指定位置顯示一個字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白顯示;1,正常顯示
//size:選擇字體 16/12
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)
{
u8 temp,t,t1;
u8 y0=y;
u8 csize=(size/8+((size%8)?1:0))*(size/2);//得到字體一個字符對應點陣集所佔的字節數
chr=chr-' ';//得到偏移後的值
for(t=0;t<csize;t++)
{
if(size==12)temp=asc2_1206[chr][t];
//調用1206字體
else if(size==16)temp=asc2_1608[chr][t];//調用1608字體
else if(size==24)temp=asc2_2412[chr][t];//調用2412字體
else return;
//沒有的字庫
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;
}
}
}
}