【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 tx
    GPIO_Module* tx_gpiox;//发送引脚分组
    uint16_t tx_pin;//发送引脚编号
    uint32_t tx_gpio_rcc;//发送引脚时钟
    uint8_t tx_afx;//引脚复用模式
    //gpio rx
    GPIO_Module* rx_gpiox;//接收引脚分组
    uint16_t rx_pin;//接收引脚号
    uint32_t rx_gpio_rcc;//接收引脚时钟
    uint8_t rx_afx;//引脚复用模式
    //uart
    USART_Module* uartx;//串口句柄
    uint32_t uart_rcc;//串口时钟
    uint32_t bate;//串口波特率
    IRQn_Type irqx;//中断编号

    uint8_t it_rx:1;//串口中断接收使能
    uint8_t it_idle:1;//串口接收空闲中断使能
    //flag
    uint8_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 tx
        GPIOA,GPIO_PIN_10,RCC_APB2_PERIPH_GPIOA,GPIO_AF4_USART1,//gpio rx
        USART1,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,//dma
        1,1,0,0//switch
    },
    //UART2
    {   GPIOB,GPIO_PIN_4,RCC_APB2_PERIPH_GPIOB,GPIO_AF4_USART2,//gpio tx
        GPIOB,GPIO_PIN_5,RCC_APB2_PERIPH_GPIOB,GPIO_AF6_USART2,//gpio rx
        USART2,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,//dma
        1,1,0,0//switch
    },
    //UART3
    {   GPIOB,GPIO_PIN_10,RCC_APB2_PERIPH_GPIOB,GPIO_AF0_USART3,//gpio tx
        GPIOB,GPIO_PIN_11,RCC_APB2_PERIPH_GPIOB,GPIO_AF5_USART3,//gpio rx
        USART3,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,//dma
        1,1,0,0//switch
    },

};


/*

 */
void bsp_uart_rcc_config(uart_t *puartx )
{

    // Enable GPIO clock
    RCC_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.mfbz.cn/a/47463.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构 | 基本数据结构——栈

目录 一、线性数据结构 二、栈 2.1 何谓栈 2.2 栈抽象数据类型 2.3 用Python实现栈 2.4 匹配括号 2.5 普通情况&#xff1a;匹配符号 2.6 将十进制数转换成二进制数 3.7 前序、中序和后序表达式 3.7.1 从中序到后序的通用转换法 3.7.2 计算后序表达式 一、线性数据结…

GAMS---典型优化模型和算法介绍、GAMS安装和介绍、GAMS程序编写、GAMS程序调试、实际应用算例演示与经验分享

优化分析是很多领域中都要面临的一个重要问题&#xff0c;求解优化问题的一般做法是&#xff1a;建立模型、编写算法、求解计算。常见的问题类型有线性规划、非线性规划、混合整数规划、混合整数非线性规划、二次规划等&#xff0c;优化算法包括人工智能算法和内点法等数学类优…

第一百一十四天学习记录:C++提高:类模板案例(黑马教学视频)

类模板案例 main.cpp代码&#xff1a; #include "myarray.hpp"void printIntArray(MyArray <int>& arr) {for (int i 0; i < arr.getSize(); i){cout << arr[i] << " ";}cout << endl; }void test01() {MyArray <int&…

图为科技T501赋能工业机器人 革新传统工业流程

工业机器人已成为一个国家制造技术与科技水平的重要衡量标准&#xff0c;在2019年&#xff0c;中国工业机器人的组装量与产量均位居了全球首位。 当前&#xff0c;工业机器人被广泛用于电子、物流、化工等多个领域之中&#xff0c;是一种通过电子科技和机械关节制作出来的智能机…

超详细推导逻辑回归公式与代码实现(二分类与多分类)

目录 概述逻辑回归理论数学推导二类分类多分类 代码实现备注 概述 本文使用梯度下降法对逻辑回归进行训练&#xff0c;使用类似于神经网络的方法进行前向传播与反向更新&#xff0c;使用数学公式详细推导前向传播与反向求导过程&#xff0c;包括二分类和多分类问题&#xff0c…

OS1_进程与线程的管理

序言 1.OS以进程、线程的方式在CPU中执行静态保存在外存(内存)中的程序&#xff0c;进程的构成与状态转化&#xff0c;特别是进程的切换&#xff1b; 2.当有多个进程处于就绪态&#xff0c;有哪些常见的挑选以执行方式&#xff1b; 3.并发执行(乱序发射)的进程&#xff0c;共享…

c# Outlook检索设定问题

基于c# 设定outlook约会予定&#xff0c;时间格式是YYYY-MM-DD HH:mm 的情报。 问题发生&#xff1a; 根据开始时间&#xff08;2023/01/01 7:00&#xff09;条件查询该时间是否存在outlook信息时&#xff0c;明明存在一条数据&#xff0c;就是查询不出来数据 c#代码 Strin…

20.1:ABC对应123问题

规定1和A对应、2和B对应、3和C对应…26和Z对应 那么一个数字字符串比如"111”就可以转化为: “AAA”、“KA"和"AK” 给定一个只有数字字符组成的字符串str&#xff0c;返回有多少种转化结果 一&#xff1a;暴力方法 public static int number(String str) {…

使用nginx和ffmpeg搭建HTTP FLV流媒体服务器(摄像头RTSP视频流->RTMP->http-flv)

名词解释 RTSP &#xff08;Real-Time Streaming Protocol&#xff09; 是一种网络协议&#xff0c;用于控制实时流媒体的传输。它是一种应用层协议&#xff0c;通常用于在客户端和流媒体服务器之间建立和控制媒体流的传输。RTSP允许客户端向服务器发送请求&#xff0c;如…

4. 方法(函数)

文章目录 4.1. 什么是方法的返回值?返回值在类的方法里的作用是什么?4.2. 为什么 Java 中只有值传递&#xff1f; 4.1. 什么是方法的返回值?返回值在类的方法里的作用是什么? 方法的返回值是指我们获取到的某个方法体中的代码执行后产生的结果&#xff01;&#xff08;前提…

机器学习02-再识K邻近算法(自定义数据集训练及测试)

定义&#xff1a; 如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别&#xff0c;则该样本也属于这个类别。简单的说就是根据你的“邻居”来推断出你的类别。 用个成语就是物以类聚 思想&#xff1a; 如果一个样本在特征空间中的K个最…

视频内存过大如何压缩变小?这个压缩方法了解一下

在日常生活中&#xff0c;不管是日常随手拍的视频还是在工作中遇到的视频文件&#xff0c;在编辑处理的时候&#xff0c;如果视频的内存过大&#xff0c;不仅会占用很大的内存&#xff0c;在传送的时候也会花费很长时间&#xff0c;这时候将视频给压缩一下就可以很好的解决这一…

使用ComPDFKit PDF SDK 构建iOS PDF阅读器

在当今以移动为先的世界中&#xff0c;为企业和开发人员创建一个iOS应用程序是必不可少的。随着对PDF文档处理需求的增加&#xff0c;使用ComPDFKit这个强大的PDF软件开发工具包&#xff08;SDK&#xff09;来构建iOS PDF阅读器和编辑器可以让最终用户轻松查看和编辑PDF文档。 …

Elasticsearch监控工具Cerebro安装

Elasticsearch监控工具Cerebro安装 1、在windwos下的安装 1.1 下载安装包 https://github.com/lmenezes/cerebro/releases/download/v0.9.4/cerebro-0.9.4.zip 1.2 解压 1.3 修改配置文件 如果需要修改相关信息&#xff0c;编辑C:\zsxsoftware\cerebro-0.9.4\conf\applica…

mybatis日志工厂

前言&#xff1a; 如果一个数据库操作&#xff0c;出现异常&#xff0c;我们需要排错&#xff0c;日志就是最好的助手 官方给我们提供了logImpl&#xff1a;指定 MyBatis 所用日志的具体实现&#xff0c;未指定时将自动查找。 默认工厂&#xff1a; 在配置文件里添加&#xf…

桥梁安全监测系统中数据采集上传用 什么?

背景 2023年7月6日凌晨时分&#xff0c;G5012恩广高速达万段230公里加80米处6号大桥部分桥面发生垮塌&#xff0c;导致造成2车受损后自燃&#xff0c;3人受轻伤。目前&#xff0c;四川省公安厅交通警察总队高速公路五支队十四大队民警已对现场进行双向管制。 作为世界第一桥梁…

msvcp140.dll丢失怎么办?(详细解决方法)

1.msvcp140.dll有什么用&#xff1f; 运行C程序&#xff1a;msvcp140.dll文件包含了许多C程序所需的函数和资源&#xff0c;使得C程序能够在计算机上正确运行。 提供运行时库&#xff1a;msvcp140.dll文件包含了C程序在运行时所需的库文件&#xff0c;如输入/输出操作、内存管…

pdf合并大小不一样怎么办?有这几个方法就够了

pdf合并大小不一样怎么办&#xff1f;在日常工作和生活中&#xff0c;我们经常需要处理PDF文件。在将多个PDF文件合并成一个时&#xff0c;由于这些文件的大小和格式可能不同&#xff0c;可能会遇到一些问题。但不用担心&#xff0c;接下来将介绍几种方法来解决这个问题。 方法…

小程序轮播图的两种后台方式(JSP)--【浅入深出系列009】

微信目录集链接在此&#xff1a; 详细解析黑马微信小程序视频–【思维导图知识范围】难度★✰✰✰✰ 不会导入/打开小程序的看这里&#xff1a;参考 让别人的小程序长成自己的样子-更换window上下颜色–【浅入深出系列001】 文章目录 本系列校训学习资源的选择啥是轮播图轮播…

【广州华锐互动】VR模拟灭火逃生体验系统

VR模拟灭火逃生体验系统由广州华锐互动开发&#xff0c;是一种基于虚拟现实技术的应急演练与培训系统&#xff0c;可以真实模拟消防逃生场景&#xff0c;让体验者在沉浸式的虚拟环境中&#xff0c;根据正确的消防逃生方法提示&#xff0c;进行自救演练。这种科学普及方法是更加…
最新文章