STM32學習筆記——OLED屏
OLED屏的特點:
1. 模塊有單色和雙色可選,單色為純藍色,雙色為黃藍雙色(本人選用雙色);
2. 顯示尺寸為0.96寸
3. 分辨率為128*64
4. 多種接口方式,該模塊提供了總共 5 種接口包括: 6800、 8080 兩種並行接口方式、 3線或4線的SPI接口,IIC接口方式
5. 不需要高壓,直接接3.3V就可以工作;(可以與stm32的引腳直接相接)
OLED圖片:
OLED引腳介紹:
CS:OLED片選信號
RST:OLED復位端口
DC: 命令/數據選擇端口(0:讀寫命令, 1: 讀寫數據)
SCLK(D0):串口時鍾線
SDIN(D1): 串口數據線
4線SPI寫操作時序圖:
OLED的常用命令:
設置OLED顯示內存的尋址方式:
設置的命令:
0x00: 表示水平尋址方式
0x01: 表示垂直尋址方式
0x10: 表示頁尋址方式(默認方式)
stm32與OLED屏接口的引腳介紹:
CS————GPIOD3;
RST————GPIOD4;
DC—————GPIOD5;
D0——————GPIOD6;
D1——————GPIOD7;
程序代碼:
1. 相關宏定義
1 #define OLED_CS(X) X?GPIO_SetBits(GPIOD, GPIO_Pin_3):GPIO_ResetBits(GPIOD, GPIO_Pin_3) //X為1時對應GPIO端口輸出高電平,X為0時對應GPIO端口輸出低電平 2 3 #define OLED_RST(X) X?GPIO_SetBits(GPIOD, GPIO_Pin_4):GPIO_ResetBits(GPIOD, GPIO_Pin_4) 4 5 #define OLED_DC(X) X?GPIO_SetBits(GPIOD, GPIO_Pin_5):GPIO_ResetBits(GPIOD, GPIO_Pin_5) 6 7 #define OLED_D0(X) X?GPIO_SetBits(GPIOD, GPIO_Pin_6):GPIO_ResetBits(GPIOD, GPIO_Pin_6) 8 9 #define OLED_D1(X) X?GPIO_SetBits(GPIOD, GPIO_Pin_7):GPIO_ResetBits(GPIOD, GPIO_Pin_7) 10 11 12 #define OLED_Order 0 //定義寫命令 13 #define OLED_Data 1 //定義寫數據
2. GPIO初始化代碼:
1 void OLED_GPIO_Init(void) 2 { 3 GPIO_InitTypeDef GPIO_InitStruct; 4 5 //開啟GPIOD的時鍾 6 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); 7 //設置GPIO的基本參數 8 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; 9 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出 10 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //輸出速度50MHz 11 12 GPIO_Init(GPIOD, &GPIO_InitStruct); 13 14 GPIO_SetBits(GPIOD, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7); 15 }
3. SPI 寫數據/命令
1 /* SPI寫數據/命令 2 * Mode :O:寫命令 1:寫數據 3 * data :數據/命令 4 * 5 */ 6 void SPI_Write(char data, int Mode) 7 { 8 int i = 0; 9 if(Mode) 10 { 11 OLED_DC(1); //DC引腳輸入高,表示寫數據 12 } 13 else 14 { 15 OLED_DC(0); //DC引腳輸入低,表示寫命令 16 } 17 OLED_CS(0); //CS引腳輸入低,片選使能 18 for(i = 0; i < 8; i++) 19 { 20 OLED_D0(0); //D0引腳輸入低 21 if(data & 0x80) //判斷傳輸的數據最高位為1還是0 22 { 23 OLED_D1(1); //D1引腳輸入高 24 } 25 else 26 { 27 OLED_D1(0); //D1引腳輸入低 28 } 29 OLED_D0(1); //D1引腳輸入高 30 data <<= 1; //將數據左移一位 31 } 32 OLED_DC(0); //DC引腳輸入低 33 OLED_CS(1); //CS引腳輸入高,片選失能 34 }
4. 設置OLED屏的顯示坐標:
例如:設置頁地址為0xB2; 列地址的低4位為0x03,列地址的高4位為0x00;則顯示的位置如下圖:
代碼:
1 /* 設置OLED屏的顯示坐標 2 * X : 表示OLED的水平坐標(0—127) 3 * Y : 表示OLED的頁(0—7) 4 * 5 */ 6 void OLED_Coord(unsigned char x, unsigned char y) 7 { 8 SPI_Write((0xb0+(y & 0x0f)), OLED_Order); //設置OLED顯示的頁 9 SPI_Write((((x & 0xf0)>>4) | 0x10), OLED_Order);//設置OLED水平坐標的高4位 10 SPI_Write((x & 0x0f)|0x01, OLED_Order); //設置OLED水平坐標的低4位 11 }
清除OLED的顯示代碼:
1 /* 2 * 清除OLED的顯示 3 * 4 * 5 */ 6 void OLED_Clear(void) 7 { 8 int i = 0, j = 0; 9 for(i = 0; i < 8; i++) 10 { 11 OLED_Coord(0, i); 12 for(j = 0; j < 128; j++) 13 { 14 SPI_Write(0x00, OLED_Data); 15 } 16 } 17 }
關閉OLED顯示代碼:
1 /* 關閉OLED顯示 2 * 3 * 4 */ 5 void OLED_Display_Off(void) 6 { 7 //電荷泵設置(初始化時必須打開,否則看不到顯示) 8 SPI_Write(0x8D, OLED_Order); 9 SPI_Write(0x10, OLED_Order);//bit2 0:關閉 1:打開 10 SPI_Write(0xAE, OLED_Order);//0xAE:關閉顯示 11 }
開啟OLED顯示代碼:
1 /* 2 * 開啟OLED顯示 3 * 4 */ 5 void OLED_Display_On(void) 6 { 7 //電荷泵設置(初始化時必須打開,否則看不到顯示) 8 SPI_Write(0x8D, OLED_Order); 9 SPI_Write(0x14, OLED_Order);//bit2 0:關閉 1:打開 10 SPI_Write(0xAF, OLED_Order);//0xAF:開顯示 11 }
OLED顯示的參數的初始化:
1. 在設置OLED的參數時,並不需要把所有的參數都設置一次;有些參數是默認的(可以不進行設置),只是需要設置一寫必要的參數;
(如:0xAF: 開顯示, 0x8D:電荷泵設置(初始化是必須打開,否則看不到顯示))
2.代碼(初始化代碼中,介紹了大部分命令):
1 /* OLED顯示參數的初始化 2 * 3 * 4 * 5 */ 6 void OLED_Init(void) 7 { 8 OLED_GPIO_Init(); 9 10 OLED_RST(1); 11 delay_ms(100); 12 OLED_RST(0); 13 delay_ms(100); 14 OLED_RST(1); 15 16 SPI_Write(0xAE, OLED_Order);//0xAE:關顯示 17 18 SPI_Write(0x00, OLED_Order);//設置低列地址 19 SPI_Write(0x10, OLED_Order);//設置高列地址 20 21 //設置行顯示的開始地址(0-63) 22 //40-47: (01xxxxx) 23 SPI_Write(0x40, OLED_Order); 24 25 //設置對比度 26 SPI_Write(0x81, OLED_Order); 27 SPI_Write(0xff, OLED_Order);//這個值越大,屏幕越亮(和上條指令一起使用)(0x00-0xff) 28 29 SPI_Write(0xA1, OLED_Order);//0xA1: 左右反置, 0xA0: 正常顯示(默認0xA0) 30 SPI_Write(0xC8, OLED_Order);//0xC8: 上下反置, 0xC0: 正常顯示(默認0xC0) 31 32 //0xA6: 表示正常顯示(在面板上1表示點亮,0表示不亮) 33 //0xA7: 表示逆顯示(在面板上0表示點亮,1表示不亮) 34 SPI_Write(0xA6, OLED_Order); 35 36 SPI_Write(0xA8, OLED_Order);//設置多路復用率(1-64) 37 SPI_Write(0x3F, OLED_Order);//(0x01-0x3f)(默認為3f) 38 39 40 //設置顯示抵消移位映射內存計數器 41 SPI_Write(0xD3, OLED_Order); 42 SPI_Write(0x00, OLED_Order);//(0x00-0x3f)(默認為0x00) 43 44 //設置顯示時鍾分頻因子/振盪器頻率 45 SPI_Write(0xD5, OLED_Order); 46 //低4位定義顯示時鍾(屏幕的刷新時間)(默認:0000)分頻因子= [3:0]+1 47 //高4位定義振盪器頻率(默認:1000) 48 SPI_Write(0x80, OLED_Order);// 49 50 //時鍾預充電周期 51 SPI_Write(0xD9, OLED_Order); 52 SPI_Write(0xF1, OLED_Order);//[3:0],PHASE 1; [7:4] PHASE 2 53 54 //設置COM硬件應腳配置 55 SPI_Write(0xDA, OLED_Order); 56 SPI_Write(0x12, OLED_Order);//[5:4] 默認:01 57 58 SPI_Write(0xDB, OLED_Order);// 59 SPI_Write(0x40, OLED_Order);// 60 61 //設置內存尋址方式 62 SPI_Write(0x20, OLED_Order); 63 //00: 表示水平尋址方式 64 //01: 表示垂直尋址方式 65 //10: 表示頁尋址方式(默認方式) 66 SPI_Write(0x02, OLED_Order);// 67 68 //電荷泵設置(初始化時必須打開,否則看不到顯示) 69 SPI_Write(0x8D, OLED_Order); 70 SPI_Write(0x14, OLED_Order);//bit2 0:關閉 1:打開 71 72 //設置是否全部顯示 0xA4: 禁止全部顯示 73 SPI_Write(0xA4, OLED_Order); 74 75 //0xA6: 表示正常顯示(在面板上1表示點亮,0表示不亮) 76 //0xA7: 表示逆顯示(在面板上0表示點亮,1表示不亮) 77 SPI_Write(0xA6, OLED_Order);// 78 79 SPI_Write(0xAF, OLED_Order);//0xAF:開顯示 80 81 SPI_Write(0xAF, OLED_Order);//0xAF:開顯示 82 83 OLED_Clear(); 84 }
顯示16*16的漢字函數代碼:
1 /* 顯示漢字 2 * x:表示顯示的水平坐標 3 * y: 表示顯示的垂直坐標 4 * *p: 表示要顯示漢字模組的首地址 5 */ 6 void OLED_ShowChinese(int x, int y, const unsigned char *p) 7 { 8 int i = 0; 9 OLED_Coord(x, y); 10 for(i = 0; i < 32; i+=2) 11 { 12 SPI_Write(p[i], OLED_Data); 13 } 14 OLED_Coord(x, y+1); 15 for(i = 1; i < 32; i+=2) 16 { 17 SPI_Write(p[i], OLED_Data); 18 } 19 }
顯示ASCII碼的函數代碼:
1 /* 顯示ASCII 2 * x:表示顯示的水平坐標 3 * y: 表示顯示的垂直坐標 4 * *p: 表示要顯示漢字模組的首地址 5 */ 6 void OLED_ShowChar(int x, int y, const unsigned char *p) 7 { 8 int i = 0; 9 OLED_Coord(x, y); 10 for(i = 0; i < 16; i+=2) 11 { 12 SPI_Write(p[i], OLED_Data); 13 } 14 OLED_Coord(x, y+1); 15 for(i = 1; i < 16; i+=2) 16 { 17 SPI_Write(p[i], OLED_Data); 18 } 19 }
注意1:在使用PCtoLCD2002完美版進行取模時,如果取模的字高大於8時一定要注意;
如果字高16;取模的順序是:從第一列開始,前8個點為第一個字節,后8個點為第二個字節
然后第二列取模,前8個點為第三個字節,后8個點為第四個字節,以此類推,而OLED屏的內存
尋址方式為0x10: 表示頁尋址方式(默認方式)時,那么顯示時將會亂碼;因為是按頁來顯示的,
那么第一個字節顯示在第一列,而第二個字節本應該顯示在第二頁的第一列,而被錯誤的顯示在第一頁的第二列,以此類推,導致顯示亂碼;
(這就是為什么OLED_ShowChar()函數和OLED_ShowChinese()函數中, 前面先顯示數組下標為偶數的數組, 后面顯示數組下標為奇數的數組)
OLED顯示的main函數代碼:
1 int main(void) 2 { 3 SysTick_Init(); 4 OLED_Init(); 5 6 OLED_ShowChinese(0, 0, xing);//‘姓’ 7 OLED_ShowChinese(18, 0, ming);//‘名’ 8 OLED_ShowChar(36, 0, ASCII_Colon);//‘:’ 9 OLED_ShowChinese(0, 2, xue);//‘學’ 10 OLED_ShowChinese(18, 2, hao);//‘號’ 11 OLED_ShowChar(36, 2, ASCII_Colon);//‘:’ 12 // SPI_Write(0x2F, OLED_Order); //0x2F:激活滾動 0x2E:關閉滾動 13 // //設置滾動方式: 14 // // 0x26/0x27 :水平滾動(右向/左向) 15 // // 0x29/0x2A :水平和垂直滾動(右向/左向) 16 // // 0xA3 :垂直滾動 17 // SPI_Write(0x27, OLED_Order); 18 // SPI_Write(0x00, OLED_Order); 19 // SPI_Write(0x00, OLED_Order); 20 // SPI_Write(0x00, OLED_Order); 21 // SPI_Write(0x03, OLED_Order); 22 // SPI_Write(0x30, OLED_Order); 23 while(1);
注意:在使用滾動命令時,一定要先寫入0x2F, 激活滾動
取模數組:
1 const unsigned char xing[]= 2 { 0x10,0x40,0x10,0x22,0xF0,0x15,0x1F,0x08, 3 0x10,0x16,0xF0,0x21,0x40,0x40,0x3C,0x42, 4 0x10,0x42,0x10,0x42,0xFF,0x7F,0x10,0x42, 5 0x10,0x42,0x10,0x42,0x00,0x40,0x00,0x00};/*"姓",0*/ 6 const unsigned char A[]= 7 { 0x00,0x20,0x00,0x3C,0xC0,0x23,0x38,0x02, 8 0xE0,0x02,0x00,0x27,0x00,0x38,0x00,0x20};/*"A",0*/ 9 const unsigned char ming[]= 10 { 0x00,0x04,0x20,0x04,0x20,0x04,0x10,0x02, 11 0x08,0xFE,0x14,0x43,0x67,0x43,0x84,0x42, 12 0x44,0x42,0x24,0x42,0x14,0x42,0x0C,0x42, 13 0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00};/*"名",0*/ 14 const unsigned char ASCII_Colon[]= 15 { 0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x30, 16 0xC0,0x30,0x00,0x00,0x00,0x00,0x00,0x00};/*":",0*/ 17 const unsigned char xue[]= 18 { 0x40,0x04,0x30,0x04,0x11,0x04,0x96,0x04, 19 0x90,0x04,0x90,0x44,0x91,0x84,0x96,0x7E, 20 0x90,0x06,0x90,0x05,0x98,0x04,0x14,0x04, 21 0x13,0x04,0x50,0x04,0x30,0x04,0x00,0x00};/*"學",0*/ 22 const unsigned char hao[]= 23 { 0x80,0x00,0x80,0x00,0x80,0x00,0xBE,0x06, 24 0xA2,0x05,0xA2,0x04,0xA2,0x04,0xA2,0x04, 25 0xA2,0x44,0xA2,0x84,0xA2,0x44,0xBE,0x3C, 26 0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00};/*"號",0*/
OLED的命令基本上已經在上面介紹,還有一些屏幕顯示滾動的命令;本人沒有進行一一實驗;
實驗現象: