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

news2024/11/16 17:56:07

🎬 秋野酱:《个人主页》
🔥 个人专栏:《Java专栏》《Python专栏》

⛺️心若有所向往,何惧道阻且长

文章目录

    • 开发流程
      • 分组创建
    • 接口定义
    • 完整代码

开发流程

  1. 在文件系统中,创建库目录Library
  2. 在keil工程中,创建分组管理库Library
  3. 编写中间件逻辑
  4. 使用中间件
    文件目录创建
    在工程根目录,创建Library目录,在这个目录中,创建具体的功能目录,当前是做串口功能,我们新建usart。
    在这里插入图片描述

分组创建

  1. 创建Library分组。右键进入Manage Project Items
    在这里插入图片描述
    右键创建头文件和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_CALLBACK
    USART0_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>
#endif

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);

#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); // 数据位:默认8bit
  usart_parity_config(USART0, USART_PM_NONE);   // 校验位:默认无校验
  usart_stop_bit_set(USART0, USART_STB_1BIT);   // 停止位:默认1bit
  usart_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);
  
  // 启用USART
  usart_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.长度不为0
  while(data && len--){
    USART0_send_byte(*data);
    data++;
  }
}

// 发送字符串 (结尾标记\0)
void USART0_send_string(char *data){
  // 满足:1.data指针不为空 2. 数据不能是\0
  while(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;
  }
}

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

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

相关文章

健身日记之倒立俯卧撑学习——起始日2024.6.4

文章目录 前言 自我介绍 昔日计划 新目标计划 瓶颈突破尝试 参考视频及文章 前言 有轻微健身基础&#xff0c;正式接触街健五大神技&#xff0c;立志在两年内解锁全部&#xff0c;将有机会的进行日常训练和目标肌群锻炼&#xff0c;这里向大家展示我的计划和安排&#xf…

【C++练级之路】【Lv.24】异常

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《算法神殿》《数据结构世界》《进击的C》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、异常的概念及定义1.1 异常的概念1.2 异常的定义 二、异常的使用2.1 异常的栈展开匹配2.2 异常的重新…

Django使用正则表达式

本书1-7章样章及配套资源下载链接: https://pan.baidu.com/s/1OGmhHxEMf2ZdozkUnDkAkA?pwdnanc 源码、PPT课件、教学视频等&#xff0c;可以从前言给出的下载信息下载&#xff0c;大家可以评估一下。 在Django框架的新版本&#xff08;v2.0 &#xff09;中&#xff0c;URLc…

电脑开机之后要很久才能进入系统?进入WinPE也是卡顿半天?

前言 小白最近接到了一张很奇怪的电脑维修单&#xff0c;客户说他的工作室电脑开机特别慢&#xff0c;开机之后特别卡顿&#xff0c;在使用的时候也会一卡一卡的。 这事情开始看很简单&#xff1a;估计就是电脑还是机械硬盘&#xff0c;所以开机很慢又卡顿。所以应该是把机械…

一键开启:盲盒小程序里的梦幻奇遇

在繁忙的都市生活中&#xff0c;每个人心中都藏着一个关于奇遇的梦想。如今&#xff0c;我们为您精心打造了一款盲盒小程序——“梦幻奇遇”&#xff0c;只需一键开启&#xff0c;就能带您走进一个充满无限惊喜和梦幻色彩的奇幻世界。 一、神秘盲盒&#xff0c;惊喜连连 “梦幻…

SolidWorks价格与其它CAD软件相比:为什么选择SolidWorks更划算

在CAD软件的浩瀚星海中&#xff0c;SolidWorks如同一颗璀璨的明星&#xff0c;以其卓越的性能、广泛的适用性和合理的定价策略&#xff0c;赢得了全球众多工程师和设计师的青睐。亿达四方&#xff0c;作为官方授权的SolidWorks代理商&#xff0c;今天将带您深入价格与功能的比较…

21、matlab生成脉冲序列:pulstran()函数

1、pulstran()函数 1&#xff09;语法 语法1&#xff1a;y pulstran(t,d,func,fs) 基于连续函数的采样产生脉冲序列。 语法2&#xff1a;y pulstran(t,d,p) 生成一个脉冲序列&#xff0c;该脉冲序列是向量p中原型脉冲的多个延迟插值的总和。 语法3&#xff1a;y pulstran…

Django缓存

由于Django是动态网站&#xff0c;所有每次请求均会去数据进行相应的操作&#xff0c;当程序访问量大时&#xff0c;耗时必然会更加明显&#xff0c;最简单解决方式是使用&#xff1a;缓存&#xff0c;缓存将一个某个views的返回值保存至内存或者memcache中&#xff0c;若某个时…

本地知识库开源框架Fastgpt、MaxKB产品体验

本地知识库开源框架Fastgpt、MaxKB产品体验 背景fastgpt简介知识库共享部署 MaxKB总结 背景 上一篇体验了Quivr、QAnything两个开源知识库模型框架&#xff0c;这次介绍两款小众但是体验比较好的产品。 fastgpt 简介 FastGPT 是一个基于 LLM 大语言模型的知识库问答系统&am…

RFID解决方案提高汽车行业的可追溯性

汽车产业是一个典型的密集型资金产业&#xff0c;为了降低成本&#xff0c;许多汽车制造商和零部件供应商选择在海外设厂&#xff0c;上中下游企业分布在世界各地。因此&#xff0c;在汽车行业内&#xff0c;可追溯性是非常重要的&#xff0c;它在整个供应链中实时识别原材料、…

CogVLM2多模态开源大模型部署与使用

CogVLM2多模态开源大模型部署与使用 项目简介 CogVLM2 是由清华大学团队发布的新一代开源模型系列。2024年5月24日&#xff0c;发布了Int4版本模型&#xff0c;只需16GB显存即可进行推理。2024年5月20日&#xff0c;发布了基于llama3-8b的CogVLM2&#xff0c;性能与GPT-4V相当…

怎么用微信小程序实现远程控制空调

怎么用微信小程序实现远程控制空调呢&#xff1f; 本文描述了使用微信小程序调用HTTP接口&#xff0c;实现控制空调&#xff0c;通过不同规格的通断器&#xff0c;来控制不同功率的空调的电源。 可选用产品&#xff1a;可根据实际场景需求&#xff0c;选择对应的规格 序号设备…

这个杂志,审稿到录用仅需一个月!毕业生的梦中情刊,本科生用NHANES数据库发文2区...

Lipids in Health and Disease 是一个公开的、同行评议的期刊&#xff0c;主要发表关于脂质所有方面的文章&#xff0c;影响因子逐年上升&#xff0c;国人发文占比排第一&#xff0c;年刊量100多篇&#xff01;最重要的是&#xff0c;该期刊文章审稿速度特别快&#xff0c;最快…

《额尔古纳河右岸》有感

看完了迟子建老师的《额尔古纳河右岸》&#xff0c;老规矩&#xff0c;写点东西吧。最近一段时间确实挺迷茫的&#xff0c;所以给自己找了点事儿&#xff0c;看看书。期初并不能认真看进去&#xff0c;慢慢的看见去之后&#xff0c;就愈发想知道故事的后来。 书里有太多关于死亡…

地址线/时钟/数据线串联电阻作用

在一些线路中会串联电阻&#xff0c;那么这个电阻的作用到底是什么&#xff1f;什么时候需要串联电阻&#xff1f; 首先高速信号线中才考虑使用这样的电阻。在低频情况下&#xff0c;一般是直接连接。这个电阻有两个作用&#xff1a; 1.第一是阻抗匹配。因为信号源的阻抗很低…

element-plus表格添加简单右键

实现如下 <template><main class"mainClass" > <el-table :data"tableData" style"width: 100%"row-contextmenu"rowContextmenu"cell-contextmenu"cellContextmenu"contextmenu.prevent><el-table-c…

excle中数据分析,excle导入用sql简单处理

前言&#xff1a; 办法一&#xff1a;直接用excle导入db就行&#xff0c;如果excle导如db不能用&#xff0c;就用笨办法下面这个方法去做 1、从系统中导出excle 2、db中插入相应的表和标题 3、先手动插入条件&#xff0c;把insert语句复制出来 INSERT INTO test.test (orders…

教师产假多少天

教师产假究竟有多少天&#xff1f;这个问题或许在您计划家庭时显得尤为重要。教师作为国家公职人员&#xff0c;享有法定的产假权益。 根据规定&#xff0c;女职工的产假一般为98天&#xff0c;包括产前15天和产后83天。但请注意&#xff0c;这一标准并非全国统一&#xff0c;不…

机器学习算法 —— 基于鸢尾花数据集的逻辑回归分类

&#x1f31f;欢迎来到 我的博客 —— 探索技术的无限可能&#xff01; &#x1f31f;博客的简介&#xff08;文章目录&#xff09; 目录 实践演示基于鸢尾花&#xff08;iris&#xff09;数据集的逻辑回归分类库函数导入数据读取/载入数据信息简单查看可视化展示利用逻辑回归模…

Java面向对象笔记

多态 一种类型的变量可以引用多种实际类型的对象 如 package ooplearn;public class Test {public static void main(String[] args) {Animal[] animals new Animal[2];animals[0] new Dog();animals[1] new Cat();for (Animal animal : animals){animal.eat();}} }class …