I2C总线协议
1.什么是I2C协议
I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。
I2C 协议的物理层和协议层
①物理层
I2C是一个支持设备的总线。可连接多个 I2C 通讯设备,支持多个通讯主机及多个通讯从机。对于I2C 总线,只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线(SCL)。
I2C 通讯设备常用连接方式(引用野火资料中的图)
②协议层
主要是定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等。
通讯的起始和停止信号。
I2C的两种方式——硬件I2C和软件I2C
①硬件I2C
直接利用 STM32 芯片中的硬件 I2C 外设。
硬件I2C的使用
只要配置好对应的寄存器,外设就会产生标准串口协议的时序。在初始化好 I2C 外设后,只需要把某寄存器位置 1,此时外设就会控制对应的 SCL 及 SDA 线自动产生 I2C 起始信号,不需要内核直接控制引脚的电平。
②软件I2C
直接使用 CPU 内核按照 I2C 协议的要求控制 GPIO 输出高低电平,从而模拟I2C。
软件I2C的使用
需要在控制产生 I2C 的起始信号时,控制作为 SCL 线的 GPIO 引脚输出高电平,然后控制作为 SDA 线的 GPIO 引脚在此期间完成由高电平至低电平的切换,最后再控制SCL 线切换为低电平,这样就输出了一个标准的 I2C 起始信号。
③两者的差别
硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活。
SPI简介
SPI是串行外设接口(Serial Peripheral Interface)的缩写,是由 Motorola 公司提出的一种高速的,全双工,同步的通信总线,被广泛地使用在 ADC、LCD 等设备与 MCU 间要求通讯速率较高的场合。SPI总线系统可直接与各个厂家生产的多种标准外围器件连接,该接口一般使用4条线:串行时钟线(SCK)、主机输入/从机输出数据线MISO、主机输出/从机输入数据线MOST和低电平有效的从机选择线C/S(有的SPI接口芯片带有中断信号线INT或INT、有的SPI接口芯片没有主机输出/从机输入数据线MOSI)。
SPI 一共有四种通讯模式,它们的主要区别是总线空闲时 SCK 的时钟状态以及数据采样时刻。为方便说明,在此引入“时钟极性 CPOL”和“时钟相位 CPHA”的概念。
时钟极性 CPOL 是指 SPI 通讯设备处于空闲状态时,SCK 信号线的电平信号(即 SPI 通讯开始前、 NSS 线为高电平时 SCK 的状态)。CPOL=0 时, SCK 在空闲状态时为低电平,CPOL=1 时,则相反。
时钟相位 CPHA 是指数据的采样的时刻,当 CPHA=0 时,MOSI 或 MISO 数据线上的信号将会在 SCK 时钟线的“奇数边沿”被采样。当 CPHA=1 时,数据线在 SCK 的“偶数边沿”采样。
使用STM32F103完成基于I2C协议的AHT20温湿度传感器的数据采集
main.c
#include "delay.h"
#include "temhum.h"
#include "sys.h"
#include "usart.h"
int main(void)
{
u32 CT_data[2]={
0};
volatile float hum=0,tem=0;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
LED_Init(); //LED端口初始化
temphum_init(); //ATH20初始化
while(1)
{
AHT20_Read_CTdata(CT_data); //不经过CRC校验,直接读取AHT20的温度和湿度数据
hum = CT_data[0]*100*10/1024/1024; //计算得到湿度值(放大了10倍)
tem = CT_data[1]*200*10/1024/1024-500;//计算得到温度值(放大了10倍)
printf("湿度:%.1f%%\r\n",(hum/10));
printf("温度:%.1f度\r\n",(tem/10));
printf("\r\n");
}
}
链接:https://pan.baidu.com/s/1D4AxGk6LAM5Ioq4wEv9QRQ
提取码:326o
结果:
用手指按住芯片,温度与湿度都产生了变化。表示实验成功
OLED屏显和汉字点阵编码原理
1.汉字点阵编码
对于计算机而言,汉字相当于一个图像,所以将每一个字当成一个点阵
在汉字的点阵字库中,每个字节的每个位都代表一个汉字的一个点,每个汉字都是由一个矩形的点阵组成,0代表没有,1代表有点,将0和1分别用不同颜色画出,就形成了一个汉字,常用的点阵矩阵有1212, 1414, 16*16三种字库。
字库根据字节所表示点的不同有分为横向矩阵和纵向矩阵,目前多数的字库都是横向矩阵的存储方式(用得最多的应该是早期UCDOS字库),纵向矩阵一般是因为有某些液晶是采用纵向扫描显示法,为了提高显示速度,于是便把字库矩阵做成纵向。
显示特定汉字与数字
由于单片机中没有汉字编码,所以我们需要在PCtoLCD中提取字模制作字库
这里笔者未将自定义格式变为C51,导致了一系列错误
按照图示操作,将字库放入oledfont.h文件
再自建一个函数
void TEST_Chinese(void)
{
OLED_Clear(0);
GUI_ShowString(50,50,"***",8,1); //此处显示学号
GUI_ShowCHinese(10,10,32,"***",1); //此处显示姓名
delay_ms(1000);
OLED_Clear(0);
}
直接在main.c中引用即可
完整代码:
链接:https://pan.baidu.com/s/1VCHS_BHKxv_8n_o12Ykh6Q
提取码:326o
效果
显示AHT20的温度和湿度
将以下代码插入AHT20显示温度工程中,并将串口输入改为显示输入即可
void TEST_Menu2(void)
{
u32 CT_data[2];