学习目标

  1. 掌握串口初始化流程
  2. 掌握串口接收逻辑
  3. 了解中断接收逻辑
  4. 熟练掌握串口开发流程

    学习内容

    需求

    181.png
    串口接收PC机发送的数据。

    串口数据接收

    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_irqn = USART0_IRQn;
    13. uint32_t usartx_p_baudrate = 115200;
    14. uint32_t usartx_p_parity = USART_PM_NONE;
    15. uint32_t usartx_p_wl = USART_WL_8BIT;
    16. uint32_t usartx_p_stop_bit = USART_STB_1BIT;
    17. uint32_t usartx_p_data_first = USART_MSBF_LSB;
    18. /************** gpio config **************/
    19. // tx
    20. rcu_periph_clock_enable(usartx_tx_rcu); // 配置时钟
    21. gpio_mode_set(usartx_tx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, usartx_tx_pin);
    22. gpio_af_set(usartx_tx_port, usartx_tx_af, usartx_tx_pin);
    23. gpio_output_options_set(usartx_tx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usartx_tx_pin);
    24. // rx
    25. rcu_periph_clock_enable(usartx_rx_rcu); // 配置时钟
    26. gpio_mode_set(usartx_rx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, usartx_rx_pin);
    27. gpio_af_set(usartx_rx_port, usartx_rx_af, usartx_rx_pin);
    28. gpio_output_options_set(usartx_rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usartx_rx_pin);
    29. /************** usart config **************/
    30. // 串口时钟
    31. rcu_periph_clock_enable(RCU_USART0);
    32. // USART复位
    33. usart_deinit(usartx);
    34. usart_baudrate_set(usartx, usartx_p_baudrate); // 波特率
    35. usart_parity_config(usartx, usartx_p_parity); // 校验位
    36. usart_word_length_set(usartx, usartx_p_wl); // 数据位数
    37. usart_stop_bit_set(usartx, usartx_p_stop_bit); // 停止位
    38. usart_data_first_config(usartx, usartx_p_data_first); // 先发送高位还是低位
    39. // 发送功能配置
    40. usart_transmit_config(usartx, USART_TRANSMIT_ENABLE);
    41. // 接收功能配置
    42. usart_receive_config(usartx, USART_RECEIVE_ENABLE);
    43. // 接收中断配置
    44. nvic_irq_enable(usartx_irqn, 2, 2);
    45. // usart int rbne
    46. usart_interrupt_enable(usartx, USART_INT_RBNE);
    47. usart_interrupt_enable(usartx, USART_INT_IDLE);
    48. // 使能串口
    49. usart_enable(usartx);
    50. }

    ```c

    define USART_RECEIVE_LENGTH 1024

    //串口接收缓冲区大小 uint8_t g_recv_buff[USART_RECEIVE_LENGTH]; // 接收缓冲区 //接收到字符存放的位置 int g_recv_length = 0;

void USART0_IRQHandler(void) { if ((usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) == SET) { uint16_t value = usart_data_receive(USART0); g_recv_buff[g_recv_length] = value;
g_recv_length++; } if (usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE) == SET) { //读取缓冲区,清空缓冲区 usart_data_receive(USART0); g_recv_buff[g_recv_length] = ‘\0’;

  1. // TODO: g_recv_buff为接收的数据,g_recv_length为接收的长度
  2. g_recv_length = 0;
  3. }

}

  1. <a name="KBf1M"></a>
  2. ### 中断函数
  3. 1. 中断函数的名称是在CMSIS的汇编接口中定义的
  4. ![182.png](https://cdn.nlark.com/yuque/0/2023/png/27903758/1691665548744-8b682765-4a38-4990-b186-9b210ba3de40.png#averageHue=%23eeedec&clientId=u5bc733c2-08d2-4&from=ui&id=u37668828&originHeight=57&originWidth=1138&originalType=binary&ratio=1&rotation=0&showTitle=false&size=16241&status=done&style=none&taskId=ue855c04c-3a37-448d-a9e9-9a39443d69e&title=)<br />![183.png](https://cdn.nlark.com/yuque/0/2023/png/27903758/1691665563474-706cb574-625f-44f0-9fc6-68e3a8e1b86e.png#averageHue=%23042030&clientId=u5bc733c2-08d2-4&from=ui&id=ub995c6ab&originHeight=93&originWidth=971&originalType=binary&ratio=1&rotation=0&showTitle=false&size=21904&status=done&style=none&taskId=u75c350a0-5f26-405f-a3f2-9cecc5ade85&title=)
  5. 2. 中断触发需要进行配置
  6. ```c
  7. ......
  8. // 接收功能配置
  9. usart_receive_config(usartx, USART_RECEIVE_ENABLE);
  10. // 接收中断配置
  11. nvic_irq_enable(usartx_irqn, 2, 2);
  12. // usart int rbne
  13. usart_interrupt_enable(usartx, USART_INT_RBNE);
  14. usart_interrupt_enable(usartx, USART_INT_IDLE);
  15. ......

串口接收流程(了解)

寄存器与电路。

  1. 数据接收缓存寄存器(接收和发送其实公用一个寄存器)
  2. 状态寄存器

外部通过串口发送数据到MCU中来时,首先会把高低电平进行转换为单个byte,接着存储到这个缓存寄存器,存储一个byte的时候,会改变寄存器状态,然后会触发中断,我们在中断中,我们就知道接收到了一个byte,我们就可以去数据接收缓存寄存器中取数据,取完后,接收方又去存,这样周而复始的进行接收。知道外部不发送数据了,这个时候如果长期没有收到数据,就会触发闲置寄存器标记。

完整示例

  1. #include "gd32f4xx.h"
  2. #include "systick.h"
  3. #include <stdio.h>
  4. #include "main.h"
  5. /**
  6. PA9 TXD
  7. PA10 RXD
  8. **/
  9. #define USART_RECEIVE_LENGTH 1024
  10. //串口接收缓冲区大小
  11. uint8_t g_recv_buff[USART_RECEIVE_LENGTH]; // 接收缓冲区
  12. //接收到字符存放的位置
  13. int g_recv_length = 0;
  14. static void USART_config() {
  15. uint32_t usartx_tx_rcu = RCU_GPIOA;
  16. uint32_t usartx_tx_port = GPIOA;
  17. uint32_t usartx_tx_pin = GPIO_PIN_9;
  18. uint32_t usartx_tx_af = GPIO_AF_7;
  19. uint32_t usartx_rx_rcu = RCU_GPIOA;
  20. uint32_t usartx_rx_port = GPIOA;
  21. uint32_t usartx_rx_pin = GPIO_PIN_10;
  22. uint32_t usartx_rx_af = GPIO_AF_7;
  23. uint32_t usartx = USART0;
  24. uint32_t usartx_rcu = RCU_USART0;
  25. uint32_t usartx_irqn = USART0_IRQn;
  26. uint32_t usartx_p_baudrate = 115200;
  27. uint32_t usartx_p_parity = USART_PM_NONE;
  28. uint32_t usartx_p_wl = USART_WL_8BIT;
  29. uint32_t usartx_p_stop_bit = USART_STB_1BIT;
  30. uint32_t usartx_p_data_first = USART_MSBF_LSB;
  31. /************** gpio config **************/
  32. // tx
  33. rcu_periph_clock_enable(usartx_tx_rcu); // 配置时钟
  34. gpio_mode_set(usartx_tx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, usartx_tx_pin);
  35. gpio_af_set(usartx_tx_port, usartx_tx_af, usartx_tx_pin);
  36. gpio_output_options_set(usartx_tx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usartx_tx_pin);
  37. // rx
  38. rcu_periph_clock_enable(usartx_rx_rcu); // 配置时钟
  39. gpio_mode_set(usartx_rx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, usartx_rx_pin);
  40. gpio_af_set(usartx_rx_port, usartx_rx_af, usartx_rx_pin);
  41. //gpio_output_options_set(usartx_rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usartx_rx_pin);
  42. /************** usart config **************/
  43. // 串口时钟
  44. rcu_periph_clock_enable(RCU_USART0);
  45. // USART复位
  46. usart_deinit(usartx);
  47. usart_baudrate_set(usartx, usartx_p_baudrate); // 波特率
  48. usart_parity_config(usartx, usartx_p_parity); // 校验位
  49. usart_word_length_set(usartx, usartx_p_wl); // 数据位数
  50. usart_stop_bit_set(usartx, usartx_p_stop_bit); // 停止位
  51. usart_data_first_config(usartx, usartx_p_data_first); // 先发送高位还是低位
  52. // 发送功能配置
  53. usart_transmit_config(usartx, USART_TRANSMIT_ENABLE);
  54. // 接收功能配置
  55. usart_receive_config(usartx, USART_RECEIVE_ENABLE);
  56. // 接收中断配置
  57. nvic_irq_enable(usartx_irqn, 2, 2);
  58. // usart int rbne
  59. usart_interrupt_enable(usartx, USART_INT_RBNE);
  60. usart_interrupt_enable(usartx, USART_INT_IDLE);
  61. // 使能串口
  62. usart_enable(usartx);
  63. }
  64. //发送一byte数据
  65. static void send_data(uint8_t data) {
  66. //通过USART发送
  67. usart_data_transmit(USART0, data);
  68. //判断缓冲区是否已经空了
  69. //FlagStatus state = usart_flag_get(USART_NUM,USART_FLAG_TBE);
  70. while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
  71. }
  72. void USART0_IRQHandler(void) {
  73. if ((usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) == SET) {
  74. uint16_t value = usart_data_receive(USART0);
  75. g_recv_buff[g_recv_length] = value;
  76. g_recv_length++;
  77. }
  78. if (usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE) == SET) {
  79. //读取缓冲区,清空缓冲区
  80. usart_data_receive(USART0);
  81. g_recv_buff[g_recv_length] = '\0';
  82. // TODO: g_recv_buff为接收的数据,g_recv_length为接收的长度
  83. printf("%s", g_recv_buff);
  84. g_recv_length = 0;
  85. }
  86. }
  87. //发送字符串
  88. static void send_string(char *data){
  89. //满足: 1.data指针不为空 2.发送的数据不是\0结束标记
  90. while(data && *data){
  91. send_data((uint8_t)(*data));
  92. data++;
  93. }
  94. }
  95. //重写fputc方法 调用printf,会自动调用这个方法实现打印
  96. int fputc(int ch, FILE *f){
  97. send_data((uint8_t)ch);
  98. return ch;
  99. }
  100. int main(void)
  101. {
  102. systick_config();
  103. USART_config();
  104. while(1) {
  105. }
  106. }