完成了引脚的连接,那么我们就来修改AHT11的代码,这里直接上代码
#include "DRV_AHT10.h"
float TempData=0,WetData=0;
void Delay_N10us(uint32_t t)//延时函数
{
uint32_t k;
while(t--)
{
for (k = 0; k < 719; k++)//110
;
}
}
void SensorDelay_us(uint32_t t)//延时函数
{
t = t-2;
for(; t>0; t--)
{
Delay_N10us(1);
}
}
void Delay_3us(void) //延时函数
{
Delay_N10us(1);
Delay_N10us(1);
Delay_N10us(1);
Delay_N10us(1);
}
void Delay_1us(void) //延时函数
{
Delay_N10us(1);
Delay_N10us(1);
Delay_N10us(1);
Delay_N10us(1);
Delay_N10us(1);
}
//--SCL_PA00---SDA-PA01---
void SDA_Pin_Output_High(void) //将P15配置为输出 , 并设置为高电平, P15作为I2C的SDA
{
GPIO_Pins_Set(GPIOB,GPIO_PIN_8);
}
void SDA_Pin_Output_Low(void) //将P15配置为输出 并设置为低电平
{
GPIO_Pins_Reset(GPIOB,GPIO_PIN_8);
}
void SDA_Pin_IN_FLOATING(void) //SDA配置为悬浮输入
{
GPIO_InitType GPIO_InitStructure;
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
//PA1-PA7-PA9
GPIO_InitStructure.Pin = GPIO_PIN_8;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
GPIO_Peripheral_Initialize(GPIOB, &GPIO_InitStructure);
}
void SDA_Pin_OUT_PP(void) //SDA配置为悬浮输入
{
GPIO_InitType GPIO_InitStructure;
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
//PA1-PA7-PA9
GPIO_InitStructure.Pin = GPIO_PIN_8;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
GPIO_Peripheral_Initialize(GPIOB, &GPIO_InitStructure);
}
void SCL_Pin_Output_High(void) //SCL输出高电平,P14作为I2C的SCL
{
GPIO_Pins_Set(GPIOB,GPIO_PIN_9);
}
void SCL_Pin_Output_Low(void) //SCL输出低电平
{
GPIO_Pins_Reset(GPIOB,GPIO_PIN_9);
}
void Init_I2C_Sensor_Port(void) //初始化I2C接口
{
GPIO_InitType GPIO_InitStructure;
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
//--SDA_PB8
GPIO_InitStructure.Pin = GPIO_PIN_8;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
GPIO_Peripheral_Initialize(GPIOB, &GPIO_InitStructure);
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
//SCL_PB9
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
GPIO_Peripheral_Initialize(GPIOB, &GPIO_InitStructure);
}
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 ZSSC_I2C_WR_Byte(uint8_t Byte) //往AHT10写一个字节
{
uint8_t Data,N,i;
SDA_Pin_OUT_PP();
Data=Byte;
i = 0x80;
for(N=0;N<8;N++)
{
SCL_Pin_Output_Low();
Delay_3us();
if(i&Data)
{
SDA_Pin_Output_High();
}
else
{
SDA_Pin_Output_Low();
}
SCL_Pin_Output_High();
Delay_3us();
Data <<= 1;
}
SCL_Pin_Output_Low();
SensorDelay_us(8);
SDA_Pin_IN_FLOATING();
SensorDelay_us(8);
}
uint8_t ZSSC_I2C_RD_Byte(void)//从AHT10读取一个字节
{
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_1us();
a=0;
if(GPIO_Input_Pin_Data_Get(GPIOB,GPIO_PIN_8)==PIN_SET)//--读取引脚状态
{
a=1;
}
Byte = (Byte<<1)|a;
SCL_Pin_Output_Low();
Delay_1us();
}
SDA_Pin_IN_FLOATING();
SensorDelay_us(8);
return Byte;
}
uint8_t Receive_ACK(void) //看AHT10是否有回复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_Input_Pin_Data_Get(GPIOB,GPIO_PIN_8)==PIN_SET) && CNT < 100)
{
CNT++;
}
if(CNT == 100)
{
return 0;
}
SCL_Pin_Output_Low();
SensorDelay_us(8);
return 1;
}
void Send_ACK(void) //主机回复ACK信号
{
SDA_Pin_OUT_PP();
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
{
SDA_Pin_OUT_PP();
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_OUT_PP();
SDA_Pin_Output_Low();
SensorDelay_us(8);
SCL_Pin_Output_High();
SensorDelay_us(8);
SDA_Pin_Output_High();
SensorDelay_us(8);
}
uint8_t JH_Read_Status(void)//读取AHT10的状态寄存器
{
uint8_t Byte_first;
I2C_Start();
ZSSC_I2C_WR_Byte(0x71);
Receive_ACK();
Byte_first = ZSSC_I2C_RD_Byte();
Send_NOT_ACK();
Stop_I2C();
return Byte_first;
}
uint8_t JH_Read_Cal_Enable(void) //查询cal enable位有没有使能?
{
uint8_t val = 0;//ret = 0,
val = JH_Read_Status();
if((val & 0x68)==0x08) //判断NOR模式和校准输出是否有效
return 1;
else return 0;
}
void JH_SendAC(void) //向AHT10发送AC命令
{
I2C_Start();
ZSSC_I2C_WR_Byte(0x70);
Receive_ACK();
ZSSC_I2C_WR_Byte(0xac);
Receive_ACK();
ZSSC_I2C_WR_Byte(0x33);
Receive_ACK();
ZSSC_I2C_WR_Byte(0x00);
Receive_ACK();
Stop_I2C();
}
void JH_Send_BA(void)//向AHT10发送BA命令
{
I2C_Start();
ZSSC_I2C_WR_Byte(0x70);
Receive_ACK();
ZSSC_I2C_WR_Byte(0xba);
Receive_ACK();
Stop_I2C();
}
void JH_Read_CTdata(uint32_t *ct) //读取AHT10的温度和湿度数据
{
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;
JH_SendAC();//向AHT10发送AC命令
SysTick_Delay_Ms(75);//等待75ms
cnt = 0;
while(((JH_Read_Status()&0x80)==0x80))//等待忙状态结束
{
SensorDelay_us(1508);
if(cnt++>=100)
{
break;
}
}
I2C_Start();
ZSSC_I2C_WR_Byte(0x71);//0x70+1 0x70为设备地址 1为方向位
Receive_ACK();
Byte_1th = ZSSC_I2C_RD_Byte();//状态字
Send_ACK();
Byte_2th = ZSSC_I2C_RD_Byte();//湿度字节
Send_ACK();
Byte_3th = ZSSC_I2C_RD_Byte();//湿度字节
Send_ACK();
Byte_4th = ZSSC_I2C_RD_Byte();//高4位为湿度 低4位为温度
Send_ACK();
Byte_5th = ZSSC_I2C_RD_Byte();//温度字节
Send_ACK();
Byte_6th = ZSSC_I2C_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;
}
unsigned char JH_Init(void) //初始化AHT10
{
unsigned int count=0;
Init_I2C_Sensor_Port();
SensorDelay_us(11038);
I2C_Start();
ZSSC_I2C_WR_Byte(0x70);
Receive_ACK();
ZSSC_I2C_WR_Byte(0xe1);//写系统配置寄存器
Receive_ACK();
ZSSC_I2C_WR_Byte(0x08);
Receive_ACK();
ZSSC_I2C_WR_Byte(0x00);
Receive_ACK();
Stop_I2C();
SysTick_Delay_Ms(500);//延时0.5S
while(JH_Read_Cal_Enable()==0)//需要等待状态字status的Bit[3]=1时才去读数据。如果Bit[3]不等于1 ,发软件复位0xBA给AHT10,再重新初始化AHT10,直至Bit[3]=1
{
JH_Send_BA(); //复位
SysTick_Delay_Ms(100);
SensorDelay_us(11038);
I2C_Start();
ZSSC_I2C_WR_Byte(0x70);
Receive_ACK();
ZSSC_I2C_WR_Byte(0xe1);//写系统配置寄存器
Receive_ACK();
ZSSC_I2C_WR_Byte(0x08);
Receive_ACK();
ZSSC_I2C_WR_Byte(0x00);
Receive_ACK();
Stop_I2C();
count++;
if(count>=10)
return 0;
SysTick_Delay_Ms(500);
}
return 1;
}
void Get_Data(void)
{
uint32_t CT_data[2];
volatile int c1,t1;
if(0)
{
}
else
{
while(JH_Read_Cal_Enable()==0)//等到校准输出使能位为1,才读取。
{
JH_Init();//如果为0再使能一次
SysTick_Delay_Ms(50);
}
JH_Read_CTdata(CT_data); //读取温度和湿度 , 可间隔1.5S读一次
c1 = CT_data[0]*1000/1024/1024; //计算得到湿度值(放大了10倍,如果c1=523,表示现在湿度为52.3%)
t1 = CT_data[1] *200*10/1024/1024-500;//计算得到温度值(放大了10倍,如果t1=245,表示现在温度为24.5℃)
TempData=t1*0.1;//因为设置了两位小数--
WetData=c1*0.1;//--放大了两倍----
}
}
复制代码测试结果还是比较准确的,我拍了视频,后面上传上来,主要是在办公室,不太好说话,所以大家感受一下结果就行了,感兴趣的话可以自己复制代码去测试。
视频链接:
https://www.bilibili.com/video/BV1AusjeuEL7/?buvid=XU268A1260BC1080F6C5DE9BB8885853A284E&is_story_h5=false&mid=ZPNijV8XOdBxHvi4hyDZnQ%3D%3D&plat_id=240&share_from=ugc&share_medium=android&share_plat=android&share_session_id=34ec3807-b268-440c-a310-66412bf9f865&share_source=WEIXIN&share_tag=s_i&spmid=dt.space-dt.0.0×tamp=1724649027&unique_k=HwCthPZ&up_id=474849000