一.介绍

该项目采用正点原子的STM32ZET6精英板+DHT11温湿度模块+泽耀科技的无线串口作为下位机,Labview+无线串口作为上位机读取下位机发来的数据并处理。

泽耀科技的产品是我在开发过程中经常用到的,他们不仅产品做的非常不错,而且资料齐全售后也非常给力,后期有技术支持,大大减少开发难度。这个项目中就用到了泽耀科技提供的STM32的驱动代码,不仅有STM32的例程,还有STM8,51,arduino的都有,主流单片机的例程几乎全覆盖,非常友好!!!


二.STM32代码讲解

无线串口型号:AS32-TTL-1W

无线串口波特率:115200

工作模式:透传模式(发送端和接收端的模块地址和信道必须相同)

这里dht11相关的就不多做赘述了,主要的问题就在与泽耀科技提供的例程中的发送数据的函数的第一个参数是发送数据的首地址,这个地方一开始没太注意,卡了好几天。所以在接收到无线串口发来的温湿度数据后不能在无线串口发送函数中处理数据。

想了解dht11的可以参考我之前的文章:(326条消息) DHT11温湿度模块入门_LJX的博客-CSDN博客

LoRa.c(选自泽耀科技例程)

#include "LoRa.h"
 
//串口发送函数
void drv_uart_tx_bytes( uint8_t* TxBuffer, uint8_t Length )
{
	while( Length-- )
	{
		while( RESET == USART_GetFlagStatus( UART_PORT, USART_FLAG_TXE ));
		UART_PORT->DR = *TxBuffer;
		TxBuffer++;
	}
}
 
//串口接收函数
uint8_t drv_uart_rx_bytes( uint8_t* RxBuffer )
{
	uint8_t l_RxLength = 0;
	uint16_t l_UartRxTimOut = 0x7FFF;
	
	while( l_UartRxTimOut-- )			
	{
		if( RESET != USART_GetFlagStatus( UART_PORT, USART_FLAG_RXNE ))
		{
			*RxBuffer = (uint8_t)UART_PORT->DR;
			RxBuffer++;
			l_RxLength++;
			l_UartRxTimOut = 0x7FFF;	
		}
		if( 100 == l_RxLength )
		{
			break;		
		}
	}
	
	return l_RxLength;					
}

DHT11.c

#include "stm32f10x.h"
#include "DHT11.h"c
#include "delay.h"
#include "stdio.h"
#include "usart.h"
#include "led.h"
#include "LoRa.h"
#include <string.h> 
 
uint16_t Rxbuff[5]={0};   //接收温湿度数据
uint8_t head[1] = {0xFF};  //帧头
uint8_t tail[1] = {0xEE};  //帧尾
 
uint8_t data2[1] = {0}; //接收到温湿度数据后进行处理
uint8_t data3[1] = {0};
uint8_t data4[1] = {0};
uint8_t data5[1] = {0};
 
void DHT11_GPIO_Init(void)   //IO输出模式
{
    GPIO_InitTypeDef  GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB,  ENABLE);
 
	GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin  =  GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed =  GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_SetBits(GPIOB,  GPIO_Pin_11);
}
 
void DHT11_GPIO_Init1(void)  //IO输入模式
{
    GPIO_InitTypeDef  GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB,  ENABLE);
 
	GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IPD;
	GPIO_InitStructure.GPIO_Pin  =  GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed =  GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_SetBits(GPIOB,  GPIO_Pin_11);
 
}
 
static uint8_t DHT11_Back()
{
   uint8_t i =200;
	
	 while(read_data && i--); //等待低电平到来
	 i= 200;
	 while(!read_data && i--); //等待高电平到来
   return 0;
}
 
void DHT11_Start(void)
{
     data0;
	 delay_ms(20);
	
     data1;
	 delay_us(10);
     DHT11_GPIO_Init1();
     while(DHT11_Back());
 
}
 
 
void DHT11_ReceptionBuff(void)
{
   uint8_t y=1;
	 uint16_t i;
	 uint8_t x;
	 LED1 = 0;
   for(x=0;x<5;x++)
	{
	    i=0;
		  for(y=1;y<9;y++)
		{
		   while(read_data)
			 {
			    __nop();
			 
			 }
			 delay_us(40);
			  while(!read_data)
			 {
			    __nop();
			 
			 }
		    i= i<<1;
			 delay_us(30);
       if(read_data)
			 {
			    i |=1;
			 
			 }
			 while(read_data);
			 
		}
	
	   Rxbuff[x] =i;
		 data2[0] = Rxbuff[0]/10 + 0x30; //处理接收到的数据并赋给要发送的数组
		 data3[0] = Rxbuff[0]%10 + 0x30;
		 data4[0] = Rxbuff[2]/10 + 0x30;
		 data5[0] = Rxbuff[2]%10 + 0x30;
	}
	
}
 
void DHT11_Check(void)  //检测DHT11是否存在
{ 
	DHT11_GPIO_Init(); //切换成发送模式
	data1;
	data0;
	delay_ms(30);
	data1;
	delay_us(60);        //在60us后读取DHT11状态,如果是低电平则模块存在
	DHT11_GPIO_Init1(); //切换成接收模式
	if(read_data == 0){
		LED0 = 0; //模块存在
	}
}	
 
 
void DHT11_UpdateData(void)
{
    DHT11_GPIO_Init();
	DHT11_Start();
	DHT11_ReceptionBuff();
	DHT11_LoRaSend();
}
 
 
 
void DHT11_LoRaSend(void)
{
 
	drv_uart_tx_bytes((uint8_t*)head,1);  //发送帧头
	drv_uart_tx_bytes((uint8_t*)data2,1); //发送湿度整数位
	drv_uart_tx_bytes((uint8_t*)data3,1);
	drv_uart_tx_bytes((uint8_t*)data4,1); //发送温度整数位
	drv_uart_tx_bytes((uint8_t*)data5,1);
	drv_uart_tx_bytes((uint8_t*)tail,1);  //发送帧尾
 
	memset(Rxbuff,'\0',5);
}

我的main函数的参考意义不大,直接在例程上改的,对于想做这个项目的小伙伴可以多借鉴DHT11.c的代码。

main.c

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "DHT11.h"
#include "LoRa.h"
 
#define __AS62_TX_MODE__	//½«ÎÞÏß´®¿ÚÉèÖÃΪ·¢ËÍģʽ.ÆÁ±ÎÔòΪ½ÓÊÕģʽ
 
#ifdef __AS62_TX_MODE__
	char *pAshining = "ashining";
#else
  uint8_t g_ashining[ 8 ] ={ 'a', 's', 'h', 'i', 'n', 'i', 'n', 'g' };
	uint8_t g_As62_rx_buffer[ 100 ] = { 0 };
	uint8_t g_RxLength = 0;
#endif
	
	
 int main(void)
{		
	initSysTick();
	usart_init();
	LED_Init();	
	delay_ms(2000);
	
	
	while(1)
	{
		DHT11_UpdateData();
		delay_ms(2000);  //小于2s数据无法传输
		
	}	 
}

三.Labview上位机

这个温湿度的上位机大概流程就是打开串口,接收数据,判断帧头帧尾和数据长度,帧头帧尾和数据长度符合设定的要求后截取字符串,转化成数字数值。

串口配置

判断数据长度 

处理数据:首先判断帧头帧尾是否和设定的一样,判断成功后把温度和湿度的数据分离开分别处理,由于数据是不断发送的(每隔两秒发送一次),所以要注意截取字符串的时候也需要动态地取截取,不然你只能收到一次数据。

调用labview中的控件,最终得到可视化数据分析。