STM32F767--->串口通信接收不定长数据的处理方法

2023-05-16

文章目录

    • 写在前面
    • 超时中断
      • 相关寄存器
        • 接收器超时寄存器(USARTx_RTOR)
    • 空闲中断
      • 整体思路
    • 附录
      • 程序代码
      • 参考

写在前面

  • 使用STM32F767有两种中断方式(超时中断空闲中断)接不定长的数据,其中超时中断要比空闲中断好用

超时中断

相关寄存器

接收器超时寄存器(USARTx_RTOR)

在这里插入图片描述

空闲中断

空闲中断:就是说每接收到一条完整的数据就会置位空闲标志位,我们只需要判断空闲标志位是否置一,就能知道是不是接收到了一条完整的数据。
用空闲中断的好处就是,对于以前我写程序通信都会在数据的后面加上尾(/n什么的),然后另一个接收的单片机通过判断数据的尾来确定是不是一条完整的数据,有了空闲中断就不需要在给数据加上尾了

整体思路

 使用STC 的HAL库在其中断服务函数USART1_IRQHandler中编写对于空闲中断触发的处理过程。
其中可以使用RXNE一个字节一个字节的获取数据,在没有数据进来的时候,进入空闲中断,这时候拿出存储的数据处理就可以了。
数据的回显使用HAL_UART_Transmit显示就好了,在有串口1连接的情况下,会直接发送至串口1

附录

程序代码

如下代码,注释部分为空闲中断实现,未注释部分使用超时中断实现

#include "sys.h"
#include "stdio.h"
#include "stm32f7xx_hal_uart.h"
#include "delay.h"
#include "uart_drv.h"
#include "string.h"

#if 1                                       //这一部分是正点原子的防止串口发送卡死的情况出现
#pragma import(__use_no_semihosting)        //
struct __FILE 
{   
    int handle; 
}; 

FILE __stdout;                              
void _sys_exit(int x) 
{ 
    x = x; 
} 

int fputc(int ch, FILE *f)                  //
{
    while((USART1->ISR&0X40)==0);           //
    USART1->TDR=(u8)ch;
    return ch;
}
#endif 

u8  bUsartRxBuf[USART_REC_LEN];             //数据接收缓冲区
u16 wUsartRxSta=0;                          //数据接收标志位
                                            //bit15     接收完成
                                            //bit14     接收完1个字节
                                            //bit13~0   数据长度

u16 wUartRxCounter=0;                       //长度计数
u8  bRxBuffer[RXBUFFERSIZE];                //HAL库使用的窗口接收缓冲区
UART_HandleTypeDef UART1_Handler;           //UART句柄

/**
  * @brief 串口初始化函数
  * @param bound(波特率)
  * @retval null
  */
void uart_init(u32 bound)
{
    UART1_Handler.Instance          =   USART1;
    UART1_Handler.Init.BaudRate     =   bound;
    UART1_Handler.Init.WordLength   =   UART_WORDLENGTH_8B;
    UART1_Handler.Init.StopBits     =   UART_STOPBITS_1;
    UART1_Handler.Init.Parity       =   UART_PARITY_NONE;
    UART1_Handler.Init.HwFlowCtl    =   UART_HWCONTROL_NONE;    //无硬件流控制
    UART1_Handler.Init.Mode         =   UART_MODE_TX_RX;        //读写模式
    HAL_UART_Init(&UART1_Handler);

//    delay_ms(1);                                                //这部分代码防止空闲中断打开就置1的情况发生
//    while ((__HAL_UART_GET_FLAG(&UART1_Handler, UART_FLAG_IDLE) != RESET))
//    {
//        __HAL_UART_CLEAR_IT(&UART1_Handler, UART_FLAG_IDLE);
//    }
    __HAL_UART_ENABLE_IT(&UART1_Handler, UART_IT_RXNE);
//    __HAL_UART_ENABLE_IT(&UART1_Handler, UART_IT_IDLE);         //打开空闲中断
    
    SET_BIT(UART1_Handler.Instance->CR2,USART_CR2_RTOEN);       //使用超时接收功能
    SET_BIT(UART1_Handler.Instance->CR1,USART_CR1_RTOIE);       //使用超时接收中断
    WRITE_REG(UART1_Handler.Instance->RTOR,22);                 //向寄存器填入需要超时的长度,单位为波特长度,2个字节*11波特长度=22
}

/**
  * @brief UART底层配置,引脚配置,中断配置
  * @param huart:串口句柄
  * @retval null
  */
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    GPIO_InitTypeDef GPIO_Initure = {0};

    if (huart->Instance == USART1)                              //如果是串口1 进行串口1MSP初始化
    {
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_USART1_CLK_ENABLE();

        GPIO_Initure.Pin        =   GPIO_PIN_9;
        GPIO_Initure.Mode       =   GPIO_MODE_AF_PP;
        GPIO_Initure.Pull       =   GPIO_PULLUP;
        GPIO_Initure.Speed      =   GPIO_SPEED_FAST;
        GPIO_Initure.Alternate  =   GPIO_AF7_USART1;
        HAL_GPIO_Init(GPIOA, &GPIO_Initure);

        GPIO_Initure.Pin = GPIO_PIN_10;
        HAL_GPIO_Init(GPIOA, &GPIO_Initure);
        
    #if EN_USART1_RX
        HAL_NVIC_EnableIRQ(USART1_IRQn);                        //使能中断通道
        HAL_NVIC_SetPriority(USART1_IRQn, 3, 3);                //设置优先级
    #endif
    }
}

void USART1_IRQHandler(void)
{ 
    uint32_t isrflags   = READ_REG(UART1_Handler.Instance->ISR);
    uint32_t cr1its     = READ_REG(UART1_Handler.Instance->CR1);
    uint32_t cr3its     = READ_REG(UART1_Handler.Instance->CR3);

    if (((isrflags & USART_ISR_ORE) != RESET) &&
        (((cr1its & USART_CR1_RXNEIE) != RESET) || ((cr3its & USART_CR3_EIE) != RESET)))
    {
        __HAL_UART_CLEAR_IT(&UART1_Handler, UART_CLEAR_OREF);
    }
    
    if ((__HAL_UART_GET_FLAG(&UART1_Handler, UART_FLAG_RXNE) != RESET))
    {
        if (wUsartRxSta == 0x0000)                                       //接收到1帧中的1个字节
        {
            wUsartRxSta = 0x4000;
            wUartRxCounter = 0;
            memset(bUsartRxBuf,0,sizeof(bUsartRxBuf));
            bUsartRxBuf[wUartRxCounter] = (uint8_t)(UART1_Handler.Instance->RDR & (uint8_t)0x00FF);
            wUartRxCounter++;
        }
        else if (wUsartRxSta == 0x4000)                                  //接收1帧中除第一个字节外的字节
        {
            bUsartRxBuf[wUartRxCounter] = (uint8_t)(UART1_Handler.Instance->RDR & (uint8_t)0x00FF);
            wUartRxCounter++;
        }
    }

//    if ((__HAL_UART_GET_FLAG(&UART1_Handler, UART_FLAG_IDLE) != RESET))  //进入空闲中断
//    {
//        __HAL_UART_CLEAR_IT(&UART1_Handler, UART_FLAG_IDLE);
//        if (wUartRxCounter > 0)
//        {
//            wUsartRxSta |= 0x8000;                                       //将状态置位接收完成状态,在处理完数据后,将该状态再重置
//        }
//    }
    
    if (READ_BIT(UART1_Handler.Instance->ISR,USART_ISR_RTOF))              //进入超时中断
    {
        SET_BIT(UART1_Handler.Instance->ICR,USART_ICR_RTOCF);              //超时中断清零
        if (wUartRxCounter > 0)
        {
            wUsartRxSta |= 0x8000;                                         
        }
    }
} 

参考

【超时中断参考】

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

STM32F767--->串口通信接收不定长数据的处理方法 的相关文章

  • vector的内存释放

    xff11 vector内存分配机制 C 43 43 中vector的一个特点是 xff1a 内存空间只会增长 xff0c 不会减小 即为了支持快速的随机访问 xff0c vector容器的元素以连续方式存放 xff0c 每一个元素都挨着前
  • MFC多人在线聊天室

    我已经在我的资源里上传了这个聊天室的代码了 基于MFC的C 43 43 的select模型的TCP聊天室 采用select网络模型 xff0c 支持多人同时登陆 xff0c 功能有上线 下线 群聊 私聊 使用CjsonObject进行数据传
  • linux---进程间通信(ipc)之共享内存

    前面我们讲解了进程间通信之管道 xff0c 这段我们讲解我们的共享内存 共享内存是所有进程间通信方式最快的一种 内存共享模型就像下面的图一样 xff0c 就是将物理内存映射到我们进程的虚拟地址上 xff0c 我们就可以直接操作我们虚拟地址空
  • Effective C++总结

    explicit关键字 C 43 43 中的explicit关键字只能用于修饰只有一个参数或者是其他参数有默认值的类构造函数 它的作用是表明该构造函数是显式的 而非隐式的 跟它相对应的另一个关键字是implicit 意思是隐藏的 类构造函数
  • 计算机网络(5)TCP之重传机制

    重传机制 超时重传数据包丢失确认应答丢失 快速重传SACKD SACK例一 ACK 丢包例2 xff1a 网络延时 TCP 是通过序列号 确认应答 重发控制 连接管理以及窗口控制等机制实现可靠性传输的 TCP 实现可靠传输的方式之一 xff
  • 中断与回调

    1 xff0c 回调函数 回调函数的原理是使用函数指针实现类似 软中断 的概念 比如在上层的两个函数A和B xff0c 把自己的函数指针传给了C xff0c C通过调用A和B的函数指针达到 当做了什么 xff0c 通知上层来调用A或者B 的
  • CUDA 程序的优化(3) 任务划分

    4 3 1任务划分原则 首先 xff0c 需要将要处理的任务划分为几个连续的步骤 xff0c 并将其划分为CPU端程序和GPU端程序 划分时需要考虑的原则有 列出每个步骤的所有可以选择的算法 xff0c 并比较不同算法在效率和计算复杂度上的
  • C++ Matlab混合编程时“函数或变量 ‘matlabrc‘ 无法识别”

    在QT中调用Matlab初始化时 xff0c 出现了 函数或变量 matlabrc 无法识别 的情况 xff0c 接着崩溃 而且比较神奇的是 xff0c 前一次是可以初始化的 xff0c 但运行过程中发生了崩溃 直接搜解决办法 xff0c
  • Notepad++全选一整列的靠谱办法

    遇到行数较少的可以直接按住ALT手动选取 xff0c 但遇到行数较多 xff0c 就得这么干 xff1a 鼠标放在第一行某一列 xff0c 按住Alt 43 Shift xff0c 然后鼠标选择最后一行该列 xff0c 输入内容即可 xff
  • 对象转xml格式工具类

    import com ruiyun gui store haikang haikang bean FCSearchDescription import com ruiyun gui store haikang haikang bean FD
  • 【无标题】MQ静态图片获取

    public void getImageV40 String path Integer buildingProjectId HttpServletResponse response JSONObject param 61 new JSONO
  • 数据加解密时Base64异常:Illegal base64 character 3a

    现象 用base64工具类对中文进行处理时出现异常 xff0c 在数据加解密场景中经常使用 java lang IllegalArgumentException Illegal base64 character 3a at java uti
  • Winsock编程实例---TCP&UDP

    0x1 基于TCP的通信 1 服务端 1 1 创建基本流程 创建一个TCP服务端的程序需要调用的函数流程 xff1a 初始化函数库 gt gt WSAStartup 创建套接字 gt gt socket 绑定套接字 gt gt bind 监
  • 数据结构---选择排序(直接选择排序和堆排序图解)

    选择排序思想 xff1a 每一次从待排序的数据元素中选出最小 xff08 或最大 xff09 的一个元素 xff0c 存放在序列的起始位置 xff0c 直到全部待排序的 数据元素排完 直接选择排序 在元素集合array i array n
  • Java HttpUtils类

    Java HttpUtils类 Java HttpUtils类 定义 Public class HttpUtils 收集HTTP Servlet使用的静态的有效方法 方法 1 getRequestURL public static Stri

随机推荐

  • Ubuntu打造家用NAS三——网盘与影视中心

    Ubuntu打造家用NAS三 网盘与影视中心 一 Ubuntu 挂载硬盘 通过 Putty 连接 NAS查看硬盘位置 xff1a sudo fdisk l找到需要挂载的硬盘 xff0c 我的是 Disk dev sdb xff1a xxx
  • Ardupilot笔记:Rover auto模式下的执行流程

    先从mode auto cpp的update 开始分析 流程如图 xff1a 进入函数update 后会执行函数navigate to waypoint mode auto cpp span class token keyword void
  • 串口通信协议 UART+I2C+SPI

    UART 异步 串行 全双工 I2C SPI 不同通信协议比较 UART UART协议详解 UART通信 xff0c 接收与发送 xff08 详细版 xff0c 附代码 xff09 UART串行通信详解 待整理 UART是Universal
  • c语言---宏

    宏 1 仅仅替换 2 不能定义宏参类型 3 不会检查宏参有没有定义 定义带参数的宏 define JH a b t t 61 a a 61 b b 61 t xff0c 对两个参数a b的值进行交换 xff0c 下列表述中正确的是 xff0
  • Ros安装rosdep update出错,解决办法(从根本入手)

    博主作为一个ros刚入门的新手 xff0c 之前也安装过ros ros2但是在Ros安装在进行rosdep update 时运气与网络是成功的关键 xff0c 在尝试了好多次 xff0c 运气好一次就成功了 xff0c 运气不好得不停的试错
  • vscode使用方法

    01 ctrl 43 u 返回上一个光标焦点 02 发送请求插件 到VSCode插件中搜索REST Client 搜索到 xff0c 点击install进行安装 创建一个 http文件 编写测试接口文件 右键选择 发送请求 xff0c 测试
  • 自主飞行无人机开发--SALM cartographer开源框架 rplidar A2/3

    参考学习网站 xff1a https google cartographer ros readthedocs io en latest 问题提出 xff1a 四旋翼搭载激光雷达A3进行SLAM室内定位 xff0c 其怎样Running Ca
  • C#串口通信中的奇偶性校验、CRC校验函数

    一般来说 xff0c 通信协议中的通用数据格式是 包头 43 指令码 43 数据长度 43 有效数据 43 校验码 43 包尾 其中 xff0c 校验方式有多种 xff0c 最流行的是CRC校验方式 xff0c 其次是简单的奇偶性校验 校验
  • 测试软件安装步骤

    目录 Ja 目录 Java安装 jdk下载 jdk环境配置 phpstudy安装 禅道的安装 xampp安装 postman安装 requests parameterized jmeter安装 JVM监控 Locust SecureCRT软
  • linux---进程信号

    进程的功能以及概念信号的生命周期以及相关的接口自定义信号的捕捉流程信号集以及阻塞信号集了解一个SIGCHLD信号 信号的功能以及概念 信号的功能 xff1a 信号就是通知我们某一个事件的发生 信号的概念 xff1a 信号就是一个软件中断 x
  • 双目立体视觉:四(双目标定matlab,图像校正,图像匹配,计算视差,disparity详解,)

    二郎也比较忙 xff0c 在某大场工作 xff0c 有时候没有时间回复 如果希望二郎尽快帮忙 xff0c 可以将代码 xff0c 数据和问题发给二郎 xff0c 谢谢大家理解 glwang20 64 mails jlu edu cn 不过还
  • conda解决 An HTTP error occurred when trying to retrieve this URL.问题

    遇到 xff1a Collecting package metadata current repodata json failed CondaHTTPError HTTP 000 CONNECTION FAILED for url lt h
  • ubuntu20.04 安装 WPS 2019

    ubuntu自带的文字处理软件对来自windows下office或在WPS创建的ppt有点不兼容 xff0c 看到WPS有linux版本的 xff0c 便果断安装试一试 一 卸载原生liboffice sudo apt get remove
  • 制作ubuntu系统的 usb启动盘

    前言 由于课程的要求 xff0c 要尝试完成 编译安装Linux系统的内核 xff0c 但是在编译内核的过程中 xff0c Ubuntu的grub引导好像出了一些问题 xff0c 不能进入系统了 所以就要制作一个usb启动盘 xff0c 看
  • 项目用到的开源库>http-parser(一个HTTP消息解析器)

    http parser 定义 xff1a 一个用C编写的HTTP消息解析器 xff0c 可以解析请求和响应 优点 xff1a 不会进行任何系统调用及内存分配 xff0c 它不会缓冲数据 xff0c 它可以被随时中断 根据你的体系结构 xff
  • 项目优化>C++,concurrentqueue(高性能并发队列)

    项目中的数据队列基于轮询和selep的实时性及CUP性能差 xff0c 需要进行优化 xff0c 尝试使用concurrentqueue进行优化 网上有一些资料介绍 可供参考 使用后的个人理解 一个线程安全的queue xff0c 并且co
  • shell>sed (对文件的内容进行替换)

    在生产环境中经常会遇到对配置文件的修改 xff0c 那写成一个脚本 xff0c 传个参数修改配置文件不就方便多了吗 对一个文件的操作那我暂且分为增删改查了 写在前面 i 这个参数很重要 xff0c 若需要更改源文件 xff0c 请配合 i参
  • Linux>软链接的作用与使用

    软链接 xff1a 为某一个文件在另外一个位置建立一个同不的链接 类似于Windows下的快捷方式 好处 xff1a 仅仅是个链接 xff0c 不占用空间 xff0c 使用还是照常使用 实际生产环境中 xff0c 使用第三方的工具 xff0
  • WPF--->自定义控件中添加按钮,TextBox添加Button为例

    span class token tag span class token tag span class token punctuation lt span Style span span class token attr name spa
  • STM32F767--->串口通信接收不定长数据的处理方法

    文章目录 写在前面超时中断相关寄存器接收器超时寄存器 USARTx RTOR 空闲中断整体思路 附录程序代码参考 写在前面 使用STM32F767有两种中断方式 超时中断和空闲中断 接不定长的数据 xff0c 其中超时中断要比空闲中断好用