‌树莓派Pico‌的pio的uart_tx


pico-sdk-api文档

rp2040-datasheet.pdf

getting-started-with-pico.pdf

树莓派 Pico 之可编程 IO(PIO)

CMakeLists.txt

bash 复制代码
cmake_minimum_required(VERSION 3.13)

include(pico_sdk_import.cmake)

project(pio_squarewave C CXX ASM)
pico_sdk_init()

add_executable(pio_squarewave
        main.c
        uart_tx.pio
)

pico_generate_pio_header(pio_squarewave ${CMAKE_CURRENT_LIST_DIR}/uart_tx.pio)

target_link_libraries(pio_squarewave pico_stdlib hardware_pio)

pico_add_extra_outputs(pio_squarewave)

uart_tx.pio

c 复制代码
;
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
;
; SPDX-License-Identifier: BSD-3-Clause
;

.program uart_tx
.side_set 1 opt       ; 使用一个 side-set 引脚,可选,用于发送起始/停止位

; 8n1 UART 发送程序
; OUT 引脚和 side-set 引脚都映射到同一个 UART TX

    pull       side 1 [7]  ; 从 TX FIFO 拉取一个字节到 OSR
                            ; side-set 输出高电平(停止位/空闲状态)
                            ; 延迟 7 个周期,总共 8 个周期完成

    set x, 7   side 0 [7]  ; 将寄存器 X 置为 7(用于位计数)
                            ; side-set 输出低电平,发送 UART 起始位
                            ; 延迟 7 个周期,使起始位持续 8 个周期

bitloop:                   ; 主循环,发送 8 个数据位
    out pins, 1            ; 将 OSR 的最低有效位输出到 TX 引脚
    jmp x-- bitloop   [6]  ; X 减 1,不为 0 则跳回 bitloop
                            ; 延迟 6 个周期,总循环每个位 8 个周期

% c-sdk {
#include "hardware/clocks.h"

static inline void uart_tx_program_init(PIO pio, uint sm, uint offset, uint pin_tx, uint baud) {
    // 初始化 TX 引脚为空闲高电平
    pio_sm_set_pins_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx);
    // 设置 TX 引脚为输出
    pio_sm_set_pindirs_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx);
    pio_gpio_init(pio, pin_tx);  // 初始化 GPIO

    pio_sm_config c = uart_tx_program_get_default_config(offset);

    // 配置 OUT 寄存器右移,禁用自动拉取
    sm_config_set_out_shift(&c, true, false, 32);

    // OUT 和 side-set 都映射到同一个 TX 引脚
    sm_config_set_out_pins(&c, pin_tx, 1);
    sm_config_set_sideset_pins(&c, pin_tx);

    // 仅 TX,使用 8 深 FIFO
    sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);

    // 设置状态机时钟分频,使每位持续 8 个周期
    float div = (float)clock_get_hz(clk_sys) / (8 * baud);
    sm_config_set_clkdiv(&c, div);

    // 初始化状态机
    pio_sm_init(pio, sm, offset, &c);
    // 启用状态机
    pio_sm_set_enabled(pio, sm, true);
}

static inline void uart_tx_program_putc(PIO pio, uint sm, char c) {
    // 阻塞方式将一个字符写入 FIFO
    pio_sm_put_blocking(pio, sm, (uint32_t)c);
}

static inline void uart_tx_program_puts(PIO pio, uint sm, const char *s) {
    // 循环发送字符串
    while (*s)
        uart_tx_program_putc(pio, sm, *s++);
}

%}

diagram.json

json 复制代码
{
  "version": 1,
  "author": "wang minglie",
  "editor": "wokwi",
  "parts": [
    {
      "type": "wokwi-pi-pico",
      "id": "pico",
      "top": -3.15,
      "left": 3.6,
      "attrs": { "builder": "pico-sdk" }
    },
    { "type": "wokwi-gnd", "id": "gnd1", "top": 240, "left": 153, "attrs": {} },
    { "type": "wokwi-vcc", "id": "vcc1", "top": -133.64, "left": 240, "attrs": {} },
    {
      "type": "wokwi-resistor",
      "id": "r1",
      "top": -34.45,
      "left": 134.4,
      "rotate": 90,
      "attrs": { "value": "1000" }
    },
    { "type": "wokwi-slide-switch", "id": "sw1", "top": 71.6, "left": 300.7, "attrs": {} },
    { "type": "wokwi-logic-analyzer", "id": "logic1", "top": -143.65, "left": 326.4, "attrs": {} }
  ],
  "connections": [
    [ "pico:GP0", "$serialMonitor:RX", "", [] ],
    [ "pico:GP1", "$serialMonitor:TX", "", [] ],
    [ "vcc1:VCC", "r1:1", "red", [ "v0", "h-86.4" ] ],
    [ "sw1:1", "r1:2", "green", [ "h-48", "v-86.4", "h-95.45" ] ],
    [ "sw1:2", "pico:GP16", "green", [ "v57.6", "h-163.1", "v28.8", "h-76.8" ] ],
    [ "gnd1:GND", "sw1:3", "black", [ "v-38.4", "h153.6" ] ],
    [ "logic1:D0", "pico:GP0", "green", [ "h-57.6", "v-57.6", "h-288", "v192" ] ]
  ],
  "dependencies": {}
}

wokwi.toml

xml 复制代码
[wokwi]
version = 1
firmware = "cmake-build-debug-pico/pio_squarewave.uf2"
elf = "cmake-build-debug-pico/pio_squarewave.elf"

main.c

c 复制代码
#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "uart_tx.pio.h"

int main() {
    // We're going to use PIO to print "Hello, world!" on the same GPIO which we
    // normally attach UART0 to.
    const uint PIN_TX = 0;
    // This is the same as the default UART baud rate on Pico
    const uint SERIAL_BAUD = 115200;

    PIO pio = pio0;
    uint sm = 0;
    uint offset = pio_add_program(pio, &uart_tx_program);
    uart_tx_program_init(pio, sm, offset, PIN_TX, SERIAL_BAUD);

    while (true) {
        uart_tx_program_puts(pio, sm, "hello word\n");
        sleep_ms(1000);
    }
}
相关推荐
硅基手札4 小时前
【I2C 技术系列 05】I2C 多主仲裁与时钟同步
驱动开发·stm32·单片机·嵌入式硬件·mcu·计算机外设
硅基手札5 小时前
【I2C 技术系列 01】I2C 电气特性与物理层
驱动开发·stm32·单片机·嵌入式硬件·mcu·计算机外设
硅基手札19 小时前
【串口技术系列文档 10】低功耗与唤醒机制
驱动开发·stm32·单片机·嵌入式硬件·mcu·计算机外设
蓝天居士1 天前
PY32F系列MCU在OTA时App区概率性跑不起来的根因分析(5)
mcu·嵌入式
小何好运暴富开心幸福1 天前
嵌入式历史与生态
stm32·单片机·mcu
Brilliantwxx1 天前
【STM32】 工程实战 WS2812B 全彩 LED 灯控制(DMA 驱动)
stm32·单片机·嵌入式硬件·mcu
蓝天居士1 天前
PY32F系列MCU在OTA时App区概率性跑不起来的根因分析(6)
mcu·嵌入式
圆周率智能 iMLite AI1 天前
嵌入式高尔夫地图如何压到单洞 100KB?离线图源的数据组织与压缩思路
mcu·边缘计算·嵌入式开发·rtos·离线地图·高尔夫·高尔夫地图
硅基手札2 天前
【串口技术系列文档 07】UART控制器寄存器详解
驱动开发·stm32·单片机·嵌入式硬件·mcu·计算机外设
硅基手札2 天前
【串口技术系列文档 09】FIFO管理与流控
驱动开发·stm32·单片机·嵌入式硬件·mcu·计算机外设