// 使用 Parola 库在显示屏上滚动文本
//
// 演示了如何通过串口接收文本并使用滚动功能显示
//
// 用户可以在串口监视器中输入文本,该文本将以滚动消息的形式显示在屏幕上。
// 滚动速度由连接到 SPEED_IN 引脚的电位器控制。
// 滚动方向由连接到 DIRECTION_SET 引脚的开关控制。
// 反转 ON/OFF 状态由连接到 INVERT_SET 引脚的开关控制。
//
// UISwitch 库可以在 https://github.com/MajicDesigns/MD_UISwitch 找到
// MD_MAX72XX 库可以在 https://github.com/MajicDesigns/MD_MAX72XX 找到
#include <MD_Parola.h> // 引入 MD_Parola 库,用于处理滚动显示
#include <MD_MAX72xx.h> // 引入 MD_MAX72xx 库,用于驱动 LED 矩阵
#include <SPI.h> // 引入 SPI 库,用于硬件 SPI 通信
// 如果为 1,则启用用户界面控件(电位器、开关等)
#define USE_UI_CONTROL 0
#if USE_UI_CONTROL
#include <MD_UISwitch.h> // 如果启用 UI 控制,则引入 UISwitch 库
#endif
// 启用调试信息输出到串口
#define DEBUG 0
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); } // 打印调试信息
#define PRINTS(x) Serial.print(F(x)) // 打印字符串调试信息
#define PRINTX(x) Serial.println(x, HEX) // 打印十六进制调试信息
#else
#define PRINT(s, x) // 如果未启用调试,则不打印任何内容
#define PRINTS(x)
#define PRINTX(x)
#endif
// 定义设备链中的设备数量和硬件接口类型
// 注意:以下引脚编号可能不适用于您的硬件,需要根据实际情况调整
#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW // 使用 Parola 硬件类型
#define MAX_DEVICES 11 // 定义设备链中的最大设备数量
#define CLK_PIN 52 // 定义时钟引脚
#define DATA_PIN 51 // 定义数据引脚
#define CS_PIN 10 // 定义片选引脚
// 硬件 SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); // 初始化 Parola 对象
// 软件 SPI(如果需要,可以启用以下代码)
//MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// 滚动参数
#if USE_UI_CONTROL
const uint8_t SPEED_IN = A5; // 速度控制电位器连接的模拟引脚
const uint8_t DIRECTION_SET = 8; // 滚动方向控制开关连接的数字引脚
const uint8_t INVERT_SET = 9; // 反转控制开关连接的数字引脚
const uint8_t SPEED_DEADBAND = 5; // 速度控制的死区范围
#endif // USE_UI_CONTROL
uint8_t scrollSpeed = 25; // 默认帧延迟值(速度)
textEffect_t scrollEffect = PA_SCROLL_LEFT; // 默认滚动效果为向左滚动
textPosition_t scrollAlign = PA_LEFT; // 默认文本对齐方式为左对齐
uint16_t scrollPause = 2000; // 滚动暂停时间(毫秒)
// 全局消息缓冲区,用于串口和滚动功能共享
#define BUF_SIZE 75
char curMessage[BUF_SIZE] = { "" }; // 当前显示的消息
char newMessage[BUF_SIZE] = { "CSLG1609,Best!" }; // 默认新消息
bool newMessageAvailable = true; // 标志是否有新消息可用
#if USE_UI_CONTROL
MD_UISwitch_Digital uiDirection(DIRECTION_SET); // 初始化方向控制开关
MD_UISwitch_Digital uiInvert(INVERT_SET); // 初始化反转控制开关
// 用户界面处理函数
void doUI(void)
{
// 如果速度发生变化,则设置新速度
{
int16_t speed = map(analogRead(SPEED_IN), 0, 1023, 10, 150); // 读取电位器值并映射到速度范围
if ((speed >= ((int16_t)P.getSpeed() + SPEED_DEADBAND)) ||
(speed <= ((int16_t)P.getSpeed() - SPEED_DEADBAND)))
{
P.setSpeed(speed); // 设置新速度
scrollSpeed = speed; // 更新全局速度变量
PRINT("\nChanged speed to ", P.getSpeed()); // 打印调试信息
}
}
// 如果方向开关被按下,则切换滚动方向
if (uiDirection.read() == MD_UISwitch::KEY_PRESS)
{
PRINTS("\nChanging scroll direction");
scrollEffect = (scrollEffect == PA_SCROLL_LEFT ? PA_SCROLL_RIGHT : PA_SCROLL_LEFT); // 切换滚动方向
P.setTextEffect(scrollEffect, scrollEffect); // 设置新的滚动效果
P.displayClear(); // 清除显示
P.displayReset(); // 重置显示
}
// 如果反转开关被按下,则切换反转模式
if (uiInvert.read() == MD_UISwitch::KEY_PRESS)
{
PRINTS("\nChanging invert mode");
P.setInvert(!P.getInvert()); // 切换反转模式
}
}
#endif // USE_UI_CONTROL
// 从串口读取新消息
void readSerial(void)
{
static char *cp = newMessage; // 指向新消息缓冲区的指针
while (Serial.available()) // 如果串口有数据可用
{
*cp = (char)Serial.read(); // 读取一个字符
if ((*cp == '\n') || (cp - newMessage >= BUF_SIZE - 2)) // 如果遇到换行符或缓冲区已满
{
*cp = '\0'; // 结束字符串
cp = newMessage; // 重置指针
newMessageAvailable = true; // 标志有新消息可用
}
else // 否则移动指针到下一个位置
cp++;
}
}
// 初始化设置
void setup()
{
Serial.begin(57600); // 初始化串口通信,波特率为 57600
Serial.print("\n[Parola Scrolling Display]\nType a message for the scrolling display\nEnd message line with a newline");
#if USE_UI_CONTROL
uiDirection.begin(); // 初始化方向控制开关
uiInvert.begin(); // 初始化反转控制开关
pinMode(SPEED_IN, INPUT); // 设置速度控制引脚为输入模式
doUI(); // 执行用户界面初始化
#endif // USE_UI_CONTROL
P.begin(); // 初始化 Parola 对象
P.displayText(curMessage, scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect); // 显示初始消息
}
// 主循环
void loop()
{
#if USE_UI_CONTROL
doUI(); // 处理用户界面输入
#endif // USE_UI_CONTROL
if (P.displayAnimate()) // 如果显示动画需要更新
{
if (newMessageAvailable) // 如果有新消息可用
{
strcpy(curMessage, newMessage); // 将新消息复制到当前消息缓冲区
newMessageAvailable = false; // 清除新消息标志
}
P.displayReset(); // 重置显示
}
readSerial(); // 从串口读取新消息
}