当前位置: 首页 > news >正文

ARM32开发--串口库封装(初级)

知不足而奋进·望远山而前行


目录

文章目录

前言

目标

内容

开发流程

文件目录创建

分组创建

接口定义

完整代码

总结


前言

在嵌入式软件开发中,封装抽取流程和抽取封装策略是非常重要的技术,能够提高代码的复用性和可维护性。本文将介绍如何在文件系统中创建库目录,并通过keil工程中创建分组管理库的方式,实现串口功能的封装和抽取。通过具体的步骤和代码示例,帮助读者掌握封装抽取流程和策略。


目标

  1. 掌握封装抽取流程
  2. 掌握抽取封装策略

内容

开发流程

  1. 在文件系统中,创建库目录Library
  2. 在keil工程中,创建分组管理库Library
  3. 编写中间件逻辑
  4. 使用中间件
文件目录创建

在工程根目录,创建Library目录,在这个目录中,创建具体的功能目录,当前是做串口功能,我们新建usart

分组创建
  1. 创建Library分组。右键进入Manage Project Items

  1. 右键创建头文件和c文件

添加include引入

接口定义

初始化及发送功能定义

void USART0_init(void);// 发送1个byte数据
void USART0_send_byte(uint8_t byte);// 发送多个byte数据
void USART0_send_data(uint8_t* data, uint32_t len);// 发送字符串 (结尾标记\0)
void USART0_send_string(char *data);

接收回调定义

// 功能开关配置
#define USART0_RECV_CALLBACK    1#if USART0_RECV_CALLBACK
// 收到串口0数据,回调函数
extern void USART0_on_recv(uint8_t* data, uint32_t len);
#endif
...
#if USART0_RECV_CALLBACKUSART0_on_recv(g_rx_buffer, g_rx_cnt);
#endif
...
  • 通过宏定义做开关

系统printf打印定义

#define USART0_PRINTF				 1#if	USART0_PRINTF
#include <stdio.h>
#endif
#if USART0_PRINTF
// 配置printf打印函数
int fputc(int ch, FILE *f) {USART0_send_byte(ch);return ch;
}
#endif

完整代码

#ifndef __USART0_H__
#define __USART0_H__#include "gd32f4xx.h"// 功能开关配置
#define USART0_RECV_CALLBACK    1
#define USART0_PRINTF           1#if	USART0_PRINTF
#include <stdio.h>
#endifvoid USART0_init(void);// 发送1个byte数据
void USART0_send_byte(uint8_t byte);// 发送多个byte数据
void USART0_send_data(uint8_t* data, uint32_t len);// 发送字符串 (结尾标记\0)
void USART0_send_string(char *data);#if USART0_RECV_CALLBACK
// 收到串口0数据,回调函数
extern void USART0_on_recv(uint8_t* data, uint32_t len);
#endif#endif
#include "USART0.h"
#include <stdio.h>void USART0_init(void) {// GPIO 初始化 ----------------------------------------------------// 启用GPIO时钟rcu_periph_clock_enable(RCU_GPIOA);/* 配置TX PA9和RX PA10引脚 */gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);/* configure the USART0 TX pin and USART0 RX pin */gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);// 串口 初始化 ----------------------------------------------------// 启用USART0时钟rcu_periph_clock_enable(RCU_USART0);// 重置(可选)usart_deinit(USART0);// 配置串口参数:波特率*, 数据位,校验位,停止位, 大小端模式usart_baudrate_set(USART0, 115200UL);         // 波特率:必填usart_word_length_set(USART0, USART_WL_8BIT); // 数据位:默认8bitusart_parity_config(USART0, USART_PM_NONE);   // 校验位:默认无校验usart_stop_bit_set(USART0, USART_STB_1BIT);   // 停止位:默认1bitusart_data_first_config(USART0, USART_MSBF_LSB);// 大小端模式:默认小端// 启用发送功能usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);// 启用接收功能usart_receive_config(USART0, USART_RECEIVE_ENABLE);// 开启接收中断nvic_irq_enable(USART0_IRQn, 2, 2);// 启用RBNE中断,读数据缓冲区不为空中断usart_interrupt_enable(USART0, USART_INT_RBNE);// 启用IDLE中断,空闲中断usart_interrupt_enable(USART0, USART_INT_IDLE);// 启用USARTusart_enable(USART0);
}// 发送1个byte数据
void USART0_send_byte(uint8_t byte){// 从USART0的TX发送一个字节出去usart_data_transmit(USART0, (uint8_t)byte);// 等待发送完成 (轮询等待发送数据缓冲区为空)while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
}// 发送多个byte数据
void USART0_send_data(uint8_t* data, uint32_t len){// 满足:1.data指针不为空 2.长度不为0while(data && len--){USART0_send_byte(*data);data++;}
}// 发送字符串 (结尾标记\0)
void USART0_send_string(char *data){// 满足:1.data指针不为空 2. 数据不能是\0while(data && *data){USART0_send_byte((uint8_t)*data);data++;}
}#if USART0_PRINTF
// 配置printf打印函数
int fputc(int ch, FILE *f) {USART0_send_byte(ch);return ch;
}
#endif/************************************
中断函数:收到标记信号,马上执行
1. 触发中断函数的原因(标记)有很多
2. 需要区分是哪个标记触发的中断
RBNE: read data buffer not empty中断函数名不能随便写,要根据中断向量表复制
*************************************/#define   RX_BUFFER_LEN   1024
uint8_t   g_rx_buffer[RX_BUFFER_LEN];
uint32_t  g_rx_cnt = 0;void USART0_IRQHandler(void){if(SET == usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)){// 收到数据
//    printf(">RBNE<\n");// 清理标记(避免多次触发中断)usart_interrupt_flag_clear(USART0, USART_INT_FLAG_RBNE);// 获取寄存器里的数据uint8_t data = usart_data_receive(USART0);// 缓存到buffer中g_rx_buffer[g_rx_cnt++] = data;// 避免缓冲区溢出 (可选)if(g_rx_cnt >= RX_BUFFER_LEN) g_rx_cnt = 0;// 原样返回 send_byte(data);}if(SET == usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE)){
//    printf(">IDLE<\n"); // 空闲// 清理标记(无效) usart_interrupt_flag_clear(USART0, USART_INT_FLAG_IDLE);// 只能使用以下方式清理IDLE标记usart_data_receive(USART0); // 必须读取一次USART0,读到的结果没有用// 添加字符串结束标记,避免打印出错g_rx_buffer[g_rx_cnt] = '\0';#if USART0_RECV_CALLBACK
//    printf("%s", g_rx_buffer);USART0_on_recv(g_rx_buffer, g_rx_cnt);
#endif// 把缓冲区[0, g_rx_cnt)设置为0x00 (可选)
//    memset(g_rx_buffer, 0x00, g_rx_cnt);// 重置缓冲区数据个数g_rx_cnt = 0;}
}


总结

通过本文的学习,我们深入探讨了如何使用文件系统中的库目录和keil工程中的分组管理库来实现串口功能的封装和抽取。通过编写中间件逻辑和定义相关接口,我们实现了串口初始化、发送数据以及接收数据的功能,并通过宏定义的开关配置来实现功能的灵活控制。同时,我们也介绍了如何配置printf打印函数以及处理串口中断的相关操作。

相关文章:

ARM32开发--串口库封装(初级)

知不足而奋进望远山而前行 目录 文章目录 前言 目标 内容 开发流程 文件目录创建 分组创建 接口定义 完整代码 总结 前言 在嵌入式软件开发中&#xff0c;封装抽取流程和抽取封装策略是非常重要的技术&#xff0c;能够提高代码的复用性和可维护性。本文将介绍如何在文…...

统一管理:Vue公共组件/公共样式/全局自定义指令

main.js 引入存放公共文件的文件路径 import "./plugins";src/plugins文件夹下的index.js 在处理公共文件中分别引入 /* 公共引入,勿随意修改,修改时需经过确认 */ import Vue from "vue";import "/icons"; // 图标 import ByuiQueryForm fr…...

Linux之旅: 基础知识点的终极指南

文章目录 1、Linux的目录结构2、ls命令3、管理文件和目录4、linux命令使用细节和技巧5、权限管理基本命令6、搜索命令7、管道符与重定向8、压缩和解压命令9、用户及vim编辑器10、用户和用户组管理一、Linux系统用户账号的基本管理二、Linux系统用户组的管理 1、Linux的目录结构…...

C#部分方法有什么用处?和传统方法有什么区别?什么时候用合适?

在C#中&#xff0c;部分类&#xff08;partial class&#xff09;和部分方法&#xff08;partial method&#xff09;是两个不同的概念&#xff0c;但它们经常一起使用&#xff0c;特别是在代码生成和框架设计中。下面我将分别解释这两个概念&#xff0c;并讨论它们的用处、与传…...

elasticsearch hanlp插件远程词典配置

elasticsearch hanlp插件远程词典配置 背景远程词典配置新增远程词典文件修改hanlp-remote.xml自动加载词典 远程词典测试 背景 在使用elasticsearch的过程中&#xff0c;总会遇到与分词相关的需求&#xff0c;这里将针对常用的elasticsearch hanlp&#xff08;后面统称为 es …...

力扣每日一题 6/18 字符串/模拟

博客主页&#xff1a;誓则盟约系列专栏&#xff1a;IT竞赛 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 2288.价格减免 【中等】 题目&#xff1a; 句子 是由若干个单词组成的字符…...

架构设计 - Nginx Proxy Cache 缓存配置

摘要&#xff1a; web 应用业务缓存通常3级&#xff1a; 一级缓存&#xff1a;JVM 本地缓存 二级缓存&#xff1a;Redis集中式缓存 三级缓存&#xff1a;Nginx Proxy Cache 缓存 或 Nginx Lua 缓存 四级缓存&#xff1a;静态资源CDN缓存 本文主要分享 Nginx Proxy Cache 缓…...

【前端】HTML5基础

目录 0 参考1 网页1.1 什么是网页1.2 什么是HTML1.3 网页的形成 2 浏览器2.1 常用的浏览器2.2 浏览器内核 3 Web标准3.1 为什么需要Web标准3.2 Web标准的构成 4 HTML 标签4.1 HTML语法规范4.1.1 基本语法概述4.1.2 标签关系4.1.2.1 包含关系4.1.2.2 并列关系 4.2 HTML基本结构标…...

9个最佳性能测试工具(2024)

1、前言 性能测试检查软件程序在预期工作负载下的速度、响应时间、可靠性、资源使用情况和可扩展性。性能测试的目的不是发现功能缺陷&#xff0c;而是消除软件或设备中的性能瓶颈。 性能测试为利益相关者提供有关其应用程序的速度、稳定性和可扩展性的信息。更重要的是&…...

RTthread+STM32F407ZGTx+烟雾报警检测+蜂鸣器报警+LED闪烁||使用RTthread Studio

目录 实验背景 1.安装环境 2.配置环境 3.先编译下载实例程序2&#xff0c;观察DS0是否闪烁 4.实验方法 5.实例代码 6.硬件连接 7.实验效果 8.关于这次开发遇到的问题 1.反应慢&#xff0c;都熄灭1分钟多了&#xff0c;才报的问题&#xff1f; 2.关于rt_pin_mode(KEY…...

k8s资源的基本操作

文章目录 一、Namespace1、概述2、预定义的k8s命名空间2.1、default2.2、kube-public2.3、kube-system2.4、kube-node-lease 3、命名空间基本操作3.1、查看3.1.1、查看所有的命名空间3.1.2、查看指定的命名空间3.1.3、指定输出格式3.1.4、查看ns详情 3.2、创建3.2.1、命令行创建…...

19.面包屑导航制作

面包屑导航制作 官网&#xff1a;组件 | Element 1. 在layout下新建BreadCrumb.vue BreadCrumb.vue <template><div class"bread-text"><el-breadcrumb class"bred"separator"/"><el-breadcrumb-item v-for"item in…...

做动画?Animatediff 和 ComfyUI 更配哦!

如果从工作流和内存利用率的角度来说&#xff0c;Animatediff 和 ComfyUI 可能更配一些&#xff0c;毕竟制作动画是一个很吃内存的操作。 首先&#xff0c;我们需要在管理器中下载 Animatediff 插件&#xff0c;当然也可以直接导入听雨的工作流&#xff0c;然后在管理器的安装…...

笔记-python里面的xlrd模块详解

那我就一下面积个问题对xlrd模块进行学习一下&#xff1a; 1.什么是xlrd模块&#xff1f; 2.为什么使用xlrd模块&#xff1f; 3.怎样使用xlrd模块&#xff1f; 1.什么是xlrd模块&#xff1f; ♦python操作excel主要用到xlrd和xlwt这两个库&#xff0c;即xlrd是读excel&…...

oracle将字符串中的字符和数字拆分开等功能

将字符串中的字符和数字拆分开 create or replace procedure F_GetNumber1( inString IN VARCHAR2,n_return1 out varchar2, n_return2 out varchar2) ISDCHAR VARCHAR2(1024); OUTCHAR VARCHAR2(1024); j number default 0; ulen number; BEGINOUTCHAR:;DCHAR:TRIM(inStr…...

汇编基础之使用vscode写hello world

汇编语言&#xff08;Assembly Language&#xff09; 概述 汇编语言&#xff08;Assembly Language&#xff09;是一种低级编程语言&#xff0c;它直接对应于计算机的机器代码&#xff08;machine code&#xff09;&#xff0c;但使用了更易读的文本符号。每台个人计算机都有…...

APS计划排程系统如何打破装备使用约束

APS计划排程系统是离散制造型企业在计划控制方向的重要支撑&#xff0c;它提供的是交期预测、订单排产计划、物料采购计划、人力分配计划等等。近些几年来&#xff0c;多品种、小批量、多订单的生产模式&#xff0c;让企业的计划员应接不暇、疲累不堪&#xff0c;传统的人工经验…...

gigachad - suid

gigachadeasyftp利用、google反图搜索、 suid提权、s-nail 提权 主机发现 ┌──(kali㉿kali)-[~/桌面/OSCP] └─$ sudo netdiscover -i eth0 -r 192.168.44.138/24服务探测 ┌──(kali㉿kali)-[~/桌面/OSCP] └─$ sudo nmap -sV -A -T 4 -p- 192.168.44.138 |_/kingchad…...

QtScript模块

在Qt中&#xff0c;可以使用Qt Script模块来将C类和方法绑定到Qt脚本引擎中&#xff0c;从而使得可以在Qt脚本中调用这些C类和方法。以下是一个简单的示例&#xff0c;演示了如何在Qt中将C类暴露给Qt Script引擎&#xff1a; 假设有一个名为 MyClass 的C类&#xff0c;其头文件…...

qt中for循环不要使用循环中会更改的变量

检查代码&#xff0c;发现始终会少了一位&#xff0c;最后发现我在使用for循环时&#xff0c;懒省事&#xff0c;判断条件中使用的变量是涉及到循环体中更改的变量&#xff0c;代码如下&#xff0c;更直观 for (int i 0; i < m_images.size(); i) {packageToDBList[0].imag…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...