Skip to main content

使用 Seeed Studio XIAO RA4M1 进行引脚复用

数字引脚

XIAO RA4M1 拥有多达 11 个常规 GPIO 引脚、6 个模拟引脚和 8 个可复用的 IO 端口。在这个示例中,我们将使用 XIAO RA4M1、XIAO 扩展板和一个继电器来演示如何使用不同的数字引脚进行读写操作。

硬件准备

Seeed Studio XIAO R4M1Seeed Studio Expansion Base for XIAO with Grove OLEDGrove - 继电器

请将 XIAO RA4M1 或 Sense 安装到扩展板上,并通过 Grove 线缆将继电器连接到扩展板的 A0/D0 接口。最后,通过 USB-C 线缆将 XIAO 连接到计算机。

软件实现

在这个示例中,我们将使用连接到 XIAO 扩展板的按钮来控制继电器的开关状态。当按钮被按下时,继电器打开;当按钮被释放时,继电器关闭。

const int buttonPin = D1;     // the number of the pushbutton pin
int buttonState = 0; // variable for reading the pushbutton status
const int relayPin = D0;

void setup() {
// initialize the Relay pin as an output:
pinMode(relayPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);

// check if the pushbutton is pressed. If it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// turn Relay on:
digitalWrite(relayPin, HIGH);
} else {
// turn Relay off:
digitalWrite(relayPin, LOW);
}
}

如果一切顺利,上传程序后,您应该看到以下效果。

数字引脚作为PWM

XIAO RA4M1上的所有GPIO引脚都支持PWM输出。因此,您可以使用任何引脚输出PWM来调节灯光亮度、控制舵机和其他功能。

硬件准备

Seeed Studio XIAO RA4M1Seeed Studio XIAO扩展板配Grove OLEDGrove - 可变色LED

请将XIAO RA4M1或Sense安装到扩展板上,然后使用Grove线缆将可变色LED连接到扩展板的A0/D0接口。最后,通过USB-C线缆将XIAO连接到您的计算机。

软件实现

在这个示例中,我们将演示如何使用PWM输出来控制灯光的亮度。

int LED_pin = D0;    // LED连接到数字引脚10

void setup() {
// 声明LED引脚为输出
pinMode(LED_pin, OUTPUT);
}

void loop() {
// 从最小值渐变到最大值,每次增加5个点:
for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 3) {
// 设置数值(范围从0到255):
analogWrite(LED_pin, fadeValue);
// 等待30毫秒以查看调光效果
delay(30);
}

// 从最大值渐变到最小值,每次减少5个点:
for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 3) {
// 设置数值(范围从0到255):
analogWrite(LED_pin, fadeValue);
// 等待30毫秒以查看调光效果
delay(30);
}
}

如果程序运行成功,您将看到以下运行效果。

模拟

XIAO RA4M1 开发板具有高达 14 位的 ADC,可高分辨率读取模拟传感器值,它可以帮助我们读取更准确的值。XIAO RA4M1 开发板上的模数转换器(ADC)。默认情况下,分辨率设置为 10 位,可以设置为 12 位和 14 位分辨率,以提高模拟读数的精度。

ADC 精度的详细数据

  • 10 位:0~1024
  • 12 位:0~4096
  • 14 位:0~16383

接下来,我们将选择两个传感器来体现 ADC 的特性。

硬件准备

Seeed Studio XIAO RA4M1Grove-可变色 LEDGrove-旋转角度传感器Seeed Studio Grove Base for XIAO

软件实现

#define ADC_Bit_Fourteen 14
#define ADC_Bit_Twelve 12
#define ADC_Bit_Ten 10

const int analogInPin = A1; // 电位器连接的模拟输入引脚
const int analogOutPin = 9; // LED 连接的模拟输出引脚

int sensorValue = 0; // 从电位器读取的值
int outputValue = 0; // 输出到 PWM 的值(模拟输出)

void setup() {

Serial.begin(115200);
// Ten_Bite_ADC_Config(); // 10位
// Twelve_Bite_ADC_Config(); // 12位
Fourteen_Bite_ADC_Config(); // 14位

}

void loop() {
sensorValue = analogRead(analogInPin);
outputValue = map(sensorValue, 0, 4095, 0, 255);
analogWrite(analogOutPin, outputValue);

Serial.print("sensor = ");
Serial.print(sensorValue);
Serial.print("\t output = ");
Serial.println(outputValue);
delay(100);
}

void Ten_Bite_ADC_Config() {
analogReadResolution(ADC_Bit_Ten);
}

void Twelve_Bite_ADC_Config() {
analogReadResolution(ADC_Bit_Twelve);
}

void Fourteen_Bite_ADC_Config() {
analogReadResolution(ADC_Bit_Fourteen);
}

如果一切顺利,上传程序后,您应该看到以下效果。

串口通信

在使用 Arduino IDE 时,串口通信是许多项目的重要组成部分。要在 Arduino IDE 中使用串口通信,您需要首先打开串口监视器窗口。这可以通过点击工具栏中的串口监视器图标或按Ctrl+Shift+M快捷键来完成。

常规用法

一些常用的串口函数包括:

  • Serial.begin() -- 以指定的波特率初始化通信;
  • Serial.print() -- 以可读格式向串口发送数据;
  • Serial.write() -- 向串口发送二进制数据;
  • Serial.available() -- 检查串口是否有可读取的数据;
  • Serial.read() -- 从串口读取单个字节的数据;
  • Serial.flush() -- 等待串口输出数据传输完成。

通过使用这些串口函数,您可以在 Arduino 开发板和计算机之间发送和接收数据,这为创建交互式项目开辟了许多可能性。

以下是一个示例程序:

void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}

void loop() {
// send data to the serial port
Serial.println("Hello World!");

// read data from the serial port
if (Serial.available() > 0) {
// read the incoming byte:
char incomingByte = Serial.read();
// print the incoming byte to the serial monitor:
Serial.print("I received: ");
Serial.println(incomingByte);
}

// wait for a second before repeating the loop
delay(1000);
}

Serial1 的使用

根据上述 XIAO RA4M1 引脚图的具体参数,我们可以观察到有 TX 引脚和 RX 引脚。 这与串行通信不同,但用法也非常相似,只是需要添加一些参数。 因此接下来,我们将使用芯片引出的引脚进行串行通信。


#define BAUD 115200

void setup() {
Serial1.begin(BAUD);
}

void loop() {
if(Serial1.available() > 0)
{
char incominByte = Serial1.read();
Serial1.print("I received : ");
Serial1.println(incominByte);
}
delay(1000);
}

软件串口的使用

#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); // RX, TX

void setup() {
// 初始化串口通信
Serial.begin(9600);
while (!Serial);

// 初始化软件串口
mySerial.begin(9600);
}

void loop() {
// 从软件串口读取数据
if (mySerial.available()) {
char data = mySerial.read();
Serial.print("接收到的数据: ");
Serial.println(data);
}

// 向软件串口写入数据
mySerial.print("Hello World!");

// 等待一秒钟后重复循环
delay(1000);
}

在这个程序中,我们首先包含 SoftwareSerial.h 库来使用软件串口。然后,我们创建一个名为 mySerial 的新 SoftwareSerial 对象,分别使用引脚 2 和 3 作为 RX 和 TX。

setup() 函数中,我们初始化硬件串口(Serial.begin())和软件串口(mySerial.begin())。

loop() 函数中,我们使用 mySerial.available() 函数检查软件串口是否有可读取的数据。如果有,我们使用 mySerial.read() 函数读取传入的字节并将其存储在名为 data 的变量中。然后我们使用 Serial.print()Serial.println() 函数向硬件串口打印"Received data: ",后跟 data 的值。

我们还使用 mySerial.print() 函数向软件串口写入"Hello World!"。这将把数据从 XIAO 发送到连接到软件串口的设备。

最后,我们添加一个 delay() 函数,在重复循环之前等待一秒钟。

IIC

XIAO RA4M1 具有 I2C 接口,可用于许多传感器的数据传输和解析,以及使用一些 OLED 屏幕。

硬件准备

Seeed Studio XIAO RA4M1Seeed Studio Expansion Base for XIAO with Grove OLED

XIAO 扩展板上的 OLED 显示屏使用 I2C 协议,通过板上的 I2C 电路连接到 XIAO 的 I2C 接口。因此,我们可以直接将 XIAO 插入扩展板并编程以在屏幕上显示内容。

软件实现

此示例介绍如何使用 Seeed Studio Expansion Base for XIAO RA4M1 上的 OLED 显示屏。

步骤 1. 将 Seeed Studio XIAO RA4M1 安装在扩展板上,然后连接 Type-C 线缆。

步骤 2. 安装 u8g2 库。

步骤 3. 复制代码并粘贴到 Arduino IDE 中,然后上传。

#include <Arduino.h>
#include <U8x8lib.h>
#include <Wire.h>

U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // OLEDs without Reset of the Display

void setup(void) {
u8x8.begin();
u8x8.setFlipMode(1); // set number from 1 to 3, the screen word will rotary 180
}

void loop(void) {
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.setCursor(0, 0);
u8x8.print("i'm XIAO RA4M1");
}

在代码的前几行中,我们包含了所需的库,如 Arduino.h、U8x8lib.h 和 Wire.h。U8x8lib.h 库提供了控制 OLED 显示屏的函数,Wire.h 库提供了 I2C 通信的函数。

setup() 函数中,我们使用 u8x8.begin() 函数初始化 OLED 显示屏。我们还使用 u8x8.setFlipMode() 函数设置显示屏的翻转模式,将屏幕旋转 180 度。

loop() 函数中,我们使用 u8x8.setFont() 函数设置字体,并使用 u8x8.setCursor() 函数指定光标在显示屏上的位置。最后,我们使用 u8x8.print() 函数在 OLED 显示屏上显示字符串 "Hello World!"。

如果您将程序上传到 XIAO RA4M1,您将在扩展板上的 OLED 显示屏上看到显示的内容。

SPI

RA4M1 芯片集成了多个外设,包括一个 SPI 接口,可用于连接外部 SPI 设备,如闪存、显示屏、传感器等。XIAO RA4M1 还支持高速 SPI 传输模式,可以实现最高 80 MHz 的 SPI 传输速率,满足大多数 SPI 设备的数据传输需求。

硬件准备

Seeed Studio XIAO RA4M1Grove - OLED Display 1.12 (SH1107) V3.0 - SPI/IIC

准备好上述硬件后,使用跳线将 XIAO 和 OLED 的 SPI 接口连接起来。请参考以下图表了解接线方法。

软件实现

接下来,我们将以下面的程序为例,介绍如何使用 SPI 接口控制 OLED 屏幕显示。

安装 u8g2 库。

#include <Arduino.h>
#include <U8g2lib.h>
#include <SPI.h>
#include <Wire.h>

U8G2_SH1107_128X128_1_4W_HW_SPI u8g2(U8G2_R3, /* cs=*/ D7, /* dc=*/ D4, /* reset=*/ D5);

void setup(void) {
u8g2.begin();
}

void loop(void) {
u8g2.firstPage();

do {
u8g2.setFont(u8g2_font_luBIS08_tf);
u8g2.drawStr(0,24,"Hello Seeed!");
} while ( u8g2.nextPage() );
}

setup() 函数中,使用适当的构造函数参数实例化 U8G2_SH1107_128X128_1_4W_HW_SPI 类,这些参数指定了用于片选 (cs)、数据/命令 (dc) 和复位的引脚。然后,调用 u8g2.begin() 函数来初始化显示器。

loop() 函数中,使用 u8g2.firstPage()u8g2.setFont()u8g2.drawStr() 函数用新内容更新显示器。u8g2.firstPage() 函数设置显示缓冲区以供写入,而 u8g2.nextPage() 显示更新的内容。do-while 循环确保内容持续显示,直到程序停止。

总的来说,这段代码演示了如何使用 U8g2 库来控制 OLED 显示器并在其上显示文本。

CAN

硬件准备

Seeed Studio XIAO RA4M1XIAO CAN Bus 扩展板

步骤 1 . 准备两个 CAN Bus 分线板和 XIAO RA4M1

步骤 2 . 将这两个 XIAO RA4M1 分别插入 CAN Bus 分线板

步骤 3 . 准备杜邦线连接

软件准备

我们提供了一个 MCP2515 板的 Arduino 库


该库包含几个示例,包括:

  • OBDII-PIDs - 从 OBD-II 接口检索数据
  • send - 向 CAN 总线发送帧
  • recv - 从 CAN 总线接收帧
  • set_mask_filter_recv - 使用掩码和过滤器设置从 CAN 总线接收帧

软件实现

tip

不允许同时为两个 XIAO RA4M1 上电并下载程序,因为这会导致下载串口时出现错误。下载一个后,拔掉它,然后为另一个 XIAO RA4M1 上电以下载程序,最后同时上电以检查串口消息

CAN 写入代码


/* 从 CAN 总线发送帧

CAN 波特率,

#define CAN_5KBPS 1
#define CAN_10KBPS 2
#define CAN_20KBPS 3
#define CAN_25KBPS 4
#define CAN_31K25BPS 5
#define CAN_33KBPS 6
#define CAN_40KBPS 7
#define CAN_50KBPS 8
#define CAN_80KBPS 9
#define CAN_83K3BPS 10
#define CAN_95KBPS 11
#define CAN_100KBPS 12
#define CAN_125KBPS 13
#define CAN_200KBPS 14
#define CAN_250KBPS 15
#define CAN_500KBPS 16
#define CAN_666KBPS 17
#define CAN_1000KBPS 18
*/

#include <mcp_can.h>
#include <SPI.h>

/* 请修改 SPI_CS_PIN 以适配您的开发板。

CANBed V1 - 17
CANBed M0 - 3
CAN Bus Shield - 9
CANBed 2040 - 9
CANBed Dual - 9
OBD-2G Dev Kit - 9
OBD-II GPS Kit - 9
Hud Dev Kit - 9

Seeed Studio CAN-Bus Breakout Board for XIAO and QT Py - D7
*/

#define SPI_CS_PIN D7

MCP_CAN CAN(SPI_CS_PIN); // 设置 CS 引脚

void setup()
{
Serial.begin(115200);
while(!Serial);

// 以下代码适用于 OBD-II GPS Dev Kit Atemga32U4 版本
// pinMode(A3, OUTPUT);
// digitalWrite(A3, HIGH);

// 以下代码适用于 OBD-II GPS Dev Kit RP2040 版本
// pinMode(12, OUTPUT);
// digitalWrite(12, HIGH);

while (CAN_OK != CAN.begin(CAN_500KBPS)) // 初始化 CAN 总线:波特率 = 500k
{
Serial.println("CAN BUS FAIL!");
delay(100);
}
Serial.println("CAN BUS OK!");
}

unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};
void loop()
{
CAN.sendMsgBuf(0x00, 0, 8, stmp);
delay(100); // 每 100ms 发送数据
}

// END FILE

CAN 读取代码

/*  从CAN总线接收帧

CAN波特率,

#define CAN_5KBPS 1
#define CAN_10KBPS 2
#define CAN_20KBPS 3
#define CAN_25KBPS 4
#define CAN_31K25BPS 5
#define CAN_33KBPS 6
#define CAN_40KBPS 7
#define CAN_50KBPS 8
#define CAN_80KBPS 9
#define CAN_83K3BPS 10
#define CAN_95KBPS 11
#define CAN_100KBPS 12
#define CAN_125KBPS 13
#define CAN_200KBPS 14
#define CAN_250KBPS 15
#define CAN_500KBPS 16
#define CAN_666KBPS 17
#define CAN_1000KBPS 18

CANBed V1: https://www.longan-labs.cc/1030008.html
CANBed M0: https://www.longan-labs.cc/1030014.html
CAN Bus Shield: https://www.longan-labs.cc/1030016.html
OBD-II CAN Bus GPS Dev Kit: https://www.longan-labs.cc/1030003.html
*/

#include <SPI.h>
#include "mcp_can.h"

/* 请修改SPI_CS_PIN以适配您的开发板。

CANBed V1 - 17
CANBed M0 - 3
CAN Bus Shield - 9
CANBed 2040 - 9
CANBed Dual - 9
OBD-2G Dev Kit - 9
OBD-II GPS Kit - 9
Hud Dev Kit - 9

Seeed Studio CAN-Bus Breakout Board for XIAO and QT Py - D7
*/


#define SPI_CS_PIN D7

MCP_CAN CAN(SPI_CS_PIN); // 设置CS引脚


void setup()
{
Serial.begin(115200);
while(!Serial);

// 以下代码适用于OBD-II GPS Dev Kit Atemga32U4版本
// pinMode(A3, OUTPUT);
// digitalWrite(A3, HIGH);

// 以下代码适用于OBD-II GPS Dev Kit RP2040版本
// pinMode(12, OUTPUT);
// digitalWrite(12, HIGH);

while (CAN_OK != CAN.begin(CAN_500KBPS)) // 初始化CAN总线:波特率 = 500k
{
Serial.println("CAN BUS FAIL!");
delay(100);
}
Serial.println("CAN BUS OK!");
}


void loop()
{
unsigned char len = 0;
unsigned char buf[8];

if(CAN_MSGAVAIL == CAN.checkReceive()) // 检查是否有数据到来
{
CAN.readMsgBuf(&len, buf); // 读取数据,len:数据长度,buf:数据缓冲区

unsigned long canId = CAN.getCanId();

Serial.println("-----------------------------");
Serial.print("Get data from ID: ");
Serial.println(canId, HEX);

for(int i = 0; i<len; i++) // 打印数据
{
Serial.print(buf[i], HEX);
Serial.print("\t");
}
Serial.println();
}
}

// END FILE

tip

在此示例中,您需要焊接CAN总线分线板终端引脚P1中的一个,只有这样才能使用任何速度,否则您只能使用125以下的CAN波特率

什么时候需要连接终端电阻?

    1. 长距离通信:如果CAN总线很长(例如超过1米),必须在总线两端连接终端电阻,以避免信号反射引起的通信问题。
    1. 多节点通信:如果多个节点连接到同一个CAN总线,终端电阻也是不可缺少的。它们确保总线的阻抗稳定性,从而防止信号失真。

什么时候可以断开终端电阻?

    1. 短距离通信:在一些短距离应用中(通常小于1米),可以省略终端电阻,因为信号反射对通信的影响相对较小。
    1. 单节点通信:如果总线上只有一个节点(如在调试环境中)且距离很短,可以暂时断开终端电阻。
发送端代码结果接收端代码结果

技术支持与产品讨论

感谢您选择我们的产品!我们在这里为您提供不同的支持,以确保您使用我们产品的体验尽可能顺畅。我们提供多种沟通渠道,以满足不同的偏好和需求。

Loading Comments...