/*出处:【STM32入门教程-2024】第12集 IIC通信与温湿度传感器AHT20(DHT20)_哔哩哔哩_bilibili
*/
AHT20驱动
这篇笔记我主要介绍代码实现,想要了解原理的请自己看视频,我不过多赘述了。
AHT20通信数据帧格式:
①对照手册上的通信流程写初始化函数
关键API介绍:
主机接收函数
HAL_StatusTypeDef HAL_I2C_Master_Receive
(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
uint8_t *pData, uint16_t Size, uint32_t Timeout)
参数名称 | 介绍 |
I2C_HandleTypeDef *hi2c | 想要操作的I2C函数句柄,eg:&hi2c1 |
uint16_t DevAddress | 设备地址 |
uint8_t *pData | 接收数据的变量的指针 |
uint16_t Size | 读取的目标位数,单位字节 |
uint32_t Timeout | 超时时间 |
主机发送函数
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c,
uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
参数名称 | 介绍 |
I2C_HandleTypeDef *hi2c | 想要操作的I2C函数句柄,eg:&hi2c1 |
uint16_t DevAddress | 设备地址 |
uint8_t *pData | 接收数据的变量的指针 |
uint16_t Size | 读取的目标位数,单位字节 |
uint32_t Timeout | 超时时间 |
初始化函数:
void AHT20_Init(void)
{
uint8_t readBuffer;
HAL_Delay(40);
/*读是写加一,这里地址实际上自动变成了0X71*/
HAL_I2C_Master_Receive(&hi2c1,AHT20_ADDRESS,&readBuffer,1,HAL_MAX_DELAY);
/*检查状态字的校准使能位Bit[3]是否为1*/
if((readBuffer&0x08)==0x00)
{
uint8_t sendBuffer[3]={0xBE,0x80,0x00};
HAL_I2C_Master_Transmit(&hi2c1,AHT20_ADDRESS,sendBuffer,3,HAL_MAX_DELAY);
}
}
②根据手册封装数据读取函数
按照老师讲解的步骤进行数据切割和移位:
void AHT20_Read(float *Temperature,float *Humidity)
{
uint8_t sendBuffer[3]={0xAC,0x33,0x00};
uint8_t readBuffer[6];
HAL_I2C_Master_Transmit(&hi2c1,AHT20_ADDRESS,sendBuffer,3,HAL_MAX_DELAY);
HAL_Delay(75);
HAL_I2C_Master_Receive(&hi2c1,AHT20_ADDRESS,readBuffer,6,HAL_MAX_DELAY);
if((readBuffer[0]&0x80)==0x00)
{
uint32_t data=0;
data=(uint32_t)(readBuffer[3]>>4)+(uint32_t)(readBuffer[2]<<4)+(uint32_t)(readBuffer[1]<<12);
*Humidity=data*100.f/(1<<20);
data=(uint32_t)((readBuffer[3]&0x0F)<<16)+(uint32_t)(readBuffer[4]<<8)+(uint32_t)(readBuffer[5]);
*Temperature=data*200.0f/(1<<20)-50;
}
}
IIC中断、DMA&状态机编程
①在选项卡中开启事件中断向量与错误中断向量
HAL_I2C_Master_Transmit_IT中断函数无需设置等待时间;但与此同时由于轮询、中断、DMA三者的工作模式的区别,并不能直接在驱动程序中替代函数名。轮询带有强制阻塞机制,程序会等待所有数据发送\接受完成才会接着向下执行,但中断\DMA是非阻塞模式,并不会进行等待。