Stm32 hal库 usart2与hc-08透传模块通讯

2023-05-16

Stm32 hal库 usart2与hc-08透传模块通讯(附数据解析)

一、stm32cubeMX配置
1、配置RCC为外部晶振
在这里插入图片描述
2、配置时钟树
在这里插入图片描述
3、配置usart1 usart2 ,其中usart1将作为打印串口使用,蓝牙透传模块将使用usart2进行通讯,配置如下。
在这里插入图片描述
usart1 不用处理接收的数据,故不用打开中断,只需配置上面即可,我们重写fgetc函数以后,就可以使用printf函数。
usart2 配置如下
在这里插入图片描述
打开usart2 中断
在这里插入图片描述
最后配置中断优先级

在这里插入图片描述
最后生成代码即可。
二、数据解析
1、usart2中断函数,在中断函数里添加这句话, HAL_UART_Receive_IT(&huart2, mReceivemBuff, BUFFER_SIZE); 再次开启中断,不然接收到指定mReceivemBuff长度的数据后,就不会开启中断了。

/**
  * @brief This function handles USART2 global interrupt.
  */
void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */

  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */
  HAL_UART_Receive_IT(&huart2, mReceiveBuff, BUFFER_SIZE);
  /* USER CODE END USART2_IRQn 1 */
}

2、中断回调函数。
以数据 B5 5B 05 01 01 01 01 00 0D BC 为例,且BUFFER_SIZE为1 ,那么发送十个字节数据,HAL_UART_RxCpltCallback函数将会回调十次,每次返回一个数据,那么我们就要对数据头 尾判断来截取我们需要的数据。


static uint16_t CRC16(uint8_t * buf, uint16_t len)
{
	uint8_t i;
	uint16_t crc = 0xffff;
 
	if (len == 0) {
		len = 1;
	}
	while (len--) {
        
		crc ^= *buf;
		for (i = 0; i<8; i++) 
		{            
			if (crc & 1) {               
				crc >>= 1;        
				crc ^= 0xA001;            
			}      
			else {               
				crc >>= 1;            
			}
			       
		}     
		buf++;
	}
	return(crc);
}
static void handlerUart2Data(uint8_t *mData, uint8_t mLen)
{
	uint8_t mLedStatusCommand[10]= {0xb5,0x5B,0x05,0x01,0x00,0x00,0x00,0x00,0x00,0x00};
	uint16_t mSendDataCrc = 0;
	uint16_t tempCrc = CRC16(mData,8);
	printf("crc==0x%x\r\n",tempCrc);
	if ((mData[0] == UART_DATA_HEAD_ONE) && (mData[1] == UART_DATA_HEAD_TWO) &&(
		(tempCrc&0x00ff)== mData[8]) && (((tempCrc>>8)&0x00ff) == mData[9]))
	{
		
		if(mData[3] == CMD_LED) 
		{
			if (mData[4] == SET_CMD)
			{
				if (mData[5] == LED_NO_1)
				{
					if (mData[6] == CMD_ON)
					{
						mainRoomLedConfigure(LED_ON);
						saveLedDataByNum(LED_NO_1,LED_ON);
					
					}else if (mData[6] == CMD_OFF)
					{
						mainRoomLedConfigure(LED_OFF);
						saveLedDataByNum(LED_NO_1,LED_OFF);
					}
				}
				else if (mData[5] == LED_NO_2)
				{
				
					if (mData[6] == CMD_ON)
					{		
						secondRoomLedConfigure(LED_ON);
						saveLedDataByNum(LED_NO_2,LED_ON);	
						printf("get  %d\r\n",getLedDataByNum(LED_NO_2));
					}else if (mData[6] == CMD_OFF)
					{
						secondRoomLedConfigure(LED_OFF);
						saveLedDataByNum(LED_NO_2,LED_OFF);
						printf("get  %d\r\n",getLedDataByNum(LED_NO_2));
					}
				}
				HAL_UART_Transmit(&huart2, mData, mLen, 1000);	
			}
			else if (mData[4] == GET_CMD){ // return all led status 
				// apk send this data === {0xb5,0x5B,0x05,0x01,0x00,0x03,0x00,0x00,0x00,0x00}
				//and stm 32 send {0xb5,0x5B,0x05,0x01,0x00,0xxx,0xxx,0xxx,0x00,0x00}
				mLedStatusCommand[7] = getLedDataByNum(LED_NO_3);
				mLedStatusCommand[6] = getLedDataByNum(LED_NO_2);
				mLedStatusCommand[5] = getLedDataByNum(LED_NO_1);
				mSendDataCrc = CRC16(mLedStatusCommand,8);
				mLedStatusCommand[9] = (mSendDataCrc >> 8);
				mLedStatusCommand[8] =  (mSendDataCrc & (0xff));
				HAL_UART_Transmit(&huart2, mLedStatusCommand, mLen, 1000);	
			}
		}
		else if(mData[3] == CMD_BEEP)
		{
			if (mData[4] == SET_CMD)
			{
				if (mData[5] == BEEP_NO_1){
				
					if (mData[6] == CMD_ON){
					
						setBeepStatus(1);
						saveBeepData(CMD_ON);
					
					}else if (mData[6] == CMD_OFF){
					
						setBeepStatus(0);
						saveBeepData(CMD_OFF);
					}
				}
				//set success and send the same data to control device
				HAL_UART_Transmit(&huart2, mData, mLen, 1000);	
			}
		}else if (mData[3] == 0x05){
		
			int value = mData[5] *7 ;
			saveLedDataByNum(LED_NO_4,mData[5]);
			__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4,value);
			HAL_UART_Transmit(&huart2, mData, mLen, 1000);	
		}
	}
	else{
		
		mData[8] = (tempCrc&0x00ff);
		mData[9] = ((tempCrc>>8)&0x00ff);
		HAL_UART_Transmit(&huart2, mData, mLen, 1000);	
	}
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	
	Uart2_Buffer[Uart2_Rx] = mReceiveBuff[0]; 
	Uart2_Rx++; 
	Uart2_Rx &= 0xFF; 
	
	if(Uart2_Buffer[Uart2_Rx-1] == 0xB5)
	{
		Uart2_head1 = Uart2_Rx-1; 
	}else if((Uart2_Rx-1 == Uart2_head1+1)&&(Uart2_Buffer[Uart2_Rx-1] == 0x5B))
	{
		Uart2_head2 = Uart2_Rx-1;
	}else if(Uart2_Rx-1 == Uart2_head2+1)
	{
    Uart2_Len = Uart2_Buffer [Uart2_Rx-1]; 
	} else if(Uart2_Rx-1 == Uart2_head1 + Uart2_Len + 4)
  {
    Uart2_temp = CRC16(Uart2_Buffer,Uart2_Len+3); 
    if(((Uart2_temp&0x00ff)==Uart2_Buffer[Uart2_head1+Uart2_Len+3])&&(((Uart2_temp>>8)&0x00ff)==Uart2_Buffer[Uart2_head1+Uart2_Len+4]))
    {
			//crc right and the data parse end and go to parse data
      Uart2_Sta = 1;  
    }
		else
		{
			//crc wrong and set contorl device the right crc value
			Uart2_Buffer[Uart2_head1+Uart2_Len+3] = Uart2_temp&0x00ff;
			Uart2_Buffer[Uart2_head1+Uart2_Len+4] = (Uart2_temp>>8)&0x00ff;
			HAL_UART_Transmit(&huart2, Uart2_Buffer, Uart2_Rx, 1000);
			Uart2_Rx = 0; 
		}	
  }
	
	if(Uart2_Sta) 
	{ 
		handlerUart2Data(Uart2_Buffer, Uart2_Rx); //parse data
		Uart2_Rx = 0; 
		Uart2_Sta = 0; 
	}
}

假如规定所有的数据都是等长的,即定义BUFFER_SIZE为10 ,发送端每次发送十个字节,那么中断回调函数每次回调一次,处理数据就简单多了。直接对mReceiveBuff处理即可。

static void handlerUart2Data(uint8_t *mData, uint8_t mLen)
{
	uint8_t mLedStatusCommand[10]= {0xb5,0x5B,0x05,0x01,0x00,0x00,0x00,0x00,0x00,0x00};
	uint16_t mSendDataCrc = 0;
	uint16_t tempCrc = CRC16(mData,8);
	printf("crc==0x%x\r\n",tempCrc);
	if ((mData[0] == UART_DATA_HEAD_ONE) && (mData[1] == UART_DATA_HEAD_TWO) &&(
		(tempCrc&0x00ff)== mData[8]) && (((tempCrc>>8)&0x00ff) == mData[9]))
	{
		
		if(mData[3] == CMD_LED) 
		{
			if (mData[4] == SET_CMD)
			{
				if (mData[5] == LED_NO_1)
				{
					if (mData[6] == CMD_ON)
					{
						mainRoomLedConfigure(LED_ON);
						saveLedDataByNum(LED_NO_1,LED_ON);
					
					}else if (mData[6] == CMD_OFF)
					{
						mainRoomLedConfigure(LED_OFF);
						saveLedDataByNum(LED_NO_1,LED_OFF);
					}
				}
				else if (mData[5] == LED_NO_2)
				{
				
					if (mData[6] == CMD_ON)
					{		
						secondRoomLedConfigure(LED_ON);
						saveLedDataByNum(LED_NO_2,LED_ON);	
						printf("get  %d\r\n",getLedDataByNum(LED_NO_2));
					}else if (mData[6] == CMD_OFF)
					{
						secondRoomLedConfigure(LED_OFF);
						saveLedDataByNum(LED_NO_2,LED_OFF);
						printf("get  %d\r\n",getLedDataByNum(LED_NO_2));
					}
				}
				HAL_UART_Transmit(&huart2, mData, mLen, 1000);	
			}
			else if (mData[4] == GET_CMD){ // return all led status 
				// apk send this data === {0xb5,0x5B,0x05,0x01,0x00,0x03,0x00,0x00,0x00,0x00}
				//and stm 32 send {0xb5,0x5B,0x05,0x01,0x00,0xxx,0xxx,0xxx,0x00,0x00}
				mLedStatusCommand[7] = getLedDataByNum(LED_NO_3);
				mLedStatusCommand[6] = getLedDataByNum(LED_NO_2);
				mLedStatusCommand[5] = getLedDataByNum(LED_NO_1);
				mSendDataCrc = CRC16(mLedStatusCommand,8);
				mLedStatusCommand[9] = (mSendDataCrc >> 8);
				mLedStatusCommand[8] =  (mSendDataCrc & (0xff));
				HAL_UART_Transmit(&huart2, mLedStatusCommand, mLen, 1000);	
			}
		}
		else if(mData[3] == CMD_BEEP)
		{
			if (mData[4] == SET_CMD)
			{
				if (mData[5] == BEEP_NO_1){
				
					if (mData[6] == CMD_ON){
					
						setBeepStatus(1);
						saveBeepData(CMD_ON);
					
					}else if (mData[6] == CMD_OFF){
					
						setBeepStatus(0);
						saveBeepData(CMD_OFF);
					}
				}
				//set success and send the same data to control device
				HAL_UART_Transmit(&huart2, mData, mLen, 1000);	
			}
		}
	}
	else{
		
		mData[8] = (tempCrc&0x00ff);
		mData[9] = ((tempCrc>>8)&0x00ff);
		HAL_UART_Transmit(&huart2, mData, mLen, 1000);	
	}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	handlerUart2Data(mReceiveBuff, BUFFER_SIZE);
	//HAL_UART_Transmit(&huart2, mReceiveBuff, BUFFER_SIZE, 1000);	
}
另外发送数据用的函数为HAL_UART_Transmit(&huart2, mReceiveBuff, BUFFER_SIZE, 1000);	

完整代码下载添加链接描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Stm32 hal库 usart2与hc-08透传模块通讯 的相关文章

  • 如何让printf在STM32F103上工作?

    我是 STM32F103 世界的新手 我有一个STM32F103的演示代码 我正在使用arm none eabi来编译它 我尝试了在谷歌上可以找到的内容 但到目前为止没有任何效果 我已经花了三天时间来解决这个问题 任何人都可以给我一个运行良
  • CMSIS 库是否应该包含在版本控制中? [复制]

    这个问题在这里已经有答案了 通常 我曾经在版本控制中包含芯片供应商 ST 提供的设备特定标头和源以及 CMSIS Core 标头 数量不多 也没有更新的习惯 我使用STM32微控制器 但我不使用立方体框架 or the 标准外设库 最近 我
  • 优化 ARM Cortex M3 代码

    我有一个 C 函数 它尝试将帧缓冲区复制到 FSMC RAM 这些函数将游戏循环的帧速率降低至 10FPS 我想知道如何分析反汇编的函数 我应该计算每个指令周期吗 我想知道CPU把时间花在哪里 在哪个部分 我确信该算法也是一个问题 因为它的
  • 138-基于stm32单片机汽车多功能仪表盘显示系统Proteus仿真+源程序

    资料编号 138 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DHT11传感器 ds1302时钟 LED灯 蜂鸣器 电位器 制作一个基于stm32单片机汽车多功能仪表盘显示系统Proteus仿真 2 通过DHT1
  • HAL库STM32常用外设教程(二)—— GPIO输入\输出

    HAL库STM32常用外设教程 二 GPIO输入 输出 文章目录 HAL库STM32常用外设教程 二 GPIO输入 输出 前言 一 GPIO功能概述 二 GPIO的HAl库驱动 三 GPIO使用示例 1 示例功能 四 代码讲解 五 总结
  • 匹配 STM32F0 和 zlib 中的 CRC32

    我正在研究运行 Linux 的计算机和 STM32F0 之间的通信链路 我想对我的数据包使用某种错误检测 并且由于 STM32F0 有 CRC32 硬件 并且我在 Linux 上有带有 CRC32 的 zlib 所以我认为在我的项目中使用
  • STM32用一个定时器执行多任务写法

    文章目录 main c include stm32f4xx h uint32 t Power check times 电量检测周期 uint32 t RFID Init Check times RFID检测周期 int main Timer
  • STM32F103

    提示 来源正点原子 参考STM32F103 战舰开发指南V1 3PDF资料 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 开发环境硬件普中科技 接线图在g
  • STM32 GPIO工作原理详解

    STM32 GPIO介绍 1 STM32引脚说明 GPIO是通用输入 输出端口的简称 是STM32可控制的引脚 GPIO的引脚与外部硬件设备连接 可实现与外部通讯 控制外部硬件或者采集外部硬件数据的功能 以STM32F103ZET6芯片为例
  • SHT10温湿度传感器——STM32驱动

    实验效果 硬件外观 接线 3 3V供电 IIC通讯 代码获取 查看下方 END
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • STM32F4XX的12位ADC采集数值超过4096&右对齐模式设置失败

    文章目录 一 前言 二 问题1 数值超过4096 三 问题1的排错过程 四 问题2 右对齐模式设置失败 五 问题2的解决方法 5 1 将ADC ExternalTrigConv设置为0 5 2 使用ADC StructInit 函数 一 前
  • for循环延时时间计算

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 之前做led点亮的实验 好像是被delay函数影响了 因为delay参数设置的不对
  • 嵌入式开发--STM32G4系列片上FLASH的读写

    这个玩意吧 说起来很简单 就是几行代码的事 但楞是折腾了我大半天时间才搞定 原因后面说 先看代码吧 读操作 读操作很简单 以32位方式读取的时候是这样的 data IO uint32 t 0x0800F000 需要注意的是 当以32位方式读
  • Cortex-M3与M4权威指南

    处理器类型 所有的ARM Cortex M 处理器是32位的精简指令集处理器 它们有 32位寄存器 32位内部数据路径 32位总线接口 除了32位数据 Cortex M处理器也可以有效地处理器8位和16位数据以及支持许多涉及64位数据的操作
  • STM32 上的位置无关代码 - 指针

    我已成功在 STM32 上构建并运行位置无关的代码 向量表和 GOT 已修补 一切正常 但我对这样的代码有问题 double myAdd double x return x 0 1 double ptrmyAdd double myAdd
  • STM32内部时钟

    我对 STM32F7 设备 意法半导体的 Cortex M7 微控制器 上的时钟系统感到困惑 参考手册没有充分阐明这些时钟之间的差异 SYSCLK HCLK FCLK 参考手册中阅读章节 gt RCC 为 Cortex 系统定时器 SysT
  • PWM DMA 到整个 GPIO

    我有一个 STM32F4 我想对一个已与掩码进行 或 运算的 GPIO 端口进行 PWM 处理 所以 也许我们想要 PWM0b00100010一段时间为 200khz 但随后 10khz 后 我们现在想要 PWM0b00010001 然后
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d
  • stm32l0: 执行MI命令失败。使用 vFlashErase 数据包擦除闪存时出错

    我正在使用 Nucleo STM32L031 和 AC6 STM32 工作台 eclipse 我编写应用程序并进入调试模式 一切正常 直到我在应用程序中添加另一个功能 我注意到当我删除 评论 新函数 软件可以再次进入调试模式 但是当我添加

随机推荐

  • VScode 中 C或C++ 结构体提示,代码补全不准确的 解决方案

    1 找到项目工作区的 settings json文件 2 修改 C Cpp intelliSenseEngine Tag Parser 为 C Cpp intelliSenseEngine Default 解释 Tag Parser 提供非
  • C/C++ 避免重复定义

    加入宏定义 第一种 xff1a span class token macro property span class token directive keyword ifndef span STUDENT H span span class
  • vscode文件标签栏显示多行

    设置步骤 xff1a 按下 ctrl 43 shift 43 p xff0c 如下图 xff1a 输入 open workspace settings xff0c 打开工作区设置 输入 workbench editor wrapTabs x
  • ::在C++中的意思

    表示作用域 xff0c 和所属关系 class A int A test 表示test是属于A类的 关于 的具体解析 xff1a 是运算符中等级最高的 xff0c 它分为三种 1 global scope 全局作用域符 xff09 xff0
  • 【Linux问题解决】操作系统用C语言多线程编程 对‘pthread_create’未定义的引用 报错解决办法

    操作系统用C语言多线程编程 对 pthread create 未定义的引用 报错解决办法 今天写操作系统作业 在Ubuntu Linux系统中用C语言编写多线程程序 在命令行进行编译 没通过编译 报错如下 xff1a In file inc
  • linux 服务器执行post请求 curl命令详解

    什么是curl xff1f curl是一个命令行访问URL的计算机逻辑语言的工具 xff0c 发出网络请求 xff0c 然后得到数据并提取出 xff0c 显示在标准输出 stdout 上面 xff0c 可以用它来构造http request
  • open-falcon 监控cpu指标及含义

    user 30512019 从系统启动开始累计到当前时刻 xff0c 用户态的CPU时间 xff0c 不包含nice值为负进程 nice 2905 从系统启动开始累计到当前时刻 xff0c nice值为负的进程所占用的CPU时间 syste
  • [Unity] 串口读取数据错误 IOException: 拒绝访问。

    错误内容 IOException 拒绝访问 System IO Ports WinSerialStream ReportIOError System String optional arg at lt 14e3453b740b4bd690e
  • px4仿真无法起飞问题(Failsafe enabled: no datalink)

    报错信息 问题描述 xff1a 使用JMAVSim和gazebo仿真px4起飞时报错如下 xff1a WARN commander Failsafe enabled no datalink 说不安全 解决方法 打开QGC 就可以起飞了
  • TCP (传输控制协议)和 UDP

    传输控制协议 xff08 TCP xff0c Transmission Control Protocol xff09 是一种面向连接的 可靠的 基于字节流的传输层通信协议 是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输
  • 全网第一篇 Jetson AGX Xaiver + Jetpack5.0.2(Ubuntu20.04) + ROS2 + ORB-SLAM3 + ZED2

    本机系统 xff1a Jetpack5 0 2 Ubuntu 20 04 LTS 注意事项 xff1a 想要避坑 xff0c 务必按照文中版本准备各种环境 一 安装软件 1 Pangolin 0 5 网址 xff1a https githu
  • java中char转化为int的几种方法

    java中char转化为int的几种方法总结 方法一 xff1a 在char后面 0 span class token keyword public span span class token keyword class span span
  • 大疆 RoboMaster 3508/2006/GM6020 电机使用教程

    19年开始使用大疆的电机 xff0c 刚开始接触有很多东西不懂 xff0c 网上除了RM官网提供的一些资料外没有很多其他的资料 xff0c 现在使用大疆电机近一年了 xff0c 想分享一下自己的经验 1 硬件部分 1 C610电调只能连接M
  • DBC文件解析及CAN通信矩阵

    一般的 DBC 文件中包含了如下的8种信息 xff1a 1 版本与新符号 2 波特率定义 3 网络节点的定义 4 报文帧的定义 5 信号的定义 6 注解部分 7 特征部分 8 数值表部分 VERSOIN 34 34 版本信息 xff0c 为
  • 基于Rplidar二维雷达使用Hector_SLAM算法在ROS中建图

    文章目录 前言一 ROS分布式通信 xff08 配置多机通信 xff09 1 简介2 步骤2 1 准备2 2 修改配置文件2 3配置主机IP2 4配置从机IP 二 RPlidar的使用教程1 创建环境2 下载激光雷达的功能包3 编译4 启动
  • TCP连接建立的步骤

    TCP连接建立的步骤 一 客户端向服务器端发送连接请求后 xff0c 就被动地等待服务器的响应 典型的TCP客户端要经过下面三步操作 xff1a 1 创建一个Socket实例 xff1a 构造函数向指定的远程主机和端口建立一个TCP连接 x
  • 能否在头文件中放置函数定义?

    语法上是可以这样做的 xff0c 但是在编程规范中并不鼓励这样做 成员函数一般是不可以在头文件中定义的 xff0c 只能在头文件中声明 因为函数只能有一次定义 xff0c 而可以有多次声明 xff0c 当头文件被多次包含的时候 xff0c
  • 万能的sprintf

    0 前言 先推荐一本书 xff0c 政治书籍 政治的人生 xff0c 算是一本日记题材 是现任 xff0c 作者大家百度一下就知道了 xff0c 这里不宜过多说明 从这本书里 xff0c 可以看出来现在的社会 这本书是30年前的 大佬就是大
  • 串口通讯UART/RS232/RS485/RS-422笔记

    串口通讯详解笔记 串口通讯概述串口通讯传输数据帧的结构UARTRS232RS485RS 422RS 232 RS 422和RS 485的主要区别 xff08 重要 xff09 串口通讯概述 串口通讯是指数据按位 xff08 bit xff0
  • Stm32 hal库 usart2与hc-08透传模块通讯

    Stm32 hal库 usart2与hc 08透传模块通讯 xff08 附数据解析 xff09 一 stm32cubeMX配置 1 配置RCC为外部晶振 2 配置时钟树 3 配置usart1 usart2 xff0c 其中usart1将作为