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. 相关宏定义- #define OLED_CS(X) X?GPIO_SetBits(GPIOD, GPIO_Pin_3):GPIO_ResetBits(GPIOD, GPIO_Pin_3) //X为1时对应GPIO端口输出高电平,X为0时对应GPIO端口输出低电平
- #define OLED_RST(X) X?GPIO_SetBits(GPIOD, GPIO_Pin_4):GPIO_ResetBits(GPIOD, GPIO_Pin_4)
- #define OLED_DC(X) X?GPIO_SetBits(GPIOD, GPIO_Pin_5):GPIO_ResetBits(GPIOD, GPIO_Pin_5)
- #define OLED_D0(X) X?GPIO_SetBits(GPIOD, GPIO_Pin_6):GPIO_ResetBits(GPIOD, GPIO_Pin_6)
- #define OLED_D1(X) X?GPIO_SetBits(GPIOD, GPIO_Pin_7):GPIO_ResetBits(GPIOD, GPIO_Pin_7)
- #define OLED_Order 0 //定义写命令
- #define OLED_Data 1 //定义写数据
复制代码 2. GPIO初始化代码:- void OLED_GPIO_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
-
- //开启GPIOD的时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
- //设置GPIO的基本参数
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //输出速度50MHz
-
- GPIO_Init(GPIOD, &GPIO_InitStruct);
-
- GPIO_SetBits(GPIOD, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);
- }
复制代码 3. SPI 写数据/命令- /* SPI写数据/命令
- * Mode :O:写命令 1:写数据
- * data :数据/命令
- *
- */
- void SPI_Write(char data, int Mode)
- {
- int i = 0;
- if(Mode)
- {
- OLED_DC(1); //DC引脚输入高,表示写数据
- }
- else
- {
- OLED_DC(0); //DC引脚输入低,表示写命令
- }
- OLED_CS(0); //CS引脚输入低,片选使能
- for(i = 0; i < 8; i++)
- {
- OLED_D0(0); //D0引脚输入低
- if(data & 0x80) //判断传输的数据最高位为1还是0
- {
- OLED_D1(1); //D1引脚输入高
- }
- else
- {
- OLED_D1(0); //D1引脚输入低
- }
- OLED_D0(1); //D1引脚输入高
- data <<= 1; //将数据左移一位
- }
- OLED_DC(0); //DC引脚输入低
- OLED_CS(1); //CS引脚输入高,片选失能
- }
复制代码 4. 设置OLED屏的显示坐标:
例如:设置页地址为0xB2; 列地址的低4位为0x03,列地址的高4位为0x00;则显示的位置如下图:
代码:- /* 设置OLED屏的显示坐标
- * X : 表示OLED的水平坐标(0—127)
- * Y : 表示OLED的页(0—7)
- *
- */
- void OLED_Coord(unsigned char x, unsigned char y)
- {
- SPI_Write((0xb0+(y & 0x0f)), OLED_Order); //设置OLED显示的页
- SPI_Write((((x & 0xf0)>>4) | 0x10), OLED_Order);//设置OLED水平坐标的高4位
- SPI_Write((x & 0x0f)|0x01, OLED_Order); //设置OLED水平坐标的低4位
- }
复制代码 清除OLED的显示代码:- /*
- * 清除OLED的显示
- *
- *
- */
- void OLED_Clear(void)
- {
- int i = 0, j = 0;
- for(i = 0; i < 8; i++)
- {
- OLED_Coord(0, i);
- for(j = 0; j < 128; j++)
- {
- SPI_Write(0x00, OLED_Data);
- }
- }
- }
复制代码 关闭OLED显示代码:- /* 关闭OLED显示
- *
- *
- */
- void OLED_Display_Off(void)
- {
- //电荷泵设置(初始化时必须打开,否则看不到显示)
- SPI_Write(0x8D, OLED_Order);
- SPI_Write(0x10, OLED_Order);//bit2 0:关闭 1:打开
- SPI_Write(0xAE, OLED_Order);//0xAE:关闭显示
- }
复制代码 开启OLED显示代码:- /*
- * 开启OLED显示
- *
- */
- void OLED_Display_On(void)
- {
- //电荷泵设置(初始化时必须打开,否则看不到显示)
- SPI_Write(0x8D, OLED_Order);
- SPI_Write(0x14, OLED_Order);//bit2 0:关闭 1:打开
- SPI_Write(0xAF, OLED_Order);//0xAF:开显示
- }
复制代码OLED显示的参数的初始化: 1. 在设置OLED的参数时,并不需要把所有的参数都设置一次;有些参数是默认的(可以不进行设置),只是需要设置一写必要的参数; (如:0xAF: 开显示, 0x8D:电荷泵设置(初始化是必须打开,否则看不到显示)) 2.代码(初始化代码中,介绍了大部分命令): - /* OLED显示参数的初始化
- *
- *
- *
- */
- void OLED_Init(void)
- {
- OLED_GPIO_Init();
-
- OLED_RST(1);
- delay_ms(100);
- OLED_RST(0);
- delay_ms(100);
- OLED_RST(1);
-
- SPI_Write(0xAE, OLED_Order);//0xAE:关显示
-
- SPI_Write(0x00, OLED_Order);//设置低列地址
- SPI_Write(0x10, OLED_Order);//设置高列地址
-
- //设置行显示的开始地址(0-63)
- //40-47: (01xxxxx)
- SPI_Write(0x40, OLED_Order);
-
- //设置对比度
- SPI_Write(0x81, OLED_Order);
- SPI_Write(0xff, OLED_Order);//这个值越大,屏幕越亮(和上条指令一起使用)(0x00-0xff)
-
- SPI_Write(0xA1, OLED_Order);//0xA1: 左右反置, 0xA0: 正常显示(默认0xA0)
- SPI_Write(0xC8, OLED_Order);//0xC8: 上下反置, 0xC0: 正常显示(默认0xC0)
-
- //0xA6: 表示正常显示(在面板上1表示点亮,0表示不亮)
- //0xA7: 表示逆显示(在面板上0表示点亮,1表示不亮)
- SPI_Write(0xA6, OLED_Order);
-
- SPI_Write(0xA8, OLED_Order);//设置多路复用率(1-64)
- SPI_Write(0x3F, OLED_Order);//(0x01-0x3f)(默认为3f)
-
-
- //设置显示抵消移位映射内存计数器
- SPI_Write(0xD3, OLED_Order);
- SPI_Write(0x00, OLED_Order);//(0x00-0x3f)(默认为0x00)
-
- //设置显示时钟分频因子/振荡器频率
- SPI_Write(0xD5, OLED_Order);
- //低4位定义显示时钟(屏幕的刷新时间)(默认:0000)分频因子= [3:0]+1
- //高4位定义振荡器频率(默认:1000)
- SPI_Write(0x80, OLED_Order);//
-
- //时钟预充电周期
- SPI_Write(0xD9, OLED_Order);
- SPI_Write(0xF1, OLED_Order);//[3:0],PHASE 1; [7:4] PHASE 2
-
- //设置COM硬件应脚配置
- SPI_Write(0xDA, OLED_Order);
- SPI_Write(0x12, OLED_Order);//[5:4] 默认:01
-
- SPI_Write(0xDB, OLED_Order);//
- SPI_Write(0x40, OLED_Order);//
-
- //设置内存寻址方式
- SPI_Write(0x20, OLED_Order);
- //00: 表示水平寻址方式
- //01: 表示垂直寻址方式
- //10: 表示页寻址方式(默认方式)
- SPI_Write(0x02, OLED_Order);//
-
- //电荷泵设置(初始化时必须打开,否则看不到显示)
- SPI_Write(0x8D, OLED_Order);
- SPI_Write(0x14, OLED_Order);//bit2 0:关闭 1:打开
-
- //设置是否全部显示 0xA4: 禁止全部显示
- SPI_Write(0xA4, OLED_Order);
- //0xA6: 表示正常显示(在面板上1表示点亮,0表示不亮)
- //0xA7: 表示逆显示(在面板上0表示点亮,1表示不亮)
- SPI_Write(0xA6, OLED_Order);//
-
- SPI_Write(0xAF, OLED_Order);//0xAF:开显示
-
- SPI_Write(0xAF, OLED_Order);//0xAF:开显示
-
- OLED_Clear();
- }
复制代码 显示16*16的汉字函数代码:- /* 显示汉字
- * x:表示显示的水平坐标
- * y: 表示显示的垂直坐标
- * *p: 表示要显示汉字模组的首地址
- */
- void OLED_ShowChinese(int x, int y, const unsigned char *p)
- {
- int i = 0;
- OLED_Coord(x, y);
- for(i = 0; i < 32; i+=2)
- {
- SPI_Write(p[i], OLED_Data);
- }
- OLED_Coord(x, y+1);
- for(i = 1; i < 32; i+=2)
- {
- SPI_Write(p[i], OLED_Data);
- }
- }
复制代码 显示ASCII码的函数代码:- /* 显示ASCII
- * x:表示显示的水平坐标
- * y: 表示显示的垂直坐标
- * *p: 表示要显示汉字模组的首地址
- */
- void OLED_ShowChar(int x, int y, const unsigned char *p)
- {
- int i = 0;
- OLED_Coord(x, y);
- for(i = 0; i < 16; i+=2)
- {
- SPI_Write(p[i], OLED_Data);
- }
- OLED_Coord(x, y+1);
- for(i = 1; i < 16; i+=2)
- {
- SPI_Write(p[i], OLED_Data);
- }
- }
复制代码注意1:在使用PCtoLCD2002完美版进行取模时,如果取模的字高大于8时一定要注意; 如果字高16;取模的顺序是:从第一列开始,前8个点为第一个字节,后8个点为第二个字节 然后第二列取模,前8个点为第三个字节,后8个点为第四个字节,以此类推,而OLED屏的内存 寻址方式为0x10: 表示页寻址方式(默认方式)时,那么显示时将会乱码;因为是按页来显示的, 那么第一个字节显示在第一列,而第二个字节本应该显示在第二页的第一列,而被错误的显示在第一页的第二列,以此类推,导致显示乱码; (这就是为什么OLED_ShowChar()函数和OLED_ShowChinese()函数中, 前面先显示数组下标为偶数的数组, 后面显示数组下标为奇数的数组)
OLED显示的main函数代码:- int main(void)
- {
- SysTick_Init();
- OLED_Init();
-
- OLED_ShowChinese(0, 0, xing);//‘姓’
- OLED_ShowChinese(18, 0, ming);//‘名’
- OLED_ShowChar(36, 0, ASCII_Colon);//‘:’
- OLED_ShowChinese(0, 2, xue);//‘学’
- OLED_ShowChinese(18, 2, hao);//‘号’
- OLED_ShowChar(36, 2, ASCII_Colon);//‘:’
- // SPI_Write(0x2F, OLED_Order); //0x2F:激活滚动 0x2E:关闭滚动
- // //设置滚动方式:
- // // 0x26/0x27 :水平滚动(右向/左向)
- // // 0x29/0x2A :水平和垂直滚动(右向/左向)
- // // 0xA3 :垂直滚动
- // SPI_Write(0x27, OLED_Order);
- // SPI_Write(0x00, OLED_Order);
- // SPI_Write(0x00, OLED_Order);
- // SPI_Write(0x00, OLED_Order);
- // SPI_Write(0x03, OLED_Order);
- // SPI_Write(0x30, OLED_Order);
- while(1);
复制代码 注意:在使用滚动命令时,一定要先写入0x2F, 激活滚动 取模数组: - const unsigned char xing[]=
- { 0x10,0x40,0x10,0x22,0xF0,0x15,0x1F,0x08,
- 0x10,0x16,0xF0,0x21,0x40,0x40,0x3C,0x42,
- 0x10,0x42,0x10,0x42,0xFF,0x7F,0x10,0x42,
- 0x10,0x42,0x10,0x42,0x00,0x40,0x00,0x00};/*"姓",0*/
- const unsigned char A[]=
- { 0x00,0x20,0x00,0x3C,0xC0,0x23,0x38,0x02,
- 0xE0,0x02,0x00,0x27,0x00,0x38,0x00,0x20};/*"A",0*/
- const unsigned char ming[]=
- { 0x00,0x04,0x20,0x04,0x20,0x04,0x10,0x02,
- 0x08,0xFE,0x14,0x43,0x67,0x43,0x84,0x42,
- 0x44,0x42,0x24,0x42,0x14,0x42,0x0C,0x42,
- 0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00};/*"名",0*/
- const unsigned char ASCII_Colon[]=
- { 0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x30,
- 0xC0,0x30,0x00,0x00,0x00,0x00,0x00,0x00};/*":",0*/
- const unsigned char xue[]=
- { 0x40,0x04,0x30,0x04,0x11,0x04,0x96,0x04,
- 0x90,0x04,0x90,0x44,0x91,0x84,0x96,0x7E,
- 0x90,0x06,0x90,0x05,0x98,0x04,0x14,0x04,
- 0x13,0x04,0x50,0x04,0x30,0x04,0x00,0x00};/*"学",0*/
- const unsigned char hao[]=
- { 0x80,0x00,0x80,0x00,0x80,0x00,0xBE,0x06,
- 0xA2,0x05,0xA2,0x04,0xA2,0x04,0xA2,0x04,
- 0xA2,0x44,0xA2,0x84,0xA2,0x44,0xBE,0x3C,
- 0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00};/*"号",0*/
复制代码 OLED的命令基本上已经在上面介绍,还有一些屏幕显示滚动的命令;本人没有进行一一实验; 实验现象:
转自网络
|