arrière-plan
Le projet utilise en fait SHT3x pour la mesure de la température et de l'humidité, la puce de contrôle principale utilise STM8S003F3P6 et utilise la connexion matérielle de l'interface IIC analogique.
diagramme schématique
Comme indiqué dans la figure ci-dessous, utilisez les broches STM8S003F3P6 PB4/PB5 pour l'interface de données SHT3x
SHT3x-DIS est le capteur de température et d'humidité de nouvelle génération de Sensirion avec une précision de ± 2% HR et ± 0,3 ℃, plage de tension d'entrée de 2,4 V à 5,5 V, interface de bus IIC, vitesse jusqu'à 1 MHz. Les plages de température et d'humidité de mesure sont -40°C ~ 125°C et 0 ~ 100%.
Sur la figure ci-dessous, nous pouvons voir que le capteur d'humidité et le capteur de température sont intégrés à l'intérieur du SHT3x, qui sont échantillonnés et entrés dans l'unité de traitement des données et de linéarisation via l'ADC, et ont une mémoire de correction pour faire face à l'influence de l'environnement sur la mesure de l'appareil. Lire les données via l'interface numérique IIC. Avec une broche d'alarme, le seuil peut être défini en modifiant la valeur du registre, et il sera défini lorsque la température et l'humidité mesurées dépasseront le seuil.
conception de logiciels
La configuration de base de STM8S003F3P6 est la suivante
Configuration de l'horloge, la configuration de l'horloge doit être mentionnée ici, si la configuration de l'horloge n'est pas mentionnée, le délai de temporisation de l'interface IIC analogique SHT3x
c'est difficile de juger
/************************************************
函数名称 : CLK_Configuration
功 能 : 时钟配置
参 数 : 无
返 回 值 : 无
作 者 : strongerHuang
*************************************************/
void CLK_Configuration(void)
{
/*
ErrorStatus clk_return_status;
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV8); //HSI = 16M (8分频)=2MHZ
//切换内部低速时钟128khz
clk_return_status = CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_LSI, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE);
if (clk_return_status == SUCCESS) //SUCCESS or ERROR
{
CLK_ClockSwitchCmd(ENABLE);
CLK_LSICmd(ENABLE);
CLK_ClockSwitchCmd(DISABLE);
}*/
// CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); //HSI = 16M (1分频)
//ErrorStatus clk_return_status;
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); //HSI = 16M (8分频)=2MHZ
/*
//切换内部低速时钟8M
clk_return_status = CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE);
if (clk_return_status == SUCCESS) //SUCCESS or ERROR
{
CLK_ClockSwitchCmd(ENABLE);
CLK_HSECmd(ENABLE);
CLK_ClockSwitchCmd(DISABLE);
}*/
CLK_DeInit();//设置为默认值
CLK_HSICmd(ENABLE);//启用HSI
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);//HSI分频
CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);//CPU分频
}
La définition de macro d'opération de broche utilisant la broche IIC PB4/PB5 est la suivante
#define SHT30_SCL (0x01<<4)
#define SHT30_SDA (0x01<<5)
#define SHT30_SCL0_O GPIOB->DDR |= SHT30_SCL; GPIOB->CR1 |= SHT30_SCL //GPIOB4 推免输出
#define SHT30_SCL0_H GPIOB->ODR |= SHT30_SCL
#define SHT30_SCL0_L GPIOB->ODR &= ~SHT30_SCL
#define SHT30_SCL0_I GPIOB->DDR &= ~SHT30_SCL; GPIOB->CR1 &= ~SHT30_SCL //GPIOB4 浮空输入
#define SHT30_SCL0_DAT ( (GPIOB->IDR>>4) & 0x01)
#define SHT30_SDA0_O GPIOB->DDR |= SHT30_SDA; GPIOB->CR1 |= SHT30_SDA //GPIOB5 推挽输出
#define SHT30_SDA0_H GPIOB->ODR |= SHT30_SDA
#define SHT30_SDA0_L GPIOB->ODR &= ~SHT30_SDA
#define SHT30_SDA0_I GPIOB->DDR &= ~SHT30_SDA; GPIOB->CR1 &= ~SHT30_SDA //GPIOB5 浮空输入
#define SHT30_SDA0_DAT ( (GPIOB->IDR>>5) & 0x01)
#define SHT30_SlaveAddress (0x44<<1) //7位地址0x44 左移1位 0x45 -- 0x8A
#define noACK 0 //用于判断是否结束通讯
#define ACK 1 //结束数据传输
Avant le démarrage de la fonction principale, les broches utilisées doivent être initialisées et configurées comme suit
Configurer PB4/PB5 pour initialiser en tant que sortie
uint8 SHT30_Init(vid)
{
uint8 vRval = 0x00;
SHT30_SCL0_O; //设置SCLK为输出
SHT30_SDA0_O; //设置SDA为输出
SHT30_SCL0_H;
SHT30_SCL0_L;
SHT30_SDA0_H;
SHT30_SDA0_L;
vRval += SHT30_Soft_Reset();
SHT30_DelayMs(1);
vRval += SHT30_ClearStaus();
SHT30_DelayMs(1);
//SHT30_Periodic_Measure(SHT30_PERIODOC_H_MEASURE_1S);
return vRval;
}
Le format de données détaillé de la commande d'acquisition de données monocoup
(commandes de mesure pour le mode d'acquisition de données monocoup) est illustré dans la figure ci-dessous. Commencez d'abord par le haut du tableau. La répétabilité fait référence à la répétabilité (plus la répétabilité est élevée, plus la précision est élevée, veuillez vous reporter à la partie Performances du capteur du manuel), l'étirement de l'horloge fait référence à l'étirement de l'horloge. Leurs fonctions seront décrites ci-dessous. Le processus de flux de données est le suivant.
Envoyez le signal de démarrage et une adresse d'un octet composée de l'adresse de périphérique à 7 bits supérieure et du signal d'écriture du bit le plus bas (WR = 0), et attendez le signal de réponse. (Notez que l'adresse est située dans les 7 bits supérieurs, vous devez donc décaler l'adresse d'un bit vers la gauche et ajouter le signal de lecture 1/écriture 0 lors du transfert de l'adresse, ADDR<<1 | WR); envoyer le
haut octet de l'instruction (octet le plus significatif, MSB) et attendre le signal de réponse ;
envoyer l'octet de poids faible (octet le moins significatif, LSB) de l'instruction et attendre le signal de réponse, puis envoyer le signal d'arrêt ;
attendre une période de temps (la mesure est en cours) ;
envoyer le signal de démarrage et l'adresse de l'appareil par les 7 bits supérieurs Une adresse d'un octet composée du signal de lecture du bit le plus bas (RD=1), puis sélectionner parmi deux directions en fonction du Étirement de l'horloge. Si la fonction d'extension d'horloge est désactivée, attendez un signal de non-réponse, envoyez un signal d'arrêt, retardez pendant un certain temps (cette étape est très importante !! Le temps de retard est d'environ 50 ms) et attendez la fin de la conversion , puis envoyez un signal de réponse à huit bits et attendez le signal de réponse, puis lisez l'octet haut, l'octet bas et l'octet de contrôle CRC de la température et de l'humidité octet par octet, et envoyez un signal de réponse après la réception de chaque octet, et enfin envoyer un signal d'arrêt. Et si la fonction d'extension d'horloge est activée, le SCL du bus est contrôlé par SHT3x, il suffit de bloquer le programme pendant que (SCL==0), attendez qu'il libère le bus et ensuite le MCU peut lire les données ;
Certaines fonctions de synchronisation pour SHT3x sont les suivantes
/*---------------------------------------------------------------------
功能描述: SHT30 测量结果计算
参数说明: vTemSymbol [out] - 返回温度符号
vTem [out] - 温度
vHum [out] - 湿度
函数返回: 无
---------------------------------------------------------------------*/
uint8 SHT30_Get_TH(uint8 *vTemSymbol, uint16 *vTem, uint16 *vHum)
{
uint8 vDat[8];
uint8 vRval = 0;
vRval = SHT30_Single_Measure(vDat);
if (!vRval) SHT30_calc(vDat, vTemSymbol, vTem, vHum);
return vRval;
}
/*---------------------------------------------------------------------
功能描述: SHT30单次测量
参数说明: vBuf [out] - 测量读取结果
函数返回: 0 - 成功 大于1出错
---------------------------------------------------------------------*/
uint8 SHT30_Single_Measure(uint8 *vBuf)
{
uint8 vRval = 0;
uint8 i = 0;
SHT30_Start();
vRval |= SHT30_SendByte(SHT30_SlaveAddress+0); //地址写
if (!vRval) vRval |= SHT30_SendByte( (SHT30_SINGLE_H_MEASURE_EN>>8)&0xFF ); //使能高精度采集
if (!vRval) vRval |= SHT30_SendByte( (SHT30_SINGLE_H_MEASURE_EN)&0xFF );
SHT30_Stop();
if (vRval) return vRval;
SHT30_SCL0_H;
SHT30_DelayMs(15); //15Ms
SHT30_Start();
if (!vRval) vRval |= SHT30_SendByte(SHT30_SlaveAddress+1); //地址读
if (vRval) return vRval;
for(i=0; i<6; i++)
{
vBuf[i] = SHT30_RecvByte(); //存储数据
if (i == 0x06)
{
SHT30_SendACK(1); //最后一个数据需要回NOACK
}
else
{
SHT30_SendACK(0); //回应ACK
}
}
SHT30_Stop();
return vRval;
}
/*---------------------------------------------------------------------
功能描述: SHT30 测量结果计算
参数说明: vBuf [in] - 测量读取结果
vTemSymbol [out] - 返回温度符号
vTem [out] - 温度
vHum [out] - 湿度
函数返回: 无
---------------------------------------------------------------------*/
void SHT30_calc(uint8 *vBuf, uint8 *vTemSymbol, uint16 *vTem, uint16 *vHum)
{
uint16 vVal = 0x00;
uint8 vCrc = 0x00;
float vTemp = 0.00;
//温度
vCrc = SHT30_CheckCrc8(vBuf, 2);
if (vCrc == vBuf[2])
{
vVal = vBuf[0];
vVal<<=8;
vVal |= vBuf[1];
vTemp = 175.0*vVal/(65536.0-1.0);
if (vTemp >= 45)
{
*vTemSymbol = 1;
*vTem = (uint16)((vTemp - 45.0)*10.0);
}
else
{
*vTemSymbol = 0;
*vTem = (uint16)((45.0 - vTemp)*10.0);
}
}
vBuf += 3;
vVal = 0x00;
vCrc = SHT30_CheckCrc8(vBuf, 2);
if (vCrc == vBuf[2])
{
vVal = vBuf[0];
vVal<<=8;
vVal |= vBuf[1];
vTemp = 100.0*vVal/(65536.0-1.0);
*vHum = (uint16)(vTemp*10);
}
}