CIU32 UART — UART1 轮询收发

CIU32 CIU32F003_STDLib V1.0.3 UART1 查询方式收发回显示例教学

UART — UART1 轮询收发(UART1_Poll)

固件库: CIU32F003_STDLib V1.0.3 芯片: CIU32F003(Cortex-M0) 源文件: CIU32/CIU32F003_STDLib_V1.0.3/Projects/UART/UART1_Poll/Source/


一、功能简介

本示例把 UART1 配置为 115200-8-N-1(波特率 115200、8 位数据、无校验、1 位停止), 采用查询(轮询)方式工作:主循环里先等收到 8 个字节存入缓冲区, 再把这 8 个字节原样发回去,最后等待发送完成。这就是最经典的串口回显(echo)。 查询方式逻辑简单,但收发期间 CPU 会被 while 占用,适合入门与低速通信。

二、硬件准备

  • CIU32F003 开发板
  • USB 转串口模块(如 CH340 / CP2102)
  • 接线:开发板 TX(PA3) → 模块 RX,开发板 RX(PA4) → 模块 TX,并共地
  • 电脑端打开串口助手(如 SSCOM、XCOM),波特率设为 115200

引脚映射:

UART1 引脚 复用
TX PA3 AF1_UART1
RX PA4 AF1_UART1

三、完整代码

3.1 主流程 main.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "main.h"

#define BUF_LEN  8
uint8_t buffer[BUF_LEN] = {0};

int main(void)
{
    system_clock_config();   /* 系统时钟 RCH 48MHz */
    gpio_init();             /* PA3/PA4 复用为 UART1 */
    uart_init();             /* 配置波特率等并使能 UART1 */

    while (1)
    {
        /* ① 查询接收 BUF_LEN 个字节 */
        for (int i = 0; i < BUF_LEN; i++)
        {
            while (!std_uart_get_flag(UART1, UART_FLAG_RXNE));  /* 等收到数据 */
            buffer[i] = std_uart_rx_read_data(UART1);           /* 读 1 字节 */
        }

        /* ② 查询发送 BUF_LEN 个字节 */
        for (int i = 0; i < BUF_LEN; i++)
        {
            while (!std_uart_get_flag(UART1, UART_FLAG_TXE));   /* 等发送寄存器空 */
            std_uart_tx_write_data(UART1, buffer[i]);           /* 发 1 字节 */
        }

        /* ③ 等待整帧发送完成(TC = Transmission Complete) */
        while (!std_uart_get_flag(UART1, UART_FLAG_TC));
    }
}

3.2 引脚与串口初始化 common.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* GPIO:PA3(TX)/PA4(RX) 复用为 UART1 */
void gpio_init(void)
{
    std_gpio_init_t gpio_config = {0};
    std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA);

    gpio_config.pin         = GPIO_PIN_3 | GPIO_PIN_4;
    gpio_config.mode        = GPIO_MODE_ALTERNATE;
    gpio_config.pull        = GPIO_PULLUP;           /* 上拉,空闲时线为高 */
    gpio_config.output_type = GPIO_OUTPUT_PUSHPULL;
    gpio_config.alternate   = GPIO_AF1_UART1;        /* 复用功能 1 = UART1 */
    std_gpio_init(GPIOA, &gpio_config);
}

/* UART1 初始化 */
void uart_init(void)
{
    std_uart_init_t uart_confg = {0};
    std_rcc_apb2_clk_enable(RCC_PERIPH_CLK_UART1);   /* 使能 UART1 时钟(APB2) */

    uart_confg.baudrate    = 115200;                 /* 波特率 */
    uart_confg.direction   = UART_DIRECTION_SEND_RECEIVE; /* 收发双向 */
    uart_confg.wordlength  = UART_WORDLENGTH_8BITS;  /* 8 位数据 */
    uart_confg.stopbits    = UART_STOPBITS_1;        /* 1 位停止 */
    uart_confg.parity      = UART_PARITY_NONE;       /* 无校验 */
    std_uart_init(UART1, &uart_confg);

    std_uart_enable(UART1);                          /* 使能 UART1 */
}

四、代码分段讲解

① 引脚复用 UART 的 TX/RX 由 GPIO 复用功能提供,本例 GPIO_AF1_UART1 把 PA3/PA4 映射给 UART1。 复用功能号(AF1)是芯片规定的,查数据手册/复用表可得。

② 串口参数 115200-8-N-1 是最通用配置:波特率 115200、8 数据位、无校验、1 停止位。 双方必须完全一致才能正确通信。奇偶校验位可选,但开启后收发都要配。

③ 查询收发

  • 接收:while 等 UART_FLAG_RXNE(接收寄存器非空)后读 std_uart_rx_read_data;
  • 发送:等 UART_FLAG_TXE(发送数据寄存器空)后写 std_uart_tx_write_data;
  • UART_FLAG_TC(发送完成):一帧所有位都移出后才置位,用于确认“已全部发出”。

④ 轮询的代价 全程 while 等待标志,CPU 不能做别的事。数据量大或要求不阻塞时,应改用中断或 DMA(见 UART1_Interrupt)。

五、实验现象

  • 串口助手发送任意 8 个字节,开发板会原样回显这 8 个字节;
  • 例如发送 01 02 03 04 05 06 07 08,收到同样的 8 字节。

六、常见问题

现象 可能原因 解决办法
串口助手乱码 波特率不一致 双方都设为 115200
完全收不到 TX/RX 接反 开发板 TX 接模块 RX,RX 接模块 TX
偶发丢字节 没共地 开发板与模块必须共 GND
收不齐 8 字节 发送间隔/缓冲 一次发满 8 字节,或改中断方式

七、小结

UART 轮询收发流程:开时钟 → 配引脚为对应 AF → 配波特率/帧格式并使能 → 等 RXNE 读、等 TXE 写、等 TC 收尾。 记住“TX 接 RX、交叉连接、必须共地、波特率一致”四句话,串口就通了。

八、拓展应用

  • 用 printf 重定向到 UART,方便打印调试信息(实现 _write/fputc);
  • 改用中断接收,避免 CPU 空等(见 UART1_Interrupt);
  • 单线半双工:省一根线,用于简单总线(见 UART_HalfDuplex)。
世界是你们
使用 Hugo 构建
主题 Stack 由 Jimmy 设计