RP2040 C SDK开发串口的使用

RP2040 C SDK开发串口的使用


  • 📍环境搭建部署篇《RP2040 VSCode C/C++开发环境快速部署
  • 🔖RP2040 有硬件串口资源有2个。
  • 🌿参考RP2040 C SDK Hardware APIS:https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#group_hardware_uart
  • 🥕官方例程参考:https://github.com/raspberrypi/pico-examples
  • 🌿串口0默认引脚定义:
// --- UART ---
#ifndef PICO_DEFAULT_UART
#define PICO_DEFAULT_UART 0
#endif
#ifndef PICO_DEFAULT_UART_TX_PIN
#define PICO_DEFAULT_UART_TX_PIN 0
#endif
#ifndef PICO_DEFAULT_UART_RX_PIN
#define PICO_DEFAULT_UART_RX_PIN 1
#endif
  • 🌿串口0初始化:
 int main() {

    // Set the GPIO pin mux to the UART - pin 0 is TX, 1 is RX; note use of UART_FUNCSEL_NUM for the general
    // case where the func sel used for UART depends on the pin number
    // Do this before calling uart_init to avoid losing data
    gpio_set_function(0, UART_FUNCSEL_NUM(uart0, 0));
    gpio_set_function(1, UART_FUNCSEL_NUM(uart0, 1));

    // Initialise UART 0
    uart_init(uart0, 115200);
    uart_puts(uart0, "Hello world!");
}

  • 🌿如果调用了stdio_init_all();则默认使用串口0(0,1),波特率默认115200;作为标准输出函数。
bool stdio_init_all(void) {
    // todo add explicit custom, or registered although you can call stdio_enable_driver explicitly anyway
    // These are well known ones

    bool rc = false;
#if LIB_PICO_STDIO_UART
    stdio_uart_init();
    rc = true;
#endif

#if LIB_PICO_STDIO_SEMIHOSTING
    stdio_semihosting_init();
    rc = true;
#endif

#if LIB_PICO_STDIO_USB
    rc |= stdio_usb_init();
#endif
    return rc;
}
//最终调用的串口初始化函数
void stdio_uart_init_full(struct uart_inst *uart, uint baud_rate, int tx_pin, int rx_pin) {
    uart_instance = uart;
    if (tx_pin >= 0) gpio_set_function((uint)tx_pin, GPIO_FUNC_UART);
    if (rx_pin >= 0) gpio_set_function((uint)rx_pin, GPIO_FUNC_UART);
    uart_init(uart_instance, baud_rate);
    stdio_set_driver_enabled(&stdio_uart, true);
}

📗串口0和串口1测试例程

#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "hardware/gpio.h"
#include "hardware/gpio.h"
#include "hardware/divider.h"




// UART defines
// By default the stdout UART is `uart0`, so we will use the second one
#define UART_ID uart1
#define BAUD_RATE 115200  //

// Use pins 4 and 5 for UART1
// Pins can be changed, see the GPIO function select table in the datasheet for information on GPIO assignments
#define UART_TX_PIN 4
#define UART_RX_PIN 5

// GPIO defines
// Example uses GPIO 2
#define GPIO 2
static const uint pin = 25;

int main()
{
    stdio_init_all();//串口0,115200,支持printf打印
    // Set the TX and RX pins by using the function select on the GPIO
    // Set datasheet for more information on function select
    gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
    gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);
    // Set up our UART
    uart_init(UART_ID, BAUD_RATE);//串口1,115200
    uart_set_hw_flow(UART_ID, false, false);//关闭硬件流控



    // GPIO initialisation.
    // We will make this GPIO an input, and pull it up by default
    gpio_init(GPIO);
    gpio_set_dir(GPIO, GPIO_OUT);
    gpio_pull_up(GPIO);
    gpio_init(pin);
    gpio_set_dir(pin, GPIO_OUT);
while (true) {

    // Example of using the HW divider. The pico_divider library provides a more user friendly set of APIs
    // over the divider (and support for 64 bit divides), and of course by default regular C language integer
    // divisions are redirected thru that library, meaning you can just use C level `/` and `%` operators and
    // gain the benefits of the fast hardware divider.
    int32_t dividend = 123456;
    int32_t divisor = -321;
    // This is the recommended signed fast divider for general use.
    divmod_result_t result = hw_divider_divmod_s32(dividend, divisor);
    printf("%d/%d = %d remainder %d\n", dividend, divisor, to_quotient_s32(result), to_remainder_s32(result));
    // This is the recommended unsigned fast divider for general use.
    int32_t udividend = 123456;
    int32_t udivisor = 321;
    divmod_result_t uresult = hw_divider_divmod_u32(udividend, udivisor);
    printf("%d/%d = %d remainder %d\n", udividend, udivisor, to_quotient_u32(uresult), to_remainder_u32(uresult));
    puts("Hello, world!1234 from uart0");
     sleep_ms(1000);
     gpio_set_mask(1ul<<GPIO);
     gpio_put(pin, true);
        sleep_ms(250);
        gpio_clr_mask(1ul<<GPIO);
        gpio_put(pin, false);
        sleep_ms(250);
 uart_puts(uart1,"Hello, from UART1!");
 //uart_puts(uart0, "Hello world!");
}

  //  return 0;
}

📘串口中断测试例程

  • 🌿中断号:
enum irq_num_rp2040 { 
TIMER_IRQ_0 = 0, 
TIMER_IRQ_1 = 1, 
TIMER_IRQ_2 = 2, 
TIMER_IRQ_3 = 3, 
PWM_IRQ_WRAP = 4, 
USBCTRL_IRQ = 5,
 XIP_IRQ = 6, 
 PIO0_IRQ_0 = 7, 
 PIO0_IRQ_1 = 8,
  PIO1_IRQ_0 = 9,
   PIO1_IRQ_1 = 10, 
   DMA_IRQ_0 = 11, 
   DMA_IRQ_1 = 12,
    IO_IRQ_BANK0 = 13, 
    IO_IRQ_QSPI = 14, 
    SIO_IRQ_PROC0 = 15, 
    SIO_IRQ_PROC1 = 16,
     CLOCKS_IRQ = 17,
      SPI0_IRQ = 18,
       SPI1_IRQ = 19,
        UART0_IRQ = 20, 
        UART1_IRQ = 21, 
        ADC_IRQ_FIFO = 22, 
        I2C0_IRQ = 23, 
        I2C1_IRQ = 24, 
        RTC_IRQ = 25, 
        IRQ_COUNT 
        } RP2040



📑通过开启串口1接收中断,将串口1(0,1)接收到的数据,通过串口0(4,5)转发.

  • 📝测试代码:
/*
 烧录命令:openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg  -c  "program USART_Test.elf verify reset exit"

 * @FilePath: \USART_Test\USART_Test.c
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "hardware/irq.h"
#include "hardware/gpio.h"
#include "hardware/divider.h"
// #include "hardware/clocks.h"


// UART defines
// By default the stdout UART is `uart0`, so we will use the second one
#define UART_ID uart1
#define BAUD_RATE 115200  //串口波特率

// Use pins 4 and 5 for UART1
// Pins can be changed, see the GPIO function select table in the datasheet for information on GPIO assignments
#define UART_TX_PIN 4
#define UART_RX_PIN 5

// GPIO defines
// Example uses GPIO 2
#define GPIO 2
static const uint pin = 25;

void uart1ISR(void)
{
while(uart_is_readable(UART_ID))
	{
		uint8_t ch = uart_getc(UART_ID);
		if(uart_is_writable(UART_ID))//确定TX FIFO中是否有可用空间。
		{
			//uart_putc(uart0, ch);//转发数据
			uart_putc_raw(uart0,ch);//同上,需要使能fifo功能才可以使用
		}
  }
}

int main()
{
    stdio_init_all();//串口0,115200
    // Set the TX and RX pins by using the function select on the GPIO
    // Set datasheet for more information on function select
    gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
    gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);
    // Set up our UART
    uart_init(UART_ID, BAUD_RATE);//串口1,115200
    uart_set_hw_flow(UART_ID, false, false);//关闭硬件流控
     uart_set_fifo_enabled(uart1, true);//开启缓存
    hw_write_masked(&uart_get_hw(uart1)->ifls, 0b100 << UART_UARTIFLS_RXIFLSEL_LSB,
					UART_UARTIFLS_RXIFLSEL_BITS);  //设置接收中断的触发条件为FIFO不为空
    irq_set_exclusive_handler(UART1_IRQ, uart1ISR);//配置中断回调
	irq_set_enabled(UART1_IRQ, true);//开启串口中断
    uart_set_irq_enables(uart1, true, false); //开启串口1中断,接收中断,关闭发送中断
    irq_set_priority (UART1_IRQ, 1); //设置中断优先级
   
 
    uart_is_enabled(UART_ID);

while (true) {
}

  • 测试结果
    在这里插入图片描述
  • 统计接收字符数量
/*
 烧录命令:openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg  -c  "program USART_Test.elf verify reset exit"

 jlink  openocd -f interface/jlink.cfg -f target/rp2040.cfg  -c  "program USART_Test.elf verify reset exit"
 * @FilePath: \USART_Test\USART_Test.c
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "hardware/irq.h"
#include "hardware/gpio.h"
#include "hardware/divider.h"
//#include "intctrl.h"
// #include "hardware/clocks.h"

// 检查是否定义了 LIB_PICO_STDIO_UART 宏
#if defined(LIB_PICO_STDIO_UART)
    // 如果定义了,取消这个宏
    #undef LIB_PICO_STDIO_UART
  #define LIB_PICO_STDIO_USB 1
#endif


// UART defines
// By default the stdout UART is `uart0`, so we will use the second one
#define UART_ID uart1
#define BAUD_RATE 115200  //

// Use pins 4 and 5 for UART1
// Pins can be changed, see the GPIO function select table in the datasheet for information on GPIO assignments
#define UART_TX_PIN 4
#define UART_RX_PIN 5

// GPIO defines
// Example uses GPIO 2
#define GPIO 2
static const uint pin = 25;
static int chars_rxed = 0;

void uart1ISR(void)
{
while(uart_is_readable(UART_ID))//确定数据是否在RX FIFO中等待。
	{
		uint8_t ch = uart_getc(UART_ID);
		// Can we send it back?
		if(uart_is_writable(UART_ID))//确定数据是否在RX FIFO中等待。
		{

			uart_putc(uart0, ch);
      //uart_putc_raw(uart0,ch);
		}
    chars_rxed++;
  }
}

int main()
{
    stdio_init_all();//串口0,115200
    // Set the TX and RX pins by using the function select on the GPIO
    // Set datasheet for more information on function select
    gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
    gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);
    // Set up our UART
    uart_init(UART_ID, BAUD_RATE);//串口1,115200
    uart_set_hw_flow(UART_ID, false, false);//关闭硬件流控
         uart_set_fifo_enabled(uart1, true);
    // hw_write_masked(&uart_get_hw(uart1)->ifls, 0b100 << UART_UARTIFLS_RXIFLSEL_LSB,
		// 			UART_UARTIFLS_RXIFLSEL_BITS); //设置接收中断的触发条件为FIFO不为空
    // Turn off FIFO's - we want to do this character by character
   // uart_set_fifo_enabled(UART_ID, false);
    irq_set_exclusive_handler(UART1_IRQ, uart1ISR);
	  irq_set_enabled(UART1_IRQ, true);
    uart_set_irq_enables(uart1, true, false); //开启中断,接收中断,关闭发送中断
    irq_set_priority (UART1_IRQ, 1); //设置中断优先级

    // Enable the UART
    uart_is_enabled(UART_ID);
    // GPIO initialisation.
    // We will make this GPIO an input, and pull it up by default
    gpio_init(GPIO);
    gpio_set_dir(GPIO, GPIO_OUT);
    gpio_pull_up(GPIO);
    gpio_init(pin);
    gpio_set_dir(pin, GPIO_OUT);
while (true) {
     sleep_ms(1000);
     gpio_set_mask(1ul<<GPIO);
     gpio_put(pin, true);
        sleep_ms(250);
        gpio_clr_mask(1ul<<GPIO);
        gpio_put(pin, false);
        sleep_ms(250);
       if(uart_is_readable(UART_ID)==0)
       {

           printf("no data,chars_rxed:%d\n",chars_rxed);
        chars_rxed = 0;
       }

}

}

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值