嵌入式温湿度传感器C语言代码求帮忙注释

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌入式温湿度传感器C语言代码求帮忙注释相关的知识,希望对你有一定的参考价值。

嵌入式温湿度无线传感器,C语言代码求帮忙注释,关键的地方注释一下,越多越好。无线传感器网络源代码发到百度贴吧了h t \t \p:// ti e ba.baidu.com/p/28 01429 171

  #include "ioCC2430.h"  //包含头文件,相应的板子以及传感器一些信息

  #include "hal.h"

  #include <math.h>

  //#include <intrins.h>

  #include <stdio.h>


  typedef union    //定义联合体,

  

  unsigned int i;

  float f;

   value;      //定义联合体类型名称为value


  #define noACK 0

  #define ACK 1

  #define STATUS_REG_W 0x06    //0x06 = 0000 0110

  #define STATUS_REG_R 0x07    //0x07 = 0000 0111

  #define MEASURE_TEMP 0x03    //0x03 = 0000 0011

  #define MEASURE_HUMI 0x05    //0x05 = 0000 0101

  #define RESET 0x1e           //0x1e = 0001 1110

  #define SDA P1_6             //定义SDA代表的是P1_6脚

  #define SCL P1_7

  #define begin P2_0

  unsigned char d1,d2,d3,d4,d5,d6,d7; //定义无符号字符型变量


  void Wait(unsigned int ms)   //定义wait函数,主要用于软件循环,延时作用

  

  unsigned char g,k;

  while(ms)

  

  for(g = 0;g <= 167; g++)

  

  for(k = 0;k <= 48; k++);

  

  ms--;

  

  


  void QWait() //1us的延时

  

  asm("NOP");  //加入汇编操作语句,空操作,主要用于机器周期执行

  asm("NOP");

  asm("NOP");

  asm("NOP");

  asm("NOP");

  asm("NOP");

  asm("NOP");

  asm("NOP");

  asm("NOP");

  asm("NOP");

  asm("NOP");

  


  void initUART(void)     //初始化单片机的串口

  

  IO_PER_LOC_USART0_AT_PORT0_PIN2345();  //具体函数的定义与用法,你得参考头文件中的程序代码了

  IO_DIR_PORT_PIN(1, 6, IO_OUT);

  IO_DIR_PORT_PIN(1, 7, IO_OUT);

  //IO_IMODE_PORT_PIN(1, 6, IO_IMODE_TRI);

  //IO_IMODE_PORT_PIN(1, 7, IO_IMODE_TRI);

  IO_DIR_PORT_PIN(2, 0, IO_OUT);

  IO_FUNC_PORT_PIN(2, 0, IO_FUNC_GIO);

  //SET_MAIN_CLOCK_SOURCE(RC);

  SET_MAIN_CLOCK_SOURCE(CRYSTAL);

  UART_SETUP(0, 115200, HIGH_STOP);  //设置传输数据的波特率115200

  

  UTX0IF = 1;

  U0CSR |= 0XC7;     //U0CSR = U0CSR | 0x1010 0111  (进行位或操作)

  IEN0 |= 0x84;

  SDA = 1;

  SCL = 0;

  

  


  int putchar (int c)    //定义输入字符函数,给的参数是一个整型的数

  

  if (c == '\\n')      //判断参数c的值是否和'\\n'的值相等

  

  while (!UTX0IF);    //执行的时候UTX0IF的值是0,此处不是很理解?

  UTX0IF = 0;         //给UTX0IF赋0

  U0DBUF = 0x0d;      //U0DBUF赋值0x0d = 0000 1011

  

  while (!UTX0IF);

  UTX0IF = 0;

  return (U0DBUF = c);    //如果c的值不是'\\n'也就是换行符的时候,将c的值传递到U0DBUF寄存器中

  


  char s_write_byte(unsigned char value)   //定义写字节函数(8位)

  

  unsigned char i,error = 0;

  for (i = 0x80;i > 0;i /= 2)   //i 赋初始值0x80 = 128, 执行判断是i > 0,执行语句是i = i / 2; 即i = 128,64,32,16,8,4,2,1,0.5(0),8位

  

  if (i & value)

  SDA = 1;

  else

  SDA = 0;

  SCL = 1;      //此时SCL端口处,也就是p1_7引脚处是高电平

  QWait();      //因为写入需要时间,所以程序之中加入下面几条语句

  QWait();

  QWait();

  QWait();

  QWait();

  SCL = 0;      //使能p1_7眼角处低电平,使的数据写入(具体需要看单片机控制芯片的手册

  asm("NOP");

  asm("NOP");

  

  SDA = 1;

  SCL = 1;

  asm("NOP");

  error = SDA;

  QWait();

  QWait();

  QWait();

  SDA = 1;

  SCL = 0;

  return error;

  


  char s_read_byte(unsigned char ack)   //读取数据,按照字节位的顺序读取(8位)128 = 1000 0000 ,64 = 0100 0000, 32 = 0010 0000 ,16 = 0001 0000, 8 = 0000 1000, 4 = 0000 0100 , 2 = 0000 0010, 1 = 0000 0001

  

  unsigned char i,val = 0;

  SDA= 1;

  for(i = 0x80;i > 0;i /= 2)   //同上

  

  SCL = 1;

  if (SDA)      //判断SDA处是否有高电平

  val = (val | i);      //进行或操作

  else

  val = (val | 0x00);

  SCL = 0;

  QWait();

  QWait();

  QWait();

  QWait();

  QWait();

  

  SDA = !ack;

  SCL = 1;

  QWait();

  QWait();

  QWait();

  QWait();

  QWait();

  SCL = 0;

  SDA = 1;


  return val;   //返回读取到的数据,一个字节,八位

  


  void s_transstart(void)  //传输使能函数,就是给控制器引脚处相应电平,使对应模块工作

  

  SDA = 1;

  SCL = 0;

  QWait();

  QWait();

  SCL = 1;

  QWait();

  QWait();

  SDA = 0;

  QWait();

  QWait();

  SCL = 0;

  QWait();

  QWait();

  QWait();

  QWait();

  QWait();

  SCL = 1;

  QWait();

  QWait();

  SDA = 1;

  QWait();

  QWait();

  SCL = 0;

  QWait();

  QWait();

  


  void s_connectionreset(void)   //复位操作函数

  

  unsigned char i;

  SDA = 1;

  SCL = 0;

  for(i = 0;i < 9; i++)

  

  SCL = 1;

  QWait();

  QWait();

  SCL = 0;

  QWait();

  QWait();

  

  s_transstart();   //调用开始函数

  


  char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode) //函数,主要统计传输的数据个数

  

  unsigned er = 0;

  unsigned int i,j;

  s_transstart();

  switch(mode)

  

  case 3 :er += s_write_byte(3);

  break;

  case 5 :er += s_write_byte(5);

  break;

  default :break;

  

  

  for(i = 0;i < 65535;i++)

  

  for(j = 0;j < 65535;j++)

  if(SDA == 0)

  

  break;

  

  

  if(SDA == 0)

  

  break;

  


  

  

  if(SDA)

  

  er += 1;

  

  

  *(p_value) = s_read_byte(ACK);

  *(p_value + 1) = s_read_byte(ACK);

  *p_checksum = s_read_byte(noACK);

  d6 = *(p_value);

  d7=*(p_value + 1);

  

  return er;

  


  void calc_sth11(float *p_humidity ,float *p_temperature)//计算温度值

  

  const float C1 =- 4.0;

  const float C2 =+ 0.0405;

  const float C3 =- 0.0000028;

  const float T1 =+ 0.01;

  const float T2 =+ 0.00008;

  float rh =* p_humidity;

  float t =* p_temperature;

  float rh_lin;

  float rh_true;

  float t_C;

  t_C = t * 0.01 - 44.0 ;

  rh_lin = C3 * rh * rh + C2 * rh + C1;

  rh_true = (t * 0.01 - 40.0 - 25) * (T1 + T2 * rh) + rh_lin;

  if(rh_true > 100)

  

  rh_true = 100;

  

  if(rh_true < 0.1)

  

  rh_true = 0.1;

  

  *p_temperature = t_C;

  *p_humidity = rh_true;

  


  void main()  //主函数

  

  value humi_val,temp_val;  //声明两个联合体变量

  unsigned char error,checksum;  //声明两个无符号的字符型变量

  initUART();    //初始化串口

  P1INP |= 0xC0;   //初始化P1引脚 , 0xC0 = 1010 0000 ,使P1_7和P1_5引脚为1

  begin = 0;

  s_connectionreset();

  while(1)  //无限循环操作

  

  error = 0;

  error += s_measure((unsigned char*) &humi_val.i,&checksum,5);  //读入串口的数据进行温度的计算

  d1 = d6;

  d2 = d7;

  error += s_measure((unsigned char*) &temp_val.i,&checksum,3);

  d3 = d6;

  d4 = d7;

  if(error != 0)

  s_connectionreset();

  else

  

  humi_val.f = (float)humi_val.i;

  temp_val.f = (float)temp_val.i;

  humi_val.f = d1 * 256 + d2;

  temp_val.f = d3 * 256 + d4;

  calc_sth11(&humi_val.f,&temp_val.f);

  printf("temp:%5.1fC humi:%5.1f%%\\n",temp_val.f,humi_val.f);

  // printf("t1:%x h1:%x\\n",d1,d2);

  //printf("t2:%x h2:%x\\n",d3,d4);

  

  Wait(150);

  

  


参考技术A 1、氧传感器:当氧传感器故障时,ECU无法获取这些信息,就不知道喷射的汽油量是否正确,而不合适的油气空燃比会导致发动机功率降低,增加排放污染;
2、轮速传感器:它主要是收集汽车的转速来判断汽车有没有打滑的征兆,所以,就有一一个专门收集汽车轮速的传感器来完成这项工作,一般安装在每个车轮的轮毂上,而一旦传感器损坏,ABS会失效;
3、水温传感器:当水温传感器故障后,往往冷车启动时显示的还是热车时的温度信号,ECU得不到正确的信号,只能供给发动机较稀薄的混合气,所以发动机冷车不易启动,且还会伴随怠速运转不稳定,加速动力不足的问题;
4、电子油门踏板位置传感器:当传感器失效后,ECU无法测得油门位置信号,无法获得油门门踏板的正确位置,所以会出现发动机加速无力的现象,甚至出现发动机不能加速的情况;
5、进气压力传感器:进气压力传感器顾名思义就是随着发动机不同的转速负荷,感应一系列的电阻和压力变化,转换成电压信号,供ECU修正喷油量和点火正时角度。一般安装在节气门边上,假如故障了会引起点火困难、怠速不稳、加速无力等问题。

《嵌入式-STM32开发指南》第三部分 外设篇 - 第1章 温湿度传感器DHT11

1.1理论分析

1.1.1 DHT11 介绍

DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。

DHT11传感器包括一个电阻式感湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个 DHT11 传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在 OTP 内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达 20 米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则。产品为 4 针单排引脚封装。连接方便,特殊封装形式可根据用户需求而提供。

在这里插入图片描述

图 1 DHT11 模块实物图

DHT11 的技术参数如下

  • 工作电压范围: 3.3V-5.5V
  • 工作电流 :平均 0.5mA
  • 输出:单总线数字信号
  • 测量范围:湿度 20~90%RH,温度 0~50℃
  • 精度 :湿度±5%,温度±2℃
  • 分辨率 :湿度 1%,温度 1℃

1.1.2 STM32读取 DHT11

DHT11 模块的数据管脚用于 MCU 与 DHT11 之间的通讯和同步,采用单总线数据格式,一次通讯时间 4ms 左右,一次完整的数据传输为 40bit,高位先出,数据分小数部分和整数部分,具体格式是:

8bit 湿度整数数据+8bit 湿度小数数据+8bi 温度整数数据+8bit 温度小数数据 +8bit校验和数据传送正确时校验和数据等于 8bit 湿度整数数据+8bit 湿度小数数据+8bi 温度整数数据+8bit 温度小数数据所得结果的末 8 位。

传感器数据输出的是未编码的二进制数据。数据(湿度、温度、整数、小数)之间应该分开处理。例如,某次从 DHT11 读到的数据如下所示。

在这里插入图片描述

由以上数据就可得到湿度和温度的值,计算方法:

湿度= byte4 . byte3=45.0 (%RH)
温度= byte2 . byte1=28.0 ( ℃)
校验= byte4+ byte3+ byte2+ byte1=73(=湿度+温度)(校验正确)

可以看出, DHT11 的数据格式是十分简单的, DHT11 和 MCU 的一次通信最大为 3ms 左右,建议主机连续读取时间间隔不要小于 100ms。

下面,介绍一下 DHT11 的传输时序。

1.主机与DHT11通讯流程
主机MCU 发送一次开始信号后,DHT11 从低功耗模式转换到高速模式,等待主机开始信号结束后,即:拉低数据线,保持至少 18ms时间,然后拉高数据线 20~40us时间。DHT11 发送响应信号,送出 40bit 的数据,并触发一次信号采集,用户可选择读取部分数据。正常情况, DHT11 会拉低数据线,保持80us时间,作为响应信号,然后 DHT11 拉高数据线,保持80us时间后,开始输出数据。DHT11 接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11 不会主动进行温湿度采集。采集数据后转换到低速模式。

在这里插入图片描述

图2 MCU 与 DHT11 通讯流程图

2.主机复位信号和 DHT11 响应信号
总线空闲状态为高电平,主机把总线拉低等待 DHT11 响应,主机把总线拉低必须大于 18 毫秒,保证 DHT11 能检测到起始信号。DHT11 接收到主机的开始信号后,等待主机开始信号结束,然后发送 80us 低电平响应信号。主机发送开始信号结束,延时等待 80us 后,读取 DHT11 的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可,总线由上拉电阻拉高,如图中黑色线所示

在这里插入图片描述

图 3 数据传输前的通讯时序

总线为低电平,说明 DHT11 发送响应信号,DHT11 发送响应信号后,再把总线拉高 80us,准备发送数据,每一 bit 数据都以 50us 低电平时隙开始,高电平的长短定了数据位是 0 还是 1。格式如图中灰色线所示。如果读取响应信号为高电平,则 DHT11 没有响应,请检查线路是否连接正常。当最后 1bit 数据传送完毕后,DHT11 拉低总线 50us,随后总线由上拉电阻拉高进入空闲状态。

3.数字‘ 0’信号表示方法
数字 0 信号表示方法如图所示

在这里插入图片描述

图 4 数字 0 信号表示方法

4.数字‘ 1’信号表示方法
数字 1 信号表示方法如图所示

在这里插入图片描述

图 5 数字 1 信号表示方法

这里我们可以看出,数字“0”和数字“1”不同的地方在于高电平的时间不同,这也是读取数据的关键所在。

1.2实验详解

1.2.1实验目的

  1. 通过实验掌握STM32 芯片GPIO 的配置方法
  2. 掌握温湿度传感器DHT11 的原理与使用

1.2.2实验设备

硬件:PC 机一台;STM32开发板一套; DHT11 一个
软件:Windows 10系统,Keil5集成开发环境、串口助手

1.2.3实验相关电路图

DHT11模块相关电路途如下图所示:
在这里插入图片描述

图6 DHT11电路图

传感器模块是单总线通信,单总线通常要求外接一个4.7kΩ的上拉电阻,这样,当总线闲置时,总线上始终是高电平

【注】VCC接开发板的5V、GND 接开发板的GND、DATA接到开发板的PC5上,当然,也可以接到其他引脚上,修改相应的GPIO代码即可。

1.2.4 Lib_V3.5.0库实现

代码很简单。主要是根据DHT11的操作即可,另外需要高精度延时,这里用到了滴答定时器,这个在前面的章节以已经讲过了,这里就不在细说了。接下来看看DHT11的数据采集实现。

1.首先对GPIO初始化,配置为推挽输出,速度设置为高速。

/**
  * @brief  配置DHT11用到的IO口
  * @param  None
  * @retval None
  */
static void DHT11_GPIO_Config ( void )
{		
  /*定义一个GPIO_InitTypeDef类型的结构体*/
  GPIO_InitTypeDef GPIO_InitStructure;

  /*开启DHT11_Dout_GPIO_PORT的外设时钟*/
  DHT11_Dout_SCK_APBxClock_FUN ( DHT11_Dout_GPIO_CLK, ENABLE );	

  /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/															   
  GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;	

  /*设置引脚模式为通用推挽输出*/
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

  /*设置引脚速率为50MHz */   
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

  /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
  GPIO_Init ( DHT11_Dout_GPIO_PORT, &GPIO_InitStructure );		  
}

2.接着就是主机MCU发送一次开始信号,主机把总线拉低必须大于 18 毫秒,保证 DHT11 能检测到起始信号,然后拉高数据线 20~40us时间。

/*输出模式*/
DHT11_Mode_Out_PP();
/*主机拉低*/
DHT11_Dout_0;
/*延时18ms*/
Delay_ms(18);

/*总线拉高 主机延时30us*/
DHT11_Dout_1; 

Delay_us(30);   //延时30us

3.DHT11 接收到主机的开始信号后,等待主机开始信号结束,然后发送 80us 低电平响应信号。主机发送开始信号结束,延时等待 80us 后, DHT11 开始输出数据。每一 bit 数据都以 50us 低电平时隙开始,高电平的长短定了数据位是 0 还是 1。

DHT11读取一个字节数据的函数如下。

/**
  * @brief  从DHT11读取一个字节,MSB先行
  * @param  None
  * @retval byte
  */
static uint8_t DHT11_ReadByte ( void )
{
	uint8_t i, byte=0;
	
	for(i=0;i<8;i++)    
	{	 
		/*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/  
		while(DHT11_Dout_IN()==Bit_RESET);

		/*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,
		 *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时 
		 */
		Delay_us(40); //延时x us 这个延时需要大于数据0持续的时间即可	   	  

		if(DHT11_Dout_IN()==Bit_SET)/* x us后仍为高电平表示数据“1” */
		{
			/* 等待数据1的高电平结束 */
			while(DHT11_Dout_IN()==Bit_SET);

			byte|=(uint8_t)(0x01<<(7-i));  //把第7-i位置1,MSB先行 
		}
		else	 // x us后为低电平表示数据“0”
		{			   
			byte&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
		}
	}
	return byte;
}

这个函数就是来读取DHT11的数据,DHT11通过不同的延时来表示“0”和“1”,以26~28us的高电平表示“0”,以40us高电平表示“1”,因此这里通过去一个中间延时来区分。

4.主机MCU读取完40位数据后,需要检查数据的正确性。

下面给出一次温湿度数据的读取代码。

/**
  * @brief  一次完整的数据传输为40bit,高位先出
  *         8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和
  * @param  DHT11_Data:DHT11数据类型
  * @retval ERROR:  读取出错
  *         SUCCESS:读取成功
  */
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{    
	/*输出模式*/
	DHT11_Mode_Out_PP();
	/*主机拉低*/
	DHT11_Dout_0;
	/*延时18ms*/
	Delay_ms(18);

	/*总线拉高 主机延时30us*/
	DHT11_Dout_1; 

	Delay_us(30);   //延时30us

	/*主机设为输入 判断从机响应信号*/ 
	DHT11_Mode_IPU();

	/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/   
	if(DHT11_Dout_IN()==Bit_RESET)     
	{
    /*轮询直到从机发出 的80us 低电平 响应信号结束*/  
    while(DHT11_Dout_IN()==Bit_RESET);

    /*轮询直到从机发出的 80us 高电平 标置信号结束*/
    while(DHT11_Dout_IN()==Bit_SET);

    /*开始接收数据*/   
    DHT11_Data->humi_int  = DHT11_ReadByte();
    DHT11_Data->humi_deci = DHT11_ReadByte();
    DHT11_Data->temp_int  = DHT11_ReadByte();
    DHT11_Data->temp_deci = DHT11_ReadByte();
    DHT11_Data->check_sum    = DHT11_ReadByte();

    /*读取结束,引脚改为输出模式*/
    DHT11_Mode_Out_PP();
    /*主机拉高*/
    DHT11_Dout_1;

    /*检查读取的数据是否正确*/
    if(DHT11_Data->check_sum==DHT11_Data->humi_int+DHT11_Data->humi_deci+DHT11_Data->temp_int+DHT11_Data->temp_deci)
    { 
      return SUCCESS;
    }
    else 
      return ERROR;
	}	
	else
		return ERROR;
}

这个完整流程如图2所示。

1.2.5 HAL库实现

我们在串口的例子的基础上进行配置。
串口通信(HAL库)

这里只用到了PC5,因此只需要将PC5配置成输出即可。

在这里插入图片描述

图7配置GPIO

生成工程即可。

HAL库和标准库的差不多,流程都是一样的,只是使用的函数稍微不同。一个字节数据读取函数如下:

/**
  * @brief  从DHT11读取一个字节,MSB先行
  * @param  None
  * @retval byte
  */
static uint8_t DHT11_ReadByte ( void )
{
	uint8_t i, byte=0;
	
	for(i=0;i<8;i++)    
	{	 
		/*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/  
		while(DHT11_Dout_IN() == GPIO_PIN_RESET);

		/*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,
		 *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时 
		 */
		delay_us(40); //延时x us 这个延时需要大于数据0持续的时间即可	   	  

		if(DHT11_Dout_IN()==GPIO_PIN_SET)/* x us后仍为高电平表示数据“1” */
		{
			/* 等待数据1的高电平结束 */
			while(DHT11_Dout_IN()==GPIO_PIN_SET);

			byte|=(uint8_t)(0x01<<(7-i));  //把第7-i位置1,MSB先行 
		}
		else	 // x us后为低电平表示数据“0”
		{			   
			byte&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
		}
	}
	return byte;
}

完整的温湿度读取数据实现如下:

/**
  * @brief  一次完整的数据传输为40bit,高位先出
  *         8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和
  * @param  DHT11_Data:DHT11数据类型
  * @retval ERROR:  读取出错
  *         SUCCESS:读取成功
  */
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{    
	/*输出模式*/
	DHT11_Mode_Out_PP();
	/*主机拉低*/
	DHT11_Dout_0;
	/*延时18ms*/
	HAL_Delay(18);

	/*总线拉高 主机延时30us*/
	DHT11_Dout_1; 

	delay_us(30);   //延时30us

	/*主机设为输入 判断从机响应信号*/ 
	DHT11_Mode_IPU();

	/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/   
	if(DHT11_Dout_IN()==GPIO_PIN_RESET)     
	{
    /*轮询直到从机发出 的80us 低电平 响应信号结束*/  
    while(DHT11_Dout_IN()==GPIO_PIN_RESET);

    /*轮询直到从机发出的 80us 高电平 标置信号结束*/
    while(DHT11_Dout_IN()==GPIO_PIN_SET);

    /*开始接收数据*/   
    DHT11_Data->humi_int  = DHT11_ReadByte();
    DHT11_Data->humi_deci = DHT11_ReadByte();
    DHT11_Data->temp_int  = DHT11_ReadByte();
    DHT11_Data->temp_deci = DHT11_ReadByte();
    DHT11_Data->check_sum    = DHT11_ReadByte();

    /*读取结束,引脚改为输出模式*/
    DHT11_Mode_Out_PP();
    /*主机拉高*/
    DHT11_Dout_1;

    /*检查读取的数据是否正确*/
    if(DHT11_Data->check_sum==DHT11_Data->humi_int+DHT11_Data->humi_deci+DHT11_Data->temp_int+DHT11_Data->temp_deci)
    { 
      return SUCCESS;
    }
    else 
      return ERROR;
	}	
	else
		return ERROR;
}

值得注意的是,这里需要实现微秒延时,系统滴答定时器是HAL库初始化的,仅仅实现了毫秒延时,微秒延时如下:

#define CPU_FREQUENCY_MHZ    72		// STM32时钟主频
void delay_us(__IO uint32_t delay)
{
    int last, curr, val;
    int temp;

    while (delay != 0)
    {
        temp = delay > 900 ? 900 : delay;
        last = SysTick->VAL;
        curr = last - CPU_FREQUENCY_MHZ * temp;
        if (curr >= 0)
        {
            do
            {
                val = SysTick->VAL;
            }
            while ((val < last) && (val >= curr));
        }
        else
        {
            curr += CPU_FREQUENCY_MHZ * 1000;
            do
            {
                val = SysTick->VAL;
            }
            while ((val <= last) || (val > curr));
        }
        delay -= temp;
    }
}

当然还可以使用定时器来实现延时。

1.2.6实验现象

不管是使用何种库,结果都是一样的,每隔1.5s就输出温湿度。

在这里插入图片描述




代码获取方法

1.长按下面二维码,关注公众号[嵌入式实验楼]
2.在公众号回复关键词[STM32F1]获取资料
在这里插入图片描述


欢迎访问我的网站:

BruceOu的哔哩哔哩
BruceOu的主页
BruceOu的博客
BruceOu的CSDN博客
BruceOu的简书

以上是关于嵌入式温湿度传感器C语言代码求帮忙注释的主要内容,如果未能解决你的问题,请参考以下文章

C语言中如何将小数或整数和字符串合二为一

一下是c语言的一段代码,我很难理解,尤其是有关bool的,求注释解释。感谢!

将C语言代码转换成汇编语言,求帮忙,建议用反汇编软件的就不要来了,我试过,那个代码太多,不实用

c语言中的星号“*” 都有啥作用,含代码提问 求帮忙读一行程序

C语言程序编程题,求大神帮帮忙

C语言编码“注释”规范