六、stm32-OLED

目录

  • 一、固件库模板
  • 二、准备资料
  • 三、OLED简介
    • 1. OLED引脚
    • 2. OLED屏幕像素与GDDRAM (Graphic Display Data RAM)
    • 3. OLED屏幕原理
    • 4. OLED屏幕指令
    • 5. 字模软件的使用(软件链接)
  • 四、OLED显示实验(模拟IIC、硬件IIC)
    • 1.硬件设计
    • 2.软件设计
      • 2.1 复制工程 ([stm32f103c8t6新建固件库模板(可自取)](https://blog.csdn.net/weixin_55999942/article/details/126022602?spm=1001.2014.3001.5502))
      • 2.2 新建oled文件(打开工程)
      • 2.3 编写代码
      • oled.c(模拟IIC)
      • oled.h(模拟IIC)
      • oledfont.h
      • oled(硬件IIC)
      • main.c
    • 3. 编译
    • 4. 选择烧录工具并配置MDK
    • 5. 成品
  • 工程链接

一、固件库模板

见博客:stm32f103c8t6新建固件库模板(可自取)

二、准备资料

  1. 固件库模板
  2. MDK5开发环境
  3. IIC协议
  4. OLED 数据手册及实物
  5. 字模软件

实验程序已经发布到百度网盘,本文末有链接可以自取

IIC协议查看这篇博客IIC协议

数据手册查看SSD1306Z

字模链接 链接:https://pan.baidu.com/s/1k_ay03xnAdGChirlTpTIVA
提取码:OLED

三、OLED简介

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

OLED显示和传统的LCD显示不同,其可以自发光,所以不需要背光灯,这使得OLED显示屏相对于LCD显示屏尺寸更薄,同时显示效果更优。

常用的OLED屏幕有蓝色、黄色、白色等几种。屏的大小为0.96寸,像素点为128*64,所以我们称为0.96oled屏或者12864屏。
在这里插入图片描述

这类屏幕大部分是由SSD1306来驱动的,查看数据手册在这:SSD1306Z

1. OLED引脚

标号PIN引脚说明
1GNDOLED显示模块电源地
2VCCOLED显示模块电源正
3SCLOLED显示模块I2C总线时钟信号
4SDAOLED显示模块I2C总线数据信号

2. OLED屏幕像素与GDDRAM (Graphic Display Data RAM)

屏幕有128列(Column ),64行(Row),共128*64像素点,每8行为1页(PAGE),共有8页
在这里插入图片描述

3. OLED屏幕原理

STM32内部建立一个缓存(共128*8个字节),每次修改的时候,只是修改STM32上的缓存(静态随机存储器 SRAM),修改完后一次性把STM32上的缓存数据写入到OLED的GRAM。

这个方法也有坏处,对于SRAM很小的单片机(51系列)就比较麻烦。

4. OLED屏幕指令

这个写的很详细,建议看看
https://wlink.blog.csdn.net/article/details/81329770

5. 字模软件的使用(软件链接)

OLED点阵的点亮方式,举个显示”P”的例子,最左边位最高位P7。

这个图画错了从下到上应该是8个点,他画了9个点。从下至上第2个点开始。
在这里插入图片描述

  1. 可以看出,要想显示”P”,首先写入0x1f,则显示一个竖杠,之后控制器自动水平移动到下一列。

  2. 再写入0X05,则出现两个小横杆,这个两个横杆就是0X05中0000 0101中两个1所处的位置,写完第二列后,控制器自动跳到第三列.

  3. 再写入0X07,第四列写入0X00后,P就显示出来了。这也说明,即使你只想再一列的最上端显示一个小点,即写入0X01。

  4. 即你不能一次性控制一个点阵,只能一次性控制八位点阵,即一列点阵。这也决定了字模选择的取模方式为“列行式”。

链接:https://pan.baidu.com/s/1k_ay03xnAdGChirlTpTIVA
提取码:OLED

在这里插入图片描述

在这里插入图片描述

四、OLED显示实验(模拟IIC、硬件IIC)

1.硬件设计

GND接GND
VCC接3.3
OLED的SCL接stm32的B8(模拟IIC)
OLED的SDA接stm32的B9(模拟IIC)
硬件IIC请查看IIC协议

2.软件设计

  1. 配置通讯使用的目标引脚为开漏模式;

  2. 使能 I2C 外设的时钟;

  3. 配置 I2C 外设的模式、地址、速率等参数并使能 I2C 外设;

  4. 编写向OLED写入函数;

  5. 编写OLED初始化指令

2.1 复制工程 (stm32f103c8t6新建固件库模板(可自取))

2.2 新建oled文件(打开工程)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.3 编写代码

oled.c(模拟IIC)

切记尽量避免使用PB3、PB4,具体看stm32f103c8t6使用PB3和PB4做普通GPIO使用时发现异常


#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"
#include "delay.h"//起始信号
void I2C_Start(void)
{OLED_SDIN_Set();OLED_SCLK_Set();OLED_SDIN_Clr();OLED_SCLK_Clr();
}//结束信号
void I2C_Stop(void)
{OLED_SCLK_Set();OLED_SDIN_Clr();OLED_SDIN_Set();
}//等待信号响应
void I2C_WaitAck(void) //测数据信号的电平
{OLED_SCLK_Set();OLED_SCLK_Clr();
}//写入一个字节
void Send_Byte(u8 dat)
{u8 i;for(i = 0; i < 8; i++){OLED_SCLK_Clr();//将时钟信号设置为低电平if(dat & 0x80) //将dat的8位从最高位依次写入{OLED_SDIN_Set();}else{OLED_SDIN_Clr();}OLED_SCLK_Set();//将时钟信号设置为高电平OLED_SCLK_Clr();//将时钟信号设置为低电平dat <<= 1;}
}//发送一个字节
//向SSD1306写入一个字节。
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat, u8 mode)
{I2C_Start();Send_Byte(0x78);I2C_WaitAck();if(mode){Send_Byte(0x40);}else{Send_Byte(0x00);}I2C_WaitAck();Send_Byte(dat);I2C_WaitAck();I2C_Stop();
}uint8_t CMD_Data[] =
{0xAE, 0x00, 0x10, 0x40, 0xB0, 0x81, 0xFF, 0xA1, 0xA6, 0xA8, 0x3F,0xC8, 0xD3, 0x00, 0xD5, 0x80, 0xD8, 0x05, 0xD9, 0xF1, 0xDA, 0x12,0xD8, 0x30, 0x8D, 0x14, 0xAF
};      //初始化命令/********************************************************************************
* @author: Luo Chen
* @date: 2022-07-01 15:15
* @brief: 写入初始化命令
* @return: None
********************************************************************************/
void Write_Cmd(void)
{int i;for (i = 0; i < 27; i++){OLED_WR_Byte(CMD_Data[i], OLED_CMD); //SET DCDC命令}
}/********************************************************************************
* @author: Luo Chen
* @date: 2022-07-01 15:19
* @brief: 向设备写控制命令
* @param: cmd
* @return: None
********************************************************************************/
void OLED_WR_CMD(uint8_t cmd)
{OLED_WR_Byte(cmd, OLED_CMD); //SET DCDC命令
}/********************************************************************************
* @author: Luo Chen
* @date: 2022-07-01 15:35
* @brief: 写数据
* @param: data
* @return: None
********************************************************************************/
void OLED_WR_DATA(uint8_t data)
{OLED_WR_Byte(data, OLED_DATA); //SET DCDC命令
}/********************************************************************************
* @author: Luo Chen
* @date: 2022-07-01 15:32
* @brief: 清屏
* @param: None
* @return: None
********************************************************************************/
void OLED_Clear(void)
{uint8_t i, n;for (i = 0; i < 27; i++){OLED_WR_CMD(0xb0 + i);OLED_WR_CMD(0x00);OLED_WR_CMD(0x10);for (n = 0; n < 128; n++){OLED_WR_DATA(0);}}
}/********************************************************************************
* @author: Luo Chen
* @date: 2022-07-01 15:59
* @brief: 开启OLed显示
* @param: None
* @return: None
********************************************************************************/
void OLED_Display_On(void)
{OLED_WR_CMD(0x8D);   //SET   DCDC设置电荷泵OLED_WR_CMD(0x14);   //DCDC  ON 开启电荷泵OLED_WR_CMD(0xAF);   //DISPlay ON开启显示
}/********************************************************************************
* @author: Luo Chen
* @date: 2022-07-01 16:36
* @brief: 关闭OLED显示
* @param:
* @return:
********************************************************************************/
void OLED_Display_Off(void)
{OLED_WR_CMD(0x8D);   //SET   DCDC设置电荷泵OLED_WR_CMD(0x10);   //DCDC  OFF 开启电荷泵OLED_WR_CMD(0xAE);   //DISPlay OFF开启显示
}/********************************************************************************
* @author: Luo Chen
* @date: 2022-07-01 16:33
* @brief: 设置起始点坐标
* @param: x,y
* @return: None
********************************************************************************/
void OLED_Set_Pos(uint8_t x, uint8_t y)
{OLED_WR_CMD(0xb0 + y);OLED_WR_CMD(((x & 0xf0) >> 4) | 0x10);OLED_WR_CMD(x & 0x0f);
}void OLED_On(void)
{uint8_t i, n;for (i = 0; i < 8; i++){OLED_WR_CMD(0xb0 + i);      //设置页地址OLED_WR_CMD(0x00);        //设置显示位置-列低地址OLED_WR_CMD(0x10);        //设置显示位置-列高地址for (n = 0; n < 128; n++){OLED_WR_DATA(1);}//刷新显示}
}/********************************************************************************
* @author: Luo Chen
* @date: 2022-07-03 15:35
* @brief: n为循环次数,得到值为m的n+1次方
* @param m
* @param n
* @return result
********************************************************************************/
unsigned int oled_pow(uint8_t m, uint8_t n)
{unsigned int result = 1;while (n--)result *= m;return result;
}//显示2个数字
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//mode:模式	0,填充模式;1,叠加模式
//num:数值(0~4294967295);
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);}
}//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示
//size:选择字体 16/12
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]);}
}/********************************************************************************
* @author: Luo Chen
* @date: 2022-07-03 15:02
* @brief: 显示一个字符号串
* @param x
* @param y
* @param chr
* @param Char_Size
* @return: None
********************************************************************************/
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;//如果--行显示的数字大于16就将行清零,y+2变成下一行if (x > 120){x = 0;y += 2;}j++;}
}/********************************************************************************
* @author: Luo Chen
* @date: 2022-07-03 14:46
* @brief: 显示汉字     hzk 用取模软件得出的数组
* @param x,设置起始点x坐标
* @param y,设置起始点y坐标
* @param no,显示数组的第n个字
* @return:
********************************************************************************/
void OLED_ShowCHinese(uint8_t x, uint8_t y, uint8_t no)
{uint8_t t, adder = 0;OLED_Set_Pos(x, y);//显示上面一部分for (t = 0; t < 16; t++){//Hzk[第几个数组][第几个值]OLED_WR_DATA(Hzk[2 * no][t]);adder += 1;}//显示下面一部分OLED_Set_Pos(x, y + 1);for (t = 0; t < 16; t++){OLED_WR_DATA(Hzk[2 * no + 1][t]);adder += 1;}
}/********************************************************************************
* @author: Luo Chen
* @date: 2022-07-01 15:38
* @brief: 初始化oled屏幕
* @param: None
* @return: None
********************************************************************************/
void OLED_Init(void)
{GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(	OLED_CLK, ENABLE );GPIO_InitStructure.GPIO_Pin = OLED_SCLK_Pin | OLED_SDIN_Pin;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(OLED_PORT, &GPIO_InitStructure);Delay_ms(100);Write_Cmd();OLED_Clear();
}

oled.h(模拟IIC)

/************************************ Copyright ************************************ (C) Copyright 2022-2022 xxx,China.** All Rights Reserved.*********************************************************************************--------------------------------------------------------------------------**** @FileName      : oled.h** @Description   : None**--------------------------------------------------------------------------**** @Author        : Luo Chen** @Version       : v1.0** @Creat Date    : 2022-07-16**--------------------------------------------------------------------------**** @Modfier       : None** @Version       : None** @Modify Date   : None** @Description   : None**--------------------------------------------------------------------------**** @Function List : None**--------------------------------------------------------------------------**** @Attention     : None**--------------------------------------------------------------------------***********************************************************************************//* Define to prevent recursive inclusion -------------------------------------*/#ifndef __OLED_H_
#define __OLED_H_#include "stm32f10x.h"#include "sys.h"
#include "stdlib.h"
////-----------------OLED端口定义----------------#define OLED_SCLK_Pin		GPIO_Pin_8
#define OLED_SDIN_Pin 	 GPIO_Pin_9
#define OLED_CLK 				     RCC_APB2Periph_GPIOB
#define OLED_PORT				   GPIOB#define OLED_SCLK_Clr() GPIO_ResetBits(OLED_PORT,OLED_SCLK_Pin)
#define OLED_SCLK_Set() GPIO_SetBits(OLED_PORT,OLED_SCLK_Pin)//SCL#define OLED_SDIN_Clr() GPIO_ResetBits(OLED_PORT,OLED_SDIN_Pin)//DIN
#define OLED_SDIN_Set() GPIO_SetBits(OLED_PORT,OLED_SDIN_Pin)#define OLED_CMD  0	//写命令
#define OLED_DATA 1	//写数据void I2C_Start(void);
void I2C_Stop(void);
void I2C_WaitAck(void);
void Send_Byte(u8 dat);
void OLED_WR_Byte(u8 dat, u8 mode);
void Write_Cmd(void);
void OLED_WR_CMD(uint8_t cmd);
void OLED_WR_DATA(uint8_t data);
void OLED_Init(void);
void OLED_Clear(void);
void OLED_Display_On(void);
void OLED_Display_Off(void);
void OLED_Set_Pos(uint8_t x, uint8_t y);
void OLED_On(void);
void OLED_ShowNum(uint8_t x, uint8_t y, unsigned int num, uint8_t len, uint8_t size2);
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t Char_Size);
void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_t Char_Size);
void OLED_ShowCHinese(uint8_t x, uint8_t y, uint8_t no);#endif/******************************** END OF FILE *********************************/

oledfont.h

    {0x04,0x24,0x44,0x84,0x64,0x9C,0x40,0x30,0x0F,0xC8,0x08,0x08,0x28,0x18,0x00,0x00},
{0x10,0x08,0x06,0x01,0x82,0x4C,0x20,0x18,0x06,0x01,0x06,0x18,0x20,0x40,0x80,0x00},/*"欢",0*/{0x40,0x40,0x42,0xCC,0x00,0x00,0xFC,0x04,0x02,0x00,0xFC,0x04,0x04,0xFC,0x00,0x00},
{0x00,0x40,0x20,0x1F,0x20,0x40,0x4F,0x44,0x42,0x40,0x7F,0x42,0x44,0x43,0x40,0x00},/*"迎",1*/{0x00,0x08,0x08,0x28,0xC8,0x08,0x08,0xFF,0x08,0x08,0x88,0x68,0x08,0x08,0x00,0x00},
{0x21,0x21,0x11,0x11,0x09,0x05,0x03,0xFF,0x03,0x05,0x09,0x11,0x11,0x21,0x21,0x00},/*"来",2*/{0x42,0x62,0x52,0x4A,0xC6,0x42,0x52,0x62,0xC2,0x00,0xF8,0x00,0x00,0xFF,0x00,0x00},
{0x40,0xC4,0x44,0x44,0x7F,0x24,0x24,0x24,0x20,0x00,0x0F,0x40,0x80,0x7F,0x00,0x00},/*"到",3*/{0x10,0x60,0x02,0x8C,0x00,0x10,0x08,0x14,0xA7,0x44,0xA4,0x14,0x0C,0x00,0x00,0x00},
{0x04,0x04,0x7E,0x01,0x02,0x02,0xFD,0x45,0x44,0x44,0x44,0x45,0xFD,0x02,0x02,0x00},/*"洛",4*/{0x00,0x40,0x20,0x10,0x0C,0x00,0x00,0x7F,0x00,0x00,0x04,0x08,0x10,0x60,0x00,0x00},
{0x40,0x40,0x44,0x44,0x44,0x44,0x44,0x7F,0x44,0x44,0x44,0x44,0x44,0x40,0x40,0x00},/*"尘",5*/{0x00,0xF8,0x0C,0x0B,0x08,0x08,0xF8,0x40,0x30,0x8F,0x08,0x08,0x08,0xF8,0x00,0x00},
{0x00,0x7F,0x21,0x21,0x21,0x21,0x7F,0x00,0x00,0x00,0x43,0x80,0x40,0x3F,0x00,0x00},/*"的",6*/{0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00},/*"C",7*/{0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00},/*"S",8*/{0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00},/*"D",9*/{0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00},/*"N",10*/

oled(硬件IIC)

oled.c已经写好(可能会有小问题哦),现在可以给自己一个小难度,自己整合main.c,实现显示在这里插入图片描述

链接:https://pan.baidu.com/s/152-9TrB_QuYDivIrDiCwTA
提取码:0000

main.c

#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "stm32f10x.h"
#include "oled.h"int main()
{/*********************************************************************************    Delay_init();				  //本实验使用的是SysTick时钟*    CPU_TS_TmrInit();      //已经使能宏,不需要初始化*    uart1_init(115200);	 	//串口初始化为115200,需要在usart.h中使能*    uart3_init(115200);	 	//串口初始化为115200********************************************************************************//* 初始化 */OLED_Init();OLED_Clear();OLED_ShowString(30,  0, "OLED", 16);   //输出字符OLED_ShowCHinese(0,  4, 0);	//欢OLED_ShowCHinese(16, 4, 1);	//迎OLED_ShowCHinese(32, 4, 2);	//来OLED_ShowCHinese(48, 4, 3);	//到OLED_ShowCHinese(64, 4, 4);	//洛OLED_ShowCHinese(80, 4, 5);	//尘OLED_ShowCHinese(96, 4, 6);	//的OLED_ShowString	(0,	 6,"CSDN",16);while(1){}
}

3. 编译

编译成功
在这里插入图片描述

4. 选择烧录工具并配置MDK

本文选择的是ST_Link烧录工具
在这里插入图片描述
在这里插入图片描述
如果没有ID号看博客:ST-Link V2烧录问题(已解决)
在这里插入图片描述
在这里插入图片描述

5. 成品

在这里插入图片描述

工程链接

链接:https://pan.baidu.com/s/103fBiqMb3REZwn1tGnOgMA 提取码:OLED


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部