Arduino RP2040 基于PIO串口的使用
- 📌RP2040基于
Earle F. Philhower, III的开发核心固件:https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json - 🎈相关开发文档在线j简要介绍:
https://arduino-pico.readthedocs.io/en/latest/piouart.html
📙RP2040 硬件PIO功能介绍
🔖在RP2040硬件上,PIO(Programmable Input/Output)功能是一种强大的可编程I/O引擎,可用于处理高速数据流、执行复杂的信号处理和实现专用硬件功能,,与FPGA芯片功能类似。
📑PIO引擎具有以下特点和功能:
- 🌾多个PIO通道:RP2040上有8个PIO通道(PIO0到PIO7),每个通道都具有独立的配置寄存器集合和I/O引脚。
- 🌾多个状态机:每个PIO通道内部可以配置多个状态机,状态机是PIO引擎的核心。每个状态机都可以以高速独立地运行,执行自定义的I/O操作和逻辑。
- 🌾高速数据处理:PIO引擎可以以每个时钟周期执行一次指令,从而实现非常高的数据处理速度。可以通过配置状态机的指令和时钟频率来调整数据处理速度以满足不同的应用需求。
- 🌾双向I/O引脚:每个PIO通道都可以配置一组I/O引脚,这些引脚可用于输入和/或输出数据。每个引脚都可以配置为不同的功能,如输入、输出、中断、协议等。
- 🌾灵活的I/O协议:PIO引擎支持灵活的I/O协议,可以根据需要配置I/O引脚的数据格式、时序和协议。
- 🌾硬件加速:PIO引擎的设计目标之一是通过硬件加速来提高性能和效率。它可以在不占用主CPU周期的情况下执行自定义的I/O操作,从而减少了MCU的负担。
- 🌾适应多种应用场景:由于PIO引擎的可编程性,
📗基于PIO的通用异步收发
RP2040硬件上有2个串口。基于PIO的通用异步收发与Arduino SoftwareSerial库相当,ArduinoPico内核中包含一个使用一个或两个PIO状态机的模拟通用异步收发设备。这允许从RP2040运行多达4个双向或多达8个单向串行端口,而无需额外的CPU资源。
📘核心库函数介绍
- 🔖在固件库文件
C:\Users\用户名\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\3.7.2\cores\rp2040\SerialPIO.cpp中包含了基于PIO串口具体实现的方法。大多数接口函数和串口函数的使用类似。
void begin(unsigned long baud = 115200) override {
begin(baud, SERIAL_8N1);
};
void begin(unsigned long baud, uint16_t config) override;
void end() override;
void setInverted(bool invTx = true, bool invRx = true);
virtual int peek() override;
virtual int read() override;
virtual int available() override;
virtual int availableForWrite() override;
virtual void flush() override;
virtual size_t write(uint8_t c) override;
bool overflow();
using Print::write;
operator bool() override;
// Not to be called by users, only from the IRQ handler. In public so that the C-language IQR callback can access it
void _handleIRQ();
- 🌿
SerialPIO(txpin, rxpin,fifosize)实例化对象,txpin:发送引脚指定,rxpin接受引脚指定,fifosize缓冲区大小,如果未指定Fifosize,则默认为32字节。 - 🌿
availableForWrite():用于流或串行数据写入,确定可以写入多少字节的数据,而不会发生阻塞。
int SerialPIO::availableForWrite() {
CoreMutex m(&_mutex);
if (!_running || !m || (_tx == NOPIN)) {
return 0;
}
return 8 - pio_sm_get_tx_fifo_level(_txPIO, _txSM);
}
- 🌿
setInverted(bool invTx, bool invRx):用在需要设置串行PIO输入输出反转状态的场景下。在某些硬件环境中,发送(输出)和接收(输入)线路需要进行反转操作,以适应特定的设备或通信协议。
🔖在特定的串行通信协议中,发送线路需要反转,而接收线路不需要反转。可以通过调用setInverted(true, false)来设置串行PIO的输出反转,在发送数据时符合协议规定。
void SerialPIO::setInverted(bool invTx, bool invRx) {
_txInverted = invTx;
_rxInverted = invRx;
}
- 📄如果仅需要实例化串行发送或接收单元,传入
SerialPIO::NOPIN作为txpin或rxpin的形参。
- 例如,要在GP16上创建一个仅传输端口:
SerialPIO transmitter( 16, SerialPIO::NOPIN );
📙发送例程
/*
RP2040有30个可配置为PIO引脚的GPIO引脚。这些引脚是:
GP0、GP1、GP2、GP3、GP4、GP5、GP6、GP7、
GP8、GP9、GP10、GP11、GP12、GP13、GP14、GP15、
GP16、GP17、GP18、GP19、GP20、GP21、GP22、GP26、
GP27、GP28、GP29、GP30、GP31。
*/
#include <Arduino.h>
#include <SerialPIO.h>
#define txpin 0
#define rxpin 1
#define fifosize 32
SerialPIO mySerial(0, 1); // 创建SerialPIO对象
//SerialPIO mySerial(0, SerialPIO::NOPIN);//仅使能发送端
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);//USB CDC
// Serial1.begin(115200);//硬件串口0
pinMode(LED_BUILTIN, OUTPUT);
mySerial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
int ledState = digitalRead(LED_BUILTIN);
ledState = !ledState;
digitalWrite(LED_BUILTIN, ledState);
mySerial.write("From PIO USART Txpin gpio0 ");
// mySerial.println("From PIO USART Txpin gpio0 ");
delay(1000);
Serial.println("USB CDC PRINT.");
}
📗PIO串口接收,USB CDC打印接收数据例程
/*
RP2040有30个可配置为PIO引脚的GPIO引脚。这些引脚是:
GP0、GP1、GP2、GP3、GP4、GP5、GP6、GP7、
GP8、GP9、GP10、GP11、GP12、GP13、GP14、GP15、
GP16、GP17、GP18、GP19、GP20、GP21、GP22、GP26、
GP27、GP28、GP29、GP30、GP31。
*/
#include <Arduino.h>
#include <SerialPIO.h>
#define txpin 0
#define rxpin 1
#define fifosize 32
SerialPIO mySerial(0, 1); // 创建SerialPIO对象
//SerialPIO mySerial( SerialPIO::NOPIN,1);//仅使能接收端
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);//USBCDC
// Serial1.begin(115200);//硬件串口0
pinMode(LED_BUILTIN, OUTPUT);
mySerial.begin(9600);//PIO USART
}
void loop() {
static unsigned long startTime = millis(); // 记录起始时间
static String receivedData; // 存储接收到的字符流
while (mySerial.available()) { // 检查是否有可用数据
char data = mySerial.read(); // 读取串口接收到的数据
receivedData += data; // 将数据添加到接收到的字符流中
startTime = millis(); // 重置起始时间
}
// 检查超时
if (millis() - startTime >= 500) {
if (receivedData.length() > 0) {
Serial.print("Received: "); // 通过USB CDC打印接收到的数据
Serial.println(receivedData);
receivedData = ""; // 清空接收到的字符流
}
startTime = millis(); // 重置起始时间
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); //gpio25 闪烁
}
}

本文详细介绍了ArduinoRP2040的PIO功能,包括其8个PIO通道、状态机、高速数据处理、双向I/O引脚和灵活的I/O协议。重点讲解了基于PIO的通用异步收发在串口通信中的应用,以及如何通过SerialPIO类实现串口操作,包括设置参数、初始化和数据传输示例。
290

被折叠的 条评论
为什么被折叠?



