当前位置: 首页 > news >正文

(三)随处可见的LED广告屏是怎么工作的呢?接入GUI

续上文,本篇我们将尝试接入一个GUI来控制点阵屏。

在前两篇中,我们相继介绍了点阵屏的控制原理,以及如何让点阵屏按照我们所想的进行显示。本篇将在此基础上接入一个GUI,使点阵屏的控制更加优雅。

限于阅读体验和展示效果,软件部分将以伪代码、图片的形式进行展示。工程代码大家可以留言或者在订阅号上回复1001进行获取。

【选择合适的GUI】

目前嵌入式上开源的GUI有很多,u8g2、GuiLite、lvgl、miniGUI等等。这些GUI完整度很高,对RTOS的支持也很不错,而我们这次要移植的是SimpleGUI。

SimpleGUI在设计上尽可能减小了资源消耗,同时提供了点、线、基本几何图形以及单色位图、文字的绘制功能,以及列表、进度条、滚动条、提示框、曲线图等复杂部件的显示功能。

【预备工作】

点阵屏和我们常见的OLED最大的区别在于:点阵屏需要我们不断的控制MCU来对屏幕进行刷新,从而维持屏幕的正常显示。用显卡来举例,点阵屏是集成显卡,屏幕的控制集成在CPU中,和CPU共享内存。OLED是独立显卡,有独立芯片或者独立板卡来驱动,同时拥有独立的内存空间。

我们来看下SimpleGUI参考例程中初始化时需要填充哪些数据:

参数上我们需要填充屏幕的宽度、高度,函数上我们需要提供:获取屏幕像素点、设置像素点、清屏和刷新。

【如何实现这些函数】

上边我们提到了点阵屏和OLED屏幕在驱动上的一些区别,同时也清楚了移植GUI需要添加的功能函数。其中,屏幕像素点信息的获取和设置是点阵屏本身所不具备的。通常,我们在使用OLED时,厂家提供的驱动中会涵盖像素点的操作函数,我们先看看他们是如何实现的。

我们参考类比一下:在程序内部创建一个二维数组作为屏幕输出的数据缓存,通过计算X、Y坐标,将LED是否被点亮的数据写入到缓冲数组中某个字节的某个bit上。这里的数据缓存相当于我们第二篇中提到用来存储字模的数组。

【屏幕缓冲区】

回忆一下第二篇中我们取模的方式,取模成功后我们将字模数据存储到了一个32行、16列的二维数组中。这个数组中每个字节代表的bit和屏幕的像素点是一一对应的。

取模方式:阴码、逐行式、逆向(低位在前)
disp_table[32][16];

参照OLED的设置屏幕像素点的功能函数,我们把这个数组的行列对调下,以便符合这个X、Y的书写习惯。

LED_GRAM[16][32];//LED数据缓存区

【设置像素点】

设置像素点,本质上是找到LED_GRAM数组中对应像素点的bit值并改写。用伪代码来做一下描述

eg:将坐标(27,18)设置为1
先找到对应的字节byte
27/8=3找到列对应的下坐标
27%8=3找到对应的位

我们通过下边这个图表来直观的看一下。

上代码:

【读取像素点】

读取像素点与设置相类似,不同点在于,我们找到对应的字节后通过与操作,来判断当前像素点是0 or 1。

留意“设置像素点”和“读取像素点”这两段代码,2~11行,代码内容是完全一样的,在13~16行发生了变化。

设置代码是通过与、或操作将数值写入到当前字节。

读取代码则是通过与操作判断当前字节是0或者1,从而得出当前点是点亮还是熄灭。

【清屏】

清屏即将屏幕显示恢复至默认的背景色,对点阵屏来讲就是全灭。

在不使用GUI的情况,我们可以通过持续向HC595写入0x00来实现。在使用GUI后,我们清屏的操作不再是直接操作屏幕了,而是操作屏幕缓冲区,将屏幕缓冲区的二维数组全部置为0。

【屏幕刷新】

屏幕刷新,我们仍使用第二章整屏显示输出中的程序。因为我们将字模数组的xy做了对调,同样在输出函数中我们也对调一下xy。

【GUI与实际屏幕的显示关系】

在接入GUI后,我们对屏的操作,其实是隔了“显存”来进行的。无论是直线、圆、字符,本质是对“显存”的每个像素点进行读、写操作,之后统一通过HC595和译码器更新到屏幕上。

【测试】

至此,整个GUI移植所需的函数,我们都已经准备完毕。按照SimpleGUI参考例程中初始化的要求,我们填入这些数据。

使用GUI自带的字符串接口,显示一个“Hello Rabbit!”,实际效果如图。

【结束】

接入GUI后,我们可以更加便利的控制屏,让屏幕显示不在单调,更多好玩的显示效果期待大家得挖掘。

注:文章中部分图片来源于网络,如侵权请联系删除。

<第三篇END 文:雷打不动的晴天>


道阻且长,行则将至。

欢迎大家关注“兔子聊电路”,会不定期的分享一些遇到的电路问题和一些有趣的电路设计,更欢迎大家一起交流电路设计上的心得。同时,也会分享一些有意义的非技术类书籍。

http://www.lryc.cn/news/24004.html

相关文章:

  • 线程池简介
  • 大数据面试题集锦-Hadoop面试题(四)-YARN
  • Python---time模块
  • 坚鹏:学习贯彻二十大精神 解码共同富裕之道(面向银行)
  • python查看程序的cpu和内存资源占用情况
  • 番外10:使用ADS对射频功率放大器进行非线性测试2(使用带宽20MHz的64QAM信号进行ACLR、EVM、CCDF测试)
  • Ubuntu搭建maven私服
  • 【JavaWeb】Servlet基础
  • pinia + pinia-plugin-persistedstate + 组合式API 写法,持久化失效问题
  • ptrace 调式详解
  • 【AI绘画】绝美春天插画,人人都是插画师
  • 蓝桥杯入门即劝退(二十四)重复的子字符串(被秒杀)
  • 针对序列级和词元级应用微调BERT(需修改)
  • (四十七)大白话表锁和行锁互相之间的关系以及互斥规则是什么呢?
  • 织梦TXT批量导入TAG标签并自动匹配相关文章插件
  • Sentinel架构篇 - 10分钟带你看滑动窗口算法的应用
  • redis主从复制
  • 近期常见组件漏洞更新:
  • 深度学习常用的激活函数总结
  • Java编程问题top100---基础语法系列(二)
  • 网页打印与导出word实现在A4纸上相同效果
  • 备战英语6级——记录复习进度
  • 实例10:四足机器人运动学逆解可视化与实践
  • Elasticsearch7.8.0版本优化——路由选择
  • Go常量的定义和使用const,const特性“隐式重复前一个表达式”,以及iota枚举常量的使用
  • Git学习(1)pro git阅读
  • PHY自协商
  • 【大数据离线开发】8.2 Hive的安装和配置
  • Capture Modules:车载网络报文捕获模块
  • 数据结构与算法系列之时间与空间复杂度