这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » 【GD32F527】串口中断不定长接收

共1条 1/1 1 跳转至

【GD32F527】串口中断不定长接收

高工
2025-11-20 07:29:51   被打赏 50 分(兑奖)     打赏

【前言】

准备做个血氧采集的程序,他的接口为串口,因此找出开发板做一个串口接收的程序,现在用不长定接收来实现一下。

【串口选择】

由于使用日志打印占用了开发板上的USART0,开发板的接口为2.0接口,也没有焊接,查找原理图,发现可以使用摄像头接口的PC6、PC7来配置为USART5接口。其原理图如下:

image.png

再看看GD32F27的数据手册,找到复用表,将其复用为AF8即可:

image.png

【串口初始化】

串口初始化的步骤是开启GPIOC时钟->开启USART时钟->配置GPIO输出模式->复用IO->配置串口参数(如波特率数据位等)->配置中断级别->使能串口接与发送->开启接收中断(RBNE)与空闲中断(IDLE)。代码如下:

#define MKS_GPIO_PORT    GPIOC
#define MKS_UART         USART5  
#define MKS_UART_AF      GPIO_AF_8
#define MKS_UART_PIN_TX  GPIO_PIN_6
#define MKS_UART_PIN_RX  GPIO_PIN_7

void MKS_UART_Init(void)
{
    /* enable GPIO clock */
    rcu_periph_clock_enable(RCU_GPIOC);

    /* enable USART clock */
    rcu_periph_clock_enable(RCU_USART5);
    
    /* enable NVIC interrupt */

    nvic_irq_enable(USART5_IRQn, 10, 0);

    /* connect port to USART5_Tx */
    gpio_af_set(GPIOC, MKS_UART_AF, MKS_UART_PIN_TX);

    /* connect port to USART5_Rx */
    gpio_af_set(GPIOC, MKS_UART_AF, MKS_UART_PIN_RX);

    /* configure USART Tx as alternate function push-pull */
    gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_PULLUP, MKS_UART_PIN_TX);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, MKS_UART_PIN_TX);

    /* configure USART Rx as alternate function push-pull */
    gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_PULLUP, MKS_UART_PIN_RX);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, MKS_UART_PIN_RX);

    /* USART configure */
    usart_deinit(MKS_UART);
    usart_baudrate_set(MKS_UART, 115200U);
    usart_word_length_set(MKS_UART, USART_WL_8BIT);         // 8位数据位
    usart_stop_bit_set(MKS_UART, USART_STB_1BIT);           // 1位停止位
    usart_parity_config(MKS_UART, USART_PM_NONE);           // 无奇偶校验
    usart_hardware_flow_rts_config(MKS_UART, USART_RTS_DISABLE);  // 禁用RTS
    usart_hardware_flow_cts_config(MKS_UART, USART_CTS_DISABLE);  // 禁用CTS
    
    usart_receive_config(MKS_UART, USART_RECEIVE_ENABLE);
    usart_transmit_config(MKS_UART, USART_TRANSMIT_ENABLE);
    usart_enable(MKS_UART);
    
    /* clear all relevant flags */
    usart_flag_clear(MKS_UART, USART_FLAG_TC);
    usart_flag_clear(MKS_UART, USART_FLAG_RBNE);
    usart_flag_clear(MKS_UART, USART_FLAG_IDLE);
    
    /* enable receive interrupt and IDLE interrupt */
    usart_interrupt_enable(MKS_UART, USART_INT_RBNE);
    usart_interrupt_enable(MKS_UART, USART_INT_IDLE);
}

接下来添加中断回调函数,在中断回调函数中,首先判断是哪个中断,如果是接收中断则进行数据接收,并将数据添加到接收数据中,如果是空闲中断,则认为这一帧数据接收完整,对数据进行处理。

代码如下:

static uint8_t rx_buffer[MAX_BUFFSIZE];    // 接收数据缓冲区
static volatile uint16_t rx_counter = 0;   // 接收字节计数器


/*!
    \brief      this function handles USART RBNE interrupt request and IDLE interrupt request
    \param[in]  none
    \param[out] none
    \retval     none
*/
void USART5_IRQHandler(void)
{

	if(RESET != usart_interrupt_flag_get(MKS_UART, USART_INT_FLAG_RBNE))// 获取USART中断标志位状态
		                                                                // USART_INT_FLAG_RBNE:读数据缓冲区非空中断标志
	{ 
		usart_interrupt_flag_clear(MKS_UART, USART_INT_FLAG_RBNE);// 清除USART中断标志位状态
		
		uint8_t ch = (uint8_t)usart_data_receive(MKS_UART);// USART接收数据功能
		rx_counter = (rx_counter + 1)% MAX_BUFFSIZE; 
		rx_buffer[rx_counter] = ch;
	}

	else if(RESET != usart_interrupt_flag_get(MKS_UART, USART_INT_FLAG_IDLE))// USART_INT_FLAG_IDLE:IDLE线检测中断标志
	{
		usart_interrupt_flag_clear(MKS_UART, USART_INT_FLAG_IDLE);
		
		if(rx_counter > 0)
		{		
			usart_interrupt_disable(MKS_UART, USART_INT_RBNE);// 失能USART中断
			usart_interrupt_disable(MKS_UART, USART_INT_IDLE);
			/* 测试部分,接收到的数据最好在main中处理掉 */
			MKS_UART_SendData(rx_buffer,rx_counter);
			usart_interrupt_enable(MKS_UART, USART_INT_RBNE);
			usart_interrupt_enable(MKS_UART, USART_INT_IDLE);
		}
	}

}

在中断处理中,在进入接收后,需要先清除中断标志位。在进入空闲中断时需要清除中断位,然后失能中断,处理数据后再开启。

【实现效果】

下载到开发板后,就可以看到发什么回给我们什么了。

image.png





关键词: GD32F527     串口     interrupt     usa    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]