STM32 I2C_OLED显示汉字及屏幕滚动



任务简介
学习I2C总线通信协议,使用STM32F103完成基于I2C协议的AHT20温湿度传感器的数据采集,并将采集的温度-湿度值通过串口输出。具体任务:


  1. 显示自己的学号和姓名;

  2. 显示AHT20的温度和湿度;

  3. 上下或左右的滑动显示长字符


一.I2C以及AHT20温湿度传感器介绍

这里可以看上一篇链接

二.用0.96寸OLED屏幕显示数据

1.OLED介绍

OLED器件由基板、阴极、阳极、空穴注入层(HIL)、电子注入层(EIL)、空穴传输层(HTL)、电子传输层(ETL)、电子阻挡层(EBL)、空穴阻挡层(HBL)、发光层(EML)等部分构成。其中,基板是整个器件的基础,所有功能层都需要蒸镀到器件的基板上;通常采用玻璃作为器件的基板,但是如果需要制作可弯曲的柔性OLED器件,则需要使用其它材料如塑料等作为器件的基板。阳极与器件外加驱动电压的正极相连,阳极中的空穴会在外加驱动电压的驱动下向器件中的发光层移动,阳极需要在器件工作时具有一定的透光性,使得器件内部发出的光能够被外界观察到;阳极最常使用的材料是ITO。空穴注入层能够对器件的阳极进行修饰,并可以使来自阳极的空穴顺利的注入到空穴传输层;空穴传输层负责将空穴运输到发光层;电子阻挡层会把来自阴极的电子阻挡在器件的发光层界面处,增大器件发光层界面处电子的浓度;发光层为器件电子和空穴再结合形成激子然后激子退激发光的地方;空穴阻挡层会将来自阳极的空穴阻挡在器件发光层的界面处,进而提高器件发光层界面处电子和空穴再结合的概率,增大器件的发光效率;电子传输层负责将来自阴极的电子传输到器件的发光层中;电子注入层起对阴极修饰及将电子传输到电子传输层的作用;阴极中的电子会在器件外加驱动电压的驱动下向器件的发光层移动,然后在发光层与来自阳极的空穴进行再结合。

  • 这里我的OLED模块是基于I2C通信的,一般还有SPI版本的也很常见

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

2.样例测试

  • 我们先以官方例程测试用软件I2C协议在OLED屏幕上显示
  • 线路连接
    在这里插入图片描述
  • 例程
  • 链接 提取码: 1234

  • 显示结果:
    在这里插入图片描述

三.汉字编码原理

所有的汉字或者英文都是下面的原理,
生成的字库说明:(以12×12例子)

  • 由左至右,每8个点占用一个字节,最后不足8个字节的占用一个字节,而且从最高位向最低位排列。
    在这里插入图片描述
  • 一个汉字占用字节数:12÷8=1····4也就是占用了2×12=24个字节。

编码排序A0A0→A0FE A1A0→A2FE依次排列。

  • 以12×12字库的“我”为例:“我”的编码为CED2,所以在汉字排在CEH-AOH=2EH区的D2H-A0H=32H个。所以在12×12字库的起始位置就是[{FE-A0}*2EH+32H]*24=104976开始的24个字节就是我的点阵模。

其他的类推即可。

英文点阵也是如此推理。


四.实验步骤

1.软件

  • 因为后文我们需要在OLED屏幕上显示汉字,所以我们需要一个取字模的软件PCtoLCD2002 提取码: 1234

  • 下面介绍字模提取的步骤“

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

2.具体实现

①.目录结构

在这里插入图片描述

②.字模函数

分析:
根据我们的任务,我们需要显示的字符有:数字,±号(数字前面的符号),以及几个汉字(“姓名”,‘温’,‘湿’,‘度’),在例程中OLED_Font.h已经有了数字以及特数字符的字模了,所以我们只需要自己取几个汉字的字模。汉字另外放在一个const数组里

const uint8_t OLED_F10x16[][40]=
{
0x00,0x00,0x00,0x00,0xFC,0x84,0x84,0xA4,0xA4,0xA4,0xFC,0xA4,0xA4,0x94,0x84,0x04,
0xFE,0x00,0x00,0x00,0x00,0x40,0x20,0x1C,0x03,0x00,0x00,0x1F,0x12,0x12,0x12,0x12,
0x1E,0x1F,0x40,0x40,0x7F,0x00,0x00,0x00,/*"周",0*/
	
0x00,0x00,0x08,0xF0,0x00,0x00,0xFE,0x00,0x00,0xF0,0x10,0x10,0xFE,0xFE,0x10,0x10,
0xF0,0x10,0x00,0x00,0x00,0x80,0x40,0x27,0x10,0x0E,0x01,0x00,0x00,0x0F,0x00,0x00,
0xFF,0x7F,0x08,0x08,0x0F,0x00,0x00,0x00,/*"帅",1*/
	
0x00,0x00,0x00,0xFC,0x78,0x88,0xA8,0xA8,0xA8,0xA8,0xFA,0xA6,0xA8,0xA8,0xA8,0xE8,
0x84,0x44,0x00,0x00,0x00,0x40,0x30,0x0F,0x00,0x20,0x20,0x16,0x1A,0x4A,0x7F,0x02,
0x06,0x1A,0x1A,0x2B,0x64,0x44,0x00,0x00,/*"康",2*/
	
	
0x00,0x20,0x40,0x04,0x0C,0xE0,0x10,0x00,0xFC,0x94,0x94,0x94,0x94,0x94,0x94,0xFC,
0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x7C,0x43,0x40,0x7E,0x42,0x42,0x42,0x7E,0x42,
0x42,0x7E,0x42,0x42,0x7E,0x42,0x40,0x00,/*"温",0*/


	
0x00,0x20,0x62,0x44,0x8C,0x60,0x10,0x00,0xFC,0x94,0x54,0x54,0x54,0x94,0x54,0x54,
0xFC,0x00,0x00,0x00,0x00,0x04,0x34,0x7E,0x01,0x40,0x42,0x4C,0x58,0x40,0x7F,0x40,
0x40,0x7F,0x50,0x48,0x44,0x43,0x42,0x00,/*"湿",0*/

0x00,0x00,0x00,0xF8,0x28,0x28,0x28,0x28,0xF8,0x28,0x26,0x24,0x28,0xF8,0x38,0x28,
0x28,0x24,0x00,0x00,0x00,0x40,0x38,0x87,0x80,0x80,0x40,0x42,0x45,0x2B,0x33,0x13,
0x33,0x2B,0x46,0x40,0x40,0x40,0x40,0x00,/*"度",1*/
};


③.显示汉字
  • 我们把汉字的字模放在一个数组里,用下标来找到对应汉字

  • 传入参数中Num指的是向显示的汉字在数组当中的位置,比如上面‘周’对应Num就是0

void OLED_ShowCN(uint8_t Line, uint8_t Column, uint8_t Num)  
{      	
	uint8_t i;
	uint8_t wide=20;//字宽
	
	OLED_SetCursor((Line-1)*2, (Column-1)*wide);		//参数1:把光标设置在第几页. 参数2:把光标设置在第几列
	for (i = 0; i < wide; i++)
	{
		OLED_WriteData(OLED_F10x16[Num][i]);			//显示上半部分内容
	}
	
	OLED_SetCursor((Line-1)*2+1,(Column-1)*wide);		
	for (i = 0; i < wide; i++)
	{
		OLED_WriteData(OLED_F10x16[Num][i+wide]);		//显示下半部分内容
	}

}
④.屏幕滚动
			OLED_WriteCommand(0x2E); //关闭滚动
			OLED_WriteCommand(0x26); //水平向左或者右滚动 26/27
			OLED_WriteCommand(0x00); //虚拟字节
			OLED_WriteCommand(0x00); //起始页 0
			OLED_WriteCommand(0x07); //滚动时间间隔,数字越大转动越慢
			OLED_WriteCommand(0x03); //终止页 3
			OLED_WriteCommand(0x00); //虚拟字节
			OLED_WriteCommand(0xFF); //虚拟字节
			OLED_WriteCommand(0x2F); //开启滚动
⑤.主函数
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AHT20-21_DEMO_V1_3.h"

int main(void)
{
	volatile float  c1=0,t1=0;
	uint32_t CT_data[2];
	Init_I2C_Sensor_Port();//初始化SDA,SCL的IO口
	Delay_1ms(500);
	OLED_Init();
	if((AHT20_Read_Status()&0x18)!=0x18)
	{
	AHT20_Start_Init(); //重新初始化寄存器
	Delay_1ms(10);
	}

	//下面显示汉字	
	OLED_ShowCN(1,1,0); //周
	OLED_ShowCN(1,2,1); //帅
	OLED_ShowCN(1,3,2); //康
	OLED_ShowString(2,1,"632007060321"); //学号
	OLED_ShowCN(3,1,3);//温
	OLED_ShowCN(3,2,5);//度
	OLED_ShowCN(4,1,4);//湿
	OLED_ShowCN(4,2,5);//度
	while(1)
	{
		
			//屏幕滚动
			OLED_WriteCommand(0x2E); //关闭滚动
			OLED_WriteCommand(0x26); //水平向左或者右滚动 26/27
			OLED_WriteCommand(0x00); //虚拟字节
			OLED_WriteCommand(0x00); //起始页 0
			OLED_WriteCommand(0x07); //滚动时间间隔,数字越大转动越慢
			OLED_WriteCommand(0x03); //终止页 3
			OLED_WriteCommand(0x00); //虚拟字节
			OLED_WriteCommand(0xFF); //虚拟字节
			OLED_WriteCommand(0x2F); //开启滚动
	
	 //AHT20_Read_CTdata(CT_data);       //不经过CRC校验,直接读取AHT20的温度和湿度数据    推荐每隔大于1S读一次
	 AHT20_Read_CTdata_crc(CT_data);  //crc校验后,读取AHT20的温度和湿度数据 
		
	 while(CT_data[0]==0x00&&CT_data[1]==0x00) //如果CRC校验不通过
	 {
	 	AHT20_Read_CTdata_crc(CT_data);
	 }
	 c1 = CT_data[0]*100*10/1024/1024;  //计算得到湿度值c1(放大了10倍)
	 t1 = CT_data[1]*200*10/1024/1024-500;//计算得到温度值t1(放大了10倍)
	////下一步客户处理显示数据,
		
			Delay_1ms(1000);
			OLED_Showfloat(3,7,t1/10.00,2,1);
			
			OLED_Showfloat(4,7,c1/10.00,2,1);
	}
	
	
}

五.实验结果

请添加图片描述

六.程序源码

链接: https://pan.baidu.com/s/1WErBaAsek_QvCTCDn8GOWQ?pwd=1234 提取码: 1234

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐