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

串口

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

bsp_uart.h

c 复制代码
#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

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);
}
相关推荐
昵称p10 天前
- 串口通信
mcu·串口·usart·中断
InJre1 个月前
QT readyRead()函数,数据分包不完整解决办法
开发语言·qt·串口·readall
C# 学习者2 个月前
C# 串口类封装(仪器控制)
c#·串口·仪器控制
tangYi0_02 个月前
MCU调试技巧-串口打印
单片机·串口·调试技巧·printf·itm·semihosting·segger-rtt
大浪淘沙胡2 个月前
C#串口通信的实现
c#·串口
不做签到员2 个月前
虚拟机Ubuntu20.04 利用串口调试机械臂
ubuntu·串口·机械臂·pyserial
启明智显3 个月前
【启明智显产品介绍】Model3C工业级HMI芯片详解专题(一)芯片性能
嵌入式硬件·串口·启明智显·hmi人机交互·国产hmi芯片·model3c·hmi方案
icysmile1313 个月前
ZYNQ7 Processing System IP核中PS侧Uart的用法
fpga开发·串口
ggtc4 个月前
基于WebSocket的modbus通信(三)- websocket和串口
websocket·c#·串口·modbus
Frey_Liu4 个月前
串口通信问题排查总结
单片机·嵌入式硬件·串口·uart·通信