今日學(xué)習(xí)一下這款A(yù)HT10 溫濕度傳感器模塊,給我的OLED手環(huán)添加上測溫濕度的功能。
文章提供源碼、測試工程下載、測試效果圖。
目錄
AHT10溫濕度傳感器:
特性:
連接方式:
適用場所范圍:
程序設(shè)計:
設(shè)計目標(biāo):
?程序設(shè)計注意點:
AHT10代碼:
?主函數(shù)代碼:
測試效果:
?完整工程下載:
AHT10溫濕度傳感器:
下圖為AHT溫濕度傳感器模塊,它長這樣,這里的介紹不重要,了解就行,快速瀏覽即可:
AHT10,新一代溫濕度傳感器在尺寸與智能方面建立了新的標(biāo)準(zhǔn):
它嵌入了適于回流焊的雙列扁平無引腳SMD封裝,底面4x5mm,高度1.6mm。
傳感器偷出經(jīng)過標(biāo)定的數(shù)字信號,標(biāo)準(zhǔn)I2C格式。AHT10配有一個全新設(shè)計的ASIC專用芯片、一個經(jīng)過改進(jìn)的MEMS半導(dǎo)體電容式濕度傳感元件和一個標(biāo)準(zhǔn)的片上溫度傳感元件,其性能己經(jīng)大大提升甚至超出了前一代傳感器的可靠性水平,一代溫濕度傳感器,經(jīng)過改進(jìn)使其在惡劣環(huán)境下的性能更穩(wěn)定。?
特性:
1.模塊尺寸:??? 16*11mm
2.接口類型:??? I2C
3.工作電壓:??? 1.8-6.0V
4.接口尺寸:??? 4*2.54mm間距
5.濕度精度:??? 典型 士 2%
6.濕度分辨率:0.024%
7.溫度精度:??? 典型 土 0.3C
8.溫度分辨率:典型0.01C
9.工作溫度:??? -40°C--85C?
連接方式:
適用場所范圍:
- 暖通空調(diào) 、除濕器
- 檢測設(shè)備
- 自動控制、數(shù)據(jù)記錄器
- 氣象站、家電
- 醫(yī)療及其他相關(guān)濕度檢測控制。
程序設(shè)計:
設(shè)計目標(biāo):
1.使用IIC通信初始化和讀取AHT10傳感器的溫濕度信息,并通過OLED打印
2.IIC通信引腳:PB3(SCL)?? PB4(SDA)
3.使用定時器2,周期性讀取AHT10的溫濕度信息(300ms為周期)
?程序設(shè)計注意點:
1.上電啟動傳感器,啟動后需要先等待40ms(設(shè)備才開始正常工作),然后發(fā)送
0x71
來獲取狀態(tài)字節(jié)2.獲取到校準(zhǔn)使能位后,查看其是否已校準(zhǔn),若已校準(zhǔn)則跳過當(dāng)前步驟;若未校準(zhǔn)則發(fā)送
0xe1
,進(jìn)行初始化,然后發(fā)送0x08
,0x00
;
3.接著開始觸發(fā)測量,測量先發(fā)送
0xac
,然后發(fā)送0x33
,0x00
;
?4.測量命令發(fā)送完成后,需要等待80ms,用于溫濕度的測量;之后再發(fā)送命令
0x71
,以讀取狀態(tài)寄存器是否處于空閑狀態(tài)(bit7 => idle
);若是空閑狀態(tài),可以直接讀取之后六個字節(jié)的溫濕度數(shù)值;
?
5.相對濕度和溫度轉(zhuǎn)換公式:
?接受的處理是使用char類型的數(shù)組 去接受每個讀取到的八位數(shù)據(jù),然后根據(jù)運算公式計算:(1024*1024=2^20 )? ,( int )強制類型轉(zhuǎn)換為int是為了不丟符號:
?最后還有倆個函數(shù),一個是檢查,一個是復(fù)位的:
?
AHT10代碼:
#include "AHT10.h"
/**
brief AHT10初始化函數(shù)
param NONE
return NONE
*/
void AHT10Init()
{
//IIC_Init();
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //設(shè)置為推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOBA
GPIO_SetBits(GPIOB,GPIO_Pin_3|GPIO_Pin_4); //PA4 輸出高
delay_ms(50);//延時50ms讓傳感器穩(wěn)定
I2C_Start();
I2C_Send_Byte(AHT10_ADDRESS); //獲取狀態(tài)
//初始化校準(zhǔn)
I2C_Send_Byte(0xe1);
I2C_Send_Byte(0x08);
I2C_Send_Byte(0x00);
I2C_Stop();
delay_ms(50);//延時50ms讓傳感器穩(wěn)定
}
/**
brief 檢查AHT10是否存在
param NONE
return 0存在 1不存在
*/
u8 AHT10Check(void)
{
u8 ack=0;
I2C_Start();
I2C_Send_Byte(AHT10_ADDRESS);
ack=I2C_Wait_Ack();
I2C_Stop();
return ack;
}
/**
brief AHT10軟復(fù)位
param NONE
return NONE
*/
void AHT10Reset(void)
{
I2C_Start();
I2C_Send_Byte(AHT10_WRITE);
I2C_Wait_Ack();
I2C_Send_Byte(0xba);
I2C_Wait_Ack();
I2C_Stop();
}
/**
brief 檢查AHT10讀溫濕度數(shù)據(jù)
param *temperature:需要讀出的溫度數(shù)據(jù),float指針類型,精度范圍+-0.3C
param *humidity:需要讀出的濕度數(shù)據(jù),u8指針類型,精度范圍+-2RH
return 0 讀數(shù)據(jù)正常 1讀數(shù)據(jù)失敗
*/
u8 AHT10ReadData(float *temperature,u8 *humidity)
{
u8 ack;
u32 SRH=0,ST=0;
u8 databuff[6];
I2C_Start();
I2C_Send_Byte(AHT10_WRITE);
I2C_Wait_Ack();
I2C_Send_Byte(0xac);
I2C_Wait_Ack();
I2C_Send_Byte(0x33);
I2C_Wait_Ack();
I2C_Send_Byte(0x00);
I2C_Wait_Ack();
I2C_Stop();
delay_ms(80);//延時一會等待數(shù)據(jù)讀出
I2C_Start();
I2C_Send_Byte(AHT10_READ);
I2C_Wait_Ack();
ack=I22C_Read_Byte(1);
if((ack&0x40)==0)
{
databuff[0]=I22C_Read_Byte(1);
databuff[1]=I22C_Read_Byte(1);
databuff[2]=I22C_Read_Byte(1);
databuff[3]=I22C_Read_Byte(1);
databuff[4]=I22C_Read_Byte(0);
I2C_Stop();
SRH=(databuff[0]<<12)+(databuff[1]<<4)+(databuff[2]>>4);
ST=((databuff[2]&0X0f)<<16)+(databuff[3]<<8)+(databuff[4]);
*humidity=(int)(SRH*100.0/1024/1024+0.5);
*temperature=((int)(ST*2000.0/1024/1024+0.5))/10.0-50;
return 0;
}
I2C_Stop();
return 1;
}
//初始化IIC
void I22C_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //使能GPIOB時鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_3|GPIO_Pin_4); //PB6,PB7 輸出高
}
//產(chǎn)生IIC起始信號
void I2C_Start(void)
{
SDA_OUT(); //sda線輸出
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;//鉗住I2C總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù)
}
//產(chǎn)生IIC停止信號
void I2C_Stop(void)
{
SDA_OUT();//sda線輸出
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//發(fā)送I2C總線結(jié)束信號
delay_us(4);
}
//等待應(yīng)答信號到來
//返回值:1,接收應(yīng)答失敗
// 0,接收應(yīng)答成功
u8 I2C_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN(); //SDA設(shè)置為輸入
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
I2C_Stop();
return 1;
}
}
IIC_SCL=0;//時鐘輸出0
return 0;
}
//產(chǎn)生ACK應(yīng)答
void I2C_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//不產(chǎn)生ACK應(yīng)答
void I2C_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//IIC發(fā)送一個字節(jié)
//返回從機有無應(yīng)答
//1,有應(yīng)答
//0,無應(yīng)答
void I2C_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低時鐘開始數(shù)據(jù)傳輸
for(t=0;t<8;t++)
{
//IIC_SDA=(txd&0x80)>>7;
if((txd&0x80)>>7)
IIC_SDA=1;
else
IIC_SDA=0;
txd<<=1;
delay_us(2); //對TEA5767這三個延時都是必須的
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
//讀1個字節(jié),ack=1時,發(fā)送ACK,ack=0,發(fā)送nACK
u8 I22C_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA設(shè)置為輸入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay_us(1);
}
if (!ack)
I2C_NAck();//發(fā)送nACK
else
I2C_Ack(); //發(fā)送ACK
return receive;
}
#ifndef _AHT10_h_
#define _AHT10_h_
#include "headfire.h"
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
//輸出寄存器
#define GPIOA_ODR_Addr (GPIOA_BASE+12)//0x4001280C
#define GPIOB_ODR_Addr (GPIOB_BASE+12)//0x40010C0C
//輸入寄存器
#define GPIOA_IDR_Addr (GPIOA_BASE+8)//0x40010808
#define GPIOB_IDR_Addr (GPIOB_BASE+8)//0x40010C08
//IO口操作,只對單一的IO口!
//確保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n)//輸出
#define PAin(n) BIT_ADDR (GPIOA_IDR_Addr,n)//輸入
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n)//輸出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n)//輸入
#define SDA_IN() {GPIOB->CRL&=0XFFF0FFFF;GPIOB->CRL|=(u32)8<<16;}
#define SDA_OUT() {GPIOB->CRL&=0XFFF0FFFF;GPIOB->CRL|=(u32)3<<16;}
//IO操作函數(shù)
#define IIC_SCL PBout(3) //SCL
#define IIC_SDA PBout(4) //SDA
#define READ_SDA PBin(4) //輸入SDA
#define AHT10_ADDRESS 0x70
#define AHT10_WRITE 0x70
#define AHT10_READ 0x71
/*****************函數(shù)聲明******************/
extern void AHT10Init(void);
extern u8 AHT10Check(void);
extern void AHT10Reset(void);
extern u8 AHT10ReadData(float *temperature,u8 *humidity);
//IIC所有操作函數(shù)
void I22C_Init(void); //初始化IIC的IO口
void I2C_Start(void); //發(fā)送IIC開始信號
void I2C_Stop(void); //發(fā)送IIC停止信號
void I2C_Send_Byte(u8 txd); //IIC發(fā)送一個字節(jié)
u8 IIC_Read_Byte(unsigned char ack);//IIC讀取一個字節(jié)
u8 I2C_Wait_Ack(void); //IIC等待ACK信號
void I2C_Ack(void); //IIC發(fā)送ACK信號
void IIC_NAck(void); //IIC不發(fā)送ACK信號
void I2C_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 I2C_Read_One_Byte(u8 daddr,u8 addr);
//讀1個字節(jié),ack=1時,發(fā)送ACK,ack=0,發(fā)送nACK
u8 I22C_Read_Byte(unsigned char ack);
#endif
?主函數(shù)代碼:
#include "main.h"
float temp;
u8 hum;
int humm,temper;
uint16_t AHT10_cnt,AHT10_flag;
char buf[30];
int main(void)
{
init_ALL(); //初始化所有函數(shù)
while(1)
{
if(AHT10_flag==1)
{
AHT10_flag=0;
AHT10ReadData(&temp,&hum);
temper=temp*10;
humm=hum;
OLED_ShowCHinese(0,0,0); //打印中文“溫”
OLED_ShowCHinese(16,0,2); //打印中文“度”
sprintf(buf,": %d.%d",temper/10,temper%10);
OLED_ShowString(32,0,(u8 *)buf,16);
OLED_ShowCHinese(0,2,1); //打印中文“濕”
OLED_ShowCHinese(16,2,2); //打印中文“度”
sprintf(buf,": %d ",humm);
OLED_ShowString(32,2,(u8 *)buf,16);
}
}
}
//初始化所有函數(shù):
void init_ALL(void)
{
SysTick_Init(72); //初始化滴答計時器
Timer2_Init(); //初始化定時器2
i2c_GPIO_Config(); //IIC初始化
OLED_Init(); //初始化OLED屏幕
OLED_Clear(); //清空屏幕數(shù)據(jù)
AHT10Init(); //初始化溫濕度傳感器
}
//定時器2中斷服務(wù)函數(shù)
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
if(++AHT10_cnt==30) //每300ms刷新一次溫濕度數(shù)據(jù)
{AHT10_cnt=0;AHT10_flag=1;}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清出中斷寄存器標(biāo)志位,用于退出中斷
}
}
測試效果:
文章來源:http://www.zghlxwxcb.cn/news/detail-682106.html
?完整工程下載:
https://download.csdn.net/download/qq_64257614/88248711?spm=1001.2014.3001.5503文章來源地址http://www.zghlxwxcb.cn/news/detail-682106.html
到了這里,關(guān)于STM32 F103C8T6學(xué)習(xí)筆記13:IIC通信—AHT10溫濕度傳感器模塊的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!