欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
STM32單片機的IIC讀取AHT20 AHT21溫濕度 源程序
[打印本頁]
作者:
736317205
時間:
2022-3-10 14:37
標題:
STM32單片機的IIC讀取AHT20 AHT21溫濕度 源程序
51hei.png
(2.35 KB, 下載次數: 66)
下載附件
2022-3-10 20:58 上傳
#include "stm32f10x.h"
#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) //將PB15配置為輸出 , 并設置為高電平, PB15作為I2C的SDA
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,& GPIO_InitStruct);
GPIO_SetBits(GPIOB,GPIO_Pin_15);
}
void SDA_Pin_Output_Low(void) //將P15配置為輸出 并設置為低電平//SDA配置為浮空輸出
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,& GPIO_InitStruct);
GPIO_ResetBits(GPIOB,GPIO_Pin_15);
}
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_15;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB,&GPIO_InitStruct);
}
void SCL_Pin_Output_High(void) //SCL輸出高電平,P14作為I2C的SCL
{
GPIO_SetBits(GPIOB,GPIO_Pin_14);
}
void SCL_Pin_Output_Low(void) //SCL輸出低電平
{
GPIO_ResetBits(GPIOB,GPIO_Pin_14);
}
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_15;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,& GPIO_InitStruct);
GPIO_SetBits(GPIOB,GPIO_Pin_15);//輸出高電平
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14;
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_15)) 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_15)) && 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]為0
Send_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]為0
Send_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(); //注意: 最后是發送NAK
Stop_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的初始化命令是0xE1
Receive_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,Byte_fourth;
I2C_Start();
AHT20_WR_Byte(0x70);//原來是0x70
Receive_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倍)
////下一步客戶處理顯示數據,
}
}
復制代碼
#ifndef _AHT20_DEMO_
#define _AHT20_DEMO_
#include "stm32f10x.h"
void Delay_N10us(uint32_t t);//延時函數
void SensorDelay_us(uint32_t t);//延時函數
void Delay_4us(void); //延時函數
void Delay_5us(void); //延時函數
void Delay_1ms(uint32_t t);
void AHT20_Clock_Init(void); //延時函數
void SDA_Pin_Output_High(void) ; //將PB15配置為輸出 , 并設置為高電平, PB15作為I2C的SDA
void SDA_Pin_Output_Low(void); //將P15配置為輸出 并設置為低電平
void SDA_Pin_IN_FLOATING(void); //SDA配置為浮空輸入
void SCL_Pin_Output_High(void); //SCL輸出高電平,P14作為I2C的SCL
void SCL_Pin_Output_Low(void); //SCL輸出低電平
void Init_I2C_Sensor_Port(void); //初始化I2C接口,輸出為高電平
void I2C_Start(void); //I2C主機發送START信號
void AHT20_WR_Byte(uint8_t Byte); //往AHT20寫一個字節
uint8_t AHT20_RD_Byte(void);//從AHT20讀取一個字節
uint8_t Receive_ACK(void); //看AHT20是否有回復ACK
void Send_ACK(void) ; //主機回復ACK信號
void Send_NOT_ACK(void); //主機不回復ACK
void Stop_I2C(void); //一條協議結束
uint8_t AHT20_Read_Status(void);//讀取AHT20的狀態寄存器
uint8_t AHT20_Read_Cal_Enable(void); //查詢cal enable位有沒有使能
void AHT20_SendAC(void); //向AHT20發送AC命令
uint8_t Calc_CRC8(uint8_t *message,uint8_t Num);
void AHT20_Read_CTdata(uint32_t *ct); //沒有CRC校驗,直接讀取AHT20的溫度和濕度數據
void AHT20_Read_CTdata_crc(uint32_t *ct); //CRC校驗后,讀取AHT20的溫度和濕度數據
void AHT20_Init(void); //初始化AHT20
void JH_Reset_REG(uint8_t addr);///重置寄存器
void AHT20_Start_Init(void);///上電初始化進入正常測量狀態
復制代碼
作者:
真的很好啊
時間:
2022-6-27 16:14
親測可以用,非常棒!!!!!!!!!
作者:
真的很好啊
時間:
2022-6-27 16:15
移植非常方便,完美!
作者:
真的很好啊
時間:
2022-6-27 16:16
親測可以用,方便移植程序,非常棒!
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1