gd32F303串口接收的几种方式

文章介绍了如何通过接收中断和空闲中断实现串口数据的接收,以及如何使用DMA优化数据传输,以减少CPU资源消耗。首先详细描述了接收中断的使用方法,然后引入空闲中断来解决数据长度未知的问题,最后展示了利用DMA进行高效串口接收的配置过程。
摘要由CSDN通过智能技术生成

一、串口接受到换行符停止

#include "usart.h"

UCHAR arr_rxData[1024]={0};//存储串口接收的数据
UINT arr_len=0;//串口已经接收数据的字节数个数
USART_RX_FLAG rxFlg=FLASE;//默认串口未接收到数据

void USART2_Init(void)
{
	rcu_periph_clock_enable(RCU_GPIOB); //enable GPIO clock 
	rcu_periph_clock_enable(RCU_USART2);// enable USART clock

	gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10); // USARTx_Tx 
	gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_11);//USARTx_Rx

	usart_deinit(USART2); //USART configure 
	usart_baudrate_set(USART2, 115200);                //设置波特率
	usart_word_length_set(USART2, USART_WL_8BIT);      //设置数据位
	usart_parity_config(Uusart_hardware_flow_rts_config(USART2, USART_RTS_DISABLE); 
	usart_hardware_flow_cts_config(USART2, USART_CTS_DISABLE); //无硬件数据流控制
	usart_receive_config(USART2, USART_RECEIVE_ENABLE);        //使能接收器
	usart_transmit_config(USART2, USART_TRANSMIT_ENABLE);      //使能发送器
	
	nvic_irq_enable(USART2_IRQn, 1, 0);//配置NVIC分组,初始化NVIC分组4
	usart_interrupt_enable(USART2, USART_INT_RBNE);//使能接收中断
	usart_enable(USART2);//使能串口
}

int fputc(int ch, FILE *f) 
{
    while(RESET == usart_flag_get(USART2, USART_FLAG_TBE));
    usart_data_transmit(USART2, (uint8_t)ch);
    return ch;
}

/****************************************************************************
1、如果使能接收中断但是还是没有进入中断处理函数,可能是硬件接线比较松,导致出现问题
2、接收数据代码书写
	if(rxFlg==TRUE)//表示接受一次数据完成
	{
		printf("receive data:%s\r\n",arr_rxData);
		
		//将接收数据的标志位,数据长度,存储数据数组都清0
		rxFlg=FLASE;
		arr_len=0;
		memset(arr_rxData,0,sizeof(arr_rxData));
	}
******************************************************************************/
void USART2_IRQHandler(void) 
{
	if(RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_RBNE)){
        arr_rxData[arr_len++]=usart_data_receive(USART2);
		if(arr_rxData[arr_len-1]==0x0a)
		{
			rxFlg=TRUE;
			arr_len--;
			arr_rxData[arr_len]='\0';
		}
    }
    //usart_interrupt_flag_clear(USART2, USART_INT_FLAG_RBNE);
	/*清除中断标志位,不用手动清除中断标志位,因为不管是直接读寄存器还是通过DMA,只要是对USART_DATA寄存器的一个读操作都可以硬件自动清除RBNE位*/
}

 

二、使用空闲中断实现串口接收 

    对于串口接收到的数据,还有很重要的一点就是不确定长度,这样就不知道何时该停止接收,这个时候,串口的空闲中断就体现出他的重要性了,那么什么是空闲中断呢?

        空闲中断是在检测到有数据接收后,总线上在一个字节的时间内没有再接收到数据时,从而产生中断。即串口的RXNE位被置位之后才开始检测,检测到空闲之后,串口的CR1寄存器的IDLE位被硬件置1。

#include "usart.h"

UCHAR arr_rxData[1024]={0};//存储串口接收的数据
UINT arr_len=0;//串口已经接收数据的字节数个数
USART_RX_FLAG rxFlg=FLASE;//默认串口未接收到数据

void USART2_Init(void)
{
	rcu_periph_clock_enable(RCU_GPIOB); //enable GPIO clock 
	rcu_periph_clock_enable(RCU_USART2);// enable USART clock

	gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10); // USARTx_Tx 
	gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_11);//USARTx_Rx

	usart_deinit(USART2); //USART configure 
	usart_baudrate_set(USART2, 115200);                //设置波特率
	usart_word_length_set(USART2, USART_WL_8BIT);      //设置数据位
	usart_parity_config(Uusart_hardware_flow_rts_config(USART2, USART_RTS_DISABLE); 
	usart_hardware_flow_cts_config(USART2, USART_CTS_DISABLE); //无硬件数据流控制
	usart_receive_config(USART2, USART_RECEIVE_ENABLE);        //使能接收器
	usart_transmit_config(USART2, USART_TRANSMIT_ENABLE);      //使能发送器
	
	nvic_irq_enable(USART2_IRQn, 1, 0);//配置NVIC分组,初始化NVIC分组4
	usart_interrupt_enable(USART2, USART_INT_RBNE);//使能接收中断
	usart_enable(USART2);//使能串口
}

int fputc(int ch, FILE *f) 
{
    while(RESET == usart_flag_get(USART2, USART_FLAG_TBE));
    usart_data_transmit(USART2, (uint8_t)ch);
    return ch;
}

void USART2_IRQHandler(void) 
{
	if(RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_RBNE)){
        arr_rxData[arr_len++]=usart_data_receive(USART2);
    }
	if(RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_IDLE))
	{
		usart_interrupt_flag_clear(USART2,USART_INT_FLAG_IDLE);	/* 清除空闲中断标志位 */
		usart_data_receive(USART2);		
		rxFlg=TRUE;
		arr_len--;
		arr_rxData[arr_len]='\0';
	}
}

三、使用DMA转运数据实现串口接收 

 对于串口的数据接收来说,和发送一样,如果采用传统的接收中断模式接收数据,同样的会因为频繁中断而导致消耗大量CPU资源,所以也使用DMA进行串口数据的接收。

#define USART2_ADDR (uint32_t)&USART_DATA(USART2)
UCHAR UART2_RX_BUF[UART2_RX_LEN*2]; 		/* 双接收缓冲区 */
USART_RX_FLAG UART2_RX_STAT = FLASE;	
UINT UART2_RX_NUM = 0;					/* 接收到的数据个数 */

void USART2_DMA_Init(void)
{
	dma_parameter_struct dma_init_struct;	/* DMA配置参数结构体 */
	
	rcu_periph_clock_enable(RCU_GPIOB); //enable GPIO clock 
	rcu_periph_clock_enable(RCU_USART2);// enable USART clock
	rcu_periph_clock_enable(RCU_DMA0);		/* 使能 DMA0 时钟 */

	gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10); 
	gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_11);

	usart_deinit(USART2); //USART configure 
	usart_baudrate_set(USART2, 115200);                //设置波特率
	usart_word_length_set(USART2, USART_WL_8BIT);      //设置数据位
	usart_parity_config(USART2, USART_PM_NONE);        //设置奇偶校验位
	usart_stop_bit_set(USART2, USART_STB_1BIT);        //设置停止位
	usart_hardware_flow_rts_config(USART2, USART_RTS_DISABLE); //禁用rts
	usart_hardware_flow_cts_config(USART2, USART_CTS_DISABLE); //无硬件数据流控制
	usart_receive_config(USART2, USART_RECEIVE_ENABLE);        //使能接收器
	usart_transmit_config(USART2, USART_TRANSMIT_ENABLE);      //使能发送器
	
	/* USART0 DMA 接收配置*/
    dma_deinit(DMA0, DMA_CH2);/*USART2_RX:CH2 USART0_RX:CH4*/
	dma_struct_para_init(&dma_init_struct);
    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;		/* 外设到存储器方向 */
    dma_init_struct.memory_addr = (uint32_t)UART2_RX_BUF;		/* 存储器基地址 */
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;	/* 存储器地址自增 */
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;		/* 存储器位宽为8位 */
   dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;			/* 软件优先级为极高*/
    dma_init(DMA0, DMA_CH2, &dma_init_struct);

    dma_circulation_disable(DMA0, DMA_CH2);/* DMA循环模式配置,不使用循环模式 */
    usart_dma_transmit_config(USART2, USART_DENT_ENABLE);
	usart_dma_receive_config(USART2, USART_DENR_ENABLE);
	nvic_irq_enable(DMA0_Channel2_IRQn, 0, 0);/* DMA0 通道2 中断优先级设置并使能 */
    dma_channel_enable(DMA0, DMA_CH2);/* 使能 DMA0 通道2 */
	
	nvic_irq_enable(USART2_IRQn, 1, 0);//配置NVIC分组,初始化NVIC分组4
	usart_interrupt_enable(USART2, USART_INT_IDLE);/* 使能USART0空闲中断 */
	usart_enable(USART2);//使能串口
}

/*
如果接收完毕,那么将数据打印出来
if(UART2_RX_STAT == TRUE)
{
	UART2_RX_STAT = FLASE;
	printf("RECEIVE %d data:%s \r\n", UART2_RX_NUM, UART2_RX_BUF);
}
*/
void USART2_IRQHandler(void)	
{
    if(RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_IDLE)) //空闲中断
	{
		usart_interrupt_flag_clear(USART2,USART_INT_FLAG_IDLE);	/* 清除空闲中断标志位 */
		usart_data_receive(USART2);								/* 清除接收完成标志位 */
		dma_channel_disable(DMA0, DMA_CH2);						/* 关闭DMA传输 */
		
		UART2_RX_NUM = sizeof(UART2_RX_BUF) - dma_transfer_number_get(DMA0,DMA_CH2);
		UART2_RX_BUF[UART2_RX_NUM] = '\0';	/* 添加字符串结束符 */
		UART2_RX_STAT = TRUE;/* 接收完成 */				
		
		/* 重新设置DMA传输 */
		dma_memory_address_config(DMA0,DMA_CH2,(uint32_t)UART2_RX_BUF);
		dma_transfer_number_config(DMA0,DMA_CH2,sizeof(UART2_RX_BUF));
		dma_channel_enable(DMA0, DMA_CH2);		/* 开启DMA传输 */
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值