涂鸦模组开发(压力传感器HX711)——3. 涂鸦模组数据通信

概述

涂鸦智能 (NYSE:TUYA) 是一家致力于让生活更智能的领先技术公司,涂鸦提供能够智连万物的云平台,打造互联互通的开发标准,连接品牌、OEM 厂商、开发者、零售商和各行业的智能化需求,涂鸦的解决方案赋能并提升合作伙伴和客户的产品价值,同时通过技术应用使消费者的生活更加便利,涂鸦智能的智慧商业 SaaS 为丰富的垂直行业提供智能解决方案。涂鸦智能领先业界的技术,符合严格的数据保护标准和安全性。
压力传感器是工业实践中最为常用的一种传感器,其广泛应用于各种工业自控环境,涉及水利水电、铁路交通、智能建筑、生产自控、航空航天、军工、石化、油井、电力、船舶、机床、管道等众多行业。
同时压力传感器可以应用于电子称重系统或者久坐系统,实现了称重显示、超限报警、校准、适应各种工作环境、远程实时监控等多种功能,可以广泛应用于各种称重场景。
本章主要是配置涂鸦模组进行数据通信。

视频演示

听不到声音的请点击跳转进行观看。
https://www.bilibili.com/video/BV1vi4y1y7nL/

涂鸦模组开发(压力传感器HX711)——3. 涂鸦模组数据通信(1)

https://www.bilibili.com/video/BV1Ni4y1C7Hy/?spm_id_from=333.788

涂鸦模组开发(压力传感器HX711)——3. 涂鸦模组数据通信(2)

资料下载

https://download.csdn.net/download/qq_24312945/84796130

涂鸦智能

想更多了解涂鸦智能化开发方案,获取相关技术资料或开发物料,可点击下方报名参加,同时有30元优惠券。。
https://t.tuya.com/AY1D3R9jGr

涂鸦调试文件下载

在涂鸦平台下载资料。
在这里插入图片描述

涂鸦模块(BT3L Bluetooth 模组)与串口模块接线方式。

涂鸦模块BT3L Bluetooth 模组)串口模块
VCCVCC
RXTX
TXRX
GNDGND

打开下载的涂鸦模组调试助手,进行串口调试。
在这里插入图片描述
在这可以查看到通讯协议(基础协议)指令收发。
在这里插入图片描述

STM32CUBEMX配置读取模块信息

配置串口3读取涂鸦模块的数据。,由于涂鸦模块使用的是9600的波特率,故配置为9600。
在这里插入图片描述
配置DMA进行数据接收。
在这里插入图片描述
开启中断。
在这里插入图片描述
stm32f103与涂鸦接线方式。

开发板涂鸦模块
VCCVCC
PB10(TX)RX
PB11(RX)TX
GNDGND

读取代码配置

/* USER CODE BEGIN PV */
#define BUFFERSIZE 255           //可以接收的最大字符个数       
uint8_t ReceiveBuff[BUFFERSIZE]; //接收缓冲区
uint8_t recv_end_flag = 0,Rx_len;//接收完成中断标志,接收到字符长度
/* USER CODE END PV */

开启串口IDLE中断。

  /* USER CODE BEGIN 2 */
  __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);//使能串口3 IDLE中断 
  HAL_UART_Receive_DMA(&huart3,ReceiveBuff,BUFFERSIZE);//开启DMA接收
  /* USER CODE END 2 */

定义接收函数。

/* USER CODE BEGIN PFP */
void uart3_data(void);	
/* USER CODE END PFP */

串口DMA接收数据,然后通过串口1进行打印数据。

/* USER CODE BEGIN 4 */
void uart3_data(void)
{
	if(recv_end_flag ==1)//接收完成标志
	{
HAL_UART_Transmit(&huart1,(uint8_t*)ReceiveBuff,Rx_len,0xFFFF);	
    for(int i = 0; i < Rx_len ; i++) //清空接收缓存区
    ReceiveBuff[i]=0;//置0
    Rx_len=0;//接收数据长度清零
    recv_end_flag=0;//接收标志位清零
    //开启下一次接收
    HAL_UART_Receive_DMA(&huart3,(uint8_t*)ReceiveBuff,BUFFERSIZE);
    }
}

/* USER CODE END 4 */

#include "stm32f1xx_it.c"文件中断外部变量引用。

/* USER CODE BEGIN 0 */
#define BUFFERSIZE 255	//可接收的最大数据量
extern uint8_t recv_end_flag,Rx_len,bootfirst;
/* USER CODE END 0 */

串口3中断函数。

void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */

  /* USER CODE END USART3_IRQn 0 */
  HAL_UART_IRQHandler(&huart3);
  /* USER CODE BEGIN USART3_IRQn 1 */
	
	uint32_t temp;
	if(USART3 == huart3.Instance)//判断是否为串口3中断
	{      
		if(RESET != __HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE))//如果为串口3
		{
			__HAL_UART_CLEAR_IDLEFLAG(&huart3);//清除中断标志
      HAL_UART_DMAStop(&huart3);//停止DMA接收
			temp  = __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);//获取DMA当前还有多少未填充
			Rx_len =  BUFFERSIZE - temp; //计算串口接收到的数据个数
			recv_end_flag = 1;
			}
		}

  /* USER CODE END USART3_IRQn 1 */
}

串口打印数据实例

在这里插入图片描述

匹配心跳检测通信协议

以心跳检测为例子,当涂鸦模块发送心跳检测给MCU时候,需要MCU上报信息给涂鸦模块,同时心跳检测数据第一次发送0x00,第二次发送0x01。

在这里插入图片描述

由于心跳检测发送的数据是固定的,故需要定义2个数组用来存放。

/* USER CODE BEGIN PV */
uint8_t wifi_first =0;//第一次开启 发送00  第二次发送01
const uint8_t Buff1[8]={0x55,0xAA,0x00,0x00,0x00,0x01,0x00,0x00};//心跳检测,第1次 0x55 aa 00 00 00 01 00 03
const uint8_t Buff2[8]={0x55,0xAA,0x00,0x00,0x00,0x01,0x01,0x01};//心跳检测,第2次 0x55 aa 00 00 00 01 01 04

/* USER CODE END PV */

在之前的uart3_data()函数中添加检测代码,通过判断接收的数据来判断模块发送过来的指令。

void uart3_data(void)
{
	if(recv_end_flag ==1)//接收完成标志
	{

		HAL_UART_Transmit(&huart1,(uint8_t*)ReceiveBuff,Rx_len,0xFFFF);//向串口发送接收到的数据
		
		if(ReceiveBuff[0]==0x55&&ReceiveBuff[1]==0xAA)//判断帧头和版本
		{
			if(ReceiveBuff[3]==0x00)//判断是否为心跳检测
			{
				if(wifi_first==0)//第一次发送心跳数据
				{
					wifi_first=1;
					HAL_UART_Transmit(&huart3,(uint8_t*)Buff1,8,0xFFFF);	//心跳检测,向涂鸦模块发送
					HAL_UART_Transmit(&huart1,(uint8_t*)Buff1,8,0xFFFF);	//心跳检测,向串口发送,方便查看数据
					}				
				else
				{
					HAL_UART_Transmit(&huart3,(uint8_t*)Buff2,8,0xFFFF);	//心跳检测,向涂鸦模块发送
					HAL_UART_Transmit(&huart1,(uint8_t*)Buff2,8,0xFFFF);	//心跳检测,向串口发送,方便查看数据
					}
				}
	
			}		
			
    for(int i = 0; i < Rx_len ; i++) //清空接收缓存区
    ReceiveBuff[i]=0;//置0
    Rx_len=0;//接收数据长度清零
    recv_end_flag=0;//接收标志位清零
		//开启下一次接收
    HAL_UART_Receive_DMA(&huart3,(uint8_t*)ReceiveBuff,BUFFERSIZE);
    }
}

查看串口接收到的数据,可以看到心跳数据已经正常接收。
在这里插入图片描述

匹配查询MCU的版本号通信协议

同时可以看到,接收的数据中,夹着一个55 AA 00 E8 00 00 E7的数据。
通过查询文档,可以知道该指令是查询MCU的版本号。
在这里插入图片描述
在涂鸦模块调试助手中可以查看到该指令的通信协议。

在这里插入图片描述
由于MCU版本号为1.0.2和硬件版本号1.0.3,故需用2个数组进行存放该版本号,同时定义一个接收模块发送的查询MCU版本信息请求数组。

/* USER CODE BEGIN PV */
uint8_t mcu_version[3]={1,0,2};
uint8_t hardware_version[3]={1,0,3};
uint8_t Buff3[13]={0x55,0xAA,0x00,0xE8,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//接收模块发送的查询MCU版本信息请求
/* USER CODE END PV */

在之前的uart3_data()函数中添加检测代码,通过判断接收的数据来判断模块发送过来的指令。

void uart3_data(void)
{
	if(recv_end_flag ==1)//接收完成标志
	{

		HAL_UART_Transmit(&huart1,(uint8_t*)ReceiveBuff,Rx_len,0xFFFF);//向串口发送接收到的数据
		
		if(ReceiveBuff[0]==0x55&&ReceiveBuff[1]==0xAA)//判断帧头和版本
		{
			if(ReceiveBuff[3]==0x00)//判断是否为心跳检测
			{
				if(wifi_first==0)//第一次发送心跳数据
				{
					wifi_first=1;
					HAL_UART_Transmit(&huart3,(uint8_t*)Buff1,8,0xFFFF);	//心跳检测,向涂鸦模块发送
					HAL_UART_Transmit(&huart1,(uint8_t*)Buff1,8,0xFFFF);	//心跳检测,向串口发送,方便查看数据
					}				
				else
				{
					HAL_UART_Transmit(&huart3,(uint8_t*)Buff2,8,0xFFFF);	//心跳检测,向涂鸦模块发送
					HAL_UART_Transmit(&huart1,(uint8_t*)Buff2,8,0xFFFF);	//心跳检测,向串口发送,方便查看数据
					}
				}		
			else if(ReceiveBuff[3]==0xE8)//判断是否为接收模块发送的查询MCU版本信息请求
			{
				for(int i=0;i<3;i++)
				{
					Buff3[6+i]=mcu_version[i];//将mcu版本放入数组中
					Buff3[9+i]=hardware_version[i];//将硬件版本放入数组中				
				}
                Buff3[12]=0;
				for(int i=0;i<12;i++)//计算校验和
				{
					Buff3[12]=Buff3[12]+Buff3[i];
				
				}
					HAL_UART_Transmit(&huart3,(uint8_t*)Buff3,13,0xFFFF);	//接收模块发送的查询MCU版本信息请求,向涂鸦模块发送
					HAL_UART_Transmit(&huart1,(uint8_t*)Buff3,13,0xFFFF);	//接收模块发送的查询MCU版本信息请求,向串口发送,方便查看数据
				}
			
	
			}		
			
    for(int i = 0; i < Rx_len ; i++) //清空接收缓存区
    ReceiveBuff[i]=0;//置0
    Rx_len=0;//接收数据长度清零
    recv_end_flag=0;//接收标志位清零
		//开启下一次接收
    HAL_UART_Receive_DMA(&huart3,(uint8_t*)ReceiveBuff,BUFFERSIZE);
    }

}

查看串口接收到的数据,可以看到查询MCU版本信息请求已经发送完毕。
在这里插入图片描述

匹配查询产品信息请求通信协议

同时可以看到,接收的数据中,夹着一个55 AA 00 01 00 00 00 的数据。
通过查询文档,可以知道该指令是查询产品信息请求。
在这里插入图片描述
故需要定义pid和初始化发送的数组,后期再将pid和mcu版本号放入数组中。

char pid[]="qhaft0y9";
uint8_t mcu_version[3]={1,0,2};
uint8_t Buff4[20]={0x55,0xAA,0x00,0x01,0x00,0x0D,0x00,0x00,0x00,0x00,
									0x00,0x00,0x00,0x00,0x00,0x2E,0x00,0x2E,0x00,0x00};//接收模块发送的查询产品信息请求             
/* USER CODE END PV */

由于有时候模块会连着发几条指令过来,故需要对指令进行切割,然后逐条返回。

/* USER CODE BEGIN 4 */
void uart3_data(void)
{
	if(recv_end_flag ==1)//接收完成标志
	{
		

		HAL_UART_Transmit(&huart1,(uint8_t*)ReceiveBuff,Rx_len,0xFFFF);//向串口发送接收到的数据

		uint8_t Rx_flag=0;//接收数据的指令数
		uint8_t RX_BUFF_flag[BUFFERSIZE];
		if(Rx_len>=4)
		{
			for(int i1=0;i1<Rx_len-2;i1++)//计算指令数量
			{
				if(ReceiveBuff[i1]==0x55&&ReceiveBuff[i1+1]==0xAA)
				{
					RX_BUFF_flag[Rx_flag]=i1;//记录节点
					Rx_flag++;//指令数+1

				}		
			}

			uint8_t Tx_flag=0;//发送数据的指令数
			uint8_t RX_BUFF[BUFFERSIZE];
			
/*复制ReceiveBuff数组到RX_BUFF数组*/		
//方法1			
//			for(int i1=0;i1<255;i1++)
//				RX_BUFF[i1]=ReceiveBuff[i1];
//			
//方法2		
			memcpy(RX_BUFF,ReceiveBuff,BUFFERSIZE);
			

			while(Tx_flag<Rx_flag)
			{
				if(RX_BUFF[0]==0x55&&RX_BUFF[1]==0xAA)//判断帧头和版本
				{
//					HAL_UART_Transmit(&huart1,&RX_BUFF[3],1,0xFFFF);//向串口发送接收到的数据
					if(RX_BUFF[3]==0x00)//判断是否为心跳检测
					{
						if(wifi_first==0)//第一次发送心跳数据
						{
							wifi_first=1;
							HAL_UART_Transmit(&huart3,(uint8_t*)Buff1,8,0xFFFF);	//心跳检测,向涂鸦模块发送
							HAL_UART_Transmit(&huart1,(uint8_t*)Buff1,8,0xFFFF);	//心跳检测,向串口发送,方便查看数据
							}				
						else
						{
							HAL_UART_Transmit(&huart3,(uint8_t*)Buff2,8,0xFFFF);	//心跳检测,向涂鸦模块发送
							HAL_UART_Transmit(&huart1,(uint8_t*)Buff2,8,0xFFFF);	//心跳检测,向串口发送,方便查看数据
							}
						}
					else if(RX_BUFF[3]==0x01)//接收模块发送的查询产品信息请求            
					{
						for(int i=0;i<8;i++)//放入pid
						{
							Buff4[i+6]=pid[i];
						
						}
						//mcu版本mcu_version->1.0.2
						Buff4[14]=mcu_version[0]+0x30;
						Buff4[16]=mcu_version[1]+0x30;
						Buff4[18]=mcu_version[2]+0x30;
						
						Buff4[19]=0;//校验和清理
						for(int i=0;i<19;i++)//计算校验和
						{
							Buff4[19]=Buff4[19]+Buff4[i];
						}
						
						
						HAL_UART_Transmit(&huart3,(uint8_t*)Buff4,20,0xFFFF);	//心跳检测,向涂鸦模块发送
						HAL_UART_Transmit(&huart1,(uint8_t*)Buff4,20,0xFFFF);	//心跳检测,向涂鸦模块发送
					
					
					}			
					else if(RX_BUFF[3]==0xE8)//判断是否为接收模块发送的查询MCU版本信息请求
					{
						for(int i=0;i<3;i++)
						{
							Buff3[6+i]=mcu_version[i];//将mcu版本放入数组中
							Buff3[9+i]=hardware_version[i];//将硬件版本放入数组中				
						}
						Buff3[12]=0;
						for(int i=0;i<12;i++)//计算校验和
						{
							Buff3[12]=Buff3[12]+Buff3[i];
						
						}
							HAL_UART_Transmit(&huart3,(uint8_t*)Buff3,13,0xFFFF);	//接收模块发送的查询MCU版本信息请求,向涂鸦模块发送
							HAL_UART_Transmit(&huart1,(uint8_t*)Buff3,13,0xFFFF);	//接收模块发送的查询MCU版本信息请求,向串口发送,方便查看数据
						}
					
			
					}		
			memset(RX_BUFF, 0,BUFFERSIZE);   //清空数组          
			if(Tx_flag<Rx_flag-1)
			{
					
					//方法1
//					for(int i1=0;i1<(Rx_len-RX_BUFF_flag[Tx_flag+1]);i1++)
//						RX_BUFF[i1]=ReceiveBuff[i1+RX_BUFF_flag[Tx_flag+1]];		
			//方法2
					memcpy(RX_BUFF,ReceiveBuff+RX_BUFF_flag[Tx_flag+1],(Rx_len-RX_BUFF_flag[Tx_flag+1]));			
				}		
			Tx_flag++;		
			}		
		}
    for(int i = 0; i < Rx_len ; i++) //清空接收缓存区
    ReceiveBuff[i]=0;//置0
    Rx_len=0;//接收数据长度清零
    recv_end_flag=0;//接收标志位清零
		//开启下一次接收
    HAL_UART_Receive_DMA(&huart3,(uint8_t*)ReceiveBuff,BUFFERSIZE);
    }

}

/* USER CODE END 4 */

手机连接涂鸦

在写完涂鸦模块的通讯协议(基础协议)之后,打开手机中的涂鸦智能,点击添加设备,然后APP会自动扫描出设备。
在这里插入图片描述
或者在右边的设备中寻找到对应的设备进行添加。
在这里插入图片描述
点击进入后就可以进行设备添加。
在这里插入图片描述
选择需要添加的设备。
在这里插入图片描述
添加成功后界面如下所示。
在这里插入图片描述
添加成功后,就可以进入该传感器的实际界面。
在这里插入图片描述

最后

以上的代码会在Q群里分享。QQ群:615061293。
或者关注微信公众号『记帖』,持续更新文章和学习资料,可加作者的微信交流学习!
在这里插入图片描述

posted @ 2022-05-28 22:04  记帖  阅读(318)  评论(0编辑  收藏  举报