关于数据通信和串口(USART)的一些笔记

Posted Mr_rustylake

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于数据通信和串口(USART)的一些笔记相关的知识,希望对你有一定的参考价值。

在上次的串口通信的实验里,我们简单介绍了一小部分串口和通信的笔记;并且在上一篇笔记里,我们介绍了三个比较常见和重要的通信协议SPI,I2C和CAN总线通信。今天我们来更深地了解数据通信和串口。

首先我们介绍一些数据通信的分类。

1、数据通信方式分类:按照这种方式,数据通信可以分为串行通信和并行通信。

在串行通信中,数据从发送设备向接收设备按顺序逐步一字节一字节依次传输。比如图中,设备1先向设备2传输b0数据,在设备2接收后,设备1再向设备2传输数据b1,接下来再传输诸如b2,b3,b4等数据。一般在传输了一个字节的数据后,设备2就会向设备2的寄存器存入该数据,进入设备2的cpu进行处理。

串行通信的传输速率较慢,抗干扰能力较强,通信距离较长,IO资源占用较少,成本较低。

在并行通信中,各位数据从发送设备向接收设备同时发送数据。比如在图中,这8位数据(b0~b7)并行同时从发送设备通过多条线路传输给接收设备。

并行通信的传输速率较快,抗干扰能力较弱,通信距离较短,IO资源占用较多,成本较高。

2、数据传输方向分类: 按照这种方式,数据通信可以分为单工通信、半双工通信、全双工通信。

在单工通信中,单方向将数据从发送端发送到接收端,但是数据只能按单一方向传输且不能改变,方向是设计时候指定的。

 在半双工通信中,数据可以从设备1传输到设备2,也可以从设备2传输到设备1,但是半双工通信只有一个信道,同一时间只能进行一次单方向的通信,只有在本次通信完成后才能进行下一次通信,可以理解为把两个不同方向的串行通信联合在一起。

在双工通信中,读者可以理解为把两个不同方向的串行通信联合在一起, 它拥有两条信道,可以在同一时间完成双向的独立通信,互不干扰。

 3、数据同步方式:按照这种方式,数据通信可以分为同步通信和异步通信。

在同步通信中,一般采用以一条数据线、一条信号线(可能还有一条CS/SS触发线),由发送端向接收端发送同步时钟信号(比如SCLK信号),双方共用同一个同步时钟信号,可以利用同步时钟信号的上升沿或者下降沿触发数据采样,比如SPI,也有利用同步时钟信号的高电平作为采样的启动标准,比如I2C。

 在异步通信中,只有一条数据线,没有同步时钟线和触发信号线,传输的信号一般分为起始位、数据位、奇偶校验位和终止位,来区分传输信号的不同目的和采样相应的数据。

 4、比特率/波特率

最后我们介绍一下比特率和波特率。

比特率为每秒传输数据的比特数(二进制),单位为bit/s。

波特率为每秒传播的码元数,单位为Baud。

这两者之间的关系是:比特率=波特率*log2M,M为每个码元所承载的信息量。

比如在二进制系统中,因为在一个二进制信息所携带的信息只有0或1两者,所以M=2,比特率=波特率;或者在16进制系统中,因为在一个16进制信息所携带的信息有0~F的16种,所以M=16,比特率(此处指的是16进制的一个字节,即0x?)=4*波特率。

最后展示一些相应的串行通信接口的一些信息供大家参考:

 

GD32F103学习笔记——USART串口使用

一、简介

通用同步异步收发器(Universal Synchronous Asynchronous Receiver and Transmitter) 是一个串行通信设备,可以灵活地与外部设备进行全双工数据交换。有别于 USART 还有一个 UART(Universal Asynchronous Receiver and Transmitter),它是在 USART 基础上裁剪掉了同步通信功能,只有异步通信。简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基本都是 UART。

串行通信一般是以帧格式传输数据,即是一帧一帧的传输,每帧包含有起始信号、数据信息、停止信息,可能还有校验信息。USART 就是对这些传输参数有具体规定,当然也不是只有唯一一个参数值,很多参数值都可以自定义设置,只是增强它的兼容性。

USART 满足外部设备对工业标准 NRZ 异步串行数据格式的要求,并且使用了小数波特率发生器,可以提供多种波特率,使得它的应用更加广泛。USART 支持同步单向通信和半双工单线通信;还支持局域互连网络 LIN、智能卡(SmartCard)协议与 lrDA(红外线数据协会) SIR ENDEC 规范。

USART 在 GD32 应用最多莫过于“打印”程序信息,一般在硬件设计时都会预留一个 USART 通信接口连接电脑,用于在调试程序是可以把一些调试信息“打印”在电脑端的串口调试助手工具上,从而了解程序运行是否正确、如果出错哪具体哪里出错等等。

USART 支持 DMA 功能,以实现高速率的数据通信,除了 UART4。

二、API说明

以下 USART 接口位于 GD32F10x_Firmware_Library_V2.2.2\\Firmware\\GD32F10x_standard_peripheral\\Include\\gd32f10x_usart.h

2.1 usart_deinit

功能复位外设USART/UART
函数定义void usart_deinit(uint32_t usart_periph)
参数usart_periph:USARTx(x=0,1,2)或UARTx(x=3,4)
返回

2.2 usart_baudrate_set

功能配置USART/UART波特率
函数定义void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval)
参数usart_periph:USARTx(x=0,1,2)或UARTx(x=3,4)
baudval:波特率值
返回

2.3 usart_word_length_set

功能配置USART/UART字长
函数定义void usart_word_length_set(uint32_t usart_periph, uint32_t wlen)
参数usart_periph:USARTx(x=0,1,2)或UARTx(x=3,4)
wlen:配置USART字长
返回

wlen:配置USART字长,详细列表如下:

含义
USART_WL_8BIT8bits
USART_WL_9BIT9bits

2.4 usart_stop_bit_set

功能配置USART/UART停止位
函数定义void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen)
参数usart_periph:USARTx(x=0,1,2)或UARTx(x=3,4)
stblen:配置USART停止位
返回

stblen:配置USART停止位,详细列表如下:

含义
USART_STB_1BIT1bit
USART_STB_0_5BIT0.5bit,该位对UARTx(x=3,4)无效
USART_STB_2BIT2bit
USART_STB_1_5BIT1.5bit,该位对UARTx(x=3,4)无效

2.5 usart_parity_config

功能配置USART/UART奇偶校验
函数定义void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg)
参数usart_periph:USARTx(x=0,1,2)或UARTx(x=3,4)
paritycfg:配置USART奇偶校验
返回

paritycfg:配置USART奇偶校验,详细列表如下:

含义
USART_PM_NONE无校验
USART_PM_ODD奇校验
USART_PM_EVEN偶校验

2.6 usart_hardware_flow_rts_config

功能配置USART RTS硬件控制流
函数定义void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig)
参数usart_periph:USARTx(x=0,1,2)或UARTx(x=3,4)
rtsconfig:使能/除能RTS
返回

rtsconfig:使能/除能RTS,详细列表如下:

含义
USART_RTS_ENABLE使能RTS
USART_RTS_DISABLE除能RTS

2.7 usart_hardware_flow_rts_config

功能配置USART CTS硬件控制流
函数定义void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig)
参数usart_periph:USARTx(x=0,1,2)或UARTx(x=3,4)
ctsconfig:使能/除能CTS
返回

ctsconfig:使能/除能CTS,详细列表如下:

含义
USART_CTS_ENABLE使能CTS
USART_CTS_DISABLE除能CTS

2.8 usart_transmit_config

功能USART/UART发送器配置
函数定义void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig)
参数usart_periph:USARTx(x=0,1,2)或UARTx(x=3,4)
txconfig:使能/失能USART发送器
返回

txconfig:使能/失能USART发送器,详细列表如下:

含义
USART_TRANSMIT_ENABLE使能USART发送
USART_TRANSMIT_DISABLE失能USART发送

2.9 usart_receive_config

功能USART/UART接收器配置
函数定义void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig)
参数usart_periph:USARTx(x=0,1,2)或UARTx(x=3,4)
rxconfig:使能/失能USART接收器
返回

rxconfig:使能/失能USART接收器,详细列表如下:

含义
USART_RECEIVE_ENABLE使能USART接收
USART_RECEIVE_DISABLE失能USART接收

2.10 usart_enable

功能使能USART/UART
函数定义void usart_enable(uint32_t usart_periph)
参数usart_periph:USARTx(x=0,1,2)或UARTx(x=3,4)
返回

2.11 usart_data_transmit

功能USART/UART发送数据功能
函数定义void usart_data_transmit(uint32_t usart_periph, uint16_t data)
参数usart_periph:USARTx(x=0,1,2)或UARTx(x=3,4)
data:发送的数据
返回

2.12 usart_data_receive

功能USART/UART接收数据功能
函数定义uint16_t usart_data_receive(uint32_t usart_periph)
参数usart_periph:USARTx(x=0,1,2)或UARTx(x=3,4)
返回接收的数据

2.13 usart_interrupt_enable

功能使能USART中断
函数定义void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag)
参数usart_periph:USARTx(x=0,1,2)或UARTx(x=3,4)
int_flag:USART中断标志
返回

int_flag:USART中断标志,详细列表如下:

含义
USART_INT_PERR校验错误中断
USART_INT_TBE发送缓冲区空中断
USART_INT_TC发送完成中断
USART_INT_RBNE读数据缓冲区非空中断和过载错误中断
USART_INT_IDLE空闲线检测中断
USART_INT_LBDLIN断开信号检测中断
USART_INT_CTSCTS中断
USART_INT_ERR错误中断

2.14 usart_flag_get

功能获取USART状态寄存器标志位
函数定义FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag)
参数usart_periph:USARTx(x=0,1,2)或UARTx(x=3,4)
flag:USART标志位
返回SET或RESET

flag:USART标志位,详细列表如下:

含义
USART_FLAG_CTSFCTS变化标志
USART_FLAG_LBDFLIN断开检测标志
USART_FLAG_TBE发送数据缓冲区空
USART_FLAG_TC发送完成
USART_FLAG_RBNE读数据缓冲区非空
USART_FLAG_IDLEF空闲线检测标志
USART_FLAG_ORERR溢出错误
USART_FLAG_NERR噪声错误标志
USART_FLAG_FERR帧错误标志
USART_FLAG_PERR校验错误标志

2.15 usart_interrupt_flag_get

功能获取USART中断标志位状态
函数定义FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag)
参数usart_periph:USARTx(x=0,1,2)或UARTx(x=3,4)
int_flag:USART中断标志
返回SET或RESET

int_flag:USART中断标志,详细列表如下:

含义
USART_INT_FLAG_PERR校验错误中断和标志
USART_INT_FLAG_TBE发送缓冲区空中断和标志
USART_INT_FLAG_TC发送完成中断和标志
USART_INT_FLAG_RBNE读数据缓冲区非空中断和标志
USART_INT_FLAG_RBNE_ORERR读数据缓冲区非空中断和过载错误中断标志
USART_INT_FLAG_IDLE空闲线检测中断和标志
USART_INT_FLAG_LBDLIN断开检测中断和标志
USART_INT_FLAG_CTSCTS中断和标志
USART_INT_FLAG_ERR_ORERR错误中断和过载错误
USART_INT_FLAG_ERR_NERR错误中断和噪声错误标志
USART_INT_FLAG_ERR_FERR错误中断和镇错误标志

三、USART收发通信

3.1 引脚分布

总线APB2总线APB1总线APB1总线APB1总线APB1总线
引脚USART0USART1USART2UART3UART4
TXPA9(重映射PB6)PA2(重映射PD5)PB10(重映射PC10)PC10PC12
RXPA10(重映射PB7)PA3(重映射PD6)PB11(重映射PC11)PC11PD2
SCLKPA8PA4(重映射PD7)PB12(重映射PC12)
CTSPA11PA0(重映射PD3)PB13
RTSPA12PA1(重映射PD4)PB14

STM32F103RCT6 系统控制器有三个 USART 和两个 UART,其中 USART0 时钟来源于 APB2 总线时钟,其最大频率为 108MHz,其他四个的时钟来源于 APB1 总线时钟,其最大频率为 54MHz。UART 只是异步传输功能,所以没有 SCLK、CTS 和 RTS 功能引脚。

3.2 编程要点

  1. 使能 RX 和 TX 引脚 GPIO 时钟和 USART 时钟
  2. 初始化 GPIO,并将 GPIO 复用到 USART 上
  3. 配置 USART 参数
  4. 配置中断控制器并使能 USART 接收中断
  5. 使能 USART
  6. 在 USART 接收中断服务函数实现接收和发送

3.3 USART初始化

使用 GPIO 之前都需要初始化配置它,并且还要添加特殊设置,因为我们使用它作为外设的引脚,一般都有特殊功能。我们在初始化时需要把它的模式设置为复用功能。这里把串口的 Tx 引脚配置为复用推挽输出,Rx 引脚为浮空输入,数据完全由外部输入决定。
接下来,我们配置 USART0 通信参数为:波特率 115200,字长为 8,1 个停止位,没有校验位,不使用硬件流控制,收发一体工作模式,然后调用 USART 初始化函数完成配置。

// GPIO时钟使能
rcu_periph_clock_enable(RCU_GPIOA);
// USART时钟使能
rcu_periph_clock_enable(RCU_USART0);
    
// 配置TX为推挽复用模式
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
// 配置RX为浮空输入模式
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
    
// 配置串口的工作参数
usart_deinit(USART0);
usart_baudrate_set(USART0, 115200U);                        // 波特率
usart_word_length_set(USART0, USART_WL_8BIT);               // 帧数据字长
usart_stop_bit_set(USART0, USART_STB_1BIT);                 // 停止位
usart_parity_config(USART0, USART_PM_NONE);                 // 奇偶校验位
usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE);  // 硬件流控制RTS
usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE);  // 硬件流控制CTS
usart_receive_config(USART0, USART_RECEIVE_ENABLE);         // 使能接收
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);       // 使能发送
usart_enable(USART0);                                       // 使能串口    

3.4 串口中断初始化

  • 抢占优先级,数字越小,优先级越高
  • 若抢占优先级相同,判断子优先级,同样,数字越小,优先级越高
// 使能USART中断
nvic_irq_enable(USART0_IRQn, 0, 0);
// 使能串口接收中断
usart_interrupt_enable(USART0, USART_INT_RBNE);

3.5 串口中断处理函数

使能了 USART0 接收中断,当 USART0 有接收到数据就会执行 USART0_IRQHandler() 函数。usart_interrupt_flag_get() 函数与 usart_flag_get() 函数类似用来获取标志位状态,但 usart_interrupt_flag_get() 函数是专门用来获取中断事件标志的,并返回该标志位状态。使用 if 语句来判断是否是真的产生 USART 数据接收这个中断事件,如果是真的就使用 USART 数据读取函数 usart_data_receive() 读取数据到指定存储区。然后再调用 USART 数据发送函数 usart_data_transmit() 把数据又发送给源设备,即 PC 端的串口调试助手。

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

    unsigned char data;
    if(RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE))
    
        data = usart_data_receive(USART0);
            
        usart_data_transmit(USART0, (uint8_t)data);
        while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));//发送完成判断
    

串口中断处理函数名称要与串口相对应,可在 startup_gd32f10x_hd.s 启动文件中查看:

;                   /* external interrupts handler */
                    DCD     WWDGT_IRQHandler                  ; 16:Window Watchdog Timer
                    DCD     LVD_IRQHandler                    ; 17:LVD through EXTI Line detect
                    DCD     TAMPER_IRQHandler                 ; 18:Tamper Interrupt   
                    DCD     RTC_IRQHandler                    ; 19:RTC through EXTI Line
                    DCD     FMC_IRQHandler                    ; 20:FMC
                    DCD     RCU_IRQHandler                    ; 21:RCU
                    DCD     EXTI0_IRQHandler                  ; 22:EXTI Line 0
                    DCD     EXTI1_IRQHandler                  ; 23:EXTI Line 1
                    DCD     EXTI2_IRQHandler                  ; 24:EXTI Line 2
                    DCD     EXTI3_IRQHandler                  ; 25:EXTI Line 3
                    DCD     EXTI4_IRQHandler                  ; 26:EXTI Line 4
                    DCD     DMA0_Channel0_IRQHandler          ; 27:DMA0 Channel 0
                    DCD     DMA0_Channel1_IRQHandler          ; 28:DMA0 Channel 1
                    DCD     DMA0_Channel2_IRQHandler          ; 29:DMA0 Channel 2
                    DCD     DMA0_Channel3_IRQHandler          ; 30:DMA0 Channel 3
                    DCD     DMA0_Channel4_IRQHandler          ; 31:DMA0 Channel 4
                    DCD     DMA0_Channel5_IRQHandler          ; 32:DMA0 Channel 5 
                    DCD     DMA0_Channel6_IRQHandler          ; 33:DMA0 Channel 6
                    DCD     ADC0_1_IRQHandler                 ; 34:ADC0 and ADC1
                    DCD     USBD_HP_CAN0_TX_IRQHandler        ; 35:USBD and CAN0 TX
                    DCD     USBD_LP_CAN0_RX0_IRQHandler       ; 36:USBD and CAN0 RX0
                    DCD     CAN0_RX1_IRQHandler               ; 37:CAN0 RX1
                    DCD     CAN0_EWMC_IRQHandler              ; 38:CAN0 EWMC
                    DCD     EXTI5_9_IRQHandler                ; 39:EXTI Line 5 to EXTI Line 9
                    DCD     TIMER0_BRK_IRQHandler             ; 40:TIMER0 Break
                    DCD     TIMER0_UP_IRQHandler              ; 41:TIMER0 Update
                    DCD     TIMER0_TRG_CMT_IRQHandler         ; 42:TIMER0 Trigger and Commutation
                    DCD     TIMER0_Channel_IRQHandler         ; 43:TIMER0 Channel Capture Compare
                    DCD     TIMER1_IRQHandler                 ; 44:TIMER1
                    DCD     TIMER2_IRQHandler                 ; 45:TIMER2
                    DCD     TIMER3_IRQHandler                 ; 46:TIMER3
                    DCD     I2C0_EV_IRQHandler                ; 47:I2C0 Event
                    DCD     I2C0_ER_IRQHandler                ; 48:I2C0 Error
                    DCD     I2C1_EV_IRQHandler                ; 49:I2C1 Event
                    DCD     I2C1_ER_IRQHandler                ; 50:I2C1 Error
                    DCD     SPI0_IRQHandler                   ; 51:SPI0
                    DCD     SPI1_IRQHandler                   ; 52:SPI1
                    DCD     USART0_IRQHandler                 ; 53:USART0
                    DCD     USART1_IRQHandler                 ; 54:USART1
                    DCD     USART2_IRQHandler                 ; 55:USART2
                    DCD     EXTI10_15_IRQHandler              ; 56:EXTI Line 10 to EXTI Line 15
                    DCD     RTC_Alarm_IRQHandler              ; 57:RTC Alarm through EXTI Line
                    DCD     USBD_WKUP_IRQHandler              ; 58:USBD WakeUp from suspend through EXTI Line
                    DCD     TIMER7_BRK_IRQHandler             ; 59:TIMER7 Break Interrupt
                    DCD     TIMER7_UP_IRQHandler              ; 60:TIMER7 Update Interrupt
                    DCD     TIMER7_TRG_CMT_IRQHandler         ; 61:TIMER7 Trigger and Commutation Interrupt
                    DCD     TIMER7_Channel_IRQHandler         ; 62:TIMER7 Channel Capture Compare 
                    DCD     ADC2_IRQHandler                   ; 63:ADC2
                    DCD     EXMC_IRQHandler                   ; 64:EXMC
                    DCD     SDIO_IRQHandler                   ; 65:SDIO
                    DCD     TIMER4_IRQHandler                 ; 66:TIMER4
                    DCD     SPI2_IRQHandler                   ; 67:SPI2
                    DCD     UART3_IRQHandler                  ; 68:UART3
                    DCD     UART4_IRQHandler                  ; 69:UART4
                    DCD     TIMER5_IRQHandler                 ; 70:TIMER5
                    DCD     TIMER6_IRQHandler                 ; 71:TIMER6
                    DCD     DMA1_Channel0_IRQHandler          ; 72:DMA1 Channel0
                    DCD     DMA1_Channel1_IRQHandler          ; 73:DMA1 Channel1
                    DCD     DMA1_Channel2_IRQHandler          ; 74:DMA1 Channel2
                    DCD     DMA1_Channel3_4_IRQHandler        ; 75:DMA1 Channel3 and Channel4

3.6 printf重定向

/**
  * @brief 重定向c库函数printf到USARTx
  * @retval None
  */
int fputc(int ch, FILE *f)

    usart_data_transmit(USART0, (uint8_t)ch);
    while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
    return ch;


/**
  * @brief 重定向c库函数getchar,scanf到USARTx
  * @retval None
  */
int fgetc(FILE *f)

    uint8_t ch = 0;
    ch = usart_data_receive(USART0);
    return ch;

四、USART0串口中断收发

4.1 board_usart.c

/*********************************************************************
 * INCLUDES
 */
#include <stdio.h>
#include "gd32f10x.h"

#include "board_usart.h"

/*********************************************************************
 * PUBLIC FUNCTIONS
 */
/**
 @brief 串口驱动初始化
 @param 无
 @return 无
*/
void USART_Init(void)

    // GPIO时钟使能
    rcu_periph_clock_enable(RCU_GPIOA);
    // USART时钟使能
    rcu_periph_clock_enable(RCU_USART0);
    
    // 配置TX为推挽复用模式
    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
    // 配置RX为浮空输入模式
    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
    
    // 配置串口的工作参数
    usart_deinit(USART0);
    usart_baudrate_set(USART0, 115200U);                        // 波特率
    usart_word_length_set(USART0, USART_WL_8BIT);               // 帧数据字长
    usart_stop_bit_set(USART0, USART_STB_1BIT);                 // 停止位
    usart_parity_config(USART0, USART_PM_NONE);                 // 奇偶校验位
    usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE);  // 硬件流控制RTS
    usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE);  // 硬件流控制CTS
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);         // 使能接收
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);       // 使能发送
    usart_enable(USART0);                                       // 使能串口    
    
    // 使能USART中断
    nvic_irq_enable(USART0_IRQn, 0, 0);
    // 使能串口接收中断
    usart_interrupt_enable(USART0, USART_INT_RBNE);


/**
 @brief 串口写入数据
 @param pData -[in] 写入数据
 @param dataLen -[in] 写入数据长度
 @return 无
*/
void UART_Write(uint8_t *pData, uint32_t dataLen)

    uint8_t i;	
    for(i = 0; i < dataLen; i++)
    
        usart_data_transmit(USART0, pData[i]);                  // 发送一个字节数据
        while(RESET == usart_flag_get(USART0, USART_FLAG_TBE)); // 发送完成判断
    


/**
  * @brief 重定向c库函数printf到USARTx
  * @retval None
  */
int fputc(int ch, FILE *f)

    usart_data_transmit(USART0, (uint8_t)ch);
    while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
    return ch;


/**
  * @brief 重定向c库函数getchar,scanf到USARTx
  * @retval None
  */
int fgetc(FILE *f)

    uint8_t ch = 0;
    ch = usart_data_receive(USART0);
    return ch;


/****************************************************END OF FILE****************************************************/

4.2 board_usart.h

#ifndef _BOARD_USART_H_
#define _BOARD_USART_H_

/*********************************************************************
 * INCLUDES
 */
 
/*********************************************************************
 * DEFINITIONS
 */

/*********************************************************************
 * API FUNCTIONS
 */
void USART_Init(void);
void UART_Write(uint8_t *pData, uint32_t dataLen);

#endif /* _BOARD_USART_H_ */

4.3 gd32f10x_it.c

/*!
    \\file    gd32f10x_it.c
    \\brief   interrupt service routines

    \\version 2014-12-26, V1.0.0, firmware for GD32F10x
    \\version 2017-06-20, V2.0.0, firmware for GD32F10x
    \\version 2018-07-31, V2.1.0, firmware for GD32F10x
    \\version 2020-09-30, V2.2.0, firmware for GD32F10x
*/

/*
    Copyright (c) 2020, GigaDevice Semiconductor Inc.

    Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this 
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice, 
       this list of conditions and the following disclaimer in the documentation 
       and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors 
       may be used to endorse or promote products derived from this software without 
       specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
*/
#include "gd32f10x_it.h"
#include "systick.h"


/*!
    \\brief      this function handles NMI exception
    \\param[in]  none
    \\param[out] none
    \\retval     none
*/
void NMI_Handler(void)



/*!
    \\brief      this function handles HardFault exception
    \\param[in]  none
    \\param[out] none
    \\retval     none
*/
void HardFault_Handler(void)

    /* if Hard Fault exception occurs, go to infinite loop */
    while(1)
    


/*!
    \\brief      this function handles MemManage exception
    \\param[in]  none
    \\param[out] none
    \\retval     none
*/
void MemManage_Handler(void)

    /* if Memory Manage exception occurs, go to infinite loop */
    while(1)
    


/*!
    \\brief      this function handles BusFault exception
    \\param[in]  none
    \\param[out] none
    \\retval     none
*/
void BusFault_Handler(void)

    /* if Bus Fault exception occurs, go to infinite loop */
    while(1)
    


/*!
    \\brief      this function handles UsageFault exception
    \\param[in]  none
    \\param[out] none
    \\retval     none
*/
void UsageFault_Handler(void)

    /* if Usage Fault exception occurs, go to infinite loop */
    while(1)
    


/*!
    \\brief      this function handles SVC exception
    \\param[in]  none
    \\param[out] none
    \\retval     none
*/
void SVC_Handler(void)



/*!
    \\brief      this function handles DebugMon exception
    \\param[in]  none
    \\param[out] none
    \\retval     none
*/
void DebugMon_Handler(void)



/*!
    \\brief      this function handles PendSV exception
    \\param[in]  none
    \\param[out] none
    \\retval     none
*/
void PendSV_Handler(void)



/*!
    \\brief      this function handles SysTick exception
    \\param[in]  none
    \\param[out] none
    \\retval     none
*/
void SysTick_Handler(void)

    delay_decrement();


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

    unsigned char data;
    if(RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE))
    
        data = usart_data_receive(USART0);
            
        usart_data_transmit(USART0, (uint8_t)data);
        while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));//发送完成判断
    

4.4 main.c

#include <stdio.h>
#include "gd32f10x.h"
#include "systick.h"

#include "board_usart.h"

int main(void)

    systick_config();//系统主频108MHZ,采用外部晶振,由两个宏决定(__SYSTEM_CLOCK_108M_PLL_HXTAL与HXTAL_VALUE)
    
    USART_Init();
    printf("a usart transmit test example!");
    uint8_t test[3] = '1', '2', '3';
    UART_Write(test, 3);
	
    while(1)
    
    

查看打印:
注意数据发多了会丢数据,不知道为什么

4.5 工程代码

百度网盘:https://pan.baidu.com/s/1GFuzNtgPDo9TiqeH9zKY6A?pwd=dl0v 提取码:dl0v


• 由 Leung 写于 2022 年 4 月 18 日

• 参考:谁能把单片机串口通信SFR介绍下?

GD32从0开始学GD32单片机—— USART串口通信详解

关于51单片机中串口通信的一些小笔记

关于51单片机中串口通信的一些小笔记

关于51单片机中串口通信的一些小笔记

STM32单片机通过USART1接收到数据后,怎么把接收到的数据通过单片机的CAN口发送出去啊?