【stm32】USART编码部分--串口数据包

USART串口数据包【源码放在最后】

关于数据包的分类

在这里插入图片描述在这里插入图片描述

关于数据包的发送

  • 如果想要发送Hex数据包,定义一个数组填充数据,然后使用串口模块函数SendArray进行发送

  • 如果想要发送文本数据包,写一个字符串然后调用SendString进行发送

  • 对于发送数据包很简单,因为发送过程完全是自主可控的,想法啥就发啥

关于接收一个数据包
  • 固定包长Hex数据包的接收方法

    • 每次收到一个字节程序都会进一次中断,在中断函数里我们可以拿到这个字节,但是拿到之后就要推出中断,所以每拿到一个数据都是个独立的过程

    • 对于数据包来说,很明显它具有前后关联性,包头之后是数据数据之后是包尾,对于包头、数据和包尾这三种状态,需要有不同的处理逻辑,所以在程序中需要设计一个能够记住不同状态的机制,在不同状态执行不同的操作,同时还要进行不同状态的合理转移,这种状态思维就叫做-------状态机

    • 状态转移图-在这里插入图片描述

    • 执行逻辑

      • 开始s=0;收到一个数据进中断,根据S=0,进入第一个状态的程序,判断包头是不是FF,如果是FF

      • 置S=1,退出中断,结束

      • 下次在进中断,根据S=1,就可以进行接收数据的程序

      • 在第一个状态如果接收到的数据不是FF、就证明数据包没有对齐,应该等待数据包包头的出现,这时状态就仍然是0,下次进中断就还是等待包头的逻辑,直到出现FF,才能转到下一个状态

      • 等到接收数据时,再收到数据就把他存到数组中,再用个变量记录接收到了多少个数据,如果没收够四个数据,就一直是接收数据的状态,如果收够了,就置S=2,进入等待包尾的程序中

      • 判断收到的数据是不是FE,如果时FE,置S=0,回到最初的状态,开始下个轮回

      • 也有可能最后一个不是包尾,比如数据和包头重复,导致包头位置判断错了,那这个包尾位置就有可能不是FE、这时就可以进入重读等待包尾的状态,直到接收到包尾

串口收发Hex数据包编码–基于串口发送+接收
  1. 建立两个字符数组,用来接收和发送载荷数据,不存储包头和包尾

  2. 先编写SendPacket函数,调用一下这个函数Txpacket数组的四个数据,就会自动加上包头包尾发送出去(发送不进中断函数),首先调用SendByte发送包头,调用SendArray发送数据,调用SendByte发送包尾

  3. 把Txpacket数组在头文件包含 变为外部可调用,在main函数中分别赋数据到数组的每个成员,添加按键,在按键的判断中不断++数组的值

  4. 对于接收这样一个数据包的代码

    1. 在接受中断函数里,需要使用状态机来执行接收逻辑,接收数据包,把载荷数据存在RxPacket数组里
    2. 首先定义一个标志当前状态的变量RxState,在中断函数里定义一个静态变量,根据RxState的不同进入不同的处理程序
    3. 定义变量RxData用于接收每次接收到的一个字节数据uint8_t RxData = USART_ReceiveData(USART1);
    4. 在状态RxState = 1时需要定义一个静态变量pRxPacket来记录接收载荷数据的个数,记得清0----pRxPacket
    5. 在状态2时等待包尾,当接收到包尾时置一个标志位,证明数据接收完成
    6. 主函数判断标志位进行显示载荷数据
串口收发文本数据包
  • 可变包长含包头包尾

  • 只写接收的部分,因为发送不方便像Hex数组一样方便的一个个更改,所以发送就直接在主函数里SendString,或者printf就行
    在这里插入图片描述

串口收发HEX数据包程序

serial.c文件

#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>uint8_t Serial_TxPacket[4];				//FF 01 02 03 04 FE
uint8_t Serial_RxPacket[4];
uint8_t Serial_RxFlag;void Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 9600;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;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);USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);USART_Cmd(USART1, ENABLE);
}void Serial_SendByte(uint8_t Byte)
{USART_SendData(USART1, Byte);while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}void Serial_SendArray(uint8_t *Array, uint16_t Length)
{uint16_t i;for (i = 0; i < Length; i ++){Serial_SendByte(Array[i]);}
}void Serial_SendString(char *String)
{uint8_t i;for (i = 0; String[i] != '\0'; i ++){Serial_SendByte(String[i]);}
}uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{uint32_t Result = 1;while (Y --){Result *= X;}return Result;
}void Serial_SendNumber(uint32_t Number, uint8_t Length)
{uint8_t i;for (i = 0; i < Length; i ++){Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');}
}int fputc(int ch, FILE *f)
{Serial_SendByte(ch);return ch;
}void Serial_Printf(char *format, ...)
{char String[100];va_list arg;va_start(arg, format);vsprintf(String, format, arg);va_end(arg);Serial_SendString(String);
}void Serial_SendPacket(void)
{Serial_SendByte(0xFF);Serial_SendArray(Serial_TxPacket, 4);Serial_SendByte(0xFE);
}uint8_t Serial_GetRxFlag(void)
{if (Serial_RxFlag == 1){Serial_RxFlag = 0;return 1;}return 0;
}void USART1_IRQHandler(void)
{static uint8_t RxState = 0;static uint8_t pRxPacket = 0;if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET){uint8_t RxData = USART_ReceiveData(USART1);if (RxState == 0){if (RxData == 0xFF){RxState = 1;pRxPacket = 0;}}else if (RxState == 1){Serial_RxPacket[pRxPacket] = RxData;pRxPacket ++;if (pRxPacket >= 4){RxState = 2;}}else if (RxState == 2){if (RxData == 0xFE){RxState = 0;Serial_RxFlag = 1;}}USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}

serial.h文件

#ifndef __SERIAL_H
#define __SERIAL_H#include <stdio.h>extern uint8_t Serial_TxPacket[];
extern uint8_t Serial_RxPacket[];void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
void Serial_Printf(char *format, ...);void Serial_SendPacket(void);
uint8_t Serial_GetRxFlag(void);#endif

main.c文件

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
#include "Key.h"uint8_t KeyNum;int main(void)
{OLED_Init();Key_Init();Serial_Init();OLED_ShowString(1, 1, "TxPacket");OLED_ShowString(3, 1, "RxPacket");Serial_TxPacket[0] = 0x01;Serial_TxPacket[1] = 0x02;Serial_TxPacket[2] = 0x03;Serial_TxPacket[3] = 0x04;while (1){KeyNum = Key_GetNum();if (KeyNum == 1){Serial_TxPacket[0] ++;Serial_TxPacket[1] ++;Serial_TxPacket[2] ++;Serial_TxPacket[3] ++;Serial_SendPacket();OLED_ShowHexNum(2, 1, Serial_TxPacket[0], 2);OLED_ShowHexNum(2, 4, Serial_TxPacket[1], 2);OLED_ShowHexNum(2, 7, Serial_TxPacket[2], 2);OLED_ShowHexNum(2, 10, Serial_TxPacket[3], 2);}if (Serial_GetRxFlag() == 1){OLED_ShowHexNum(4, 1, Serial_RxPacket[0], 2);OLED_ShowHexNum(4, 4, Serial_RxPacket[1], 2);OLED_ShowHexNum(4, 7, Serial_RxPacket[2], 2);OLED_ShowHexNum(4, 10, Serial_RxPacket[3], 2);}}
}

串口收发文本数据包程序

serial.c文件

#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>char Serial_RxPacket[100];				//"@MSG\r\n"
uint8_t Serial_RxFlag;void Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 9600;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;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);USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);USART_Cmd(USART1, ENABLE);
}void Serial_SendByte(uint8_t Byte)
{USART_SendData(USART1, Byte);while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}void Serial_SendArray(uint8_t *Array, uint16_t Length)
{uint16_t i;for (i = 0; i < Length; i ++){Serial_SendByte(Array[i]);}
}void Serial_SendString(char *String)
{uint8_t i;for (i = 0; String[i] != '\0'; i ++){Serial_SendByte(String[i]);}
}uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{uint32_t Result = 1;while (Y --){Result *= X;}return Result;
}void Serial_SendNumber(uint32_t Number, uint8_t Length)
{uint8_t i;for (i = 0; i < Length; i ++){Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');}
}int fputc(int ch, FILE *f)
{Serial_SendByte(ch);return ch;
}void Serial_Printf(char *format, ...)
{char String[100];va_list arg;va_start(arg, format);vsprintf(String, format, arg);va_end(arg);Serial_SendString(String);
}void USART1_IRQHandler(void)
{static uint8_t RxState = 0;static uint8_t pRxPacket = 0;if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET){uint8_t RxData = USART_ReceiveData(USART1);if (RxState == 0){if (RxData == '@' && Serial_RxFlag == 0){RxState = 1;pRxPacket = 0;}}else if (RxState == 1){if (RxData == '\r'){RxState = 2;}else{Serial_RxPacket[pRxPacket] = RxData;pRxPacket ++;}}else if (RxState == 2){if (RxData == '\n'){RxState = 0;Serial_RxPacket[pRxPacket] = '\0';Serial_RxFlag = 1;}}USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}

serial.h文件

#ifndef __SERIAL_H
#define __SERIAL_H#include <stdio.h>extern char Serial_RxPacket[];
extern uint8_t Serial_RxFlag;void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
void Serial_Printf(char *format, ...);#endif

main.c文件

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
#include "LED.h"
#include "string.h"int main(void)
{OLED_Init();LED_Init();Serial_Init();OLED_ShowString(1, 1, "TxPacket");OLED_ShowString(3, 1, "RxPacket");while (1){if (Serial_RxFlag == 1){OLED_ShowString(4, 1, "                ");OLED_ShowString(4, 1, Serial_RxPacket);if (strcmp(Serial_RxPacket, "LED_ON") == 0){LED1_ON();Serial_SendString("LED_ON_OK\r\n");OLED_ShowString(2, 1, "                ");OLED_ShowString(2, 1, "LED_ON_OK");}else if (strcmp(Serial_RxPacket, "LED_OFF") == 0){LED1_OFF();Serial_SendString("LED_OFF_OK\r\n");OLED_ShowString(2, 1, "                ");OLED_ShowString(2, 1, "LED_OFF_OK");}else{Serial_SendString("ERROR_COMMAND\r\n");OLED_ShowString(2, 1, "                ");OLED_ShowString(2, 1, "ERROR_COMMAND");}Serial_RxFlag = 0;}}
}

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

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

相关文章

Spark 起源发展与项目架构说明

文章目录 前言Spark 的起源Spark 是什么速度易用性模块化可扩展性 分析方法的统一Spark SQLSpark MLlibSpark Structured StreamingGraphX Spark的分布式执行Spark driverSparkSessionCluster managerSpark executor部署模式分布式数据和分区 开发的经验Spark 的使用人群与使用…

关于其他服务器篡改请求头导致登录失效

问题描述 此问题是单点登录转发问题&#xff0c;客户服务器域名访问一个本程序对外接口获取token&#xff0c;并跳转至本系统登录页面&#xff0c;在网关日志中发现token为空的异常。 问题排查 1、拿token在postman中发送&#xff0c;发现请求是成功的&#xff0c;本程序通过n…

App测试中ios和Android的区别

1、Android长按home键呼出应用列表和切换应用&#xff0c;然后右滑则终止应用&#xff1b; 2、多分辨率测试&#xff0c;Android端20多种&#xff0c;ios较少&#xff1b; 3、手机操作系统&#xff0c;Android较多&#xff0c;ios较少且不能降级&#xff0c;只能单向升级&…

InfluxDB2的数据查询示例

有用influxdb2 不支持sql&#xff0c;并且实质是个列存储数据库&#xff0c;这里基于 influxdb-client-java 和 beanutils反射&#xff0c;写了个数据查询&#xff0c;把结果以行对象的形式返回的工具类。 package com.joy.malltools.influxdb2;import com.influxdb.client.Q…

越南工厂连接中国总部服务器解决方案---案例分享

随着全球化的不断深入&#xff0c;许多中国企业走出国门&#xff0c;在世界各地设立分支机构和生产基地。然而&#xff0c;随之而来的是跨国网络通信的挑战。近期&#xff0c;客户越南的工厂与中国总部之间的网络连接出现了一些问题&#xff0c;这直接影响了企业的日常运营效率…

vscode shadertoy插件,非常方便的glsl着色器编写工具

很著名的shadertoy网站&#xff0c;集合了非常多大神利用数学写出美妙的shader效果。像shadertoy创始人之一的IQ大神它在这方面有很多的建树。他的利用光线步进和躁声可以创建很多不可思议的3D场景。 vscode有一件shadertoy的插件&#xff0c;安装后可以新建一个*.glsl文件&am…

使用 FinalShell 进行远程连接(ssh 远程连接 Linux 服务器)

目录 前言 基本使用教程 新建远程连接 连接主机 自定义命令 路由追踪 前言 后端开发&#xff0c;必然需要和服务器打交道&#xff0c;部署应用&#xff0c;排查问题&#xff0c;查看运行日志等等。一般服务器都是集中部署在机房中&#xff0c;也有一些直接是云服务器&am…

Synchronized锁升级过程

无锁-->偏向锁---> 轻量级锁---->重量级锁 ①、从无锁到偏向锁&#xff1a; 当一个线程首次访问同步块时&#xff0c;如果此对象无锁状态且偏向锁未被禁用&#xff0c;JVM 会将该对象头的锁标记改为偏向锁状态&#xff0c;并记录下当前线程的 ID。此时&#xff0c;对…

IntelliJ IDEA - 快捷键 Win Mac 对照表

基本 Ctrl CommandAlt Option WinMacCtrl YCommand DeleteCtrl WOption 方向键上Ctrl NCommand OCtrl F11Option F3Shift F11Command F3Ctrl SpaceControl SpaceCtrl 方向键Option 方向键Alt Control VAlt EnterOption EnterAlt InsertCommand NAlt 方…

Flume学习笔记

视频地址:https://www.bilibili.com/video/BV1wf4y1G7EQ/ 定义 Flume是一个高可用的、高可靠的、分布式的海量日志采集、聚合和传输的系统。 Flume高最要的作用就是实时读取服务器本地磁盘的数据,将数据写入HDFS。 官网:https://flume.apache.org/releases/content/1.9.0/…

云智慧发布对象关系型数据库CloudPanguDB,打破传统技术壁垒

近日&#xff0c;云智慧推出关系型数据库CloudPanguDB&#xff08;中文名称&#xff1a;盘古数据库&#xff09;&#xff0c;旨在通过高兼容性能和创新技术架构&#xff0c;降低企业项目整体运营成本。 无论是处理海量复杂数据&#xff0c;还是构建清晰有序的数据结构关系&…

练习 17 Web [极客大挑战 2019]PHP

常见的网站源码备份文件名和后缀&#xff0c;反序列化攻击 unserialize()&#xff1a;wakeup绕过&#xff0c;private类以及属性序列化后的%00修改 开靶机 提到”备份“ 那看看有没有backup.php啥的 如果网站存在备份文件&#xff0c;常见的备份文件后缀名有&#xff1a;“.gi…

嵌入式数据库-Sqlite3

阅读引言&#xff1a; 本文将会从环境sqlite3的安装、数据库的基础知识、sqlite3命令、以及sqlite的sql语句最后还有一个完整的代码实例&#xff0c; 相信仔细学习完这篇内容之后大家一定能有所收获。 目录 一、数据库的基础知识 1.数据库的基本概念 2.常用数据库 3.嵌入式…

Qt中的OpenGL

一、OpenGL简介 1.1什么是OpenGL Open Graphics Library&#xff0c;它是一个由Khronos组织制定并维护的规范(Specification)OpenGL核心是一个C库&#xff0c;同时也支持多种语言的派生 1.2 核心模式&#xff08;Core-profile&#xff09; 也叫可编程管线&#xff0c;提供了…

网络安全应急响应:保护网络安全的最后一道防线

网络安全应急响应&#xff1a;保护网络安全的最后一道防线 网络安全是当今信息社会中至关重要的问题&#xff0c;网络攻击的频繁发生使得企业、政府和个人面临着越来越大的安全威胁。为了及时有效地应对网络安全事件&#xff0c;网络安全应急响应成为了必不可少的一环。 小德将…

WPF中继承ItemsControl子类控件数据模板获取选中属性

需求场景 列表类控件&#xff0c;如 ListBox、ListView、DataGrid等。显示的行数据中&#xff0c;部分内容依靠选中时触发控制&#xff0c;例如选中行时行记录复选&#xff0c;部分列内容控制显隐。 案例源码以ListView 为例。 Xaml 部分 <ListView ItemsSource"{Bi…

centOS安装git客户端

测试环境&#xff1a;centOS stream 9 first:更新centos系统 sudo yum update sencond:安装git客户端 sudo yum install git third:验证安装是否成功 git --version 第四步&#xff1a;配置Git用户名和电子邮件地址 git config --global user.name "你的用户名&qu…

Go语言介绍及Go语言成功的项目列举

Go语言介绍&#xff1a; Go即 Golang &#xff0c;是 Google 公司 2009 年 11 月正式对外公开的一门编程语言。 根据 Go 语言开发者自述&#xff0c;近 10 多年&#xff0c;从单机时代的 C 语言到现在互联网时代的 Java &#xff0c; 都没有令人满意的开发语言&a…

【卫星家族】 | 高分六号卫星影像及获取

1. 卫星简介 高分六号卫星&#xff08;GF-6&#xff09;于2018年6月2日在酒泉卫星发射中心成功发射&#xff0c;是高分专项中的一颗低轨光学遥感卫星&#xff0c;也是我国首颗精准农业观测的高分卫星&#xff0c;具有高分辨率、宽覆盖、高质量成像、高效能成像、国产化率高等特…

37.HarmonyOS鸿蒙系统 App(ArkUI) 创建第一个应用程序hello world

HarmonyOS App(ArkUI) 创建第一个应用程序helloworld 线性布局 1.鸿蒙应用程序开发app_hap开发环境搭建 3.DevEco Studio安装鸿蒙手机app本地模拟器 打开DevEco Studio,点击文件-》新建 双击打开index.ets 复制如下代码&#xff1a; import FaultLogger from ohos.faultL…