SHT3x是新一代的溫濕度傳感器,精度為±2%RH和±0.3℃,輸入電壓范圍從2.4V到5.5V,采用IIC總線接口,速率可達(dá)1MHz。測(cè)量溫濕度范圍分別為是-40℃ ~ 125℃和0 ~ 100%。工作電流為600uA,空閑電流在2ua。因此非常適合用在低功耗溫濕度監(jiān)測(cè)項(xiàng)目之上。 SHT3X的獲取溫度只需要二步,一是發(fā)送溫度轉(zhuǎn)換命令,接著讀取6個(gè)字節(jié)。進(jìn)行溫濕度測(cè)量,需先發(fā)送一個(gè)開(kāi)始信號(hào),然后發(fā)送一個(gè) I2C的寫操作頭,然后再跟隨一個(gè) 16 位的溫濕度轉(zhuǎn)換命令。傳感器收到上位機(jī)發(fā)送的每個(gè)字節(jié)數(shù)據(jù)后,會(huì)通過(guò)將 SDA 總線拉到低電平給出ACK 信號(hào)。在正確的收到溫濕度轉(zhuǎn)換命令并發(fā)送 ACK 信號(hào)給微處理器之后,SHT3x 內(nèi)部開(kāi)始啟動(dòng)溫度和濕度的轉(zhuǎn)換測(cè)量。二是在傳感器完成溫濕度測(cè)量之后,上位機(jī)可以通過(guò)發(fā)送 START信號(hào)+I2C 讀取數(shù)據(jù)頭來(lái) 讀取溫濕度數(shù)據(jù),如果溫濕度數(shù)據(jù)已經(jīng)準(zhǔn)備好,那么芯片會(huì)向上位機(jī)發(fā)送 ACK 信號(hào),并隨后發(fā)送 2 字節(jié)的溫度數(shù)據(jù)加 1 字節(jié)的 CRC 校驗(yàn)數(shù)據(jù),然后再發(fā)送 2 字節(jié)的濕度數(shù)據(jù)加 1 字節(jié)的 CRC 校驗(yàn)數(shù)據(jù)。上位機(jī)需要對(duì)接收到的每個(gè)字節(jié)數(shù)據(jù)發(fā)送 ACK,否則芯片會(huì)停止發(fā)送數(shù)據(jù)。微處理器在收到濕度數(shù)據(jù)的CRC 字節(jié)后應(yīng)該發(fā)送一個(gè)NACK 和一個(gè) STOP 信號(hào)來(lái)結(jié)束本次數(shù)據(jù)傳輸,
下面開(kāi)始CW32L083的溫度采集:
1、選取PB10、PB11為I2C通信,采取軟件I2C。初始化代碼如下:
void IIC_Init(void)
{
//配置PB10 為輸出
//使能GPIOB時(shí)鐘
CW_SYSCTRL->AHBEN_f.GPIOB = 1;
//配置PB10 為輸出
CW_GPIOB->ANALOG_f.PIN10 = 0; //設(shè)置 GPIOx_ANALOG.PINy 為 0,將端口配置為數(shù)字功能;
CW_GPIOB->DIR_f.PIN10 = 0; //設(shè)置 GPIOx_DIR.PINy 為 0,將端口配置成輸出;
CW_GPIOB->OPENDRAIN_f.PIN10 = 0; //0:推挽輸出
CW_GPIOB->ODR_f.PIN10 = 1;
CW_GPIOB->ANALOG_f.PIN11 = 0; //設(shè)置 GPIOx_ANALOG.PINy 為 0,將端口配置為數(shù)字功能;
CW_GPIOB->DIR_f.PIN11 = 0; //設(shè)置 GPIOx_DIR.PINy 為 0,將端口配置成輸出;
CW_GPIOB->OPENDRAIN_f.PIN11 = 0; //0:推挽輸出
CW_GPIOB->ODR_f.PIN11 = 1;
}
2、設(shè)置IO方向,SDA需要轉(zhuǎn)換輸出與輸入,我們采用對(duì) GPIOx_DIR.PINy進(jìn)行設(shè)置,來(lái)實(shí)現(xiàn)IO的數(shù)據(jù)輸入與輸出的轉(zhuǎn)換。
//IO方向設(shè)置(SDA)
/ xxxxxxxxxxxxxx ****/
void SDA_IN()
{
CW_GPIOB->DIR_f.PIN11 = 1; //設(shè)置 GPIOx_DIR.PINy 為 0,將端口配置成輸出;
}
void SDA_OUT()
{
CW_GPIOB->DIR_f.PIN11 = 0; //設(shè)置 GPIOx_DIR.PINy 為 0,將端口配置成輸出;
CW_GPIOB->OPENDRAIN_f.PIN11 = 0; //0:推挽輸出
}
3、定義讀取SDA的宏:#define READ_SDA PB11_GETVALUE() //輸入SDA
4、定義IIC的STAT、STOP、ACK、NACK等時(shí)序,代碼如下:
//產(chǎn)生IIC起始信號(hào)
void IIC_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停止信號(hào)
void IIC_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é)束信號(hào)
delay_us(4);
}
//等待應(yīng)答信號(hào)到來(lái)
//返回值:1,接收應(yīng)答失敗
// 0,接收應(yīng)答成功
/ xxxx修改超時(shí)時(shí)間 ***/
uint8_t IIC_Wait_Ack(void)
{
uint8_t ucErrTime=0;
SDA_IN(); //SDA設(shè)置為輸入
IIC_SDA=1;delay_us(3);
IIC_SCL=1;delay_us(3);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
//printf("超時(shí)
");IIC_Stop();
return 1;
}
}
IIC_SCL=0;//時(shí)鐘輸出0
return 0;
}
//產(chǎn)生ACK應(yīng)答
void IIC_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 IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
5、定義發(fā)送一個(gè)字節(jié):
//IIC發(fā)送一個(gè)字節(jié)
//返回從機(jī)有無(wú)應(yīng)答
//1,有應(yīng)答
//0,無(wú)應(yīng)答
void IIC_Send_Byte(uint8_t txd)
{
uint8_t t;
SDA_OUT();
IIC_SCL=0;//拉低時(shí)鐘開(kāi)始數(shù)據(jù)傳輸
for(t=0;t<8;t++)
{
if((txd&0x80)>>7)
IIC_SDA=1;
else
IIC_SDA=0;
txd<<=1;
delay_us(2); //對(duì)TEA5767這三個(gè)延時(shí)都是必須的
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
6、定義讀取一個(gè)字節(jié)
//讀1個(gè)字節(jié),ack=1時(shí),發(fā)送ACK,ack=0,發(fā)送nACK
uint8_t IIC_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(100);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay_us(100);
}
if (!ack)
IIC_NAck();//發(fā)送nACK
else
IIC_Ack(); //發(fā)送ACK
return receive;
}
到這里IIC的初始化工作結(jié)束。
6、SHT3x的數(shù)據(jù)獲取,采集廠家出廠的標(biāo)準(zhǔn)DEMO。主要是發(fā)送轉(zhuǎn)換溫度的命令與讀取命令,sth30.c代碼如下:
#include "sht30.h"
#define POLYNOMIAL_CXDZ 0x31 // X^8 + X^5 + X^4 + 1
//SHT3X CRC校驗(yàn)
unsigned char SHT3X_CRC(uint8_t *data, uint8_t len)
{
unsigned char bit; // bit mask
unsigned char crc = 0xFF; // calculated checksum
unsigned char byteCtr; // byte counter
// calculates 8-Bit checksum with given polynomial @GZCXDZ
for(byteCtr = 0; byteCtr < len; byteCtr++) {
crc ^= (data[byteCtr]);
for(bit = 8; bit > 0; --bit) {
if(crc & 0x80) {
crc = (crc << 1) ^ POLYNOMIAL_CXDZ;
} else {
crc = (crc << 1);
}
}
}
return crc;
}
//SHT30命令函數(shù)
//addr:表示產(chǎn)品的序號(hào),因?yàn)镾HT30使用IIC總線的話一條線上可以掛兩個(gè)
void SHT30_CMD(uint16_t cmd)
{
IIC_Start();
IIC_Send_Byte(SHT30_ADDR+0); //發(fā)送設(shè)備地址,寫寄存器
IIC_Wait_Ack();
IIC_Send_Byte((cmd>>8)&0xff); //MSB
IIC_Wait_Ack();
IIC_Send_Byte(cmd&0xff); //LSB
IIC_Wait_Ack();
IIC_Stop();
SysTickDelay(500);//命令發(fā)完后需要等待20ms以上才能讀寫
}
//SHT30讀取溫濕度
//temp:溫度,-400~1250,實(shí)際溫度=temp/10,分辨率0.1℃,精度±0.3℃
//humi:濕度,0~1000,實(shí)際濕度=humi/10,分辨率0.1%rh,精度±3
//返回0成功,1失敗
uint8_t SHT30_Read_Humiture(int *temp,uint16_t *humi)
{
uint8_t buff[6];
SHT30_CMD(SHT30_READ_HUMITURE);//讀溫濕度命令
IIC_Start();
IIC_Send_Byte(SHT30_ADDR+1); //發(fā)送設(shè)備地址,讀寄存器
IIC_Wait_Ack();
buff[0]=IIC_Read_Byte(1);//繼續(xù)讀,給應(yīng)答
buff[1]=IIC_Read_Byte(1);//繼續(xù)讀,給應(yīng)答
buff[2]=IIC_Read_Byte(1);//繼續(xù)讀,給應(yīng)答
buff[3]=IIC_Read_Byte(1);//繼續(xù)讀,給應(yīng)答
buff[4]=IIC_Read_Byte(1);//繼續(xù)讀,給應(yīng)答
buff[5]=IIC_Read_Byte(0);//不繼續(xù)給停止應(yīng)答
IIC_Stop();
//printf("buff=%d,%d,%d,%d,%d,%d
",buff[0],buff[1],buff[2],buff[3],buff[4],buff[5]);//CRC校驗(yàn)
if(SHT3X_CRC(&buff[0],2)==buff[2] && SHT3X_CRC(&buff[3],2)==buff[5])
{
temp=(-45+(175.0 ((buff[0]<<8)+buff[1])/65535.0)) *10;
humi=10100* ((buff[3]<<8)+buff[4])/65535.0;
if(*temp>1250) *temp=1250;
else if(*temp<-400) *temp=-400;
return 0;
}
else return 1;
}
//SHT30初始化
void SHT30_Init()
{
IIC_Init();
}
sht30.h頭文件代碼如下:
#ifndef SHT30_H
#define SHT30_H
#include "main.h"
#define SHT30_ADDR (uint8_t)(0x44<<1) //sht30 i2c地址,ADDR管腳接低電平時(shí)為0x44,接高電平為0x45
//SHT30命令
#define SHT30_READ_HUMITURE (uint16_t)0x2c06 //讀溫濕度
//CRC多項(xiàng)式
#define POLYNOMIAL 0x31 // X^8 + X^5 + X^4 + 1
uint8_t SHT30_Read_Humiture(int *temp,uint16_t *humi);
void SHT30_Init(void);
#endif
8、在主程序中,我們把讀取到的數(shù)據(jù)顯示到LCD段碼屏上:
while(1)
{
SHT30_Read_Humiture(t,h);
temp = t[0];
Lcd_clear();
show_num(2, temp/100,0);
show_num(1, (temp/10)%10,1);
show_num(0, temp%10,0);
temp = h[0];
show_num(7, temp/100,0);
show_num(6, (temp/10)%10,1);
show_num(5, temp%10,0);
SysTickDelay(50000);
}
最后實(shí)現(xiàn)的效果如圖:
-
傳感器
+關(guān)注
關(guān)注
2550文章
51035瀏覽量
753063 -
lcd
+關(guān)注
關(guān)注
34文章
4424瀏覽量
167396
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論