单片机学习(八)点阵LED的使用
参考资料:https://www.bilibili.com/video/BV1Mb411e7re?p=21
一、点阵LED的理论知识
1. 点阵屏的打开方式
默认情况下我的点阵屏是无法直接使用的,即使用了正确的代码也无法点亮点阵屏,此时我们需要先将点阵附近的跳线帽拔掉或移动到左边才能打开点阵屏:
2. LED点阵简介
- LED点阵屏由若干个独立的LED组成,LED以矩阵的形式排列,以灯珠亮灭来显示文字、图片、视频等。LED点阵屏广泛应用于各种公共场合,如汽车报站器、广告屏以及公告牌等
- LED点阵屏分类
- 按颜色:单色、双色、全彩
- 按像素:8 * 8(开发板上的点阵)、16 *16等(大规模的LED点阵通常由很多个小点阵拼接而成)
3. 点阵LED的结构和操作方式
示意图:
- LED点阵屏的结构类似于数码管,只不过是数码管把每一列的像素以“8”字型排列而已
- LED点阵屏与数码管一样,有共阴和共阳
两种接法
,不同的接法对应的电路结构不同 - LED点阵屏需要进行逐行或逐列扫描,才能使所有LED同时显示
例如我们当前希望左上到右下的对角线的LED灯亮,而其他的灯都不亮,可以按照如下方式运行:
- 第一行置一,其他行都置零,同时第一列置零,其他列都置一
即:
置一 | 置零 | |
---|---|---|
行 | 第1行 | 其他行 |
列 | 其他列 | 第1列 |
- 以上的操作是第一个周期的操作,然后第二个周期则和第一个周期基本相同,只是切换了置一和置零的行和列而已,后面往复进行即可
置一 | 置零 | |
---|---|---|
行 | 第2行 | 其他行 |
列 | 其他列 | 第2列 |
通过类似这种的行扫描或列扫描操作,我们即可使我们希望的LED同时发光了。
通俗地说就是:先使一行正常显示,再使下一行正常显示,只要速度够快,就能看到LED同时显示的情景了。
对应到厂商提供的原理图:
P00~P07
用于控制列,而DPa~DPh
用于控制行。
4. 74HC595模块
为什么我们会需要了解这个模块的相关内容呢,我们先仔细观察一下原理图:
可以发现这里的8个输出对应着LED点阵的8个行输入,而且这个模块是只有3个输入端的,这说明了我们可以通过使用这个模块,使用3个输入即可得到LED点阵的8个行输入了。
此外,这个图中还包括了OE
引脚,可以看到它的上面有着一个横杠,根据b站老师的说法,这样的写法表示该模块在低电平时有效,所以我们要使用这个模块之前需要将OE
与GND
相连,这也就是为什么我们需要先把跳线帽移动到左侧才能使用LED点阵模块。
PPT上的简介
74HC595是串行输入并行输出的移位寄存器,可用3根线输入串行数据,8根线输出并行数据,多片级联后,可输出16位、24位、32位等,常用于I0口扩展。
串行转并行的工作原理
- 首先先设置
SER
的值 - 使用时钟发送一个上升信号,则全部数据向下移动一位,
SER
中的数据被写入到最上面 - 给
SERCLK
置零 - 是否够8位数据?否:转1;是:转5
RCLK
置一,左边的数据搬运到右边,8个信号同时输出,然后RCLK
置零
级联操作
如果需要更多的位数输出,我们可以将QH'
接到下一个模块的SER
,这样即可完成不断扩展。
二、编码实现
1. C51中的sfr和sbit【补充知识】
- sfr (special function register) : 特殊功能寄存器声明
例:sfrPO=0x80;
声明P0口寄存器,物理地址为0x80
- sbit (special bit) : 特殊位声明
例:sbit PO_1 = 0x81;
或sbit p0_1 = P0^1;
声明P0寄存器的第1位 - 可位寻址/不可位寻址:
在单片机系统中,操作任意寄存器或者某一位的数据时,必须给出其物理地址,又因为一个寄存器里有8位,所以位的数量是寄存器数量的8倍,单片机无法对所有位进行编码,故每8个寄存器中,只有一个是可以位寻址的。对不可位寻址的寄存器,若要只操作其中一位而不影响其它位时,可用&=
、|=
、^=
的方法进行位操作
tips:在使用寄存器中的某一位时,我们往往使用类似
sbit LED = P2^0;
的写法获取到某一位,但这种在声明中使用到的'^'符号并不表示异或,而是进行取位。
2. 编写74HC595的驱动程序
首先定义出三个需要使用的寄存器位
:
sbit RCK = P3 ^ 5;
sbit SRCLK = P3 ^ 6;
sbit SER = P3 ^ 4;
其中RCK
即为原理图中的RCLK
,但由于和库中的变量重名了,故改为RCK
。
然后我们需要编写74HC595模块的驱动程序:
void _74HC595_WriteByte(unsigned char Byte) {
unsigned char i = 0;
// i为计数变量,重复执行8次
for (i = 0; i < 8; i++) {
// 每次取第i位(从左到右),写入到SER中
SER = Byte & (0x80 >> i);
// SRCLK置一,使寄存器进行移位
SRCLK = 1;
SRCLK = 0;
}
// 将八位输入到LED的8个行输入中
RCK = 1;
RCK = 0;
}
即输入一个byte(八位)的数据,可以并行地输入到点阵LED的8个行输入中。
3. 编写控制单列亮灯的程序
代码如下:
void MatrixLED_ShowColumn(unsigned char column, unsigned char Data) {
_74HC595_WriteByte(Data);
// 对某列进行使能,列数为0~7
P0=~(0x80>>column);
}
我们先将数据写入到点阵LED的左侧输入中,然后对某列进行使能,具体的操作为使P0
寄存器的某位置零,而其他位置一,因此我们可以将0x80
先右移column
位,然后取反,我们即可得到第column
位为0
的数据,接着赋值进去即可。
写个简单的程序进行测试:
void main(void) {
SRCLK = 0;
RCK = 0;
_74HC595_WriteByte(0xF0);
while (1) {
MatrixLED_ShowColumn(0,0xAA);
}
}
运行结果:
可以看到,第0列的LED灯按照0xAA【1010 1010】进行显示了!
4. 控制多列同时发光
首先我们先讨论一下消影的操作,当我们如果不进行消影时,段选的数据就会先写入到上一次的选择的位置中(在这里是指上一列),因此就会发现新列中的数据在上一列也显示了出来。
因此我们需要在每个周期的末尾加上延时和位清零的操作:
void MatrixLED_ShowColumn(unsigned char column, unsigned char Data) {
// 段选
_74HC595_WriteByte(Data);
// 位选
P0 = ~(0x80 >> column);
// 延时
deley(50);
// 位清零
P0 = 0xFF;
}
这样我们可以先将希望展示的数据写入到数组中(8个byte数据,代表每列希望展示的数据),然后通过循环列扫描的方式展示出来:
void main(void) {
unsigned char i;
unsigned char Data[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
SRCLK = 0;
RCK = 0;
while (1) {
for (i = 0; i < 8; i++) {
MatrixLED_ShowColumn(i, Data[i]);
}
}
}
运行结果:
可以看到在运行结果中第3列灯【从3开始数】没法点亮,估计是开发板是个次品,第三列的灯都没法点亮,现在才发现QAQ。。。
显示心形
先设计一个心形:
然后根据每列的数据,写入到数组中:
unsigned char Data[] = {0x18, 0x3c, 0x7e, 0x3f, 0x3f, 0x7e, 0x3c, 0x18};
运行结果:
5. 封装成模块
// MatrixLED.c
#include "MatrixLED.h"
#include <Atmel/REGX52.H>
#include "Deley.h"
sbit RCK = P3 ^ 5;
sbit SRCLK = P3 ^ 6;
sbit SER = P3 ^ 4;
void MatrixLED_Init() {
SRCLK = 0;
RCK = 0;
}
void _74HC595_WriteByte(unsigned char Byte) {
unsigned char i = 0;
for (i = 0; i < 8; i++) {
SER = Byte & (0x80 >> i);
SRCLK = 1;
SRCLK = 0;
}
RCK = 1;
RCK = 0;
}
void MatrixLED_ShowColumn(unsigned char column, unsigned char Data) {
_74HC595_WriteByte(Data);
// 对某列进行使能,列数为0~7
MATRIX_LED_PORT = ~(0x80 >> column);
deley(50);
MATRIX_LED_PORT = 0xFF;
}
而MatrixLED.h
文件只需加上三个函数的函数声明即可。
6. LED点阵动画
使用字模提取工具
我们需要先将字节倒序的勾去掉:
然后点击新建图像按钮新建图像,选择8和32
我们画出“Hello!”这样的文本:
然后我们点击取模方法
>C51格式
即可得到图像的编码:
然后我们将这些数据复制到代码中即可:
unsigned char animation[] = {
0x7F,0x08,0x08,0x08,0x7F,0x00,0x0E,0x15,0x15,0x15,0x08,0x00,0x7E,0x01,0x02,0x00,
0x7E,0x01,0x02,0x00,0x0E,0x11,0x11,0x0E,0x00,0x7D,0x00,0x00,0x00,0x00,0x00,0x00
}
为了使字幕经过之后可以有一段空白,我们需要为数组的前后都加上8个0x00:
unsigned char animation[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x0E, 0x15, 0x15, 0x15, 0x08, 0x00, 0x7E, 0x01, 0x02, 0x00,
0x7E, 0x01, 0x02, 0x00, 0x0E, 0x11, 0x11, 0x0E, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
代码编写
为MatrixLED
模块添加一个函数:
void Matrix_ShowAll(unsigned char arr[], unsigned char startIndex) {
unsigned char i;
for (i = 0; i < 8; i++) {
MatrixLED_ShowColumn(i, arr[i + startIndex]);
}
}
然后主函数:
void main(void) {
unsigned char offset = 0, count = 0;
unsigned char animeSize = sizeof(animation) / sizeof(unsigned char);
MatrixLED_Init();
while (1) {
while (1) {
Matrix_ShowAll(animation, offset);
count++;
if (count == 10) {
count = 0;
break;
}
}
if (offset == animeSize - 8) {
offset = 0;
}
offset++;
}
}
这样我们即可看到从左向右移动的“Hello!”字幕了!
单片机学习(八)点阵LED的使用的更多相关文章
- led指示灯电路图大全(八款led指示灯电路设计原理图详解)
led指示灯电路图大全(八款led指示灯电路设计原理图详解) led指示灯电路图(一) 图1所示电路中只有两个元件,R选用1/6--1/8W碳膜电阻或金属膜电阻,阻值在1--300K之间. Ne为氖泡 ...
- 51单片机-独立按键控制led矩阵的左移和右移
51单片机学习 独立按键 控制led灯光矩阵的左移和右移 开发板采用的是普中的A2学习开发板,具体的代码如下: typedef unsigned int u16; void delay(u16 tim ...
- Python Tutorial 学习(八)--Errors and Exceptions
Python Tutorial 学习(八)--Errors and Exceptions恢复 Errors and Exceptions 错误与异常 此前,我们还没有开始着眼于错误信息.不过如果你是一 ...
- SVG 学习<八> SVG的路径——path(2)贝塞尔曲线命令、光滑贝塞尔曲线命令
目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...
- 单片机远程控制步进电机、LED灯和蜂鸣器
通过採用C#语言实现的上位机控制单片机的步进电机模块.LED灯和蜂鸣器模块,使步进电机进行正.反转和停止并控制转速:LED灯模块进行有选择的呼吸式表达:蜂鸣器模块的開始和终止. 上位机通过串口和自己定 ...
- 51单片机学习笔记(清翔版)(13)——LED点阵、74HC595
如图3,点阵屏分单色和彩色,点阵屏是由许多点组成的,在一个点上,只有一颗一种颜色的灯珠,这就是单色点阵屏,彩色的在一个点上有三颗灯珠,分别是RGB三原色. 图4你可能没看出来,那么大块黄色的就是点阵屏 ...
- 51单片机学习笔记(郭天祥版)(1)——单片机基础和点亮LED灯
关于单片机型号的介绍: STC89C52RC40C-PDIP 0721CV4336..... STC:STC公司 89:89系列 C:COMS 52(还有51,54,55,58,516,):2表示存储 ...
- 学习笔记——单片机简介 & 点亮LED & 流水灯 & 电路基础【更新Ing】
视频地址:https://www.bilibili.com/video/av10765766 超详细!!!!!! 单片机内部三大资源 [资源:单片机可提供使用的东西] FLASH 可以重复擦写 断电后 ...
- 单片机学习(二)开发板LED灯的控制
目录 开发板上LED灯相关的电路图 点灯 LED闪烁 LED流水灯 其他效果 灯光二进制计数器 进阶版流水灯 开发板上LED灯相关的电路图 这是P2相关7个引脚的电路图,在默认情况下它是直接接着VCC ...
随机推荐
- 浅谈C++11中的多线程(一)
摘要 本篇文章围绕以下几个问题展开: 进程和线程的区别 何为并发?C++中如何解决并发问题?C++中多线程的基本操作 同步互斥原理以及多进程和多线程中实现同步互斥的两种方法 Qt中的多线程应用 c++ ...
- python 抓取异常
aa={"a":2,"b":1} for i in range(10): aa["a"]=aa["a"]-i print ...
- C语言枚举类型
在实际编程中,有些数据的取值往往是有限的,只能是非常少量的整数,并且最好为每个值都取一个名字,以方便在后续代码中使用,比如一个星期只有七天,一年只有十二个月,一个班每周有六门课程等.以每周七天为例,我 ...
- C语言变量类型
#include <stdio.h> // C 语言中,任何数据类型都不可以直接存储一个字符串.那么字符串如何存储? //在 C 语言中,字符串有两种存储方式,一种是通过字符数组存储,另一 ...
- 使用jquery的on方法注册事件遇到的坑
1,使用on注册事件 $(selector).on(event,childSelector,data,function) 2,$(selector)中的selector可以是document,那么意味 ...
- IDEA搭建springmvc环境之后无故出现404
其实这应该是IDEA的自身问题 打开项目结构
- 微信小程序云开发-云存储-使用云开发控制台存储文件
一.存储 进入[云开发控制台]>点击[存储].将需要存储的文件通过[上传文件]方式上传上去.或者通过拖拽的方式上传文件. 二.存储文件的类型 可以存储的文件有很多,常见的文件类型包括:word ...
- centos7 几种修改系统时区的方法
1. # cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime # ln -sf /usr/share/zoneinfo/Asia/Shanghai ...
- odoo里面context用法
原文转自:https://www.cnblogs.com/zhaoweihang/p/9698852.html <field name="partner_id" string ...
- 17Java进阶——反射、进程、Java11新特性
1.Java反射机制 Java反射(Reflection)概念:在运行时动态获取类的信息以及动态调用对象方法的功能. 1.1反射的应用--通过全类名获取类对象及其方法 package two.refl ...