关于STM32串口3的使用,接收并解析一帧数据

2023-05-16

关于STM32串口3的使用,接收并解析一帧数据

当stm32的串口1被使用时,我们可以使用其他串口来使用。

步骤:

  1. 串口3定义、初始化;
  2. 串口3中断服务函数(接收的一帧数据并判断是否正确);
  3. 主函数使用;

首先,我们要将串口3初始化并加上中断:

  1. 我这里使用的是STM32F103C8T6的芯片,串口3对应的引脚是PB10、PB11
    引脚

  2. 程序如下:

/**********************************************************************************
  *函数名              :USART3_Config
  *函数功能            :USART3初始化
  *输入                :无
  *输出                :无   

*******************************************************************************/
void USART3_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;     //GPIO初始化结构体声明
USART_InitTypeDef USART_InitStructure;   //串口初始化结构体声明
NVIC_InitTypeDef    NVIC_InitStructure;  //NVIC初始化结构体声明
	

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);      //使能PB端口时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);    //USART3时钟

	
//USART3的Tx---GPIO----PA.10----复用推挽输出
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
	
//USART3的Rx---GPIO----PA.11----浮空输入
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB,&GPIO_InitStructure);
	
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;             //中断通道为USART3_IRQn
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;     //设置抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;            //设置响应优先级2 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;               //通道使能
NVIC_Init(&NVIC_InitStructure);                      //调用NVIC_Init()函数完成端口初始化
	
USART_InitStructure.USART_BaudRate=9600;             //设置波特率为9600
USART_InitStructure.USART_WordLength=USART_WordLength_8b;                      //数据位8位
USART_InitStructure.USART_StopBits=USART_StopBits_1;                           //停止位1位
USART_InitStructure.USART_Parity=USART_Parity_No;                              //无校验位
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;  //无硬件流控
USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;   //接受和发送模式都打开
USART_Init(USART3,&USART_InitStructure);	        //调用USART_Init()函数完成端口初始化

USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);      //使能接收中断

USART_Cmd(USART3,ENABLE);                           //使能串口3

}

注意:

上面程序中使能时钟函数要分开,毕竟RCC_APB2Periph_GPIOB与RCC_APB1Periph_USART3是不一样的,

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);      //使能PB端口时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);    //USART3时钟

而在串口1使能时钟时,却可以放在一起,比如:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);
//使能PA端口时钟、USART1时钟

这个一定要注意,不然程序编译是检测不出的。

接下来,我们就要码串口中断函数了

  1. 在中断函数里,我们可以接收到数据,并进行处理。我这里是用串口助手的hex来发送数据给STM32,故STM32接收到的数据是一个字节一个字节的。

下面的函数是接收到数据(一个字节),并判断帧头(0xFF)是否正确,再存放在数组data(十六进制)中,继续接收数据(一个字节)存放在数组data中,接收满四个字节就结束,重新循环判断。其中COM3_RecvFin 是接收一帧数据成功的标志,主函数可以用这个来检验是否接收成功,再进行数据处理。

void USART3_IRQHandler(void) //串口1中断服务程序
{
	u8 shujv;
	if(USART_GetFlagStatus(USART3,USART_IT_RXNE) != RESET)  //接收到数据
	{			
		shujv=USART_ReceiveData(USART3);
		
		if((shujv == 0xFF)  &&  (h == 0)){h=1; data[0]=shujv; }
		else if(h == 1){h=2; data[1]=shujv; }
		else if(h == 2){h=3; data[2]=shujv; }
		else if(h == 3){ COM3_RecvFin = 1;  h=0;data[3]=shujv; }
		else h=0;
	
		USART_ClearITPendingBit(USART3,USART_IT_RXNE);        //清除接收标志位,每次接收完成都需要清除一下
		while(USART_GetFlagStatus(USART3,USART_FLAG_TC) ==RESET);	  //用于检查串口UART1是否发送完成,完成时,TC中断标志置位,退出轮询等待!	
	}
}

上面的方法是接收到固定长度的数据,当我们不知道数据有多长,只有帧头0xFF、帧尾0xEE,应该怎么办呢?下面就是另一种方法:

如果检测数据的帧头是0xFF,就将Start_Receiving置1,到后面判断Start_Receiving,再将数据存在数组data中;检测到数据的帧尾是0xEE时就结束并将COM3_RecvFin置1。

这种方法虽然可以接收不定长度的数据,但是我们的数据(不包括帧头、帧尾)出现0xEE时,数据接收就会提前结束。

void USART3_IRQHandler(void)
{  	     
  if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET);//接收到数据		
  {
		shujv = USART_ReceiveData(USART3);			
		if(shujv==0xFF)
		{
			Start_Receiving=1;
		}
		else if(shujv == 0xEE)
		{
			COM3_RecvFin=1;
			Start_Receiving=0;
			i=0;
		}
				
		if(Start_Receiving==1)
		{
			data[i]=shujv;
			i++;
		}
		USART_ClearITPendingBit(USART3,USART_IT_RXNE);        //清除接收标志位,每次接收完成都需要清除一下
		while(USART_GetFlagStatus(USART3,USART_FLAG_TC) ==RESET);	  //用于检查串口UART1是否发送完成,完成时,TC中断标志置位,退出轮询等待!				
	}										
}

有利有弊,两种方法你会选什么呢?

最后,我们来码主函数了

主函数,我这里只是码简单的,易于理解,后期能理解的天才可以添加的其他程序,使之更完美!

int main(void)
{
	USART3_Config();                       //USART初始化函数
	while(1)                               //死循环,永为真。所以用中断函数来中断
	{
		if(COM3_RecvFin==1)               //判断到COM3_RecvFin标志为1,表示接收成功 
    	{
            COM3_RecvFin=0;                //COM3_RecvFin标志清零,防止死循环
            USART_SendData(USART3,data[1]);//发送数组data的第2个字节,这里简单发送,可以添加自己需要的程序   
        }		
	}
}

手痒的,想要试试的,记得开头添加下面的头文件、函数声明、变量定义

/*---------头文件---------*/
#include "stm32f10x.h"

/*---------函数声明---------*/
void USART3_Config(void);
void USART3_IRQHandler(void);
u8 COM3_RecvFin=0;
u8 Start_Receiving=0;
u8 i=0;
unsigned  char data[10];

有什么遗漏、错误,请在下面的评论写,一起交流交流。

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

关于STM32串口3的使用,接收并解析一帧数据 的相关文章

随机推荐

  • 将UIColor转换为RGB值

    objc view plain copy 将UIColor转换为RGB值 NSMutableArray changeUIColorToRGB UIColor color NSMutableArray RGBStrValueArr 61 NS
  • 业余时间你在做什么,你就会变成什么样的人?

    改变 xff0c 从业余时间开始 博客定位 xff1a 技术 43 思考 其余统统不要 2017 xff0c 我来了 xff01
  • Xcode9 无证书真机调试

    写在前面 公司分配了新的测试机 证书99台名额已满 所以上网找教程 学习了一下如何使用Xcode无证书进行真机调试 一 创建证书 1 运行Xcode xff0c Xcode Preference 添加账号 xff08 能在appstore下
  • CSP考试复习:第一单元 C++语言基础 1.1 程序结构

    第一单元 C 43 43 语言基础 1 1 程序结构 1 程序框架 注释 xff1a 注释有两种 xff0c 一种是 xff0c 另一种是 必须单独放置一行 xff0c 或代码所在行 的后面 xff1b 而 成对存在 xff0c 可以插入到
  • Intel Realsense T265开箱测试

    前言 xff1a 最近因为要做VIO xff0c 在实验室蹭到一个Realsense T265来用 xff0c 仅此记录下简单测试过程 xff08 官方文档写非常清楚 xff0c 建议详细阅读 xff0c 链接 xff1a https gi
  • posix thread介绍

    xfeff xfeff posix thread是 操作系统级 xff08 OS level xff09 的API规范 xff0c 主要用来定义线程及线程间同步的相关操作 xff0c 采用C语言定义 posix规范主要在unix like类
  • PX4飞控之自主起飞Takeoff控制逻辑

    本文主要以PX4飞控1 5 5版本为例 xff0c 介绍Navigator中自主起飞 xff08 Takeoff xff09 算法控制逻辑 注 xff1a mission任务中的自主起飞与此模块不同 Takeoff与导航中的其他模块类似 x
  • PX4飞控之导航及任务架构

    本文重点介绍PX4飞控的Navigator和mission控制框架和逻辑 Navigator导航部分是无人机自主飞行控制的核心所在 xff0c 其中包括自主起飞 自主降落 自主返航 自主任务以及GPS失效保护等各个部分 搞懂这个部分有助于理
  • PX4飞控之位置控制(1)整体架构

    位置控制是无人机飞控的核心算法之一 xff0c 一方面根据commander中的flag标志位和Navigator中提供的航点信息进行控制 xff08 自主模式下 xff09 xff0c 另一方面得到期望姿态角 xff08 setpoint
  • spring整合ehcache找不到org.springframework.cache.ehcache.EhCacheCacheManager的解决方案

    一般org springframework cache ehcache EhCacheCacheManager和org springframework cache ehcache EhCacheManagerFactoryBean会同时找不
  • CC3200之GPIO引脚分析

    预备知识 xff1a xff08 1 xff09 volatile关键字 xff1a volatile定义的变量一般为无需开发者自己赋值 xff0c 会自动改变的变量 在普通的程序中 xff0c 编译器都具有优化功能 xff0c 为了避免浪
  • OpenStack 之 OVS介绍

    一 概述 Open vSwitch的官方定义 xff1a Open vSwitch是一个具有工业级质量的多层虚拟交换机 通过可编程扩展 xff0c 可以实现大规模网络的自动化 xff08 配置 管理 维护 xff09 它支持现有标准管理接口
  • OVN是OVS 5倍的性能--性能测试报告

    我们已经对OVN做了许多次的性能测试 xff0c 但是缺少一个OVN和 xff08 ML2 43 OVS xff09 的性能对比测试 我和许多人一起对比了这2种后端 本文是第一部分 xff1a 控制平面的性能对比 后面会另外发文公布数据平面
  • OpenStack 中的5种分配IPv6地址的方式

    在OpenStack Pike版本中创建IPv6子网时 xff0c 有五种设置地址方式供选择 上图中这五种方式显示不全 xff0c 现将其全部展示 No options specified xff08 Default xff09 xff0c
  • STM32 | TCP通信实例分析

    1024G 嵌入式资源大放送 xff01 包括但不限于C C 43 43 单片机 Linux等 关注微信公众号 嵌入式大杂烩 xff0c 回复1024 xff0c 即可免费获取 xff01 前言 关于socket的笔记 xff0c 之前已经
  • RT-Thread和Freertos的区别?

    关注 嵌入式大杂烩 xff0c 选择 星标公众号 一起进步 xff01 Freertos是一个国外推出的一个迷你的实时操作系统内核 xff0c 开源 xff0c 功能包括 xff1a 任务管理 时间管理 信号量 消息队列 内存管理 记录功能
  • C语言 | 函数指针作为函数的参数

    1024G 嵌入式资源大放送 xff01 包括但不限于C C 43 43 单片机 Linux等 关注微信公众号 嵌入式大杂烩 xff0c 回复1024 xff0c 即可免费获取 xff01 函数指针有两种常用的用法 xff0c 一种是作为结
  • 解析I2C通信协议

    一 I2C的概念 1 I2C总线是PHLIPS公司推出的一种串行总线 xff0c I2C总线只有两根双向信号线 其中一根是数据线SDA xff0c 另一根是时钟线SCL 2 每个接到I2C总线上的器件都有唯一的地址 发送数据到总线上的称为发
  • uCOS-II任务间通信之信号量 [转载]

    uCOS II任务间通信之信号量 信号量是什么 xff1f 信号量有什么用 xff1f 信号量是可以用来表示一个或多个事件的发生 xff0c 还可以用来对共享资源的访问 uCOS II提供了5个对信号量进行操作的函数 如下所示 xff1a
  • 关于STM32串口3的使用,接收并解析一帧数据

    关于STM32串口3的使用 xff0c 接收并解析一帧数据 当stm32的串口1被使用时 xff0c 我们可以使用其他串口来使用 步骤 xff1a 串口3定义 初始化 xff1b 串口3中断服务函数 接收的一帧数据并判断是否正确 xff1b