详细源代码请查看GitHub:https://github.com/vamoosebbf/hub75

HUB75E 点阵屏是一块分辨率为 64*64,32 扫的点阵屏, 为了方便解释定义 SINGLE_WIDTH = 64 为单个屏幕的宽, SINGLE_HEIGHT = 64 位单个屏幕的高, SCAN_MODE = 32 为扫描模式

关于32扫

32 扫即选中 i 地址刷新的是第 i 行和第 i+SCAN_MODE 行(一次刷新两行), 这样刚好可以用 32 个地址刷新 64 行。

接口定义

  • RGB1 和 RGB2 为数据接口, 代表了两行数据线
  • A, B, C, D, E 为地址接口, 最多可以表示 (2^5)32 个地址(也就是行号)
  • Latch(门闩) 脚,不清楚有什么
  • OE 为使能接口

单个点

该点阵屏为 rgb 三色, 因此控制一个点的颜色只需要三个 bit 即可,共可形成八种颜色。

单个点阵屏

地址选中 0 开始, 每次点亮两行, 到地址为 SCAN_MODE 即可完成整块屏幕的刷新

分析

  • 整个点阵屏分为上下两部分, 每部分 SINGLE_HEIGHT / 2 行。
  • 上半部分颜色数据线为 R1,G1, B1, 下半部分为 R2,G2,B2

扫描一次

例如扫描第 0x11 行和第 0x11 + SCAN_MODE 行

  • 填充 linebuffer,将 img 第 0x11 行填入 RGB1,第 0x11 + SCAN_MODE 行填入 RGB2.
  • 选中地址 0x11, 此时调用 set_addr 函数设置 A, B, C, D, E 选中 0x11。
  • 地址选中函数示例如下:
static inline void hub75e_set_addr(hub75e_t* hub75e_obj, uint8_t addr)
{my_set_gpiohs(hub75e_obj->a_gpio, addr & 0x01);my_set_gpiohs(hub75e_obj->b_gpio, (addr & 0x02) >> 1);my_set_gpiohs(hub75e_obj->c_gpio, (addr & 0x04) >> 2);my_set_gpiohs(hub75e_obj->d_gpio, (addr & 0x08) >> 3);my_set_gpiohs(hub75e_obj->e_gpio, (addr & 0x10) >> 4);
}

点亮单个屏

  1. 需要准备一个长度为 SINGLE_WIDTH bytes 的 linebuf 来存储行数据, 每个 byte 其中 6 位来存储 rgb1(3 bit) rgb2(3 bit) 的数据, 这样刚好可以表示 i,i+SCAN_MODE 两行。
  2. 将数据通过 SPI 发送出去
  3. latch 脚拉高
  4. latch 脚拉低
  5. 选中地址, 地址为 5 位, A B C D E 由低位到高位
  6. 拉高 OE 使能
  7. 返回步骤1, 循环直到所有地址都扫描了一次

多个点阵屏

分析

  1. 多个点阵屏可以看做时一个长度为:SINGLE_WIDTH*屏幕个数,高度为: SINGLE_HEIGHT 的长条形点阵屏
  2. 该点阵屏上半部分颜色由 RGB1 控制,下半部分由 RGB2 控制。
  3. 长条形点阵屏弯折即可拓展成高度大于 64 的矩阵屏,如图所示:
  4. 这样做只是重新排列了一次而已,控制方式仍然是以单个长条型点阵屏控制,只是需要注意发送数据的顺序

点亮流程

这个随摆放方式不同而不同, 我使用的是 S 型摆放, 这里有一个问题是第偶数行点阵屏会是倒过来的, 总之先发送的肯定是排在最后的点阵屏, 以下图为例就是右下角那块。

以上排列方式代码如下:

int hub75e_display(int core)
{if(!(hub75e_obj&&image)) return -1;int y, t, x;uint16_t vertical_boards = hub75e_obj->height / HEIGHT_PER_BOARD;uint16_t line_buf_size = hub75e_obj->width * vertical_boards;uint16_t *rgb444 = (uint16_t *)malloc(hub75e_obj->width * hub75e_obj->height * sizeof(uint16_t));uint32_t *line_buffer = (uint32_t *)malloc(line_buf_size * sizeof(uint32_t));volatile spi_t *spi_handle = spi[hub75e_obj->spi];// rgb565 -> rgb444 损失色彩, 但是提高速率for (y = 0; y < hub75e_obj->height; y++){for (x = 0; x < hub75e_obj->width; x++){uint16_t rgb565_yx = *(image + y * hub75e_obj->width + x);*(rgb444 + y * hub75e_obj->width + x) = rgb565_to_rgb444[SWAP_TO_MP16(rgb565_yx)];}}// 每张图刷新 16 次, 可以达到用占空比控制的效果, 16 为 4 位所能表示的全部色彩for (t = 0; t < 16; t++){// 32 扫, 每次将 y 和 y+32 行填入 linebuffer       for (y = 0; y < SCAN_TIMES; y++){// 每次发送一个 linebuffer , linebuffer 大小为 每块的行宽*屏幕块数for (int bs = vertical_boards; bs  > 0; bs--)//刷新第 bs 行的板子, 板子总行数为 vertical_boards{// line_buffer 填充起点int line_buf_base_index = ((vertical_boards - bs)*hub75e_obj->width);if(bs % 2 ==0){// 垂直第偶数行板子, 刷新顺序从下到上, 从右至左// 填入 linebuffer 的 img 行号int img_line_num = bs * HEIGHT_PER_BOARD - y - 1;// 填入 linebuffer 的 img 出发点int img_line_begin = img_line_num * hub75e_obj->width;// 填入 linebuffer 的 img 行加 32 扫, 因为从下往上int img_line_scan_begin  = (img_line_num - SCAN_TIMES) * hub75e_obj->width;// 需要填充的 linebuffer 的结束点下标int line_buf_end_index = line_buf_base_index + hub75e_obj->width - 1;for(int  x = hub75e_obj->width - 1; x >= 0; x--){// 编码每行的点, 一次两行, 高三位: 7(r1),6(g1),5(b1)为第 img_line_num 行), 后三位: 4(r2),3(g2),2(b2) 为第 img_line_num - SCAN_TIMES 行)line_buffer[line_buf_end_index - x] = ((pwm_table[t][*(rgb444 + img_line_begin + x)]) | \pwm_table[t][*(rgb444 + img_line_scan_begin + x)] >> 3);}}else{// 垂直第奇数块所在行, 刷新顺序从上到下, 从左至右// 填入 line-buffer 的 img 行号int img_line_num = (bs - 1) * HEIGHT_PER_BOARD + y;// 当前显示 img 行的出发点int img_line_begin = img_line_num * hub75e_obj->width;// 填入 linebuffer 的 img 行加 32 扫int img_line_scan_begin = (img_line_num + SCAN_TIMES) * hub75e_obj->width;// 显示第 bs 行板的第 y 行for(int  x = 0; x < hub75e_obj->width; x++){// 编码每行的点,高三位: 7(r1),6(g1),5(b1)为第 img_line_num 行), 后三位: 4(r2),3(g2),2(b2) 为第 img_line_num + SCAN_TIMES 行)line_buffer[x+line_buf_base_index] = ((pwm_table[t][*(rgb444 + img_line_begin + x)]) | \pwm_table[t][*(rgb444 + img_line_scan_begin + x)] >> 3);}}}            fill_line(hub75e_obj, spi_handle, line_buffer, y, line_buf_size); // 发送行数据}}   free(line_buffer);free(rgb444);return 0;
}
  • 其中将 rgb565 转化为 rgb444 使用了查表方式,更快,该表运行 convert.py生成, 共65536个元素。
  • 可以看到每张图屏片发送了 16(rgb444 中 2^4) 次, 这是为了控制 rgb 三个灯亮灭占空比达到形成多种颜色的效果,同样使用查表方式,运行 convert.py生成。
  • 每张图刷新一次发送32次, 因为是32扫, 只需要发送32次即即可扫描所有屏

建议使用排线连接,信号更稳定,不过排线也有可能某根是坏的

HUB75E 点阵屏的使用相关推荐

  1. STC8H驱动hub75e接口的64*64LED点阵屏

    由于最近在做毕业设计,应导师要求学习LED点阵屏的显示原理,学习并驱动hub75e接口的64*64LED点阵屏.点阵屏上一个点有三个颜色分量R,G,B,1为亮,0为灭.当这个点为110时,颜色为红色和 ...

  2. 表决器c语言课程设计,项目二:玩转RGB点阵屏——表情表决器

    项目二:玩转RGB点阵屏--表情表决器项目二:玩转RGB点阵屏--表情表决器(建议2课时) [情境导入] 图2.1 医护人员"逆行"湖北 是她们不畏生死驰援湖北,为中国抗疫带来胜利 ...

  3. 用python实现点阵屏_MicroPython拼插编程实例:点亮心形8x8点阵

    一.什么是TPYBoard开发板 TPYBoard是以遵照MIT许可的MicroPython为基础的一款MicroPython开发板,它基于STM32F405单片机,通过USB接口进行数据传输.该开发 ...

  4. 51单片机8*8点阵屏、取模软件的使用

    取模软件网盘提取 链接:https://pan.baidu.com/s/1YYQo_tZNCXlo9uWVbtsNdg 提取码:jfbr 74HC595芯片原理图: 两片595芯片级联驱动点阵屏只需要 ...

  5. 【51单片机快速入门指南】2.4:74HC595、LED点阵屏及其SPI控制

    目录 硬知识 IO 口扩展方式-串转并 74HC595 芯片介绍 硬件设计 测试源码 HC74595.c HC74595.h main.h 实验现象 SPI控制 普中51-单核-A2 STC89C52 ...

  6. 51单片机 16*64LED单红点阵屏驱动测试,上位机改字软件免费版

    public.h #ifndef __PUBLIC_H__ #define __PUBLIC_H__#include "STC12C5A60S2.h" #include <i ...

  7. arduino点阵声音频谱_Arduino基础入门篇19—点阵屏

    将8个LED发光二极管封装在一起就组成了数码管,将更多的LED组合在一起就组成了点阵屏.本篇我们来认识点阵屏,通过Arduino的IO口直接驱动点阵屏来了解其驱动方式. 1. 点阵屏介绍 LED点阵屏 ...

  8. 单片机汉字点阵c语言程序,51单片机C语言多种点阵屏驱动程序(开发软件为keil C...

    51单片机C语言多种点阵屏驱动程序(开发软件为keil C 2016-08-23 1 0 0 暂无评分 其他 1 积分下载 如何获取积分? 51单片机C语言多种点阵屏驱动程序(开发软件为keil C ...

  9. 51单片机 8x8LED点阵屏循环显示数字0~9

    在8x8点阵屏上循环显示数字0~9 使用的是普中科技的开发板,一个点阵显示模块是由8x8共64个LED按照共阴或共阳的连接方式组成. 每行的8个LED的负极连接一起,构成8根行线,每列的8个LED的正 ...

最新文章

  1. 互联网的中层管理,一个庞大且易脆的群体
  2. _id 和 ObjectId
  3. 让AI说话告别三观不正,OpenAI只用80个文本就做到了
  4. Winform开发框架之数据曲线报表
  5. Box2D教程3-刚体绑定外观
  6. CodeForces - 1339C Powered Addition(思维+贪心)
  7. require_once的用法
  8. java内存加载dll_jacob调用dll控件,是否要执行内存释放,具体方法怎么写
  9. js 中 的时间类和 setTimeout 和setInterval
  10. 力扣两数之和jAVA_力扣----1.两数之和(JavaScript, Java实现)
  11. python爬虫之多线程、多进程爬虫_python 多线程,多进程,高效爬虫
  12. Hello软件项目相关功能测试点
  13. IDEA felix osgi项目搭建(1)
  14. 基于决策树算法对良/恶性乳腺癌肿瘤预测
  15. shell脚本之国际象棋棋盘
  16. 职教云助手手机版_职教云app下载安装_职教云最新版本下载网址
  17. android 安装第三方应用,Android手机常识 第三方应用如何安装
  18. java类编来那个初始化顺序_Java类及对象的初始化顺序
  19. RS-232或RS-485与CAN网络互联互通
  20. 目标检测领域论文和代码集合(2013年~2018年8月)

热门文章

  1. 2021年电赛 E题 数字传输
  2. 我在印尼工作的日子-初来乍到
  3. java 线程间变量共享_多线程:(五)多个线程之间共享数据
  4. Spring Boot第八篇-关于web静态资源的整合
  5. 学生党如何选择好的蓝牙耳机呢?蓝牙耳机高性价比点评
  6. vs开发,添加try catch(...)发现没有捕获异常,需要对编译命令进行设置
  7. PyQt4的学习历程(3)
  8. python操作ffmpeg,做视频转码【上篇】
  9. [TJOI2017]可乐(矩阵快速幂)
  10. 2018年职称英语计算机考试,职称英语考试一般过去时的用法