STM32和国民技术(N32)单片机串口中断接收数据及数据解析

news2025/1/14 1:14:41
一、串口配置

根据单片机不同,串口IO口配置也不同,像STM32单片机,RX脚可以配置为复用输出,也可以配置为浮空输入模式。但是国民技术单片机(N32)的RX是不能配置为复用输出模式的,这样是收不到数据的,只能配置为浮空输入模式。其他的单片机情况也不一样。使用时候需要注意。

STM32单片机串口接收中断配置代码如下:

 void uart_init(u32 bound)
{
  GPIO_InitTypeDef GPIO_Initstructure;
	USART_InitTypeDef USART_Initstructure;
	NVIC_InitTypeDef NVIC_Initstrcuture;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE );
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA ,ENABLE );
	
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
	
  GPIO_Initstructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_Initstructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_Initstructure.GPIO_OType = GPIO_OType_PP;
	GPIO_Initstructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_Initstructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(GPIOA,&GPIO_Initstructure);
	GPIO_Initstructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_Initstructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_Initstructure.GPIO_OType = GPIO_OType_PP;
	GPIO_Initstructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_Initstructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(GPIOA,&GPIO_Initstructure);
	
	USART_Initstructure.USART_BaudRate = bound;
	USART_Initstructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_Initstructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Initstructure.USART_Parity = USART_Parity_No;
	USART_Initstructure.USART_StopBits = USART_StopBits_1;
	USART_Initstructure.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1,&USART_Initstructure);
	
	NVIC_Initstrcuture.NVIC_IRQChannel = USART1_IRQn;
	NVIC_Initstrcuture.NVIC_IRQChannelPreemptionPriority=3;
	NVIC_Initstrcuture.NVIC_IRQChannelSubPriority =3;		
	NVIC_Initstrcuture.NVIC_IRQChannelCmd = ENABLE;		
	NVIC_Init(&NVIC_Initstrcuture);	
	
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);	//串口接收中断
	//USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);	//串口空闲中断
  USART_Cmd(USART1, ENABLE);
}

N32单片机串口接收中断配置如下:

   void Uart_Init(u32 band)
   {
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA|RCC_APB2_PERIPH_AFIO,ENABLE);
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1,ENABLE);
    GPIO_InitType GPIO_InitStructure;
	USART_InitType USART_InitStructure;
	NVIC_InitType NVIC_InitStructure;
	
     GPIO_InitStructure.Pin  = GPIO_PIN_10;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
     GPIO_InitPeripheral(UART_GPIO_INIT, &GPIO_InitStructure);
	
	 GPIO_InitStructure.Pin = GPIO_PIN_9;
	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	 GPIO_InitPeripheral(USART1, &GPIO_InitStructure);
  
   USART_InitStructure.BaudRate = band;
	 USART_InitStructure.Parity = USART_PE_NO;
	 USART_InitStructure.StopBits = USART_STPB_1;
	 USART_InitStructure.WordLength = USART_WL_8B;
	 USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
	 USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
	
	 USART_Init(USART1, &USART_InitStructure);
   
    NVIC_InitStructure.NVIC_IRQChannel                   = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
  
    USART_ConfigInt(USART1, USART_INT_RXDNE, ENABLE);
	
	 USART_Enable(USART1, ENABLE);
	}

这个中断就是串口缓冲区有数据时候就会产生中断,也就是接收到一个字节就中断一次。如果是那种数据量很大且需要持续发的情况可以选择使用DMA结合串口空闲中断使用比较方便。串口空闲中断就是发完一整包数据才进行中断。

二、串口中断解析

以0x12 ,0x13 0x0a 0x01 0x02 0x03,0x04,0x05,0xab,0xac这帧简单数据为例子讲解。
前两个字节为头和功能码
第三个字节为总长度
最后两个字节为尾
没有校验

volatile u32 Buff_Num; //全局变量
u32 Buff_Len;
//正取写法
void USART1_IRQHandler(void)
{
    if(USART_GetIntStatus(USART1,USART_INT_RXDNE))
   {
      Rece_Buff[Buff_Num++] =USART_ReceiveData(USART1);
      USART_ClrIntPendingBit(USART1,USART_INT_RXDNE); //先取数据后清标准正确写法
          
      if(Buff_Num ==1)       
      {
         if(Rece_Buff[0]!=0xfe)
         {
            Buff_Num=0;
         }
      }
      else if(Buff_Num ==2)
      {
         if(Rece_Buff[1]!=0x54)
         {
            Buff_Num=0;
         }
      }  //逐一字节对齐正确写法
      else if(Buff_Num ==3)
      {
        Buff_Len = Rece_Buff[2];
      }
      else
      {
        if(Buff_Num==Buff_Len)
         { 
            Buff_Num=0;
            if(Rece_Buff[Buff_Len-2]==0xab&&Rece_Buff[Buff_Len-1]==0xac)
            {
             //取出数据使用
            }
            else
            {
              //尾不对
            }
        }
     }
  }
}

//错误写法
void USART1_IRQHandler(void)
{
    if(USART_GetIntStatus(USART1,USART_INT_RXDNE))
   { 
      USART_ClrIntPendingBit(USART1,USART_INT_RXDNE);
      Rece_Buff[Buff_Num++] =USART_ReceiveData(USART1); //先清标志后取数据错误写法
       
      if(Buff_Num ==2)       
      {
         if(Rece_Buff[0]!=0xfe&&Rece_Buff[1]!=0x54)
         {
            Buff_Num=0;
         }
      }  //不逐一字节进行对齐错误写法
      
      else if(Buff_Num ==3)
      {
        Buff_Len = Rece_Buff[2];
      }
      else
      {
        if(Buff_Num==Buff_Len)
         { 
            Buff_Num=0;
            if(Rece_Buff[Buff_Len-2]==0xab&&Rece_Buff[Buff_Len-1]==0xac)
            {
             //取出数据使用
            }
            else
            {
              //尾不对
            }
        }
     }
  }
}

串口接收中断和数据解析需要注意两个问题:

1.应该先取数据后清标志。

如果先清标志位,在取数据。会出现,数据还没有取出来就告诉单片机我数据已经取出来,然后下一个数据过来了,而寄存器上一个数据还在,没有读出去无法接收下一个数据就会导致触发溢出中断。如果没有清除溢出中断标志位,会一直触发溢出中断卡在中断出不去。
这就好比,碗里成满饭,还没开始吃,就告诉盛饭的人你的碗空了,那下一碗饭过来,碗装不下就会溢出。但是先取数据再清标志位就是碗里有饭,先吃完饭再告诉盛饭的人碗空了,那下一碗饭来才能正常装。

2.数据从头对齐时候必须一个一个字节进行对齐

我平时习惯那种错误写法,头两个字节一起去对,这样只有没有其他数据,或者刚好数据长度是对的时候才能对齐。有其他数据包或者长度不对的时候,除了第一包可以对齐,后面永远对不齐。就不能正常接收数据包了。

三,需要接收多包数据并解析

只需要在判断头那里或上其他的头就可以。
例如:
1 . 接收0xa1 0xa2为头的数据包。
2 . 接收0xb1 0xb2为头的数据包。
3 . 接收0xc1 0xc2为头的数据包。

//中断接收多包数据
void USART1_IRQHandler(void)
{
    if(USART_GetIntStatus(USART1,USART_INT_RXDNE))
   {
      Rece_Buff[Buff_Num++] =USART_ReceiveData(USART1);
      USART_ClrIntPendingBit(USART1,USART_INT_RXDNE); //先取数据后清标准正确写法
          
      if(Buff_Num ==1)       
      {
         if(Rece_Buff[0]!=0xa1||Rece_Buff[0]!=0xb1||Rece_Buff[0]!=0xc1)
         {
            Buff_Num=0;
         }
      }
      else if(Buff_Num ==2)
      {
         if(Rece_Buff[1]!=0xa2||Rece_Buff[1]!=0xb2||Rece_Buff[1]!=0xc2)
         {
            Buff_Num=0;
         }
      }  //正确写法
      else if(Buff_Num ==3)
      {
        Buff_Len = Rece_Buff[2];  //各包长度不一样这里会取
      }
      else
      {
        if(Buff_Num==Buff_Len)
         { 
            Buff_Num=0;
            if(Rece_Buff[Buff_Len-2]==0xab&&Rece_Buff[Buff_Len-1]==0xac)
            {
             //取出数据使用
            }
            else
            {
              //尾不对
            }
        }
     }
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2276230.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unreal Engine 5 (UE5) Metahuman 的头部材质

在图中,你展示了 Unreal Engine 5 (UE5) Metahuman 的头部材质部分,列出了头部材质的多个元素。以下是对每个部分的解释: 材质解释 Element 0 - MI_HeadSynthesized_Baked 作用: 这是 Metahuman 的主要头部材质,控制整…

《自动驾驶与机器人中的SLAM技术》ch7:基于 ESKF 的松耦合 LIO 系统

目录 基于 ESKF 的松耦合 LIO 系统 1 坐标系说明 2 松耦合 LIO 系统的运动和观测方程 3 松耦合 LIO 系统的数据准备 3.1 CloudConvert 类 3.2 MessageSync 类 4 松耦合 LIO 系统的主要流程 4.1 IMU 静止初始化 4.2 ESKF 之 运动过程——使用 IMU 预测 4.3 使用 IMU 预测位姿进…

SQL从入门到实战-2

高级语句 窗口函数 排序窗口函数 例题二十九 select yr,party,votes, rank() over (PARTITION BY yr ORDER BY votes desc) as pson from ge where constituency S14000021 order by party,yr 偏移分析函数 例题三十 select name,date_format(whn,%Y-%m-%d) data, confi…

Spring Security单点登录

本文介绍了Spring Security单点登录的概念和基本原理。单点登录是指用户只需登录一次,即可在多个相互信任的系统中实现无缝访问和授权。通过Spring Security框架的支持,可以实现有效的用户管理和权限控制。最后,本文提供了实际应用案例&#…

LKT4304新一代算法移植加密芯片,守护物联网设备和云服务安全

凌科芯安作为一家在加密芯片领域深耕18年的企业,主推的LKT4304系列加密芯片集成了身份认证、算法下载、数据保护和完整性校验等多方面安全防护功能,可以为客户的产品提供一站式解决方案,并且在调试和使用过程提供全程技术支持,针对…

浅谈云计算04 | 云基础设施机制

探秘云基础设施机制:云计算的基石 一、云基础设施 —— 云计算的根基![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/1fb7ff493d3c4a1a87f539742a4f57a5.png)二、核心机制之网络:连接云的桥梁(一)虚拟网络边界&#xff…

Qt C++读写NFC标签NDEF网址URI

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.1d292c1biFgjSs&ftt&id615391857885 #include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> #include "QLibrary" …

Java 如何传参xml调用接口获取数据

传参和返参的效果图如下&#xff1a; 传参&#xff1a; 返参&#xff1a; 代码实现&#xff1a; 1、最外层类 /*** 外层DATA类*/ XmlRootElement(name "DATA") public class PointsXmlData {private int rltFlag;private int failType;private String failMemo;p…

2024年度漏洞态势分析报告,需要访问自取即可!(PDF版本)

2024年度漏洞态势分析报告&#xff0c;需要访问自取即可!(PDF版本),大家有什么好的也可以发一下看看

不同音频振幅dBFS计算方法

1. 振幅的基本概念 振幅是描述音频信号强度的一个重要参数。它通常表示为信号的幅度值&#xff0c;幅度越大&#xff0c;声音听起来就越响。为了更好地理解和处理音频信号&#xff0c;通常会将振幅转换为分贝&#xff08;dB&#xff09;单位。分贝是一个对数单位&#xff0c;能…

Nginx反向代理请求头有下划线_导致丢失问题处理

后端发来消息说前端已经发了但是后端没收到请求。 发现是下划线的都没收到&#xff0c;搜索之后发现nginx默认request的header中包含’_’时&#xff0c;会自动忽略掉。 解决方法是&#xff1a;在nginx里的nginx.conf配置文件中的http部分中添加如下配置&#xff1a; unders…

C语言程序环境和预处理详解

本章重点&#xff1a; 程序的翻译环境 程序的执行环境 详解&#xff1a;C语言程序的编译链接 预定义符号介绍 预处理指令 #define 宏和函数的对比 预处理操作符#和##的介绍 命令定义 预处理指令 #include 预处理指令 #undef 条件编译 程序的翻译环境和执行环…

计算机组成原理(1)

系统概述 计算机硬件基本组成早期冯诺依曼机现代计算机 计算机各部分工作原理主存储器运算器控制器计算机工作过程 此文章的图片资源获取来自于王道考研 计算机硬件基本组成 早期冯诺依曼机 存储程序是指将指令以二进制的形式事先输入到计算机的主存储器&#xff0c;然后按照…

基于element UI el-dropdown打造表格操作列的“更多⌵”上下文关联菜单

<template><div :class"$options.name"><el-table :data"tableData"><el-table-column type"index" label"序号" width"60" /><!-- 主要列 BEGIN---------------------------------------- --&g…

Oracle 表分区简介

目录 一. 前置知识1.1 什么是表分区1.2 表分区的优势1.3 表分区的使用条件 二. 表分区的方法2.1 范围分区&#xff08;Range Partitioning&#xff09;2.2 列表分区&#xff08;List Partitioning&#xff09;2.3 哈希分区&#xff08;Hash Partitioning&#xff09;2.4 复合分…

罗永浩再创业,这次盯上了 AI?

罗永浩&#xff0c;1972年7月9日生于中国延边朝鲜族自治州的一个军人家庭&#xff0c;是一名朝鲜族人&#xff1b;早年在新东方授课&#xff0c;2004年当选 “网络十大红人” &#xff1b;2006年8月1日&#xff0c;罗永浩创办牛博网&#xff1b;2008年5月&#xff0c;罗永浩注册…

自然语言处理基础:全面概述

自然语言处理基础&#xff1a;全面概述 什么是NLP及其重要性、NLP的核心组件、NLU与NLG、NLU与NLG的集成、NLP的挑战以及NLP的未来 自然语言处理&#xff08;NLP&#xff09;是人工智能&#xff08;AI&#xff09;中最引人入胜且具有影响力的领域之一。它驱动着我们日常使用的…

WPF系列八:图形控件Path

简介 Path控件支持一种称为路径迷你语言&#xff08;Path Mini-Language&#xff09;的紧凑字符串格式&#xff0c;用于描述复杂的几何图形。这种语言通过一系列命令字母和坐标来定义路径上的点和线段&#xff0c;最终绘制出想要的图形。 绘制任意形状&#xff1a;可以用来绘…

计算机图形学【绘制立方体和正六边形】

工具介绍 OpenGL&#xff1a;一个跨语言的图形API&#xff0c;用于渲染2D和3D图形。它提供了绘制图形所需的底层功能。 GLUT&#xff1a;OpenGL的一个工具库&#xff0c;简化了窗口创建、输入处理和其他与图形环境相关的任务。 使用的函数 1. glClear(GL_COLOR_BUFFER_BIT |…

有限元分析学习——Anasys Workbanch第一阶段笔记(10)桌子载荷案例分析_实际载荷与均布载荷的对比

目录 0 序言 1 桌子案例 2 模型简化 3 方案A 前处理 1&#xff09;分析类型选择 2&#xff09;材料加载 3&#xff09;约束、载荷及接触 4&#xff09;控制网格(网格大小需要根据结果不断调整) 初始计算结果 加密后计算结果 4 方案B、C 前处理 1&#xff09;分析…