【雕爷学编程】Arduino动手做(104)---16X16点阵汉字屏
37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来---小小的进步或是搞不掂的问题,希望能够抛砖引玉。
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百零四:16X16点阵UART接口LED汉字显示屏模块
LED点阵屏
通过LED(发光二极管)组成,以灯珠亮灭来显示文字、图片、动画、视频等,是各部分组件都模块化的显示器件,通常由显示模块、控制系统及电源系统组成。LED点阵显示屏制作简单,安装方便,被广泛应用于各种公共场合,如汽车报站器、广告屏以及公告牌等。
显示原理
以简单的8X8点阵为例,它共由64个发光二极管组成,且每个发光二极管是放置在行线和列线的交叉点上,当对应的某一行置1电平,某一列置0电平,则相应的二极管就亮;如要将第一个点点亮,则9脚接高电平13脚接低电平,则第一个点就亮了;如果要将第一行点亮,则第9脚要接高电平,而(13、3、4、10、6、11、15、16)这些引脚接低电平,那么第一行就会点亮;如要将第一列点亮,则第13脚接低电平,而(9、14、8、12、1、7、2、5)接高电平,那么第一列就会点亮。
一般我们使用点阵显示汉字是用的16*16的点阵宋体字库,所谓16*16,是每一个汉字在纵、横各16点的区域内显示的。也就是说用四个8*8点阵组合成一个16*16的点阵。比如要显示“你”则相应的点要点亮,由于点阵在列线上是低电平有效,而在行线上是高电平有效,所以要显示“你”字,则它的位代码信息要取反,即所有列(13~16脚)送(0xF7,0x7F),而第一行(9脚)送1信号,然后第一行送0。再送第二行要显示的数据(13~16脚)送(0xF7,0x7F),而第二行(14脚)送1信号。依此类推,只要每行数据显示时间间隔够短,利用人眼的视觉暂停作用,这样送16次数据扫描完16行后就会看到一个“你”字;第二种送数据的方法是字模信号送到行线上再扫描列线也是同样的道理。同样以“你”字来说明,16行(9、14、8、12、1、7、2、5)上送(,0x00,0x00)而第一列(13脚)送、“0”。同理扫描第二列。当行线上送了16次数据而列线扫描了16次后一个“你”字也就显示出来了。
点阵屏驱动
由LED点阵显示器的内部结构可知,器件宜采用动态扫描驱动方式工作,由于LED管芯大多为高型,因此某行或某列的单体 LED驱动电流可选用窄脉冲,但其平均电流应限制在20mA内.多数点阵显示器的单体LED的正向压降约在2V左右.但大亮点∮10的点阵显示器单体 LED的正向压降约为6V。大屏幕显示系统一般是将由多个LED点阵组成的小模块以搭积木的方式组合而成的,每一个小模块都有自己的独立的控制系统,组合在一起后只要引入一个总控制器控制各模块的命令和数据即可,这种方法既简单而且具有易装、易维修的特点。LED点阵显示系统中各模块的显示方式有静态和动态显示两种。静态显示原理简单、控制方便,但硬件接线复杂,在实际应用中一般采用动态显示方式,动态显示采用扫描的方式工作,由峰值较大的窄脉冲驱动,从上到下逐次不断地对显示屏的各行进行选通,同时又向各列送出表示图形或文字信息的脉冲信号,反复循环以上操作,就可显示各种图形或文字信息。
点阵屏分类
LED点阵屏有单色和双色、全彩三类,可显示红,黄,绿,橙等。LED点阵有4×4、4×8、5×7、5×8、 8×8、16×16、24×24、40×40等多种;根据图素的数目分为等,双原色、三原色等,根据图素颜色的不同所显示的文字、图像等内容的颜色也不同,单原色点阵只能显示固定色彩如红、绿、黄等单色,双原色和三原色点阵显示内容的颜色由图素内不同颜色发光二极体点亮组合方式决定,如红绿都亮时可显示黄色,假如按照脉冲方式控制二极体的点亮时间,则可实现256或更高级灰度显示,即可实现真彩色显示。
主要特点
1、亮度高:相对0603或0805等形式的分立表贴,LED可以有更多的光通量被反射出。
可实现超高密度:室内可高达62.500点/平米(P4)。也有厂家可以做到p3的。密度越大所需要的散热性能越好。
2、混色好:利用发光器件本身的微化处理和光的波粒二象性,使得红光粒子,纯绿光粒子,蓝光粒子三种粒子都将得到充分地相互混合搅匀。
3、环境性能好:耐湿、耐冷热、耐腐蚀
4、抗静电性能优势超强:制作环境有着严格的标准还有产品结构的绝缘设计。
5、可视角度大:140度(水平方向)
6、通透性高:新一代点阵技术凭借自身的高度纯度性能,以及几近100%光通率的环氧树脂材料,达到了接近完美的通透率。
16X16串口LED点阵模块
本模块采用超高亮LED灯芯、74HC595驱动芯片和高性价 比工业级单片机专业制造,工作稳定,刷新频率高,显示效果好;支持二次开发,应用方便。可以通过串口控制点阵模块显示方式:开启/关闭、正显/反显、左右翻转、上下翻转等;通过串口可以更新显示内容,也可以直接发送(16x16单色)bmp文件,方便接驳现有流行的智能硬件平台,如Arduino、树莓派等。
接线示意图与引脚功能
模块特点
1. 模块尺寸64mm X 64mm X 12mm(不含背面排针高度)
2. 仅需一根串口TXD信号即可(用广播设备号:0xFFFFFFFF)控制;
3. 超高亮贴片LED,5V或3.3V供电都可以。
4. 采用恒流亮度驱动电路, 亮度均匀。
5. 性价比高,开发速度快,提供网站自动生成arduino演示代码,粘贴到arduino IDE,下载即可实验与使用。
16X16串口LED点阵模块
采用74HC595作为LED扫描驱动器,板载时序控制器提供74HC595驱动信号和显示数
据;同时接收上位机发送的命令,实现点阵模块显示控制。发送命令格式如下:
[长度][设备号][命令号][参数...]
其中:长度表示本次发送的所有字节数,不包括本字节。本串口点阵模块收完一帧命令后会做长度校验,过滤干扰数据;设备号表示本串口点阵模块在多模块显示系统中的标识号,便于区分,当前版本支持32bit设备号。如果只控制单个模块,可以使用广播设备号(0xFFFFFFFF);命令号定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | typedef enum { LEP_CMD_NO_OPERATION, // 0-空操作 LEP_CMD_SCREEN_HIDE, // 1-屏幕关闭 LEP_CMD_SCREEN_INVERT, // 2-屏幕反显 LEP_CMD_SCREEN_MIRROR, // 3-屏幕镜像 LEP_CMD_SCREEN_TURN, // 4-屏幕倒影 LEP_CMD_SCREEN_PIXEL, // 5-屏幕像素 LEP_CMD_SCREEN_FILL, // 6-屏幕填充 LEP_CMD_SCREEN_LOAD, // 7-屏幕载入 LEP_CMD_CAVAS_ICON, // 8-显示图标 LEP_CMD_PRINT_ASCII, // 9-英文字符 } lepCmdNo_t; //命令号定义 |
Arduino参考开源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | /* 【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程) 实验一百零四: 16X16点阵串口LED汉字显示屏模块UART接口 1、安装库:打开Arduino IDE——工具——管理库,搜索marde 2、项目:显示“智”字 3、连线: VDD → 5V GND → GND TXD → D0 RXD → D1 */ #include <MdLep16X16.h> byte message[][2] ={ {0x20,0x00}, //line_0 {0x3e,0x7c}, //line_1 {0x48,0x44}, //line_2 {0x08,0x44}, //line_3 {0xff,0x44}, //line_4 {0x14,0x44}, //line_5 {0x22,0x7c}, //line_6 {0x40,0x00}, //line_7 {0x1f,0xf0}, //line_8 {0x10,0x10}, //line_9 {0x10,0x10}, //line_10 {0x1f,0xf0}, //line_11 {0x10,0x10}, //line_12 {0x10,0x10}, //line_13 {0x1f,0xf0}, //line_14 {0x10,0x10}, //line_15 }; MdLep16X16 mdLep(0xFF, 0xFF, 0xFF, 0xFF); void setup() { // put your setup code here, to run once: Serial.begin(9600); delay(1000); mdLep.loadScreen(( byte *)message); } void loop() { // put your main code here, to run repeatedly: } |
实验场景图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 | /* 【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程) 实验一百零四: 16X16点阵串口LED汉字显示屏模块UART接口 1、安装库:打开Arduino IDE——工具——管理库,搜索marde 2、项目:滚动显示汉字 3、连线: VDD → 5V GND → GND TXD → D0 RXD → D1 */ #include <MsTimer2.h> #include <MdLep16X16.h> byte message[][2] = { {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, /*移出,9*/ //-----------------------------以下内容自行更改 {0x00,0x28}, //line_0 {0x7f,0x24}, //line_1 {0x49,0x40}, //line_2 {0x49,0x7e}, //line_3 {0x5d,0xc8}, //line_4 {0x49,0x48}, //line_5 {0x7f,0x7e}, //line_6 {0x41,0x48}, //line_7 {0x5d,0x48}, //line_8 {0x55,0x7e}, //line_9 {0x55,0x48}, //line_10 {0x5d,0x48}, //line_11 {0x41,0x48}, //line_12 {0x41,0x7e}, //line_13 {0x45,0x40}, //line_14 {0x82,0x40}, //line_15/*"雕",0*/ {0x04,0x40}, //line_0 {0x08,0x20}, //line_1 {0x18,0x50}, //line_2 {0x24,0x88}, //line_3 {0x03,0x00}, //line_4 {0x0c,0xc0}, //line_5 {0x30,0x30}, //line_6 {0xc0,0x0e}, //line_7 {0x1f,0xf0}, //line_8 {0x02,0x10}, //line_9 {0x02,0x10}, //line_10 {0x02,0x10}, //line_11 {0x02,0x50}, //line_12 {0x02,0x20}, //line_13 {0x02,0x00}, //line_14 {0x02,0x00}, //line_15/*"爷",1*/ {0x22,0x08}, //line_0 {0x11,0x08}, //line_1 {0x11,0x10}, //line_2 {0x00,0x20}, //line_3 {0x7f,0xfe}, //line_4 {0x40,0x02}, //line_5 {0x80,0x04}, //line_6 {0x1f,0xe0}, //line_7 {0x00,0x40}, //line_8 {0x01,0x80}, //line_9 {0xff,0xfe}, //line_10 {0x01,0x00}, //line_11 {0x01,0x00}, //line_12 {0x01,0x00}, //line_13 {0x05,0x00}, //line_14 {0x02,0x00}, //line_15/*"学",2*/ {0x10,0x80}, //line_0 {0x10,0x40}, //line_1 {0x23,0xfc}, //line_2 {0x22,0x04}, //line_3 {0x4a,0x04}, //line_4 {0xfb,0xfc}, //line_5 {0x12,0x00}, //line_6 {0x22,0x00}, //line_7 {0x43,0xfc}, //line_8 {0xfb,0x54}, //line_9 {0x43,0x54}, //line_10 {0x05,0xfc}, //line_11 {0x1d,0x54}, //line_12 {0xe5,0x54}, //line_13 {0x49,0x44}, //line_14 {0x01,0x0c}, //line_15/*"编",3*/ {0x08,0x00}, //line_0 {0x1d,0xfc}, //line_1 {0xf1,0x04}, //line_2 {0x11,0x04}, //line_3 {0x11,0x04}, //line_4 {0xfd,0xfc}, //line_5 {0x10,0x00}, //line_6 {0x30,0x00}, //line_7 {0x39,0xfe}, //line_8 {0x54,0x20}, //line_9 {0x54,0x20}, //line_10 {0x91,0xfc}, //line_11 {0x10,0x20}, //line_12 {0x10,0x20}, //line_13 {0x13,0xfe}, //line_14 {0x10,0x00}, //line_15/*"程",4*/ //-----------------------------内容区域结束 {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, {0x00,0x00}, /*移入,9*/ }; MdLep16X16 mdLep(0xFF, 0xFF, 0xFF, 0xFF); byte i = 0; byte *ptr; const int maxColumn = sizeof (message)/ROW_OCTS - LEP_ROWS; void onTimer() { mdLep.loadScreen(ptr+i*ROW_OCTS); i++; if (i == maxColumn) i = 0; } void setup() { ptr = &message[0][0]; Serial.begin(9600); mdLep.mirrorOff(); //(关闭汉字镜像) //mdLep.mirrorOn(); MsTimer2:: set (100, onTimer); MsTimer2::start(); } void loop() { } |
实验场景图
实验场景动态图
https://www.arduino.cn/data/attachment/forum/201909/06/194759gm2k505p9viek9pl.gif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | /* 【花雕动手做】有趣好玩的音乐可视化系列小项目(08)---四位32段点阵屏 项目之一:八段分频8X8点阵屏的音乐频谱灯 接脚连线:MAX9814 接A0 MAX7219 UNO VCC →→→→→ 5V GND →→→→→ GND DIN →→→→→ D11(数据,数据接收引脚) CS →→→→→ D10(负载,命令接收引脚) CLK →→→→→ D13(时钟,时钟引脚) */ #include "LedControl.h" /* Led matrix - Max7219 Declared */ LedControl lc = LedControl(11, 13, 10, 1); const int maxScale = 11; /* Sensor - Max9812 Declared */ const int sensorPin = A0; const int sampleWindow = 50; // 50ms = 20Hz unsigned int sample; unsigned long startMillis; unsigned long timeCycle; unsigned int signalMax = 0; unsigned int signalMin = 1024; unsigned char index = 0; unsigned int peakToPeak[8]; unsigned int displayPeak[8]; unsigned int temp[8] = {0, 0, 0, 0, 0, 0, 0, 0}; unsigned int signalMaxBuff[8]; unsigned int signalMinBuff[8]; void setup() { // Led matrix lc.shutdown(0, false ); // bật hiện thị lc.setIntensity(0, 2); // chỉnh độ sáng lc.clearDisplay(0); // tắt tất cả led Serial.begin(9600); } void loop() { startMillis = millis(); //peakToPeak = 0; signalMax = 0; signalMin = 1024; // Get data in 50ms while (millis() - startMillis < sampleWindow) { sample = analogRead(sensorPin); if (sample < 1024) { if (sample > signalMax) { signalMax = sample; } if (sample < signalMin) { signalMin = sample; } } // 20Hz - 64Hz - 125Hz - 250Hz - 500Hz - 1kHz (timeCycle = 1/F)(ms) timeCycle = millis() - startMillis; if (timeCycle == 1 || timeCycle == 2 || timeCycle == 4 || timeCycle == 8 || timeCycle == 16 || timeCycle == 32 || timeCycle == 40 || timeCycle == 50) { signalMaxBuff[index] = signalMax; signalMinBuff[index] = signalMin; index = (index + 1) % 8; delay(1); Serial.println(timeCycle); } } // Delete pointer to array index = 0; // Calculation after get samples for ( int i = 0; i < 8; i++) { // i = row (led matrix) // sound level peakToPeak[i] = signalMaxBuff[i] - signalMinBuff[i]; // Map 1v p-p level to the max scale of the display displayPeak[i] = map(peakToPeak[i], 0, 1023, 0, maxScale); // Show to led matrix displayLed(displayPeak[i], i); // Led drop down if (displayPeak[i] >= temp[i]) { temp[i] = displayPeak[i]; } else { temp[i]--; } lc.setLed(0, i, temp[i], true ); delayMicroseconds(10); } } void displayLed( int displayPeak, int row) { switch (displayPeak) { case 0 : lc.setRow(0, row, 0x80); break ; case 1 : lc.setRow(0, row, 0xC0); break ; case 2 : lc.setRow(0, row, 0xE0); break ; case 3 : lc.setRow(0, row, 0xF0); break ; case 4 : lc.setRow(0, row, 0xF8); break ; case 5 : lc.setRow(0, row, 0xFC); break ; case 6 : lc.setRow(0, row, 0xFE); break ; case 7 : lc.setRow(0, row, 0xFF); break ; } } |
实验场景动态图
https://img.mydigit.cn/forum/202111/20/154104vqvzuvmddc0d1nln.gif
实验场景图
实验视频剪辑(2分40秒)
https://v.youku.com/v_show/id_XNTgyMTMyMzM2MA==.html?spm=a2hcb.playlsit.page.1
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性