资讯详情

GD32F4(4):GD32F450串口的使用

GD32F44使用标准库配置串口

文章目录

  • GD32F44使用标准库配置串口
    • 1. 系统环境
    • 2. 初始化串口(USART0为例)
      • 2.1 打开引脚和外设时钟
      • 2.2 将引脚配置为复用功能
      • 2.3 配置引脚模式
      • 2.4 配置串口参数
      • 2.5 使能串口
      • 2.6 举一个完整的例子
    • 3. 使用串口中断
      • 3.1 开启中断
      • 3.2 举一个完整的例子

1. 系统环境

2. 初始化串口(USART0为例)

2.1 打开引脚和外设时钟

//打开时钟 rcu_periph_clock_enable(RCU_GPIOA);//使能引脚时钟 rcu_periph_clock_enable(RCU_USART0);//使外设时钟 

2.2 将引脚配置为复用功能

//配置复用功能 gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9); //配置PA9为复用类别7 gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10); 

在数据手册中指出,对于GPIO,作为外设接口使用时AFIO功能(在用户手册叫备用功能),也就是复用,引脚最多支持16种复用模式,每个引脚支持的复用种类,和种类所对应的功能是固定的,如下图(我的是在《GD32F450xx_Datasheet_Rev2.2.pdf》的第2.6.4章节): 在这里插入图片描述

从红框可以看出,当将引脚PA9.PA10复用为AF_7.引脚功能为串口0收发接口。对于将串口0复用于其他引脚,需要在数据手册中找到相应的AF组别。

2.3 配置引脚模式

在数据手册中,我们知道标准gpio结构图如下:

//配置pa9引脚的模式 gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_9);//配置pa9复用上拉模式 gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);//配置pa9为推挽输出,速度为50M //配置pa10引脚的模式 gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_10);//配置pa10复用上拉模式 //gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10);//这句话只对输出引脚有效,输入不需要添加这句话 

2.4 配置串口参数

//串口配置 usart_deinit(USART0); //复位口
usart_baudrate_set(USART0,115200U);	//设置串口波特率 

这里只设置了波特率,起始奇偶校验,数据位数,停止位设置都有相应的函数,在gd32f4xx_usart.c中,如:

void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg)//设置奇偶校验
void usart_word_length_set(uint32_t usart_periph, uint32_t wlen)//配置数据位数
void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen)//设置停止位
void usart_data_first_config(uint32_t usart_periph, uint32_t msbf)//设置数据发送和接收的时候数据高位在前还是低位在前

对于串口,波特率是必须设置的,其他可以不设置,就会配置成:不奇偶校验、8位数据位、一个停止位、数据低位在前的默认模式。

2.5 使能串口

usart_receive_config(USART0, USART_RECEIVE_ENABLE);//使能串口接收
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);//使能串口发送
usart_enable(USART0);//使能串口

2.6 举一个完整的例子

#include "gd32f4xx.h"
#include "gd32f450z_eval.h"
#include "systick.h"

void uart0_init()
{ 
        
    //开启时钟
    rcu_periph_clock_enable(RCU_GPIOA);//使能引脚时钟
    rcu_periph_clock_enable(RCU_USART0);//使能外设时钟

    //配置复用功能
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9); //配置PA9为复用类别7
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);

    //配置引脚的模式
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_9);//配置pa9为复用上拉模式
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);//配置pa9为推挽输出,速度为50M

    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_10);
    //gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10);//这就话对输入引脚来说

    //串口配置
    usart_deinit(USART0);	//复位串口
    usart_baudrate_set(USART0,115200U);	//设置串口波特率 
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);//使能串口接收
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);//使能串口发送
    usart_enable(USART0);//使能串口
}

int main(void)
{ 
        
    uint16_t rx_data = 0;
	//初始化串口
	uart0_init();

    while(1){ 
        
        //数据接收
        while (usart_flag_get(USART0, USART_FLAG_RBNE) == RESET);
		rx_data = usart_data_receive(USART0); //获取字符 
        //发送数据 
        usart_data_transmit(USART0, (uint8_t)rx_data);
        while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
    }
}

现在把usb转串口接到mcu引脚上,上位机发送什么,mcu就会返回什么,一个简单的串口0回显就完成了。

3. 串口中断的使用

上面虽然可以使用串口,但是对于我们来讲,使用串口中断接收才是我们最常用的方式。

3.1 开启中断

开启中断一般包括部分:

  • 系统刚启动,首先要配置系统的中断优先级分组,抢占优先级和响应优先级位数。

  • 配置外设中断的响应优先级和抢占优先级。

  • 对于外设,要配置使能中断的类型,比如:使能串口接收中断和发送中断。

  • 编写中断函数。

针对这4点,下面分别实现。

  1. gd32f4xx_misc.c里面有GD标准库提供的函数nvic_priority_group_set是设置中断优先级分组的函数,参数对应如下:
NVIC_PRIGROUP_PRE0_SUB4     :0 bits for pre-emption priority 4 bits for subpriority
NVIC_PRIGROUP_PRE1_SUB3     :1 bits for pre-emption priority 3 bits for subpriority
NVIC_PRIGROUP_PRE2_SUB2     :2 bits for pre-emption priority 2 bits for subpriority
NVIC_PRIGROUP_PRE3_SUB1     :3 bits for pre-emption priority 1 bits for subpriority
NVIC_PRIGROUP_PRE4_SUB0     :4 bits for pre-emption priority 0 bits for subpriority
nvic_priority_group_set(NVIC_PRIGROUP_PRE0_SUB4)

对于中断分组还有另外一个函数NVIC_SetPriorityGrouping,在core_cm4.h中,这两个函数效果是一样的。

  1. 同样设置中断的优先级也提供了GD标准库和ARM核心库两种函数,:
nvic_irq_enable(USART0_IRQn, 0, 0);//GD标准库
NVIC_SetPriority(SysTick_IRQn, 0x00U);//基于CMSIS标准的ARM库函数
  1. 对于开启中断,我们要在初始化串口后,添加:
//使能串口接收中断
usart_interrupt_enable(USART0, USART_INT_RBNE);
//使能串口发送中断
//usart_interrupt_enable(USART0, USART_INT_TBE);

  1. 编写串口中断函数

开启中断后,就要编写中断函数,一般我们都将中断函数放在gd32f4xx_it.c中,和STM32一样,GD的中断函数名字也是固定的。

void USART0_IRQHandler(void)
{ 
        
    if((RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) && 
       (RESET != usart_flag_get(USART0, USART_FLAG_RBNE))){ 
        
        /* Read one byte from the receive data register */
    }
       
    if((RESET != usart_flag_get(USART0, USART_FLAG_TBE)) && 
       (RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_TBE))){ 
        
        /* Write one byte to the transmit data register */
    }
}

3.2 举一个完整的例子

针对上面的叙述,进行总结,如下:

#include "gd32f4xx.h"
#include "gd32f450z_eval.h"
#include "systick.h"

void uart0_init()
{ 
        
    //开启时钟
    rcu_periph_clock_enable(RCU_GPIOA);//使能引脚时钟
    rcu_periph_clock_enable(RCU_USART0);//使能外设时钟

    //配置复用功能
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9); //配置PA9为复用类别7
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);

    //配置引脚的模式
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_9);//配置pa9为复用上拉模式
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);//配置pa9为推挽输出,速度为50M

    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_10);
    //gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10);

    //串口配置
    usart_deinit(USART0);	//复位串口
    usart_baudrate_set(USART0,115200U);	//设置串口波特率 
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);//使能串口接收
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);//使能串口发送
    usart_enable(USART0);//使能串口
}

int main(void)
{ 
        
    uint16_t rx_data = 0;
    nvic_priority_group_set(NVIC_PRIGROUP_PRE0_SUB4);//配置优先级分组
	//初始化串口
	uart0_init();
	nvic_irq_enable(USART0_IRQn, 0, 0);//设置串口中断的优先级
	//开启串口接收中断
    usart_interrupt_enable(USART0, USART_INT_RBNE);
    //开启串口发送中断
    //usart_interrupt_enable(USART0, USART_INT_TBE);//暂时不开启串口发送中断
    while(1){ 
        
		;
    }
}

gd32f4xx_it.c编写串口中断函数

void USART0_IRQHandler(void)
{ 
        
    uint8_t rx_data = 0;
    //当接收中断发生
    if((RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) && 
       (RESET != usart_flag_get(USART0, USART_FLAG_RBNE))){ 
        
        /* Read one byte from the receive data register */
        rx_data = (uint8_t)usart_data_receive(USART0);//获取接收到的数据
 		usart_data_transmit(USART0, rx_data);//将接收到的字符输出,做回显显示
    }
    
     //当发送中断发生
    if((RESET != usart_flag_get(USART0, USART_FLAG_TBE)) && 
       (RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_TBE))){ 
        
        /* Write one byte to the transmit data register */
    }
}

通过这个程序就能实现串口的中断接受了。

:相对于stm32的标准库需要手动清除中断标志位,GD在发生中断后不需要手动调用clear函数清零,那是因为它可以自动清零,在用户手册里面写了它自动清零的条件,如下:

即可以调用函数清零:

usart_interrupt_flag_clear(USART0, USART_INT_FLAG_RBNE);//清除接收中断发生标志位

或,当读取接收寄存器的时候,接收中断发生标志位自动清除

usart_data_receive(USART0);//获取接收到的数据

标签: 220f450v5a三极管f450光电开关传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台