文章目录

  • 一、SPI简介
    • 1.1 什么是SPI
    • 1.2 SPI原理
    • 1.3 SPI的连接方式
    • 1.4 协议层
  • 二、OLED
    • 2.1 OLED原理
    • 2.2 点阵编码原理与显示
  • 三、OLED显示实验
    • 3.1 汉字取模
    • 3.2 修改代码
    • 3.3 编译烧录运行
  • 四、滚动显示
    • 4.1 修改代码
    • 4.2 编译烧录运行
  • 五、添加读取温湿度
    • 5.1 添加文件
    • 5.2 修改代码
    • 5.3编译烧录运行
  • 六、总结
  • 七、参考文章

一、SPI简介

1.1 什么是SPI

SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。

1.2 SPI原理

SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚。SPI 是一个环形总线结构,由 ss(cs)、sck、sdi、sdo 构成,时序主要是在 sck 的控制下,两个双向移位寄存器进行数据交换。
上升沿发送、下降沿接收、高位先发送。
上升沿到来的时候,sdo 上的电平将被发送到从设备的寄存器中。
下降沿到来的时候,sdi 上的电平将被接收到主设备的寄存器中。

1.3 SPI的连接方式

  • SS( Slave Select):从设备选择信号线,常称为片选信号线。
  • SCK (Serial Clock):时钟信号线,用于通讯数据同步。
  • MOSI (Master Output, Slave Input):主设备输出/从设备输入引脚。
  • MISO(Master Input,,Slave Output):主设备输入/从设备输出引脚。

1.4 协议层

与I2C的类似,SPI协议定义了通讯的起始和停止信号、数据有效性、时钟同步等环节

MOSI 与 MISO 的信号只在 NSS 为低电平的时候才有效,在 SCK 的每个时钟周期 MOSI 和 MISO 传输一位数据。

二、OLED

2.1 OLED原理

OLED(OrganicLight-Emitting Diode),又称为有机电激光显示、有机发光半导体(OrganicElectroluminesence Display,OLED)。OLED属于一种电流型的有机发光器件,是通过载流子的注入和复合而致发光的现象,发光强度与注入的电流成正比。OLED在电场的作用下,阳极产生的空穴和阴极产生的电子就会发生移动,分别向空穴传输层和电子传输层注入,迁移到发光层。当二者在发光层相遇时,产生能量激子,从而激发发光分子最终产生可见光。

2.2 点阵编码原理与显示

汉字点阵编码
在汉字的点阵字库中,每个字节的每个位都代表一个汉字的一个点,每个汉字都是由一个矩形的点阵组成,0 代表没有点,1 代表有点,将 0 和 1 分别用不同颜色画出,就形成了一个汉字,常用的点阵矩阵有 1212, 1414, 16*16 三 种字库。
字库根据字节所表示点的不同有分为横向矩阵和纵向矩阵,目前多数的字库都是横向矩阵的存储方式(用得最多的应该是早期 UCDOS 字库),纵向矩阵一 般是因为有某些液晶是采用纵向扫描显示法,为了提高显示速度,于是便把字库 矩阵做成纵向,省得在显示时还要做矩阵转换。
OLED点阵显示
点阵屏像素按128列X64行组织,每一行128个像素单元的阴极是连接在一起,作为公共极(COM),每一列64个像素单元的阳极也连接在一起,作为一段(SEG)。行列交叉点上的LED就是一个显示单元,即一个像素。要点亮一个像素,只要在该像素所在列电极上加上正电压、行电极接地。同样,要驱动一整行图像,就需要同时把128列信号加载到列电极上,把该行行电极接地。该行显示时,其他63行均不能显示,其行电极应为高电平或悬空。
可见,整屏的显示,只能分时扫描进行,一行一行的显示,每次显示一行。行驱依次产生低电平扫描各行,列驱动读取显示数据依次加载到列电极上。扫描一行的时间称为行周期,完成一次全屏扫描,就叫做一帧。一般帧频大于60,人眼观察不到逐行显示。每行扫描显示用时叫占空比,占空比小,为达到相同的显示亮度,驱动电流就大。SSD1306段驱动最大电流为100uA,当整行128个像素全部点亮时,行电极就要流过12.8mA的电流。

三、OLED显示实验

实验工具与材料
软件:keil
硬件:PC机,STM32F103C8T6开发板,0.96寸OLED显示屏
0.96寸OLED显示屏相关介绍

运行厂家给出的Demo程序
①下载程序
程序下载链接:
0.96寸SPI_OLED模块配套资料包
②打开资料包,选择与自己平台相同的实例,打开Demo的工程,使用keil编译
③将程序烧录到开发板
④连接显示屏和开发板

3.1 汉字取模

打开取字模软件

模式切换为字符模式,格式切换为C51

3.2 修改代码

打开demo中的第四个文件

打开 gui.c下的 oledfont.h 头文件,将 cfont16[] 数组内的内容修改成自己的中文文字点阵
如果直接点开项目后gui.c无法点开,先编译一下,编译完成后点击gui.c前面的加号

将 test.c 里 void TEST_MainPage(void) 函数中的语句注释掉,添加自己的执行语句

修改mian函数中的while循环

连线

3.3 编译烧录运行


四、滚动显示

4.1 修改代码

跟前面一样,获取字模后,向 gui.c下的 oledfont.h头文件里的cfont16[] 数组内的添加中文文字点阵

修改 test.c里 void TEST_MainPage(void) 函数如下

修改mian函数中的while循环

4.2 编译烧录运行



五、添加读取温湿度

该操作需要基于AHT20芯片
可参考博主以前博文:STM32通过I2C接口实现温湿度(AHT20)的采集

5.1 添加文件

将AHT文件放在HARDWARE目录下



5.2 修改代码

修改AHT20-21_DEMO_V1_3.c

#include "AHT20-21_DEMO_V1_3.h" void Delay_N10us(uint32_t t)//延时函数
{uint32_t k;while(t--){for (k = 0; k < 2; k++);//110}
}void SensorDelay_us(uint32_t t)//延时函数
{for(t = t-2; t>0; t--){Delay_N10us(1);}
}void Delay_4us(void)       //延时函数
{   Delay_N10us(1);Delay_N10us(1);Delay_N10us(1);Delay_N10us(1);
}
void Delay_5us(void)        //延时函数
{   Delay_N10us(1);Delay_N10us(1);Delay_N10us(1);Delay_N10us(1);Delay_N10us(1);}void Delay_1ms(uint32_t t)      //延时函数
{while(t--){SensorDelay_us(1000);//延时1ms}
}//void AHT20_Clock_Init(void)      //延时函数
//{//  RCC_APB2PeriphClockCmd(CC_APB2Periph_GPIOB,ENABLE);
//}void SDA_Pin_Output_High(void)   //将PB7配置为输出 , 并设置为高电平, PB7作为I2C的SDA
{GPIO_InitTypeDef  GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,& GPIO_InitStruct);GPIO_SetBits(GPIOB,GPIO_Pin_7);
}void SDA_Pin_Output_Low(void)  //将P7配置为输出  并设置为低电平
{GPIO_InitTypeDef  GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,& GPIO_InitStruct);GPIO_ResetBits(GPIOB,GPIO_Pin_7);
}void SDA_Pin_IN_FLOATING(void)  //SDA配置为浮空输入
{GPIO_InitTypeDef  GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;//GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init( GPIOB,&GPIO_InitStruct);
}void SCL_Pin_Output_High(void) //SCL输出高电平,PB6作为I2C的SCL
{GPIO_SetBits(GPIOB,GPIO_Pin_6);
}void SCL_Pin_Output_Low(void) //SCL输出低电平
{GPIO_ResetBits(GPIOB,GPIO_Pin_6);
}void Init_I2C_Sensor_Port(void) //初始化I2C接口,输出为高电平
{   GPIO_InitTypeDef  GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,& GPIO_InitStruct);GPIO_SetBits(GPIOB,GPIO_Pin_15);//输出高电平GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,& GPIO_InitStruct);GPIO_SetBits(GPIOB,GPIO_Pin_15);//输出高电平}
void I2C_Start(void)         //I2C主机发送START信号
{SDA_Pin_Output_High();SensorDelay_us(8);SCL_Pin_Output_High();SensorDelay_us(8);SDA_Pin_Output_Low();SensorDelay_us(8);SCL_Pin_Output_Low();SensorDelay_us(8);
}void AHT20_WR_Byte(uint8_t Byte) //往AHT20写一个字节
{uint8_t Data,N,i;  Data=Byte;i = 0x80;for(N=0;N<8;N++){SCL_Pin_Output_Low(); Delay_4us();  if(i&Data){SDA_Pin_Output_High();}else{SDA_Pin_Output_Low();}   SCL_Pin_Output_High();Delay_4us();Data <<= 1;}SCL_Pin_Output_Low();SensorDelay_us(8);   SDA_Pin_IN_FLOATING();SensorDelay_us(8);
}   uint8_t AHT20_RD_Byte(void)//从AHT20读取一个字节
{uint8_t Byte,i,a;Byte = 0;SCL_Pin_Output_Low();SDA_Pin_IN_FLOATING();SensorDelay_us(8);   for(i=0;i<8;i++){SCL_Pin_Output_High();       Delay_5us();a=0;if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)) a=1;Byte = (Byte<<1)|a;SCL_Pin_Output_Low();Delay_5us();}SDA_Pin_IN_FLOATING();SensorDelay_us(8);  return Byte;
}uint8_t Receive_ACK(void)   //看AHT20是否有回复ACK
{uint16_t CNT;CNT = 0;SCL_Pin_Output_Low();    SDA_Pin_IN_FLOATING();SensorDelay_us(8);    SCL_Pin_Output_High();  SensorDelay_us(8);  while((GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7))  && CNT < 100) CNT++;if(CNT == 100){return 0;}SCL_Pin_Output_Low();  SensorDelay_us(8);  return 1;
}void Send_ACK(void)          //主机回复ACK信号
{SCL_Pin_Output_Low();  SensorDelay_us(8);  SDA_Pin_Output_Low();SensorDelay_us(8); SCL_Pin_Output_High();  SensorDelay_us(8);SCL_Pin_Output_Low(); SensorDelay_us(8);SDA_Pin_IN_FLOATING();SensorDelay_us(8);
}void Send_NOT_ACK(void)    //主机不回复ACK
{SCL_Pin_Output_Low();  SensorDelay_us(8);SDA_Pin_Output_High();SensorDelay_us(8);SCL_Pin_Output_High();    SensorDelay_us(8);      SCL_Pin_Output_Low();   SensorDelay_us(8);SDA_Pin_Output_Low();SensorDelay_us(8);
}void Stop_I2C(void)      //一条协议结束
{SDA_Pin_Output_Low();SensorDelay_us(8);SCL_Pin_Output_High();  SensorDelay_us(8);SDA_Pin_Output_High();SensorDelay_us(8);
}uint8_t AHT20_Read_Status(void)//读取AHT20的状态寄存器
{uint8_t Byte_first;    I2C_Start();AHT20_WR_Byte(0x71);Receive_ACK();Byte_first = AHT20_RD_Byte();Send_NOT_ACK();Stop_I2C();return Byte_first;
}uint8_t AHT20_Read_Cal_Enable(void)  //查询cal enable位有没有使能
{uint8_t val = 0;//ret = 0,val = AHT20_Read_Status();if((val & 0x68)==0x08)return 1;else  return 0;}void AHT20_SendAC(void) //向AHT20发送AC命令
{I2C_Start();AHT20_WR_Byte(0x70);Receive_ACK();AHT20_WR_Byte(0xac);//0xAC采集命令Receive_ACK();AHT20_WR_Byte(0x33);Receive_ACK();AHT20_WR_Byte(0x00);Receive_ACK();Stop_I2C();}//CRC校验类型:CRC8/MAXIM
//多项式:X8+X5+X4+1
//Poly:0011 0001  0x31
//高位放到后面就变成 1000 1100 0x8c
//C现实代码:
uint8_t Calc_CRC8(uint8_t *message,uint8_t Num)
{uint8_t i;uint8_t byte;uint8_t crc=0xFF;for(byte=0; byte<Num; byte++){crc^=(message[byte]);for(i=8;i>0;--i){if(crc&0x80) crc=(crc<<1)^0x31;else crc=(crc<<1);}}return crc;
}void AHT20_Read_CTdata(uint32_t *ct) //没有CRC校验,直接读取AHT20的温度和湿度数据
{volatile uint8_t  Byte_1th=0;volatile uint8_t  Byte_2th=0;volatile uint8_t  Byte_3th=0;volatile uint8_t  Byte_4th=0;volatile uint8_t  Byte_5th=0;volatile uint8_t  Byte_6th=0;uint32_t RetuData = 0;uint16_t cnt = 0;AHT20_SendAC();//向AHT10发送AC命令Delay_1ms(80);//延时80ms左右 cnt = 0;while(((AHT20_Read_Status()&0x80)==0x80))//直到状态bit[7]为0,表示为空闲状态,若为1,表示忙状态{SensorDelay_us(1508);if(cnt++>=100){break;}}I2C_Start();AHT20_WR_Byte(0x71);Receive_ACK();Byte_1th = AHT20_RD_Byte();//状态字,查询到状态为0x98,表示为忙状态,bit[7]为1;状态为0x1C,或者0x0C,或者0x08表示为空闲状态,bit[7]为0Send_ACK();Byte_2th = AHT20_RD_Byte();//湿度Send_ACK();Byte_3th = AHT20_RD_Byte();//湿度Send_ACK();Byte_4th = AHT20_RD_Byte();//湿度/温度Send_ACK();Byte_5th = AHT20_RD_Byte();//温度Send_ACK();Byte_6th = AHT20_RD_Byte();//温度Send_NOT_ACK();Stop_I2C();RetuData = (RetuData|Byte_2th)<<8;RetuData = (RetuData|Byte_3th)<<8;RetuData = (RetuData|Byte_4th);RetuData =RetuData >>4;ct[0] = RetuData;//湿度RetuData = 0;RetuData = (RetuData|Byte_4th)<<8;RetuData = (RetuData|Byte_5th)<<8;RetuData = (RetuData|Byte_6th);RetuData = RetuData&0xfffff;ct[1] =RetuData; //温度}void AHT20_Read_CTdata_crc(uint32_t *ct) //CRC校验后,读取AHT20的温度和湿度数据
{volatile uint8_t  Byte_1th=0;volatile uint8_t  Byte_2th=0;volatile uint8_t  Byte_3th=0;volatile uint8_t  Byte_4th=0;volatile uint8_t  Byte_5th=0;volatile uint8_t  Byte_6th=0;volatile uint8_t  Byte_7th=0;uint32_t RetuData = 0;uint16_t cnt = 0;// uint8_t  CRCDATA=0;uint8_t  CTDATA[6]={0};//用于CRC传递数组AHT20_SendAC();//向AHT10发送AC命令Delay_1ms(80);//延时80ms左右 cnt = 0;while(((AHT20_Read_Status()&0x80)==0x80))//直到状态bit[7]为0,表示为空闲状态,若为1,表示忙状态{SensorDelay_us(1508);if(cnt++>=100){break;}}I2C_Start();AHT20_WR_Byte(0x71);Receive_ACK();CTDATA[0]=Byte_1th = AHT20_RD_Byte();//状态字,查询到状态为0x98,表示为忙状态,bit[7]为1;状态为0x1C,或者0x0C,或者0x08表示为空闲状态,bit[7]为0Send_ACK();CTDATA[1]=Byte_2th = AHT20_RD_Byte();//湿度Send_ACK();CTDATA[2]=Byte_3th = AHT20_RD_Byte();//湿度Send_ACK();CTDATA[3]=Byte_4th = AHT20_RD_Byte();//湿度/温度Send_ACK();CTDATA[4]=Byte_5th = AHT20_RD_Byte();//温度Send_ACK();CTDATA[5]=Byte_6th = AHT20_RD_Byte();//温度Send_ACK();Byte_7th = AHT20_RD_Byte();//CRC数据Send_NOT_ACK();                           //注意: 最后是发送NAKStop_I2C();if(Calc_CRC8(CTDATA,6)==Byte_7th){RetuData = (RetuData|Byte_2th)<<8;RetuData = (RetuData|Byte_3th)<<8;RetuData = (RetuData|Byte_4th);RetuData =RetuData >>4;ct[0] = RetuData;//湿度RetuData = 0;RetuData = (RetuData|Byte_4th)<<8;RetuData = (RetuData|Byte_5th)<<8;RetuData = (RetuData|Byte_6th);RetuData = RetuData&0xfffff;ct[1] =RetuData; //温度}else{ct[0]=0x00;ct[1]=0x00;//校验错误返回值,客户可以根据自己需要更改}//CRC数据
}void AHT20_Init(void)   //初始化AHT20
{   Init_I2C_Sensor_Port();I2C_Start();AHT20_WR_Byte(0x70);Receive_ACK();AHT20_WR_Byte(0xa8);//0xA8进入NOR工作模式Receive_ACK();AHT20_WR_Byte(0x00);Receive_ACK();AHT20_WR_Byte(0x00);Receive_ACK();Stop_I2C();Delay_1ms(10);//延时10ms左右I2C_Start();AHT20_WR_Byte(0x70);Receive_ACK();AHT20_WR_Byte(0xbe);//0xBE初始化命令,AHT20的初始化命令是0xBE,   AHT10的初始化命令是0xE1Receive_ACK();AHT20_WR_Byte(0x08);//相关寄存器bit[3]置1,为校准输出Receive_ACK();AHT20_WR_Byte(0x00);Receive_ACK();Stop_I2C();Delay_1ms(10);//延时10ms左右}
void JH_Reset_REG(uint8_t addr)
{uint8_t Byte_first,Byte_second,Byte_third;I2C_Start();AHT20_WR_Byte(0x70);//原来是0x70Receive_ACK();AHT20_WR_Byte(addr);Receive_ACK();AHT20_WR_Byte(0x00);Receive_ACK();AHT20_WR_Byte(0x00);Receive_ACK();Stop_I2C();Delay_1ms(5);//延时5ms左右I2C_Start();AHT20_WR_Byte(0x71);//Receive_ACK();Byte_first = AHT20_RD_Byte();Send_ACK();Byte_second = AHT20_RD_Byte();Send_ACK();Byte_third = AHT20_RD_Byte();Send_NOT_ACK();Stop_I2C();Delay_1ms(10);//延时10ms左右I2C_Start();AHT20_WR_Byte(0x70);///Receive_ACK();AHT20_WR_Byte(0xB0|addr);//寄存器命令Receive_ACK();AHT20_WR_Byte(Byte_second);Receive_ACK();AHT20_WR_Byte(Byte_third);Receive_ACK();Stop_I2C();Byte_second=0x00;Byte_third =0x00;
}void AHT20_Start_Init(void)
{JH_Reset_REG(0x1b);JH_Reset_REG(0x1c);JH_Reset_REG(0x1e);
}//int32_t main(void)
//{//    uint32_t CT_data[2];
//  volatile int  c1,t1;
//  /***********************************************************************************/
//  /**///①刚上电,产品芯片内部就绪需要时间,延时100~500ms,建议500ms
//  /***********************************************************************************/
//  Delay_1ms(500);
//  /***********************************************************************************/
//  /**///②上电第一次发0x71读取状态字,判断状态字是否为0x18,如果不是0x18,进行寄存器初始化
//  /***********************************************************************************/
//  if((AHT20_Read_Status()&0x18)!=0x18)
//  {//  AHT20_Start_Init(); //重新初始化寄存器
//  Delay_1ms(10);
//  }
//
//  /***********************************************************************************/
//  /**///③根据客户自己需求发测量命令读取温湿度数据,当前while(1)循环发测量命令读取温湿度数据,仅供参考
//  /***********************************************************************************/
//  while(1)
//  {//   AHT20_Read_CTdata(CT_data);       //不经过CRC校验,直接读取AHT20的温度和湿度数据    推荐每隔大于1S读一次
//    //AHT20_Read_CTdata_crc(CT_data);  //crc校验后,读取AHT20的温度和湿度数据
//  //   c1 = CT_data[0]*100*10/1024/1024;  //计算得到湿度值c1(放大了10倍)
//   t1 = CT_data[1]*200*10/1024/1024-500;//计算得到温度值t1(放大了10倍)
//  下一步客户处理显示数据,
//   }// }

修改main.c

#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "gui.h"
#include "test.h"
#include "AHT20-21_DEMO_V1_3.h" //存放温度和湿度
uint32_t CT_data[2]={0,0};
//湿度和温度
volatile int  c1,t1;//用于LED显示的温度和湿度
u8 temp[10];
u8 hum[10];//初始化PC13用于测试
void GPIOC13_Init(void){GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_ResetBits(GPIOC,GPIO_Pin_13);}
//初始化以及前期准备
void Init(void);//读取温湿度
void getData(void);//显示温湿度
void showData(void);int main(void)
{   //初始化Init();while(1){//获取数据getData();//显示数据showData();//开启滚动OLED_WR_Byte(0x2F,OLED_CMD);//延时Delay_1ms(3100);//OLED_Clear(0); }}//初始化以及前期准备
void Init(void){//初始化PC12GPIOC13_Init();        //延时函数初始化     delay_init();    //初始化OLED OLED_Init();//清屏(全黑) OLED_Clear(0);    //开机显示信息  GUI_ShowCHinese(10,0,16,"胡开心",1);GUI_ShowString(10,24,"632007060204",16,1);Delay_1ms(1000);AHT20_Init();/***********************************************************************************//**///①刚上电,产品芯片内部就绪需要时间,延时100~500ms,建议500ms/***********************************************************************************/Delay_1ms(1000);OLED_Clear(0); OLED_WR_Byte(0x2E,OLED_CMD); //关闭滚动OLED_WR_Byte(0x27,OLED_CMD); //水平向左或者右滚动 26/27OLED_WR_Byte(0x00,OLED_CMD); //虚拟字节OLED_WR_Byte(0x00,OLED_CMD); //起始页 0OLED_WR_Byte(0x07,OLED_CMD); //滚动时间间隔OLED_WR_Byte(0x02,OLED_CMD); //终止页 2OLED_WR_Byte(0x00,OLED_CMD); //虚拟字节OLED_WR_Byte(0xFF,OLED_CMD); //虚拟字节GUI_ShowCHinese(10,0,16,"祝川哥公考上岸",1);
}//读取温湿度
void getData(){//AHT20_Read_CTdata(CT_data);       //不经过CRC校验,直接读取AHT20的温度和湿度数据    推荐每隔大于1S读一次AHT20_Read_CTdata_crc(CT_data);;  //crc校验后,读取AHT20的温度和湿度数据 c1 = CT_data[0]*1000/1024/1024;  //计算得到湿度值c1(放大了10倍)t1 = CT_data[1]*2000/1024/1024-500;//计算得到温度值t1(放大了10倍)//转为字符串易于显示temp[0]=t1/100+'0';temp[1]=(t1/10)%10+'0';temp[2]='.';temp[3]=t1%10+'0';temp[4]='\0';hum[0]=c1/100+'0';hum[1]=(c1/10)%10+'0';hum[2]='.';hum[3]=c1%10+'0';hum[4]=32;hum[5]='%';hum[6]='\0';
}//显示温湿度
void showData(){//显示温度GUI_ShowCHinese(15,28,16,"温度",1);GUI_ShowString(47,28,":",16,1);GUI_ShowString(62,28,temp,16,1);//显示湿度GUI_ShowCHinese(15,48,16,"湿度",1);GUI_ShowString(47,48,":",16,1);GUI_ShowString(62,48,hum,16,1);
}

5.3编译烧录运行

六、总结

本次实验了解了SPI协议的基本原理,汉字点阵的存储与显示,并且运用了SPI协议在OLED显示屏上实现了文字显示与传感器读取的数据显示,相当于进行了数据可视化。

七、参考文章

STM32开发基于SPI接口的OLED数据显示
STM32开发基于SPI接口的OLED数据显示

STM32基于SPI接口的OLED数据显示相关推荐

  1. STM32开发基于SPI接口的OLED数据显示

    文章目录 一.SPI简介 二.0.96inch SPI OLED 介绍 三.实验内容及结果 1. 任务要求 2. 准备工作 3. 演示如下 四.参考 一.SPI简介 SPI,是英语Serial Per ...

  2. 基于SPI接口的OLED数据显示

    文章目录 一.实验目的 二.准备工作 三.理论基础 1.0.96OLED简介 2.接线说明 四.实验步骤 1.显示自己的学号和姓名 2.显示AHT20的温度和湿度 3.上下或左右的滑动显示长字符 一. ...

  3. 基于spi接口的oled屏Android服务框架

    上一篇写了一个oled驱动,那么现在有一个问题:apk要怎么使用这个硬件,这里就需要提供一个硬件服务,apk通过这个服务就可以操作到硬件了. 基于rk3288 Android5.1 Android的硬 ...

  4. 实验 STM32 基于SPI的OLED屏显示

    STM32 基于SPI的OLED屏显示 一.任务要求 二.显示自己的学号和姓名 1.例子程序的改写 (1)下载资料 (2)解压后找到文件,并用KEIL打开. (3)改写程序 2.连接硬件 3.运行结果 ...

  5. 【嵌入式】STM32基于SPI通信协议OLED屏显示

    STM32基于SPI通信协议OLED屏显示 一.SPI协议和OLED介绍 1.SPI协议介绍 物理层 协议层 2.OLED显示屏介绍 二.显示个人学号姓名实验 1.题目要求 2.代码部分 1.完整代码 ...

  6. 基于SPI通信方式的OLED显示

    基于SPI通信方式的OLED显示 文章目录 基于SPI通信方式的OLED显示 1.SPI简介 2.OLED屏幕介绍 3.OLED显示屏显示数据 4.总结 5.参考文献 1.SPI简介 SPI 协议是由 ...

  7. FPGA实现的SPI协议(二)----基于SPI接口的FLASH芯片M25P16的使用

    写在前面 SPI协议系列文章: FPGA实现的SPI协议(一)----SPI驱动 FPGA实现的SPI协议(二)----基于SPI接口的FLASH芯片M25P16的使用 在上篇文章,简要介绍了SPI协 ...

  8. 基于SPI方式实现OLED屏显

    文章目录 一.SPI简介 1.1物理层 1.2协议层 二.OLED 2.1定义 2.2优势 2.3模块工作模式选择 2.4模块特点 三.实验过程 3.1实验准备 3.2硬件连接 3.3程序烧录 3.3 ...

  9. STM32通过SPI协议驱动OLED屏

    坚持就是胜利 一.SPI协议介绍 01 简介 02 SPI物理层 03 SPI基本通讯过程 二.OLED显示器介绍 01 简介 02 接口定义 03 与STM32接线图 三.汉字取模软件介绍 01 下 ...

最新文章

  1. java圆周率流程图,流程图、PI图入门知识 课件.doc
  2. 彩图完美解释:麦克斯韦方程组
  3. SUPPORTDIR引用的文件的加入
  4. Linux centos7安装nfs及服务端配置
  5. java nio connect_Java NIO系列教程(八) SocketChannel
  6. 拖链电缆 机器人电缆_干货!拖链电缆用途及安装注意事项
  7. 信息学奥赛一本通C++语言——1086:角谷猜想
  8. String.split()与StringUtils.split()的区别
  9. 大数据分析师的报考条件是什么?
  10. easyui datagrid 多一列
  11. 《计算机网络》-- 第一章 概述
  12. 平面解析几何----焦点弦上焦半径长度之比公式
  13. iOS10开发哪些坑
  14. matlab封装的模块,matlab模块封装
  15. 【电子签名】如何使用Adobe Acrobat Pro DC给PDF文件添加自己的电子签名、选项勾选和日期填写
  16. C++中cos,sin,asin,acos这些三角函数操作
  17. cmd命令下,使用java命令,运行指定目录下的*.class文件。
  18. ‘XXX‘ is declared but its value is never read.
  19. 直插DC插头内部分解,哪个是正哪个是负
  20. 计算机假期计划内容,寒假计划表内容

热门文章

  1. K线形态识别_下跌三连阴
  2. 人血清白蛋白修饰磺胺嘧啶/磺胺多辛 HSA-Sulfadiazine/Sulfadoxine
  3. 黑马程序员——99乘法表
  4. Django之CSRF跨站请求伪造(老掉牙的钓鱼网站模拟)
  5. php实现 DES/CBC/PCCS5padding 加解密模式
  6. oracle 客户端
  7. 飞秋的文件读取、写入代码
  8. 游戏音乐制作中什么是编曲?
  9. 万字长文|如何定义“失败的产品经理”
  10. 2021CCSP全国决赛深圳游记