一、认识I2C协议
(1)软件I2C协议:
直接使用 CPU 内核按照 I2C 协议的要求控制 GPIO 输出高低电平,从而模拟I2C。
(2)硬件I2C协议:
对应 STM32 芯片中的硬件 I2C 外设,有相应的I2C驱动电路,其所使用的I2C管脚也是专用。
(3)两者的区别:
所谓硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用的;软件I2C一般是用GPIO管脚,用软件控制管脚状态以模拟I2C通信波形。
硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活。
模拟I2C 是通过GPIO,软件模拟寄存器的工作方式,而硬件(固件)I2C是直接调用内部寄存器进行配置。
二、了解AHT20温湿度传感器
本次实验所使用的AHT20温湿度传感器:
1、相关参数:
GND 地线
SCL I2C通信模式时钟信号,双向
SDA I2C通信模式数据信号,双向
NC 保持悬空
2、温湿度测量范围:
温度范围为: 测量范围为 -40 ℃ ~+ 85 ℃ 精度±0.3℃,转化如下图:
湿度范围为:测量范围为0% - 100% 精度为±2%RH,转化如下图:
3、通讯方式:
采用I2C的接口方式 ,i2c通讯方式:SCL --> 时钟线、SDI --> 数据线
4、优点:
(1)高精度,完全校准
(2)极高的可靠性与卓越的长期稳定性(较上一代aht10有 极大的提升)
(3)抗干扰能力强
(4)性价比极高
(4)适用于恶劣的环境条件下
三、使用STM32F103完成基于I2C协议的AHT20温湿度传感器的数据采集
1.完成接线
本次实验中本人的接线如下:
AHT20 | STM32 |
---|---|
VDD | 3.3V |
GND | GND |
SCL | B0 |
SDA | B1 |
截图效果如下图:
2、代码实现
main.c
#include "stm32f10x.h" // Device header
#include "AHT20-21_DEMO_V1_3.h"
#include "Serial.h"
int main(void)
{
uint32_t CT_data[2];
volatile int c1,t1;
float c,t;
/***********************************************************************************/
/**///上电初始化SDA,SCL的IO口
/***********************************************************************************/
Init_I2C_Sensor_Port();
/***********************************************************************************/
/**///①刚上电,产品芯片内部就绪需要时间,延时100~500ms,建议500ms
/***********************************************************************************/
Delay_1ms(500);
/***********************************************************************************/
/**///②上电第一次发0x71读取状态字,判断状态字是否为0x18,如果不是0x18,进行寄存器初始化
/***********************************************************************************/
if((AHT20_Read_Status()&0x18)!=0x18)
{
AHT20_Start_Init(); //重新初始化寄存器
Delay_1ms(10);
}
Serial_Init();
/***********************************************************************************/
/**///③根据客户自己需求发测量命令读取温湿度数据,当前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倍)
c=c1/10.0;
t=t1/10.0;
下一步客户处理显示数据,
/***********************************************************************************/
/**///延时2s
/***********************************************************************************/
Delay_1ms(4000);
printf("温度:%.3f\n",t);
printf("湿度:%.3f\n",c);
}
}
Interface.c
#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>
uint8_t Interface_RxData;
uint8_t Interface_RxFlag;
void Interface_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //打开USART1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //打开GPIOA的时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1,&USART_InitStructure);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1,ENABLE);
}
void Interface_SendByte(uint8_t Byte)
{
USART_SendData(USART1,Byte);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
}
void Interface_SendByteArray(uint8_t *Array,uint16_t Length)
{
uint16_t i;
for(i=0;i<Length;i++)
{
Interface_SendByte(Array[i]);
}
}
void Interface_SendString(char *String)
{
uint8_t i;
for(i=0;String[i] !='\0';i++)
{
Interface_SendByte(String[i]);
}
}
uint32_t Interface_Pow(uint32_t X,uint32_t Y)
{
uint32_t Result = 1;
while(Y--)
{
Result *= X;
}
return Result;
}
void Interface_SendNumber(uint32_t Number,uint8_t Length)
{
uint8_t i;
for(i=0;i<Length;i++)
{
Interface_SendByte((Number/Interface_Pow