学习目标

  1. 掌握串口初始化流程
  2. 掌握串口输出单个字符
  3. 掌握串口输出字符串
  4. 掌握通过串口printf
  5. 熟练掌握串口开发流程

    学习内容

    需求

    181.png
    串口循环输出内容到PC机。

    串口数据发送

    添加Usart功能。
    首先,选中Firmware,鼠标右键,点击Manage Project Items
    184.png
    接着,将gd32f4xx_usart.c添加到依赖中
    添加usart实现.gif
    最后,观察Firmware
    187.png

    1. static void USART_config() {
    2. /************** gpio config **************/
    3. // 配置时钟
    4. rcu_periph_clock_enable(RCU_GPIOA);
    5. // 配置模式
    6. gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
    7. gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
    8. // 配置复用功能
    9. gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);
    10. gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);
    11. // 配置输出参数
    12. gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
    13. gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
    14. /************** usart config **************/
    15. // 串口时钟
    16. rcu_periph_clock_enable(RCU_USART0);
    17. // USART复位
    18. usart_deinit(USART0);
    19. // 波特率
    20. usart_baudrate_set(USART0, 115200);
    21. // 校验位
    22. usart_parity_config(USART0, USART_PM_NONE);
    23. // 数据位数
    24. usart_word_length_set(USART0, USART_WL_8BIT);
    25. // 停止位
    26. usart_stop_bit_set(USART0, USART_STB_1BIT);
    27. // 先发送高位还是低位
    28. usart_data_first_config(USART0, USART_MSBF_LSB);
    29. // 发送功能配置
    30. usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
    31. // 使能串口
    32. usart_enable(USART0);
    33. }
    1. //发送一byte数据
    2. static void send_data(uint8_t data) {
    3. //通过USART发送
    4. usart_data_transmit(USART0, data);
    5. //判断缓冲区是否已经空了
    6. //FlagStatus state = usart_flag_get(USART_NUM,USART_FLAG_TBE);
    7. while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
    8. }
    1. //发送字符串
    2. static void send_string(char *data){
    3. //满足: 1.data指针不为空 2.发送的数据不是\0结束标记
    4. while(data && *data){
    5. send_data((uint8_t)(*data));
    6. data++;
    7. }
    8. }

    串口打印实现

    1. int fputc(int ch, FILE *f){
    2. send_data((uint8_t)ch);
    3. return ch;
    4. }

    复用功能

    016.png
    串口为PA9PA10,通过文档查询复用功能。

    串口发送流程(了解)

    寄存器与电路。

  6. 数据发送缓存寄存器

  7. 状态寄存器

数据发送的流程,就是向发送缓冲区里放数据,这个发送缓存区寄存器只有有数据,就会触发电路,电路就按照这个数据模拟出高低电平往外发数据。
发送缓存区寄存器有个特点,小,只有一个byte,但是超快,寄存器在芯片内部寸土寸金。
存在一个问题,如果发送大量数据,这个寄存器的数据还没发送完成,会覆盖掉,这时候有一个状态寄存器记录了当前发送缓冲去是否是闲置的。(GD32是USART_FLAG_TBE,STM32是UART_FLAG_TXE

关心的内容

将代码进行抽取

  1. static void USART_config() {
  2. uint32_t usartx_tx_rcu = RCU_GPIOA;
  3. uint32_t usartx_tx_port = GPIOA;
  4. uint32_t usartx_tx_pin = GPIO_PIN_9;
  5. uint32_t usartx_tx_af = GPIO_AF_7;
  6. uint32_t usartx_rx_rcu = RCU_GPIOA;
  7. uint32_t usartx_rx_port = GPIOA;
  8. uint32_t usartx_rx_pin = GPIO_PIN_10;
  9. uint32_t usartx_rx_af = GPIO_AF_7;
  10. uint32_t usartx = USART0;
  11. uint32_t usartx_rcu = RCU_USART0;
  12. uint32_t usartx_p_baudrate = 115200;
  13. uint32_t usartx_p_parity = USART_PM_NONE;
  14. uint32_t usartx_p_wl = USART_WL_8BIT;
  15. uint32_t usartx_p_stop_bit = USART_STB_1BIT;
  16. uint32_t usartx_p_data_first = USART_MSBF_LSB;
  17. /************** gpio config **************/
  18. // tx
  19. rcu_periph_clock_enable(usartx_tx_rcu); // 配置时钟
  20. gpio_mode_set(usartx_tx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, usartx_tx_pin);
  21. gpio_af_set(usartx_tx_port, usartx_tx_af, usartx_tx_pin);
  22. gpio_output_options_set(usartx_tx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usartx_tx_pin);
  23. // rx
  24. rcu_periph_clock_enable(usartx_rx_rcu); // 配置时钟
  25. gpio_mode_set(usartx_rx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, usartx_rx_pin);
  26. gpio_af_set(usartx_rx_port, usartx_rx_af, usartx_rx_pin);
  27. gpio_output_options_set(usartx_rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usartx_rx_pin);
  28. /************** usart config **************/
  29. // 串口时钟
  30. rcu_periph_clock_enable(RCU_USART0);
  31. // USART复位
  32. usart_deinit(usartx);
  33. usart_baudrate_set(usartx, usartx_p_baudrate); // 波特率
  34. usart_parity_config(usartx, usartx_p_parity); // 校验位
  35. usart_word_length_set(usartx, usartx_p_wl); // 数据位数
  36. usart_stop_bit_set(usartx, usartx_p_stop_bit); // 停止位
  37. usart_data_first_config(usartx, usartx_p_data_first); // 先发送高位还是低位
  38. // 发送功能配置
  39. usart_transmit_config(usartx, USART_TRANSMIT_ENABLE);
  40. // 使能串口
  41. usart_enable(usartx);
  42. }

总结起来:

  1. GPIO引脚配置 ```c uint32_t usartx_tx_rcu = RCU_GPIOA; uint32_t usartx_tx_port = GPIOA; uint32_t usartx_tx_pin = GPIO_PIN_9; uint32_t usartx_tx_af = GPIO_AF_7;

uint32_t usartx_rx_rcu = RCU_GPIOA; uint32_t usartx_rx_port = GPIOA; uint32_t usartx_rx_pin = GPIO_PIN_10; uint32_t usartx_rx_af = GPIO_AF_7;

  1. - **哪个引脚**
  2. - **复用端口是哪个**
  3. 2. 串口配置
  4. ```c
  5. uint32_t usartx = USART0;
  6. uint32_t usartx_rcu = RCU_USART0;
  7. uint32_t usartx_p_baudrate = 115200;
  8. uint32_t usartx_p_parity = USART_PM_NONE;
  9. uint32_t usartx_p_wl = USART_WL_8BIT;
  10. uint32_t usartx_p_stop_bit = USART_STB_1BIT;
  11. uint32_t usartx_p_data_first = USART_MSBF_LSB;
  • 哪个串口
  • 波特率是多少。(剩余的基本百年不变)

    完整示例

    ```c

    include “gd32f4xx.h”

    include “systick.h”

    include

    include “main.h”

static void USART_config() { uint32_t usartx_tx_rcu = RCU_GPIOA; uint32_t usartx_tx_port = GPIOA; uint32_t usartx_tx_pin = GPIO_PIN_9; uint32_t usartx_tx_af = GPIO_AF_7;

  1. uint32_t usartx_rx_rcu = RCU_GPIOA;
  2. uint32_t usartx_rx_port = GPIOA;
  3. uint32_t usartx_rx_pin = GPIO_PIN_10;
  4. uint32_t usartx_rx_af = GPIO_AF_7;
  5. uint32_t usartx = USART0;
  6. uint32_t usartx_rcu = RCU_USART0;
  7. uint32_t usartx_p_baudrate = 115200;
  8. uint32_t usartx_p_parity = USART_PM_NONE;
  9. uint32_t usartx_p_wl = USART_WL_8BIT;
  10. uint32_t usartx_p_stop_bit = USART_STB_1BIT;
  11. uint32_t usartx_p_data_first = USART_MSBF_LSB;
  12. /************** gpio config **************/
  13. // tx
  14. rcu_periph_clock_enable(usartx_tx_rcu); // 配置时钟
  15. gpio_mode_set(usartx_tx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, usartx_tx_pin);
  16. gpio_af_set(usartx_tx_port, usartx_tx_af, usartx_tx_pin);
  17. gpio_output_options_set(usartx_tx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usartx_tx_pin);
  18. // rx
  19. rcu_periph_clock_enable(usartx_rx_rcu); // 配置时钟
  20. gpio_mode_set(usartx_rx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, usartx_rx_pin);
  21. gpio_af_set(usartx_rx_port, usartx_rx_af, usartx_rx_pin);
  22. gpio_output_options_set(usartx_rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usartx_rx_pin);
  23. /************** usart config **************/
  24. // 串口时钟
  25. rcu_periph_clock_enable(RCU_USART0);
  26. // USART复位
  27. usart_deinit(usartx);
  28. usart_baudrate_set(usartx, usartx_p_baudrate); // 波特率
  29. usart_parity_config(usartx, usartx_p_parity); // 校验位
  30. usart_word_length_set(usartx, usartx_p_wl); // 数据位数
  31. usart_stop_bit_set(usartx, usartx_p_stop_bit); // 停止位
  32. usart_data_first_config(usartx, usartx_p_data_first); // 先发送高位还是低位
  33. // 发送功能配置
  34. usart_transmit_config(usartx, USART_TRANSMIT_ENABLE);
  35. // 使能串口
  36. usart_enable(usartx);

}

//发送一byte数据 static void send_data(uint8_t data) { //通过USART发送 usart_data_transmit(USART0, data); //判断缓冲区是否已经空了 //FlagStatus state = usart_flag_get(USART_NUM,USART_FLAG_TBE); while(RESET == usart_flag_get(USART0, USART_FLAG_TBE)); }

//发送字符串 static void send_string(char data){ //满足: 1.data指针不为空 2.发送的数据不是\0结束标记 while(data && data){ send_data((uint8_t)(*data)); data++; } }

int fputc(int ch, FILE *f){ send_data((uint8_t)ch); return ch; }

int main(void) { systick_config(); USART_config(); uint8_t cnt; while(1) { // send_data(cnt++); // send_string(“hello\r\n”); // printf(“hello %d\r\n”, cnt++); delay_1ms(1000); } } ```

如果按照如上代码配置还是不能输出日志,则需要勾选MicroLIB
image.png

练习题

  1. 实现串口数据发送
  2. 创建属于自己的串口发送模板代码