SPI+OLED的简单显示

这篇具有很好参考价值的文章主要介绍了SPI+OLED的简单显示。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、硬件工作原理和原理图

1. STM32F103RBT6 nano开发板SPI硬件连接原理图

spi显示屏原理图,单片机,stm32,嵌入式硬件

本实验中我们使用SPI控制器的 MOSI(PA7) 和 SCK(PA5) 引脚。

spi显示屏原理图,单片机,stm32,嵌入式硬件

本实验中我们使用的SSD1306驱动的OLED屏幕共有六脚,除开电源引脚VCC, GND;

SPI屏幕为单工通信,只写不读,所以只用了SCL(SCK), SDA(MOSI)引脚;

NSS在片内已拉低,不用再连,默认选中(SPI总线不可再连其他设备);

另有RST(硬复位), D/C(写数据/命令),为SSD1306驱动的专用引脚,需要配置专门的GPIO引脚操控;

实验引脚连线如下:

SSD1306驱动OLED屏幕

开发板引脚

GND

GND

VCC

3V3

SCL

PA5

SDA

PA7

RST

PA6

DC

PA4

STM32F1NANO开发板共有两个硬件SPI,本实验使用SPI1,SPI2用于外部Flash

spi显示屏原理图,单片机,stm32,嵌入式硬件

2. SSD1306 OLED模块

2.1 OLED简介

 

OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电 激光显示(Organic Electroluminesence Display, OELD)。OLED由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术。

OLED显示技术具有自发光的特性,采用非常薄的有机材料涂层和玻璃基板,当有电流通过时,这些有机材料就会发光,而且OLED显示屏幕可视角度大,并且能够节省电能,从2003年开始这种显示设备在MP3播放器上得到了应用。

本次实验选用的是一块0.96inch的128x64点阵的单色OLED(最上16行为黄色,其余为蓝色),引出6针。

2.2 SSD1306

该屏幕由SSD1306驱动,SD1306 是一个单片 CMOS OLED/PLED 驱动芯片可以驱动有机/聚合发光二极管点阵图形显示系统。由 128 segments 和 64 Commons 组成。该芯片专为共阴极 OLED 面板设计。
SSD1306 中嵌入了对比度控制器、显示 RAM 和晶振,并因此减少了外部器件和功耗。有 256级亮度控制。数据/命令的发送有三种接口可选择: 6800/8000 串口, I2C 接口或 SPI 接口,适用于多数简介的应用。

1)工作模式

SSD1306MCU 接口由 8 个数据引脚和 5 个控制引脚组成。引脚分配由不同的接口选择决定,详情如下表。不同的 MCU 模块可以通过 BS[2:0]引脚的硬件选择设置。

spi显示屏原理图,单片机,stm32,嵌入式硬件

本模块采用的是4线SPI工作模式。

2)引脚描述

spi显示屏原理图,单片机,stm32,嵌入式硬件

模块引出6针,分别为:

  1. VCC:电源3.3V供电;
  2. GND:地线,须与通信设备共地;
  3. SCL:OLED从时钟信号;
  4. SDA:数据线,该设备为单工通信,只需从主机接收数据/命令,接MOSI;
  5. RST(RES):硬复位OLED;
  6. D/C(RS):命令/数据标志,主机通过该信号告知驱动芯片当前发的是数据还是命令(0,写命令;1,写数据)

3)内部框图

spi显示屏原理图,单片机,stm32,嵌入式硬件

其基本显示原理是:

  1. SSD1306驱动芯片通过接口电路接收单片机的数据或指令。
  2. 对于指令,送到指令系统去解析与执行。
  3. 对于数据,即128x64点阵单色屏上具体点的亮灭信息,是先写在一个点------bit一一对应的图形数据存储器(GDDRAM)上,再由其去控制驱动单元,在屏幕上显示图形。
  4. 该 RAM 的大小为 128 * 64 为, RAM分为 8 页,从 PAGE0 到 PAGE7,用于单色 128 * 64 点阵显示,如下图所示

    spi显示屏原理图,单片机,stm32,嵌入式硬件

  1. 当一个数据字节写到 GDDRAM 中,所有当前列的同一页的行图像数据都会被被填充(比如,被列地址指针指向的整列(8 位)都会被填充)。数据位 D0 写到顶行,而数据位 D7 写到底行,如下图所示。

spi显示屏原理图,单片机,stm32,嵌入式硬件

  1. 起始指针的 行(页)可通过相应命令设置到任意字节。
  2. 显示数据可连续输入,GDDRAM内容将根据不同的地址模式从起始指针开始连续更新。
  3. 三种地址模式,有不同的指针移动方式:
    1. 页地址模式

      spi显示屏原理图,单片机,stm32,嵌入式硬件

    2. 水平地址模式

      spi显示屏原理图,单片机,stm32,嵌入式硬件

    3. 垂直地址模式

      spi显示屏原理图,单片机,stm32,嵌入式硬件

4)指令系统

当D/C端为第电平时,传输的是命令,详见手册命令表。

重点关注地址模式配置、指针模式、初始化指令、清屏指令和滚动指令。

步骤

1. 完成 CubeMX初始化配置

1.1 利用CubeMX完成HAL库工程模板和初始化:

通过选择芯片型号创建CubeMX工程

在弹出的对话框中输入开发板上的芯片型号,STM32F103RB

在右侧筛选栏中选择Tx型,即开发板上芯片所用的LQFP64型封装,双击建立工程

spi显示屏原理图,单片机,stm32,嵌入式硬件

1.2 RCC时钟模块引脚的配置

在弹出的工程配置对话框中的第一个引脚配置选项卡下,先完成RCC时钟模块引脚配置:

选择启用外部的高速和低速时钟源,HSE和LSE,配置为晶振连接;

配置完成后,对应时钟引脚变绿,同时旁边出现其将要配置模式的文字说明;

spi显示屏原理图,单片机,stm32,嵌入式硬件

1.3 配置时钟

我们前面启用了RCC时钟模块的外部时钟引脚,这里我们需要将外部时钟源配置为实际使用的频率;

查看手册可知:LSE为32.768KHz,HSE为8MHz;

spi显示屏原理图,单片机,stm32,嵌入式硬件

点击上方的时钟配置选项卡,进入时钟配置界面;

前面启用了外部晶振源,这里检查修改HSE\LSE的频率,和实际一致;

在主频选择框中输入72MHz,然后按两下回车;

系统将自动将时钟源、时钟流向、PLL等配置好,以产生相应的主频;

spi显示屏原理图,单片机,stm32,嵌入式硬件

1.4 RTC配置

1.在侧边栏的计时器中选择RTC

2.勾选Activate Clock Source 激活时钟源
Activate calendar 激活日历

3.配置时间日期

spi显示屏原理图,单片机,stm32,嵌入式硬件

1.5配置SPI1

1.在侧边栏的通信外设中选择SPI1。

2.Mode处选 Transmit Only Master(因为只需要MCU向OLED发送指令即可,不需要接收数据)

3.SPI的参数默认即可,无需修改。

spi显示屏原理图,单片机,stm32,嵌入式硬件

1.6生成工程

spi显示屏原理图,单片机,stm32,嵌入式硬件

 

新建OLED.c/.h 与 OLED_font.h文件,添加到工程中。

MAX30102的需配置的寄存器的功能和地址

spi显示屏原理图,单片机,stm32,嵌入式硬件

我们要向里面写数据点亮里面的像素点,必须找到对应的页位置和列位置,再把一个字节的数据,以纵向8点下高位的形式填充进去,哪我们如何运用oled的命令来锁定位置呢?如下表所示

spi显示屏原理图,单片机,stm32,嵌入式硬件

1)单片机向SSD1306 OLED发送命令

 

/**
  * @brief  向设备写控制命令
  * @param  cmd: 要写入的命令
  * @param  无
  * @param  无
  * @retval 无
  */
static void OLED_WR_CMD(uint8_t cmd)
{ 
  /* <低电平是命令> */
  Data_Cmd_State(OLED_CMD);
  HAL_SPI_Transmit(&OLED_SPI, &cmd, 1, 0xff);
  /* <恢复> */
  Data_Cmd_State(1);   
}

2)单片机向SSD1306 OLED发送数据 

/**
  * @brief  向设备写数据
  * @param  data: 要写入的数据
  * @param  无
  * @param  无
  * @retval 无
  */
static void OLED_WR_DATA(uint8_t data)
{  
  /* <高电平是数据> */
  Data_Cmd_State(OLED_DAT);
  HAL_SPI_Transmit(&OLED_SPI, &data, 1, 0xff);
  /* <恢复> */
  Data_Cmd_State(1);
}

3)OLED 初始化

/**
  * @brief  初始化oled屏幕
  * @param  无
  * @param  无
  * @param  无
  * @retval 无
  */
void OLED_Init(void)
{
	OLED_RST_State(0);
	HAL_Delay(200);
	OLED_RST_State(1);

	for(int16_t i=0; i<sizeof(CMD_Data); i++)	
    OLED_WR_CMD(CMD_Data[i]);
	
	OLED_Clear();
}

4)OLED 清屏

/**
  * @brief  清屏
  * @param  无
  * @param  无
  * @param  无
  * @retval 无
  */
void OLED_Clear(void)
{     
  for(int i=0;i<8;i++)  
  {  
    OLED_WR_CMD(0xb0+i);
    OLED_WR_CMD(0x00);
    OLED_WR_CMD(0x10);
    
    for(int n=0;n<128;n++)
      OLED_WR_DATA(0x00);
  }
}

5)OLED 显示单个字符与显示字符串 

 

/**
  * @brief  显示一个数字或英文
  * @param  x坐标(0-127)
  * @param  y坐标(0-63)
  * @param  chr: 要显示的字符
  * @param  Char_Size: 要显示的字符的大小
  * @retval 无
  */
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t Char_Size)
{       
  unsigned char c=0,i=0;  
  
  c=chr-' ';//得到偏移后的值 
  
  if(x>128-1){x=0; y=y+2;}
  
  if(Char_Size == 16)
  {
    OLED_Set_Pos(x, y);     
    for(i=0; i<8; i++)
      OLED_WR_DATA(F8x16[c*16+i]);
    OLED_Set_Pos(x,y+1);
    for(i=0;i<8;i++)
      OLED_WR_DATA(F8x16[c*16+i+8]);
  }
  else 
  { 
    OLED_Set_Pos(x,y);
    for(i=0;i<6;i++)
      OLED_WR_DATA(F6x8[c][i]);    
  }
}


/**
  * @brief  OLED显示字符串
  * @param  x坐标(0-127)
  * @param  y坐标(0-63)
  * @param  *chr: 显示的字符串
  * @param  Char_Size: 要显示的字符串的大小 
  * @retval 无
  */
void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_t Char_Size)
{ 
  unsigned char j = 0;
  
  while (chr[j] != '\0')
  {   
    OLED_ShowChar(x, y, chr[j], Char_Size);
    x+=8;    
    if(x>120){x=0; y+=2;}
    j++;
  }
}

6)OLED 显示数字

/**
  * @brief  显示2个数字
  * @param  x坐标(0-127)
  * @param  y坐标(0-63)
  * @param  num : 数值(0~4294967295)
  * @param  len : 数字的位数
  * @param  size2: 字体大小
  * @retval 无
  */ 
void OLED_ShowNum(uint8_t x, uint8_t y, unsigned int num, uint8_t len, uint8_t size2)
{           
  uint8_t t,temp;
  uint8_t enshow=0;     
  
  for(t=0;t<len;t++)
  {
    temp = (num/OLED_Pow(10, len-t-1))%10;
    
    if(enshow == 0 && t<(len-1))
    {
      if(temp==0)
      {
        OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
        continue;
      }
      else 
        enshow=1;        
    }
    OLED_ShowChar(x+(size2/2)*t, y, temp+'0', size2); 
  }
}

 7)OLED 显示中文

/**
  * @brief  显示汉字
  * @param  x坐标(0-127)
  * @param  y坐标(0-63)
  * @param  no: 汉字的顺序
  * @retval 无
  */
void OLED_ShowCHinese(uint8_t x, uint8_t y, uint8_t no)
{               
  uint8_t t;
  uint8_t adder = 0;
  
  OLED_Set_Pos(x, y); 
  
  for(t=0; t<16; t++)
  {
    OLED_WR_DATA(CN_Library1[2*no][t]);
    adder += 1;
  } 
  
  OLED_Set_Pos(x,y+1);  
  
  for(t=0;t<16;t++)
  { 
    OLED_WR_DATA(CN_Library1[2*no+1][t]);
    adder += 1;
  }         
}

 8)OLED 显示图片文章来源地址https://www.toymoban.com/news/detail-626580.html

/**
  * @brief  显示图片函数(写全屏屏幕)
  * @param  data: 要显示图片的数组
  * @param  无
  * @param  无
  * @retval 无
  */
void OLED_ShowPicture(uint8_t *data)
{
  uint16_t j = 0;
  uint8_t x, y;
  
  for(y = 0; y<8; y++)
  {
    OLED_Set_Pos(0, y);
    
    for(x = 0; x<128; x++)    
      OLED_WR_DATA(data[j++]);    
  }
}

到了这里,关于SPI+OLED的简单显示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包