關于模擬SPI可以看我的另一篇博客
基于STM32的0.96寸OLED顯示屏(模擬SPI)
- 相關引數
- 代碼
- GPIO初始化
- 寫資料和寫命令
- 配置OLED模式
- OLED頁尋址方式
- OLED清屏
- 顯示字符
- 主函式
- 效果圖
我使用的是中景園電子的 0.96 寸 OLED 顯示屏,0.96 寸 OLED 有黃藍,白,藍三種顏色可選;其中黃藍是屏上 1/4 部分為黃光,下 3/4 為藍;而且是固定區域顯示固定顏色,顏色和顯示區域均不能修改;白光則為純白,也就是黑底白字;藍色則為純藍,也就是黑底藍字,解析度為 128*64,
相關引數
- GND 電源地
- VCC 電源正(3~5.5V)
- D0 OLED 的 D0 腳,在 SPI 和 IIC 通信中為CLK管腳
- D1 OLED 的 D1 腳,在 SPI 和 IIC 通信中為MOSI管腳
- RES OLED 的 RES#腳,用來復位(低電平復位)
- DC OLED 的 D/C#E 腳,資料和命令控制管腳 1表示資料 0表示命令
- CS OLED 的 CS#腳,也就是片選管腳
關于RES復位引腳:所有 OLED 本身都會有一個復位腳;因為 OLED 在被操作之前需要在將寄存作一次復位;然后才能對期進行初始貨操作;否則 OLED 可能會出現不穩定的情況,(先將 RES 拉低延遲 200ms 左右;然后再拉高一直處于高電平狀態)
本屏所用的驅動 IC 為 SSD1306;其具有內部升壓功能;所以在設計的時候不需要再專一設計升壓電路;當然了本屏也可以選用外部升壓,具體的請詳查資料手冊,SSD1306 的每頁包含了128 個位元組,總共 8 頁,這樣剛好是 128*64 的點陣大小,這點與 1.3 寸 OLED 驅動 IC SSD1106稍有不同,SSD1106 每頁是 132 個位元組,也是 8 頁,所以在用 0.96 寸 OLED 移植 1.3 寸 OLED 程式的時候需要將 0.96 寸的顯示地址向右偏移 2,這樣顯示就正常了;否則在用 1.3 寸的時候 1.3寸屏右邊會有 4 個像素點寬度顯示不正常或是全白,這點大家注意一下 ,其它的 SSD1306 和SSD1106 區別不大,
代碼
GPIO初始化
全都是GPIO_Mode_Out_PP模式
static void OLED_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(OLED_RES_CLK|OLED_DC_CLK,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = OLED_RES_Pin|OLED_DC_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(OLED_RES_PORT,&GPIO_InitStructure);
Software_SPI_Init();
/*復位暫存器*/
OLED_RES_0();
SysTick_Delay_Ms(200);
OLED_RES_1();
}
寫資料和寫命令
void OLED_WriteCmd(u8 Cmd)
{
OLED_DC_Cmd();//DC引腳低電平表示命令
Software_SPI_Write(Cmd);
}
void OLED_WriteData(u8 Cmd)
{
OLED_DC_Data();//DC引腳高電平表示資料
Software_SPI_Write(Cmd);
}
配置OLED模式
void OLED_Init(void)
{
OLED_GPIO_Init();
OLED_WriteCmd(0XAE);//關閉OLED面板
OLED_WriteCmd(0X00);//設定頁地址模式的列起始地址低位
OLED_WriteCmd(0X10);//設定頁地址模式的列起始地址高位
OLED_WriteCmd(0X40);//設定螢屏起始行
OLED_WriteCmd(0X81);//設定對比度(相當于螢屏亮度)
OLED_WriteCmd(0X00);//對比度設定值,范圍0X00-0XFF
/*好像是設定顯示方向的*/
OLED_WriteCmd(0XA1);//設定行掃描方向為從左到右
OLED_WriteCmd(0XC8);//設定列掃描方向為資料低位在前
OLED_WriteCmd(0XA8);//設定復用率
OLED_WriteCmd(0X3F);
/*顯示偏移*/
OLED_WriteCmd(0XD3);//設定顯示偏移
OLED_WriteCmd(0x00);//不偏移
/*設定時鐘*/
OLED_WriteCmd(0XD5);//設定顯示時鐘分頻值/震蕩頻率
OLED_WriteCmd(0x80);//設定分頻比,將時鐘設定為100幀/秒
/*充電*/
OLED_WriteCmd(0XD9);//設定預充電周期
OLED_WriteCmd(0xF1);//1個充電時鐘和15個放電時鐘
OLED_WriteCmd(0XDA);//設定列引腳硬體配置
OLED_WriteCmd(0x12);//列輸出掃描方向從COM63到COM0(C8h), 啟用列左/右映射(DAh A[5]=1)
OLED_WriteCmd(0XDB);//設定VCOMH反壓值
OLED_WriteCmd(0X40);//設定VCOM取消選擇級別
OLED_WriteCmd(0X20);//設定記憶體尋址模式
OLED_WriteCmd(0x02);//頁地址尋址模式
OLED_WriteCmd(0x8D);//電荷泵啟用/禁用
OLED_WriteCmd(0x14);//關閉
OLED_WriteCmd(0xA4);//點亮螢屏
OLED_WriteCmd(0xA6);//設定正常顯示,不反轉,1表示點亮像素
OLED_WriteCmd(0xAF);//打開OLED面板
OLED_Clear();//清屏
OLED_Set_Pos(0,0);//設定起始坐標
}
OLED頁尋址方式
OLED_WriteCmd(0X20);//設定記憶體尋址模式
OLED_WriteCmd(0x02);//頁地址尋址模式

OLED顯示屏每一行為一頁,一頁共128位元組,
COLx表示圖形顯示資料RAM列,
void OLED_Set_Pos(unsigned char x, unsigned char y)
{
OLED_WriteCmd(0xb0+y);
OLED_WriteCmd(((x&0xf0)>>4)|0x10);
OLED_WriteCmd((x&0x0f)|0x00);
}
OLED_WriteCmd(0xb0+y);相當于設定在OLED的第幾行顯示;

又表可得知X坐標是分兩次分別發送,
OLED_WriteCmd(((x&0xf0)>>4)|0x10);
取X坐標的高4位與表中D7~D4(0001)組成新的8位數寫入OLED,
==OLED_WriteCmd((x&0x0f)|0x00); ==
取X坐標的低4位與表中D7~D4(0000)組成新的8位數寫入OLED,
如此一來,我們就按照資料手冊將坐標寫入到了OLED暫存器,
詳情可見該博客STM32學習筆記—OLED頁尋址方式
OLED清屏
在頁尋址模式下,讀/寫顯示RAM后,列地址指標自動加1,如果列地址指標達到列結束地址,則列地址指標重置為列起始地址,頁地址指標不變,用戶必須設定新的頁面和列地址才能訪問下一頁RAM內容,
void OLED_Clear(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
OLED_WriteCmd(0XB0+i);//設定頁地址 0XB0~0XB7
OLED_WriteCmd(0X00);//設定顯示位置—列低地址
OLED_WriteCmd(0X10);//設定顯示位置—列高地址
for(n=0;n<128;n++)
{
OLED_WriteData(0);
}
}
}
當將清屏寫入的資料改為1時OLED_WriteData(0);會發現螢屏上出現了8條橫線,
因為SSD1306寫入資料是一次性寫入一個位元組,寫入1相當于二進制0000 0001,低位在前高位在后,

顯示字符
GDDRAM是位映射的靜態RAM,其中包含要顯示的位模式, RAM的大小為128 x 64位,RAM分為8頁,從PAGE0到PAGE7,用于單色128x64點矩陣顯示,如圖8-13所示,
當將一個資料位元組寫入GDDRAM時,當前列同一頁的所有行影像資料都將被填充(即,由列地址指標指向的整個列(8位)將被填充), 如圖8-14所示,資料位D0被寫入頂部行,而資料位D7被寫入底部行,
根據資料手冊的圖片與說明得知OLED模塊的取模方向為列行式,低位在前,

顯示漢字
/*
* @brief 顯示一個漢字
* @para x 橫坐標 0-111
* @para y 縱坐標 0-6
*/
void OLED_ShowChar(u8 x,u8 y,u8 Char)
{
u8 t;
OLED_Set_Pos(x,y);
for(t=0;t<16;t++)
{
OLED_WriteData(chinese[2*Char][t]);
}
OLED_Set_Pos(x,y+1);
for(t=0;t<16;t++)
{
OLED_WriteData(chinese[2*Char+1][t]);
}
}
一個漢字占用兩行,取模時要對應上位置,不然會出現漢字錯位,
顯示多個漢字
/*
* @brief 顯示多個漢字
* @para x 橫坐標
* @para y 縱坐標
* @para length 待顯示漢字的長度
*/
void OLED_ShowCHinese(u8 x,u8 y,u8 length)
{
u8 i;
for(i=0;i<length;i++)
{
OLED_ShowChar(x,y,i);
x += 16;
}
}
顯示字串
/*
* @brief 顯示8x16字串
* @para x 橫坐標
* @para y 縱坐標
* @para ch 指標
*/
void OLED_8x16Str(u8 x,u8 y,char *ch)
{
u8 c=0,i=0,j=0;
while(ch[j]!='\0')
{
c = ch[j]-32;
if(x>120)//換行顯示
{
x=0;
y++;
}
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
{
OLED_WriteData(F8X16[c*16+i]);//前8位字模資料
}
OLED_Set_Pos(x,y+1);//下一頁
for(i=0;i<8;i++)
{
OLED_WriteData(F8X16[c*16+i+8]);//前8位字模資料
}
x+=8;//下一個字符的坐標
j++;//字符的序列號
}
}
要點:因為字模陣列第一個字符是空格,所以需要減去空格(c = ch[j]-32;)才能得到正確字模所對應的位置,
主函式
int main(void)
{
USART_Config();
Software_SPI_Init();
OLED_Init();
while(1)
{
OLED_ShowCHinese(0,0,4);
OLED_8x16Str(2,2,"2020/11/10");
OLED_8x16Str(2,4,"CSDN");
}
}
效果圖

完整工程下載
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/211934.html
標籤:其他
上一篇:【基于普中stm32f103的專案】第一篇 硬體除錯與引腳連接
下一篇:Vue中使用echarts
