当前位置:   article > 正文

STM32-OLED屏幕显示教程_stm32oled屏幕

stm32oled屏幕

目录

1.OLED屏幕介绍

2.OLED屏幕显示一个点的思路

3.配置OLED屏幕

4.OLED显示字符串

5.OLED屏幕显示汉字

6.OLED屏幕显示图片

7.总结


我的上篇文章已经介绍过IIC协议(本篇文章不对IIC协议做过多赘述),这篇文章对我在学习OLED屏幕的时候做的一个总结。

1.OLED屏幕介绍

OLED即有机发光管(Organic Light-Emitting Diode,OLED)。OLED显示技术具有自发光、广视角、几乎无穷高的对比度、较低功耗、极高反应速度、可用于绕曲性面板、使用温度范围广、构造及制程简单等有点,被认为是下一代的平面显示屏新兴应用技术。

OLED显示和传统的LCD显示不同,其可以自发光,所以不需要背光灯,这使得OLED显示屏相对于LCD显示屏尺寸更薄,同时显示效果更优。 常用的OLED屏幕有蓝色、黄色、白色等几种。屏的大小为0.96寸,像素点为 128*64,所以我们称为0.96oled屏或者12864屏。

OLED屏幕特点

1.模块尺寸:23.7 *23.8mm

2.电源电压:3.3-5.5V

3.驱动芯片:SSD1306

4.测试平台:提供       k60/k10,9s12XS128,51,stm32,stm8等单片机  

OLED屏幕接线说明

 OLED屏幕显存

OLED本身是没有显存的,他的现存是依赖SSD1306提供的,而SSD1306提供一块显存。

SSD1306显存总共为128*64bit大小,SSD1306将这些显存分成了8页。每页包含了128个字节。

OLED屏幕原理

STM32内部建立一个缓存(共128*8个字节),每次修改的时候,只是修改STM32上的缓存(实际上就是SRAM),修改完后一次性把STM32上的缓存数据写入到OLED的GRAM。这个方法也有坏处,对于SRAM很小的单片机(51系列)就比较麻烦。

OLED屏幕常用指令

  · 命令0X81: 设置对比度。包含两个字节,第一个0X81为命令,随后方法是的一个字节要设置这个对比度,值越大屏幕越亮。

 ·命令0XAE/0XAF: 0XAE为关闭显示命令,0XAF为开启显示命令

 ·0X8D: 包含两个字节,第一个为命令字,第二个为设置值,第二个字节的BIT2表示电荷泵的开关状态,该位为1开启电荷泵,为0则关闭。模块初始化的时候,这个必须要开启,否则看不到屏幕显示。

  ·命令0XB0~B7:用于设置页地址,其低三位的值对应GRAM页地址。

  ·命令0X00~0X0F:用于设置显示时的起始列地址低四位。

  ·命令0X10~0X1F: 用于设置显示时的起始列地址高四位。

2.OLED屏幕显示一个点的思路

OLED屏幕分为页寻址模式,水平地址模式,垂直地址模式。

这里主要介绍用的最多的页寻址模式,页寻址模式如下图,把整个OLED屏幕分成了八页,说白了就是把OLED的屏幕把宽平均分成了八份。比如想要在第0列第三行的开头显示一个点那就是按位来配置,0000 0100(0x08)。

3.配置OLED屏幕

我们配置硬件IIC的步骤就是根据下面这张时序图,发送一次数据后不断获取不同的应答即可。

 oled.c

硬件IIC配置

  1. #include "stm32f10x.h"
  2. #include "oled.h"
  3. void IIC_Configuration(void)
  4. {
  5. GPIO_InitTypeDef GPIO_InitStructure;
  6. I2C_InitTypeDef I2C_InitStructure;
  7. RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
  8. RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE );
  9. //PB6--SCL PB7--SDL
  10. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
  11. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  12. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  13. GPIO_Init(GPIOB, &GPIO_InitStructure);
  14. I2C_DeInit(I2C1);
  15. I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
  16. I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  17. I2C_InitStructure.I2C_ClockSpeed = 400000;
  18. I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
  19. I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  20. I2C_InitStructure.I2C_OwnAddress1 = 0x30;
  21. I2C_Init(I2C1, &I2C_InitStructure);
  22. I2C_Cmd(I2C1, ENABLE);
  23. }
  24. void I2C_WriteByte(uint8_t addr,uint8_t data)
  25. {
  26. while( I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); //检查IIC总线是否繁忙
  27. I2C_GenerateSTART(I2C1, ENABLE); //开启IIC,发送起始信号
  28. while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //EV5主模式
  29. I2C_Send7bitAddress(I2C1, OLED_ADDRESS , I2C_Direction_Transmitter); //发送OLED地址
  30. while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //检查EV6
  31. I2C_SendData(I2C1, addr); //发送寄存器地址
  32. while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));
  33. I2C_SendData(I2C1, data); //发送数据
  34. while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));
  35. I2C_GenerateSTOP(I2C1, ENABLE);
  36. }

关于OLED屏幕我们需要写命令函数和写数据函数来填入我们想要的数据。

写命令函数/写数据函数

  1. void WriteCmd(unsigned char IIC_Command) //写命令
  2. {
  3. I2C_WriteByte(0x00,IIC_Command);
  4. }
  5. void WriteDat(unsigned char IIC_Data) //写数据
  6. {
  7. I2C_WriteByte(0x40,IIC_Data);
  8. }

OLED初始化(厂家提供的源码,复制粘贴即可,无需深究)

  1. void OLED_Init(void) //OELD屏幕初始化
  2. {
  3. delay_ms(100);
  4. WriteCmd(0xAE); //display off
  5. WriteCmd(0x20); //Set Memory Addressing Mode
  6. WriteCmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
  7. WriteCmd(0xb0); //Set Page Start Address for Page Addressing Mode,0-7
  8. WriteCmd(0xc8); //Set COM Output Scan Direction
  9. WriteCmd(0x00); //---set low column address
  10. WriteCmd(0x10); //---set high column address
  11. WriteCmd(0x40); //--set start line address
  12. WriteCmd(0x81); //--set contrast control register
  13. WriteCmd(0xff); //ÁÁ¶Èµ÷½Ú 0x00~0xff
  14. WriteCmd(0xa1); //--set segment re-map 0 to 127
  15. WriteCmd(0xa6); //--set normal display
  16. WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
  17. WriteCmd(0x3F); //
  18. WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
  19. WriteCmd(0xd3); //-set display offset
  20. WriteCmd(0x00); //-not offset
  21. WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
  22. WriteCmd(0xf0); //--set divide ratio
  23. WriteCmd(0xd9); //--set pre-charge period
  24. WriteCmd(0x22); //
  25. WriteCmd(0xda); //--set com pins hardware configuration
  26. WriteCmd(0x12);
  27. WriteCmd(0xdb); //--set vcomh
  28. WriteCmd(0x20); //0x20,0.77xVcc
  29. WriteCmd(0x8d); //--set DC-DC enable
  30. WriteCmd(0x14); //
  31. WriteCmd(0xaf); //--turn on oled panel
  32. }

设置起点坐标

  1. void SetPos(unsigned char x,unsigned char y) //设置起点坐标
  2. {
  3. WriteCmd(0xb0+y);
  4. WriteCmd((x&0xf0)>>4|0x10); //取高位
  5. WriteCmd((x&0x0f)|0x01); //取低位

全屏填充(可以全屏填充,也可用于清屏)

  1. void OLED_Fill(unsigned char Fill_Data) //全屏填充
  2. {
  3. unsigned char m,n;
  4. for(m=0;m<8;m++){
  5. WriteCmd(0xb0+m);
  6. WriteCmd(0x00);
  7. WriteCmd(0x10);
  8. for(n=0;n<128;n++){
  9. WriteDat(Fill_Data);
  10. }
  11. }
  12. }

清屏

  1. void OLED_Clean(void) //清屏
  2. {
  3. OLED_Fill(0x00);
  4. }

打开/关闭OLED

  1. void OLED_ON(void) //打开OLED
  2. {
  3. WriteCmd(0X8D); //设置电荷泵
  4. WriteCmd(0X14); //开启电荷泵
  5. WriteCmd(0XAF); //OLED唤醒
  6. }
  7. void OLED_OFF(void) //关闭OLED
  8. {
  9. WriteCmd(0X8D); //设置电荷泵
  10. WriteCmd(0X10); //关闭电荷泵
  11. WriteCmd(0XAE); //关闭OLED
  12. }

4.OLED显示字符串

  1. //显示字符串
  2. void OLED_ShowStr(unsigned char x,unsigned char y,unsigned char ch[],unsigned TextSize)
  3. {
  4. unsigned char c = 0,i = 0,j = 0;
  5. switch(TextSize)
  6. {
  7. case 1: //8*16模式
  8. {
  9. while(ch[j] != '\0')
  10. {
  11. c = ch[j] - 32;
  12. if(x>126)
  13. {
  14. x= 0;
  15. y++;
  16. }
  17. OLED_SetPos(x,y);
  18. for(i=0;i<6;i++)
  19. WriteDat( F6x8[c][i] );
  20. x+=6 ;
  21. j++;
  22. }
  23. }break;
  24. case 2: //16*16模式
  25. {
  26. while(ch[j] !='\0')
  27. {
  28. c= ch[j] - 32;
  29. if(x >120)
  30. {
  31. x = 0;
  32. y++ ;
  33. }
  34. OLED_SetPos(x,y);
  35. for(i = 0;i<8;i++)
  36. WriteDat( F8X16[c*16+i] );
  37. OLED_SetPos(x,y+1);
  38. for(i = 0;i<8;i++)
  39. WriteDat( F8X16[c*16+i+8] );
  40. x+=8;
  41. j++;
  42. }
  43. }break;
  44. }
  45. }

main.c

  1. #include "stm32f10x.h"
  2. #include "main.h"
  3. #include "oled.h"
  4. #include "sys.h"
  5. #include "delay.h"
  6. int main(void)
  7. {
  8. initSysTick();
  9. IIC_Configuration();
  10. OLED_Init();
  11. delay_ms(1000);
  12. OLED_Fill(0XFF); //全屏亮
  13. delay_ms(1000);
  14. OLED_Fill(0X00); //全屏灭
  15. delay_ms(1000);
  16. OLED_ShowStr( 0,1,"hello world", 1);
  17. OLED_ShowStr( 0,2,"hello world", 2);
  18. while(1)
  19. {
  20. }
  21. }

注:写命令函数,写数据函数,全屏填充函数,示字符串函数等都需要添加到oled.c文件里。

效果展示:

5.OLED屏幕显示汉字

  1. //显示汉字 (x:横坐标 y:纵坐标 N:字数)
  2. void OLED_ShowCN(unsigned char x,unsigned char y,unsigned char N)
  3. {
  4. unsigned char wm=0;
  5. unsigned int addr = 32*N;
  6. OLED_SetPos(x,y);
  7. for(wm=0;wm<16;wm++)
  8. {
  9. WriteDat( F16X16[addr]);
  10. addr +=1;
  11. }
  12. OLED_SetPos(x,y+1);
  13. for(wm=0;wm<16;wm++)
  14. {
  15. WriteDat( F16X16[addr]);
  16. addr +=1;
  17. }
  18. }

接着我们打开取字模软件,输入我们想显示的汉字和大小。在设置中改为C51模式(STM32和51单片机都使用的C51模式)。

 把生成的代码添加进字库当中(OLED_Codetab.h这个文件是我们添加的字库,厂家也会提供)

 

 我们选的是16*16大小的,所以我们把生成的代码粘贴到对应的结构体中。

main.c

  1. #include "stm32f10x.h"
  2. #include "main.h"
  3. #include "oled.h"
  4. #include "sys.h"
  5. #include "delay.h"
  6. int main(void)
  7. {
  8. unsigned char i=0;
  9. initSysTick();
  10. IIC_Configuration();
  11. OLED_Init(); //OELD初始化
  12. delay_ms(1000);
  13. OLED_Fill(0XFF); //全屏亮
  14. delay_ms(1000);
  15. OLED_Fill(0X00); //全屏灭
  16. delay_ms(1000);
  17. while(1)
  18. {
  19. for(i=0;i<4;i++){
  20. OLED_ShowCN(1+i*16,0,i);
  21. }
  22. }
  23. }

效果展示:

6.OLED屏幕显示图片

  1. //显示图片
  2. //x0:横坐标;y0:纵坐标;x1:图片起点;y1:所占页数;BMP[]:选用的结构体名称
  3. void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
  4. {
  5. unsigned int j=0;
  6. unsigned char x,y;
  7. if(y1%8 == 0)
  8. y = y1/8;
  9. else
  10. y = y1/8 +1;
  11. for(y=y0;y<y1;y++)
  12. {
  13. OLED_SetPos(x0,y);
  14. for(x=x0;x<x1;x++)
  15. {
  16. WriteDat(BMP[j++]);
  17. }
  18. }
  19. }

选一张照片,保存格式改为.png。

接着大小调整为跟我们的屏幕一样的分辨率。

 

 改完大小之后再保存为BMP格式。

 打开我们的取模软件,各种参数改成如下图所示。

 点击保存后就会生成这样一个文档。

 然后把数组里面的内容粘贴到BMP1的结构体里面。

 效果展示:

7.总结

本篇文章使用的硬件IIC驱动OLED屏幕,大家用软件IIC也可以实现同样的效果,软件IIC的代码可以参考中景园电子的,直接调用中景园封装好的函数即可,对新手也算友好。希望对大家有所帮助。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号