一、硬件工作原理和原理图
1. STM32F103RBT6 nano开发板SPI硬件连接原理图
本实验中我们使用SPI控制器的 MOSI(PA7) 和 SCK(PA5) 引脚。
本实验中我们使用的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
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]引脚的硬件选择设置。
本模块采用的是4线SPI工作模式。
2)引脚描述
模块引出6针,分别为:
- VCC:电源3.3V供电;
- GND:地线,须与通信设备共地;
- SCL:OLED从时钟信号;
- SDA:数据线,该设备为单工通信,只需从主机接收数据/命令,接MOSI;
- RST(RES):硬复位OLED;
- D/C(RS):命令/数据标志,主机通过该信号告知驱动芯片当前发的是数据还是命令(0,写命令;1,写数据)
3)内部框图
其基本显示原理是:
- SSD1306驱动芯片通过接口电路接收单片机的数据或指令。
- 对于指令,送到指令系统去解析与执行。
- 对于数据,即128x64点阵单色屏上具体点的亮灭信息,是先写在一个点------bit一一对应的图形数据存储器(GDDRAM)上,再由其去控制驱动单元,在屏幕上显示图形。
- 该 RAM 的大小为 128 * 64 为, RAM分为 8 页,从 PAGE0 到 PAGE7,用于单色 128 * 64 点阵显示,如下图所示
- 当一个数据字节写到 GDDRAM 中,所有当前列的同一页的行图像数据都会被被填充(比如,被列地址指针指向的整列(8 位)都会被填充)。数据位 D0 写到顶行,而数据位 D7 写到底行,如下图所示。
- 起始指针的 行(页)和列 可通过相应命令设置到任意字节。
- 显示数据可连续输入,GDDRAM内容将根据不同的地址模式从起始指针开始连续更新。
- 三种地址模式,有不同的指针移动方式:
-
- 页地址模式
- 水平地址模式
- 垂直地址模式
- 页地址模式
4)指令系统
当D/C端为第电平时,传输的是命令,详见手册命令表。
重点关注地址模式配置、指针模式、初始化指令、清屏指令和滚动指令。
步骤
1. 完成 CubeMX初始化配置
1.1 利用CubeMX完成HAL库工程模板和初始化:
通过选择芯片型号创建CubeMX工程
在弹出的对话框中输入开发板上的芯片型号,STM32F103RB
在右侧筛选栏中选择Tx型,即开发板上芯片所用的LQFP64型封装,双击建立工程
1.2 RCC时钟模块引脚的配置
在弹出的工程配置对话框中的第一个引脚配置选项卡下,先完成RCC时钟模块引脚配置:
选择启用外部的高速和低速时钟源,HSE和LSE,配置为晶振连接;
配置完成后,对应时钟引脚变绿,同时旁边出现其将要配置模式的文字说明;
1.3 配置时钟
我们前面启用了RCC时钟模块的外部时钟引脚,这里我们需要将外部时钟源配置为实际使用的频率;
查看手册可知:LSE为32.768KHz,HSE为8MHz;
点击上方的时钟配置选项卡,进入时钟配置界面;
前面启用了外部晶振源,这里检查修改HSE\LSE的频率,和实际一致;
在主频选择框中输入72MHz,然后按两下回车;
系统将自动将时钟源、时钟流向、PLL等配置好,以产生相应的主频;
1.4 RTC配置
1.在侧边栏的计时器中选择RTC
2.勾选Activate Clock Source 激活时钟源
Activate calendar 激活日历
3.配置时间日期
1.5配置SPI1
1.在侧边栏的通信外设中选择SPI1。
2.Mode处选 Transmit Only Master(因为只需要MCU向OLED发送指令即可,不需要接收数据)
3.SPI的参数默认即可,无需修改。
1.6生成工程
新建OLED.c/.h 与 OLED_font.h文件,添加到工程中。
MAX30102的需配置的寄存器的功能和地址
我们要向里面写数据点亮里面的像素点,必须找到对应的页位置和列位置,再把一个字节的数据,以纵向8点下高位的形式填充进去,哪我们如何运用oled的命令来锁定位置呢?如下表所示
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 显示中文文章来源:https://www.toymoban.com/news/detail-626580.html
/**
* @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模板网!