【N32L40X】学习笔记05-串口库(空闲中断+接收非空中断)

串口

  1. 该函数库的目的就是在统一的地方配置,将配置的不同项放置在一个结构体内部
  2. 使用一个枚举来定义一个的别名

bsp_uart.h

#ifndef _BSP_UART_H_
#define _BSP_UART_H_
#include<stdio.h>
#include<stdint.h>
#include "n32l40x.h"#define BUFF_SIZE 48
//调试串口指定
#define DEBUG_UART USART1//dma接收数据和中断接收数据不可以同时使用typedef enum
{UART_1,UART_2,UART_3,UART_NUM,
}em_uart_t;typedef struct
{//gpio txGPIO_Module* tx_gpiox;//发送引脚分组uint16_t tx_pin;//发送引脚编号uint32_t tx_gpio_rcc;//发送引脚时钟uint8_t tx_afx;//引脚复用模式//gpio rxGPIO_Module* rx_gpiox;//接收引脚分组uint16_t rx_pin;//接收引脚号uint32_t rx_gpio_rcc;//接收引脚时钟uint8_t rx_afx;//引脚复用模式//uartUSART_Module* uartx;//串口句柄uint32_t uart_rcc;//串口时钟uint32_t bate;//串口波特率IRQn_Type irqx;//中断编号uint8_t it_rx:1;//串口中断接收使能uint8_t it_idle:1;//串口接收空闲中断使能//flaguint8_t rx_idle;//发生了空闲中断uint16_t rx_count;//接收到的数据长度uint8_t txbuffer[BUFF_SIZE];//接收缓冲区uint8_t rxbuffer[BUFF_SIZE];//发送缓存区} uart_t;/*一键初始化所有串口
*/
void bsp_uarts_init(void);
//发送数据
void bsp_uart_rs232_send(uint8_t * data,int len);
void bsp_uart_rs485_1_send(uint8_t * data,int len);
void bsp_uart_rs485_2_send(uint8_t * data,int len);/*从串口接收数据
*/
void bsp_get_uart_data(em_uart_t id,uint8_t * data,uint16_t *len);
#endif

bsp_uart.c

#include <stdio.h>
#include <math.h>
#include <string.h>#include "bsp_include.h"
#include "uart/bsp_uart.h"
static uart_t s_uarts[UART_NUM]= {//UART1{   GPIOA,GPIO_PIN_9,RCC_APB2_PERIPH_GPIOA,GPIO_AF4_USART1,//gpio txGPIOA,GPIO_PIN_10,RCC_APB2_PERIPH_GPIOA,GPIO_AF4_USART1,//gpio rxUSART1,RCC_APB2_PERIPH_USART1,115200,USART1_IRQn,//uart// DMA_CH1,DMA_CH2,DMA_REMAP_USART1_RX,DMA_REMAP_USART1_TX,DMA_Channel1_IRQn,DMA_Channel2_IRQn,1,1,//dma1,1,0,0//switch},//UART2{   GPIOB,GPIO_PIN_4,RCC_APB2_PERIPH_GPIOB,GPIO_AF4_USART2,//gpio txGPIOB,GPIO_PIN_5,RCC_APB2_PERIPH_GPIOB,GPIO_AF6_USART2,//gpio rxUSART2,RCC_APB1_PERIPH_USART2,115200,USART2_IRQn,//uart// DMA_CH1,DMA_CH2,DMA_REMAP_USART1_RX,DMA_REMAP_USART1_TX,DMA_Channel1_IRQn,DMA_Channel2_IRQn,1,1,//dma1,1,0,0//switch},//UART3{   GPIOB,GPIO_PIN_10,RCC_APB2_PERIPH_GPIOB,GPIO_AF0_USART3,//gpio txGPIOB,GPIO_PIN_11,RCC_APB2_PERIPH_GPIOB,GPIO_AF5_USART3,//gpio rxUSART3,RCC_APB1_PERIPH_USART3,115200,USART3_IRQn,//uart// DMA_CH1,DMA_CH2,DMA_REMAP_USART1_RX,DMA_REMAP_USART1_TX,DMA_Channel1_IRQn,DMA_Channel2_IRQn,1,1,//dma1,1,0,0//switch},};/**/
void bsp_uart_rcc_config(uart_t *puartx )
{// Enable GPIO clockRCC_EnableAPB2PeriphClk(puartx->uart_rcc, ENABLE);// 使能串口时钟if(USART3 == puartx->uartx || USART2 == puartx->uartx){RCC_EnableAPB1PeriphClk(puartx->uart_rcc,ENABLE);}else{RCC_EnableAPB2PeriphClk(puartx->uart_rcc,ENABLE);}}/*** @brief  Configures the different GPIO ports.*/
void bsp_uart_gpio_config(uart_t *puartx)
{GPIO_InitType GPIO_InitStructure;RCC_EnableAPB2PeriphClk(puartx->rx_gpio_rcc,ENABLE);RCC_EnableAPB2PeriphClk(puartx->tx_gpio_rcc,ENABLE);/* 初始化*/GPIO_InitStruct(&GPIO_InitStructure);/* 发送引脚*/GPIO_InitStructure.Pin            = puartx->tx_pin;GPIO_InitStructure.GPIO_Mode      = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Alternate = puartx->tx_afx;GPIO_InitPeripheral(puartx->tx_gpiox, &GPIO_InitStructure);/* 接收引脚 */GPIO_InitStructure.Pin            = puartx->rx_pin;GPIO_InitStructure.GPIO_Mode      = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pull			= GPIO_Pull_Up;GPIO_InitStructure.GPIO_Alternate = puartx->rx_afx;GPIO_InitPeripheral(puartx->rx_gpiox, &GPIO_InitStructure);}/*** @brief  Configures the nested vectored interrupt controller.*/
void bsp_uart_nvic_config(uart_t *puartx)
{NVIC_InitType NVIC_InitStructure;/* Enable the USARTz Interrupt */if(puartx->it_idle || puartx->it_rx){NVIC_InitStructure.NVIC_IRQChannel                   = puartx->irqx;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 7;NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;NVIC_Init(&NVIC_InitStructure);//volatile uint32_t pri =   NVIC_GetPriority(puartx->irqx);NVIC_SetPriority(puartx->irqx,7);}/* 使能接收中断 */if(puartx->it_rx){USART_ConfigInt(puartx->uartx, USART_INT_RXDNE, ENABLE);}/*使能空闲终端 */if(puartx->it_idle){USART_ConfigInt(puartx->uartx, USART_INT_IDLEF, ENABLE);}}int bsp_uart_get_id(USART_Module* uartx)
{for(int i=0; i<UART_NUM; i++){if(uartx == s_uarts[i].uartx){return i;}}return -1;
}
int  bsp_uart_iaq_handler(uart_t *puartx)
{int result=0;if (USART_GetIntStatus(puartx->uartx, USART_INT_RXDNE) != RESET){/* 读取串口数据*/puartx->rxbuffer[puartx->rx_count%BUFF_SIZE] = USART_ReceiveData(puartx->uartx);puartx->rx_count++;}else if(USART_GetIntStatus(puartx->uartx, USART_INT_IDLEF) != RESET){USART_ReceiveData(puartx->uartx);puartx->rx_idle = 1;result=1;}return result;
}/*从串口接收数据
*/
void bsp_get_uart_data(em_uart_t id,uint8_t * data,uint16_t *len)
{if(UART_NUM<id || !data||!len){*len=0;return;}uart_t *puart = s_uarts+id;*len=0;if(puart->rx_idle){puart->rx_idle=0;*len = puart->rx_count;memcpy(data,puart->rxbuffer,*len);puart->rx_count=0;}
}
/*** 串口初始化*/
void  bsp_uart_init(uart_t *puartx)
{USART_InitType USART_InitStructure;/* 1.时钟配置 */bsp_uart_rcc_config(puartx);/* 2.中断配置 */bsp_uart_nvic_config(puartx);/* 3.串口涉及的gpio配置 */bsp_uart_gpio_config(puartx);/* Configure the DMA *///bsp_uart_dma_config(puartx);/*4.串口的相关参数设置 */USART_StructInit(&USART_InitStructure);USART_InitStructure.BaudRate            = puartx->bate;USART_InitStructure.WordLength          = USART_WL_8B;USART_InitStructure.StopBits            = USART_STPB_1;USART_InitStructure.Parity              = USART_PE_NO;USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;/* 参数初始化 */USART_Init(puartx->uartx, &USART_InitStructure);/* 5.使能串口*/USART_Enable(puartx->uartx, ENABLE);}/*一键初始化所有串口
*/
void bsp_uarts_init(void)
{for(int i=0; i<UART_NUM; i++){bsp_uart_init(s_uarts+i);}
}void USART1_IRQHandler(void)
{int id = bsp_uart_get_id(USART1);if(id!=-1) {bsp_uart_iaq_handler(s_uarts+id);}}void USART2_IRQHandler(void)
{int id = bsp_uart_get_id(USART2);if(id!=-1) {bsp_uart_iaq_handler(s_uarts+id);}}
void USART3_IRQHandler(void)
{//		BaseType_t  TaskWoken;int id = bsp_uart_get_id(USART3);if(id!=-1) {if( bsp_uart_iaq_handler(s_uarts+id)){//通知gui线程收数据
//					if(task_hd_gui_recv)
//						
//						xTaskNotifyFromISR(task_hd_gui_recv, 1, eSetValueWithOverwrite, &TaskWoken);}}}/*** @brief  This function handles UART4 global interrupt request.*/
void UART4_IRQHandler(void)
{int id = bsp_uart_get_id(UART4);if(id!=-1) {bsp_uart_iaq_handler(s_uarts+id);}
}/*** @brief  This function handles UART7 global interrupt request.*/
void UART5_IRQHandler(void)
{int id = bsp_uart_get_id(UART5);if(id!=-1) {bsp_uart_iaq_handler(s_uarts+id);}
}/* retarget the C library printf function to the USART */
int fputc(int ch, FILE* f)
{USART_SendData(DEBUG_UART, (uint8_t)ch);while (USART_GetFlagStatus(DEBUG_UART, USART_FLAG_TXDE) == RESET);return (ch);
}void bsp_uart_rs232_send(uint8_t * data,int len)
{for(int i=0;i<len;i++){USART_SendData(USART3, (uint8_t)data[i]);while (USART_GetFlagStatus(USART3, USART_FLAG_TXDE) == RESET);}}void bsp_uart_rs485_1_send(uint8_t * data,int len)
{for(int i=0;i<len;i++){USART_SendData(USART1, (uint8_t)data[i]);while (USART_GetFlagStatus(USART1, USART_FLAG_TXDE) == RESET);}}
void bsp_uart_rs485_2_send(uint8_t * data,int len)
{led_on_off(RS485_DE,Bit_SET);for(int i=0;i<len;i++){USART_SendData(USART2, (uint8_t)data[i]);while (USART_GetFlagStatus(USART2, USART_FLAG_TXDE) == RESET);}led_on_off(RS485_DE,Bit_RESET);
}

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

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

相关文章

ChatGPT开放自定义系统级别的指令,可设置偏好变成专属助理

OpenAI官方消息https://openai.com/blog/custom-instructions-for-chatgpt OpenAI为其大型语言模型接口ChatGPT引入了自定义指令&#xff0c;旨在为用户提供更加量身定制和个性化的体验&#xff0c;可以设置您的偏好&#xff0c;ChatGPT将在未来的所有对话中记住它们。 该功…

Redis高可用部署架构

目录 1. 主从复制与哨兵架构&#xff1a;2. Redis集群架构&#xff1a; Redis高可用部署可以采用主从复制与哨兵架构或Redis集群架构。下面将分别介绍这两种架构的架构图、优缺点和具体应用场景。 1. 主从复制与哨兵架构&#xff1a; 架构图&#xff1a; ----------| Client…

Python—数据结构(一)

先放一张自己学习和整理归纳的思维导图&#xff0c;以便让大家都知道我自己的整体学习路线。 数据结构的学习路上内容枯燥&#xff0c;但坚持下来一定有很大的收获&#xff01;加油&#x1f4aa;&#x1f3fb;&#xff01; 数据结构 数据的概念数据元素&#xff1a; 若干基本…

Go语言通过反射获取各种类型变量的值

Go语言通过反射获取各种类型变量的值 反射是程序在运行期间获取变量的类型和值、或者执行变量的方法的能力。 1、什么是反射 反射是程序在运行期间获取变量的类型和值、或者执行变量的方法的能力。 Golang 反射包中有两对非常重要的函数和类型&#xff0c;两个函数分别是&a…

音视频开发-ffmpeg介绍-系列二

目录 一、FFmpeg核心结构体 二、解码流程 三、FFmpeg解码实现 四、FFmpeg编码实现 五、FFmpeg转码实现 一、FFmpeg核心结构体 AVFormatContext&#xff1a;解封装功能的结构体&#xff0c;包含文件名、音视频流、时长、比特率等信息&#xff1b; AVCodecContext&#xf…

【算法基础:数学知识】4.3 欧拉函数

文章目录 欧拉函数定义性质 例题列表873. 欧拉函数&#xff08;使用质因数分解求一个数的欧拉函数&#xff09;原理讲解&#xff08;公式推导&#xff09;⭐解法代码 874. 筛法求欧拉函数&#xff08;求 1 ~ n 中所有数字的欧拉函数&#xff09;⭐ 欧拉函数 https://oi-wiki.o…

[数据结构 -- 手撕排序算法第六篇] 递归实现快速排序(集霍尔版本,挖坑法,前后指针法为一篇的实现方法,很能打)

目录 1、常见的排序算法 1.1 交换排序基本思想 2、快速排序的实现方法 2.1 基本思想 3 hoare&#xff08;霍尔&#xff09;版本 3.1 实现思路 3.2 思路图解 3.3 为什么实现思路的步骤2、3不能交换 3.4 hoare版本代码实现 3.5 hoare版本代码测试 4、挖坑法 4.1 实现…

Java设计模式解析:迭代器模式的实现与应用

迭代器模式是一种行为型设计模式&#xff0c;它提供了一种统一的方式来遍历集合中的元素&#xff0c;而无需暴露集合的内部结构。在本文中&#xff0c;我们将深入探讨迭代器模式的实现和应用。 在软件开发中&#xff0c;集合是一种常见的数据结构&#xff0c;用于存储和管理一…

【手撕排序算法】---基数排序

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【数据结构初阶&#xff08;C实现&#xff09;】 我们直到一般的排序都是通过关键字的比较和移动这两种操作来进行排序的。 而今天介绍的…

​MySQL高阶语句(三)

目录 1、内连接 2、左连接 3、右连接&#xff1a; 二、存储过程⭐⭐⭐ 4. 调用存储过程 5.查看存储过程 5.1 查看存储过程 5.2查看指定存储过程信息 三. 存储过程的参数 3.1存储过程的参数 3.2修改存储过程 四.删除存储过程 MySQL 的连接查询&#xff0c;通常都是将来…

微服务一 实用篇 - 5.分布式搜索引擎(ElasticSearch基础)

《微服务一 实用篇 - 5.分布式搜索引擎&#xff08;ElasticSearch基础&#xff09;》 提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!! 《微服务一 实用篇 - 5.分布式搜索引擎&#xff08;ElasticSearch基础&#xff09;》 《微服务一 实用篇 - 5.分布式搜索…

【广州华锐互动】列车人员疏散VR虚拟演练系统

随着科技的不断发展&#xff0c;虚拟现实(VR)技术已经逐渐应用于各个领域。在火车站安全方面&#xff0c;为了提高旅客的安全意识和应对突发事件的能力&#xff0c;列车人员疏散VR虚拟演练系统应运而生。 列车人员疏散VR虚拟演练系统是一种基于虚拟现实技术的教育培训系统&…

数据结构问答7

1. 图的定义和相关术语 答: 定义:图是由顶点集V和边集E组成,其中V为有限非空集。 相关术语:n个顶点,e条边,G=(V,E) ① 邻接点和端点:无向图中,若存在一条边(i, j),则称i,j为该边的端点,且它们互为邻接点;在有向图中,若存在一条边<i, j>,则称i,j分别为…

js浅拷贝与深拷贝

var value 10; var valueCopy value; valueCopy 1000 console.log(value, valueCopy) // 10 1000以上value结果的值没有随着valueCopy的改变而改变是因为数字&#xff0c;字符串是原始值&#xff0c;当重新给它赋值时不会在原地址修改而是新开一块地址 引用类型就是指向同…

【Vue】day03-VueCli(脚手架)

day03 一、今日目标 1.生命周期 生命周期介绍 生命周期的四个阶段 生命周期钩子 声明周期案例 2.综合案例-小黑记账清单 列表渲染 添加/删除 饼图渲染 3.工程化开发入门 工程化开发和脚手架 项目运行流程 组件化 组件注册 4.综合案例-小兔仙首页 拆分模块-局部…

SpringBoot 如何使用 MockMvc 进行 Web 集成测试

SpringBoot 如何使用 MockMvc 进行 Web 集成测试 介绍 SpringBoot 是一个流行的 Java Web 开发框架&#xff0c;它提供了一些强大的工具和库&#xff0c;使得开发 Web 应用程序变得更加容易。其中之一是 MockMvc&#xff0c;它提供了一种测试 SpringBoot Web 应用程序的方式&…

什么是神经网络?

我们常常使用深度学习来指训练神经网络的过程。 在这里举一个房屋价格预测的例子&#xff1a;假设有一个数据集&#xff0c;它包含了六栋房子的信息。所以&#xff0c;你知道房屋的面积是多少平方米&#xff0c;并且知道这个房屋的价格。这是&#xff0c;你想要拟合一个根据房屋…

el-form 初值和resetFields问题

配置片段。 给dataForm动态赋初值&#xff0c;必须如下&#xff0c;用 this.dataForm{}这种方式&#xff0c;其他的形式如 this.dataForm.属性、this.dataForm[属性] 都会失败且造成 el-form和resetFields 出现问题 <el-formref"dataForm":model"dataForm&qu…

【论文阅读】DQnet: Cross-Model Detail Querying for Camouflaged Object Detection

DQnet: Cross-Model Detail Querying for Camouflaged Object Detection DQnet&#xff1a;伪装目标检测中的跨模型细节查询 论文地址&#xff1a;https://arxiv.org/abs/2212.08296 这篇文章提出了一个交叉模型框架&#xff08;CNN-Transformer并行&#xff09;来检测伪装目…

【自启动配置】Ubuntu 设置开机自启动脚本

Ubuntu 开机运行的脚本和当前操作系统运行的级别有关&#xff0c;OS 的运行级别大概分为七个 目录 1、查看 OS 运行级别 2、创建自启动脚本 3、添加软链接 1、查看 OS 运行级别 输入命令 runlevel 查看当前系统运行级别。当前系统的运行级别为 5 2、创建自启动脚本 在 /et…