Arduino R4 WIFI横向滚动显示16×16LED屏

实现一个从左向右横向滚动的"吉祥如意"显示效果。

arduino r4 WiFi滚动显示16*16led

#include <SPI.h>// 引脚定义
const int RowA = 2, RowB = 3, RowC = 4, RowD = 5;
const int OE = 6;
const int LATCH = 10;// 字模数据 (吉祥如意)
const PROGMEM byte characterData[4][32] = {// 吉{0x01,0x00,0x01,0x00,0x01,0x04,0xFF,0xFE,0x01,0x00,0x01,0x00,0x01,0x10,0x3F,0xF8,0x00,0x00,0x00,0x10,0x1F,0xF8,0x10,0x10,0x10,0x10,0x10,0x10,0x1F,0xF0,0x10,0x10},// 祥{0x22,0x08,0x11,0x10,0x10,0xA0,0xFB,0xFC,0x08,0x40,0x10,0x40,0x3B,0xF8,0x54,0x40,0x94,0x40,0x10,0x44,0x17,0xFE,0x10,0x40,0x10,0x40,0x10,0x40,0x10,0x40,0x10,0x40},// 如{0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x04,0xFE,0xFE,0x22,0x84,0x22,0x84,0x22,0x84,0x22,0x84,0x42,0x84,0x24,0x84,0x14,0x84,0x08,0x84,0x14,0xFC,0x22,0x84,0x40,0x00},// 意{0x01,0x00,0x3F,0xF8,0x08,0x20,0x04,0x44,0xFF,0xFE,0x00,0x00,0x1F,0xF0,0x10,0x10,0x1F,0xF0,0x10,0x10,0x1F,0xF0,0x02,0x08,0x51,0x04,0x51,0x24,0x90,0x20,0x0F,0xE0}
};SPISettings spiSettings(10000000, MSBFIRST, SPI_MODE0);// 横向滚动缓冲区 (64列 x 16行)
byte scrollBuffer[16][8]; // 每行8字节=64位 (4个汉字)// 滚动状态
int scrollOffset = 0;
unsigned long lastScrollTime = 0;
const int scrollDelay = 50; // 滚动速度 (毫秒)// 显示控制
unsigned long lastFrameTime = 0;
const int targetFPS = 200;  // 目标帧率 (200帧/秒)
const int frameInterval = 1000 / targetFPS; // 5ms/帧void setup() {// 初始化引脚pinMode(RowA, OUTPUT); pinMode(RowB, OUTPUT);pinMode(RowC, OUTPUT); pinMode(RowD, OUTPUT);pinMode(OE, OUTPUT); pinMode(LATCH, OUTPUT);digitalWrite(OE, HIGH);digitalWrite(LATCH, HIGH);SPI.begin();// 初始化横向滚动缓冲区initializeScrollBuffer();Serial.begin(115200);Serial.println("横向滚动显示器准备就绪");
}// 设置行选择
void setRow(byte row) {digitalWrite(RowA, row & 0x01);digitalWrite(RowB, (row >> 1) & 0x01);digitalWrite(RowC, (row >> 2) & 0x01);digitalWrite(RowD, (row >> 3) & 0x01);
}// 初始化横向滚动缓冲区
void initializeScrollBuffer() {// 将四个汉字转换为横向排列的缓冲区for (int row = 0; row < 16; row++) {for (int charIndex = 0; charIndex < 4; charIndex++) {// 获取每个汉字的左右字节byte leftByte = pgm_read_byte(&characterData[charIndex][row * 2]);byte rightByte = pgm_read_byte(&characterData[charIndex][row * 2 + 1]);// 将每个汉字的16位分为两个字节存储scrollBuffer[row][charIndex * 2] = leftByte;scrollBuffer[row][charIndex * 2 + 1] = rightByte;}}
}// 横向滚动内容
void scrollContent() {scrollOffset++;if (scrollOffset >= 64) { // 64列 = 4汉字 * 16列scrollOffset = 0;}
}// 获取当前列的数据
byte getColumnData(byte row, int column) {int byteIndex = column / 8;int bitIndex = 7 - (column % 8); // 高位在前return (scrollBuffer[row][byteIndex] >> bitIndex) & 0x01;
}// 显示单帧内容
void displayFrame() {// 确保固定帧率unsigned long currentTime = micros();unsigned long elapsed = currentTime - lastFrameTime;if (elapsed < frameInterval * 1000) {delayMicroseconds(frameInterval * 1000 - elapsed);}lastFrameTime = micros();// 逐行显示for (byte row = 0; row < 16; row++) {digitalWrite(OE, HIGH);  // 关闭显示// 准备SPI传输SPI.beginTransaction(spiSettings);// 构建当前行的16位数据 (从右向左排列)uint16_t rowData = 0;// 从滚动偏移位置开始,取16列数据for (int col = 0; col < 16; col++) {int actualCol = (scrollOffset + col) % 64;byte pixel = getColumnData(row, actualCol);// 设置位 (从最高位开始)rowData = (rowData << 1) | pixel;}// 发送数据 (高8位和低8位)SPI.transfer(~(rowData >> 8));   // 高8位SPI.transfer(~(rowData & 0xFF)); // 低8位// 结束SPI传输SPI.endTransaction();// 设置当前行setRow(row);// 锁存数据digitalWrite(LATCH, LOW);digitalWrite(LATCH, HIGH);// 开启显示digitalWrite(OE, LOW);// 行显示时间 (100μs)delayMicroseconds(100);}// 所有行显示完毕后立即关闭显示digitalWrite(OE, HIGH);
}void loop() {// 滚动控制if (millis() - lastScrollTime > scrollDelay) {scrollContent();lastScrollTime = millis();}// 显示当前帧displayFrame();
}

横向滚动实现原理

数据结构设计

图表

横向滚动过程

  1. 缓冲区初始化

    • 将四个汉字按顺序排列在64列×16行的缓冲区中

    • 每个汉字占据16列空间

  2. 滚动显示

    图表

  1. 取数据逻辑

    • scrollOffset位置开始取16列

    • 构建16位行数据

    • 发送给74HC595

关键优化

  1. 高效数据结构

    • 使用16×8字节缓冲区存储64列数据

    • 直接访问列数据,无需实时计算

  2. 平滑滚动

    arduino

  • const int scrollDelay = 50; // 每50ms滚动1列
  • 视觉效果优化

    • 从左向右滚动符合阅读习惯

    • 完整显示每个汉字的时间:16列 × 50ms = 800ms

    • 四个汉字完整显示时间:3.2秒

  • 亮度均衡

    arduino

  1. delayMicroseconds(100); // 每行显示时间一致

参数调整指南

  1. 滚动速度

    arduino

  • // 较慢速度 (约每秒10列)
    const int scrollDelay = 100;// 中等速度 (约每秒20列)
    const int scrollDelay = 50;// 较快速度 (约每秒33列)
    const int scrollDelay = 30;
  • 显示亮度

    arduino

  • // 较低亮度
    delayMicroseconds(80);// 中等亮度
    delayMicroseconds(100);// 较高亮度
    delayMicroseconds(120);
  • 刷新率

    arduino

  1. // 减少闪烁 (推荐)
    const int targetFPS = 200;// 更高刷新率 (需要更快的硬件)
    const int targetFPS = 300;

常见问题解决

  1. 显示方向反了
    如果文字从右向左滚动,修改数据构建方式:

    arduino

  • // 原代码 (从左向右)
    rowData = (rowData << 1) | pixel;// 改为从右向左
    rowData = (rowData >> 1) | (pixel << 15);
  • 亮度不均匀

    • 检查OE信号是否在每行结束后立即拉高

    • 确保每行显示时间严格一致

    • 增加帧间延时:

      arduino

    • const int frameInterval = 1000 / 150; // 降低刷新率
  • 汉字显示不完整

    • 确认缓冲区初始化正确

    • 检查字模数据是否正确加载

    • 增加滚动延迟:

      arduino

    • const int scrollDelay = 80; // 更慢的滚动

扩展功能

  1. 添加新文字

    arduino

  • // 添加第五个字
    const PROGMEM byte characterData[5][32] = {// 原有四个字...// 新字数据...
    };// 更新缓冲区大小
    byte scrollBuffer[16][10]; // 5汉字 * 16列/8 = 10字节
  • 双向滚动

    arduino

  • bool scrollDirection = true; // true=向右, false=向左void scrollContent() {if(scrollDirection) {scrollOffset++;} else {scrollOffset--;}// 边界检查...
    }
  • 暂停功能

    arduino

  1. const int pauseButton = 7;void setup() {pinMode(pauseButton, INPUT_PULLUP);
    }void loop() {if (digitalRead(pauseButton) == LOW) {// 显示当前帧但不滚动while (digitalRead(pauseButton) == LOW) {displayFrame();}}// 正常滚动...
    }

这个横向滚动方案解决了之前纵向滚动时文字看不清的问题,同时保持了流畅的动画效果和均衡的亮度显示。每个汉字都有足够的时间完整显示,便于观看。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/85435.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/85435.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

html css js网页制作成品——HTML+CSS+js力学光学天文网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…

嵌入式开发之freeRTOS移植

FreeRTOS 是一款广泛应用于嵌入式系统的开源实时操作系统&#xff08;RTOS&#xff09;&#xff0c;其移植过程需要结合具体硬件平台和编译器进行适配。以下是 FreeRTOS 移植的详细步骤和关键注意事项&#xff1a; 一、移植前的准备工作 1. 硬件平台确认 处理器架构&#xf…

【算法 day07】LeetCode 344.反转字符串 | 541. 反转字符串II | 卡码网:54.替换数字

344.反转字符串 题目链接 | 文档讲解 |视频讲解 : 链接 1.思路&#xff1a; 采用双指针&#xff0c;left从0开始移动,right从尾元素进行移动 循环判断条件&#xff1a;left< right,边界值使用举例法&#xff0c;eg: [ h ,e ,l,o ]偶数个不会相遇, [h ,e ,l ,l ,o ]奇数个&…

从检索到生成:RAG 如何重构大模型的知识边界?

引言&#xff1a;知识边界的突破与重构 在人工智能技术快速发展的今天&#xff0c;大型语言模型&#xff08;LLMs&#xff09;已经展现出强大的文本生成和理解能力。然而&#xff0c;这些模型在实际应用中仍面临着知识时效性、事实准确性和可溯源性等核心挑战。检索增强生成&a…

前端基础知识CSS系列 - 05(BFC的理解)

一、是什么 我们在页面布局的时候&#xff0c;经常出现以下情况&#xff1a; 这个元素高度怎么没了&#xff1f;这两栏布局怎么没法自适应&#xff1f;这两个元素的间距怎么有点奇怪的样子&#xff1f;...... 原因是元素之间相互的影响&#xff0c;导致了意料之外的情况&…

Prompt Engineering 学习指南:从入门到精通的最佳路径与资源

本 Prompt Engineering 技术报告,旨在提供一个从入门到精通的清晰学习路径、核心方案,并附上最关键的 GitHub 仓库资源。您可以将此报告作为快速提升 Prompt 能力的“速查手册”和“成长地图”。 Prompt Engineering 学习指南:从入门到精通的最佳路径与资源 技术报告摘要 (…

fastmcp MCPConfig多服务器使用案例;sse、stdio、streamable-http使用

1、sse、stdio、streamable-http使用 参考&#xff1a;https://gofastmcp.com/deployment/running-server#the-run-method stdio本地使用&#xff1b;sse、streamable-http远程调用&#xff08; Streamable HTTP—New in version: 2.3.0&#xff09; 调用&#xff1a; stdio、…

网站服务器被DDOS攻击打不开,是要换高防服务器还是加CDN能防护住?

高防云服务器、高防 IP 和高防 CDN 作为常见应对网络攻击的重要利器&#xff0c;它们各自有着独特的特点和应用场景&#xff0c;从技术架构看&#xff0c;高防云服务器是资源型防护&#xff0c;深度整合计算与防御资源&#xff1b;高防IP是流量型防护&#xff0c;以代理模式实现…

深入解析原型模式:从理论到实践的全方位指南

深入解析原型模式&#xff1a;从理论到实践的全方位指南 引言&#xff1a;为什么需要原型模式&#xff1f; 在软件开发过程中&#xff0c;对象创建是一个频繁且关键的操作。传统方式&#xff08;如直接使用new关键字&#xff09;在某些场景下会显得效率低下且不够灵活。想象这…

HuggingFace镜像配置失效问题深度解析:Python模块导入机制的陷阱

前言 在使用HuggingFace的transformers和datasets库时&#xff0c;国内用户经常会遇到网络连接问题。虽然设置了镜像源环境变量&#xff0c;但仍然报错无法连接到huggingface.co。本文将深入分析这个问题的根因&#xff0c;并从Python模块导入机制的角度解释为什么环境变量设置…

leetcode146-LRU缓存

leetcode 146 思路 什么是LRU缓存&#xff1f; LRU&#xff08;Least Recently Used&#xff09;缓存是一种常见的缓存淘汰策略&#xff0c;核心思想是&#xff1a;当缓存容量满时&#xff0c;优先淘汰最久未使用的数据。LeetCode 146 题要求实现一个支持get和put操作的 LR…

MQTT:构建高效物联网通信的轻量级协议

MQTT – 轻量级物联网消息推送协议 MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是机器对机器(M2M)/物联网(IoT)连接协议。它被设计为一个极其轻量级的发布/订阅消息传输协议。对于需要较小代码占用空间和/或网络带宽非常宝贵的远程连接非常有用&#xf…

AI自动生成复杂架构图,流程图,思维导图

AI自动生成复杂架构图&#xff0c;流程图&#xff0c;思维导图方案 1. 背景 在我们自己去绘制架构图&#xff0c;流程图&#xff0c;思维导图的时候&#xff0c;我们通常需要花费大量的时间去绘制。 目前的一些直接生图的模型也只能生成简单的流程图&#xff0c;不能生成复杂…

129. 求根节点到叶节点数字之和 --- DFS +回溯(js)

129. 求根节点到叶节点数字之和 --- DFS 回溯&#xff08;js&#xff09; 题目描述解题思路完整代码 题目描述 129. 求根节点到叶节点数字之和 解题思路 和 257. 二叉树的所有路径&#xff08;js&#xff09; 是一样的思路。 不一样的地方就是遇到叶子节点的时候把路径拼接…

SpringBoot电脑商城项目--修改默认收货地址

1. 修改默认收货地址-持久层 1.1 规划sql语句 检测当前用户向设置为默认收货地址的这条数据是否存在 SELECT * FROM t_address WHERE aid#{aid} 在修改用户的收获默认地址之前&#xff0c;先将所有的收货地址设置为非默认 UPDATE t_address SET is_default0 WHERE uid#{uid} …

LabVIEW FPGA 资源扩展

针对NI CompactRIO 9045 控制器 Kintex-7 70T FPGA 资源不足问题&#xff0c;通过 NI 9151 R 系列可重配置 I/O 模块扩展外部 FPGA 处理能力&#xff0c;在保留原有机箱架构下实现实时任务分流&#xff0c;解决Slice、LUT 等资源紧张问题&#xff0c;提升系统并行处理能力。 ​…

【漏洞复现】Apache Kafka Connect 任意文件读取漏洞(CVE-2025-27817)

文章目录 前言一、Apache Kafka 简介二、漏洞描述三、影响版本四、FOFA查询语句五、漏洞原理分析六、漏洞复现七、修复建议前言 由于Apache Kafka客户端未对用户输入进行严格验证和限制,未经身份验证的攻击者可通过构造恶意配置读取环境变量或磁盘任意内容,或向非预期位置发…

day13-软件包管理

1.每日复盘与今日内容 1.1复盘 yum源/apt源配置文件,核心下载地址.二进制部署服务.编译安装软件. 2.软件包管理-实战部分 2.1 yum源/apt源配置 源下载软件的地址配置多种源 1️⃣系统也有默认的源&#xff0c;里面也包含很多常用的软件. 2️⃣安装nginx、yum源 3️⃣安…

榕壹云快递寄件系统:聚合快递、智能追踪、二次开发,一站式物流解决方案

在电商物流高速发展的今天&#xff0c;快递寄件需求呈现爆炸式增长。传统分散的寄件方式效率低下&#xff0c;用户迫切需要一个整合多家快递公司的便捷平台。榕壹云公司开发的快递寄件系统应运而生&#xff0c;通过聚合多家快递资源、优化操作流程、提供丰富的功能模块&#xf…

一款功能强大的专业CSV编辑工具

Rons Data Edit是一款为Windows操作系统设计的现代CSV文件编辑器&#xff0c;它结合了优雅、强大和易用性&#xff0c;它可以打开任何格式的分隔文本文件(如CSV、TSV等)&#xff0c;并允许用户完全控制文件的内容和结构。 功能特点 支持明暗主题&#xff0c;可以在预定义的20多…