51单片机学习笔记-7LED点阵屏

news2024/12/23 23:21:31

7 点阵屏

[toc]

注:笔记主要参考B站江科大自化协教学视频“51单片机入门教程-2020版 程序全程纯手打 从零开始入门”。
注:工程及代码文件放在了本人的Github仓库。


7.1 LED点阵屏介绍

LED点阵屏由若干个独立的LED组成,LED以矩阵的形式排列,以灯珠亮灭来显示文字、图片、视频等。LED点阵屏广泛应用于各种公共场合,如汽车报站器、广告屏以及公告牌等。LED点阵屏分类:

按颜色:单色、双色、全彩。
按像素:8*8、16*16等(大规模的LED点阵通常由很多个小点阵拼接而成)。

LED点阵屏的结构类似于数码管,只不过是数码管把每一列的像素以“8”字型排列而已。LED点阵屏与数码管一样,有共阴和共阳两种接法,不同的接法对应的电路结构不同(单色LED点阵没有区别)。LED点阵屏需要进行逐行或逐列扫描,才能使所有LED同时显示。与数码管使用38译码器(74HC138)作为片选信号节省引脚相同,LED点阵屏使用74HC595作为片选信号节省引脚所以本实验的难点在于对74HC595的控制。

图7-1 74HC595 及 LED点阵屏 原理图

74HC595是串行输入并行输出的移位寄存器,可用3根线输入串行数据,8根线输出并行数据,将串行输出、串行输入进行多片级联后,可输出16位、24位、32位等,常用于IO口扩展。下面介绍其引脚及功能真值表:

  • 引脚16、8:VCC、GND电源供电。
  • 引脚15,1~7:8位并行输出端。
  • 引脚9:串行数据输出。
  • 引脚14:串行输入。
  • 剩下的,引脚13为输出有效(高电平);引脚10为主复位(低电平);引脚11为移位寄存器时钟;引脚12为存储寄存器时钟。
表7-1 74HC595控制引脚真值表
引脚13/OESRCLR/VCCSRCLK/P36RCLK/P35功能
HXXX清空移位寄存器
并行输出为高阻状态
LLXX清空移位寄存器
LHX移位寄存器锁定
QN=Q(N-1), Q'=SER
LHX移位寄存器的内容移入到输出寄存器
图7-2 74HC595逻辑框图

通过上面的真值表可以看出,要想遍历每一行LED,首先硬件上OE引脚保持度电平,SRCLR保持高电平。软件方面,串行输入只需要最开始为1,而后均为0。然后,每次都进行移位寄存器的更新及输出寄存器的更新,即可遍历到每一行LED。

下面是会用到的51单片机语法:

  • sfr(special function register):特殊功能寄存器声明。
    例:sfr P0 = 0x80;
    声明P0口寄存器,物理地址为0x80。
  • sbit(special bit):特殊位声明
    例:sbit P0_1 = 0x81; 或 sbit P0_1 = P0^1;//P0的第1位
    声明P0寄存器的第1位
  • 可位寻址/不可位寻址:在单片机系统中,操作任意寄存器或者某一位的数据时,必须给出其物理地址,又因为一个寄存器里有8位,所以位的数量是寄存器数量的8倍,单片机无法对所有位进行编码,故每8个寄存器中,只有一个是可以位寻址的。对不可位寻址的寄存器,若要只操作其中一位而不影响其它位时,可用“&=”、“|=”、“^=”的方法进行位操作

7.2 实验:LED点阵屏显示图片

需求:在LED点阵屏上显示一个“我的世界”的方脸。

图7-3 “LED点阵显示图片”代码调用关系

代码展示:
- main.c

#include <REGX52.H>
#include "Matrix_LED.h"

// 定义图案数据,注意是按列循环的
unsigned char led_face[8] = 
{0xc0,0xdb,0xd9,0xc5,0xc5,0xd9,0xdb,0xc0};
//            {{1,1,1,1,1,1,1,1},
//             {1,1,1,1,1,1,1,1},
//             {0,0,0,0,0,0,0,0},
//             {0,1,1,0,0,1,1,0},
//
//             {0,1,1,0,0,1,1,0},
//             {0,0,0,1,1,0,0,0},
//             {0,1,0,0,0,0,1,0},
//             {0,1,1,1,1,1,1,0},};

void main(){
  unsigned char i;
  P3_5 = 0; P3_6 = 0; // 对移动寄存器时钟复位
  while(1){
    for(i=0;i<8;i++){
      MatrixLED_ShowColumn(i,led_face[i]);
    }
  }
}

- Matrix_LED.h

#ifndef __MATRIX_LED_H__
#define __MATRIX_LED_H__

void MatrixLED_ShowColumn(unsigned char Column,Data); // 控制LED点阵的某一列显示

#endif

- Matrix_LED.c

#include <REGX52.H>

/*随开发板的不同,此段代码中的端口定义会有所变化,使用前注意更新*/
/**********************************************************/
// LED点阵通用,延时cycles ms,晶振@11.0592MHz
// 静态函数,只能在本源文件中被调用
static void Delay(unsigned int cycles){
  unsigned char i, j;
  do{
    i = 2;
    j = 199;
    do{
      while (--j);
    }while (--i);
  }while(--cycles);
}

// 为了方便,先给几个引脚重新起名
sbit RCK = P3^5; // 重复了所以不叫RCLK
sbit SCK = P3^6; // SRCLK
sbit SER = P3^4;
#define MATRIX_LED_PORT P0
/*********************************************************/

/*下面的代码无需更新*/
/*********************************************************/
/**
  * @brief :向74HC595串行输入口输入8bit数据。
  * @param :输入的8bit数据,高位先进。
  * @retval :无。
 */
void _74HC595_WriteByte(unsigned char Byte){
  unsigned char i;
  for(i=0;i<8;i++){
    SER = Byte&(0x80>>i); // 右边只要不是0,1bit宽度的SER就为1
    SCK = 1;
    SCK = 0;
  }
  RCK = 1;
  RCK = 0;
}

/**
  * @brief :在LED点阵的指定列,输入数据。
  * @param :Column,列位置,范围0~7。
  * @param :Data,该列需要显示的数据。
  * @retval :无。
 */
void MatrixLED_ShowColumn(unsigned char Column,Data){
  _74HC595_WriteByte(Data); // 段选信号
  MATRIX_LED_PORT = ~(0x80>>Column); // 片选信号
  Delay(1);
  MATRIX_LED_PORT = 0xff; // 消影
}
/*********************************************************/

编程感想:

  • 回顾数码管、LED点阵屏的实验,发现二极管的正极都是被其他芯片强化过的,而不是直接通过单片机引脚进行供电。本质上这是因为,单片机的引脚高电平只是弱上拉,但是低电平则具有很强的吸收电流的功能。所以单片机引脚专门连LED的低电平。注意编程时按列输出!
  • 另外,涉及到“片选→段选→片选→段选→……”这样的结果,为了防止在“段选→片选”过程中出现“拖影现象”。有两种方法可以消影,一个是“片选→段选→段选归0→片选→段选→……”,另一个是“片选→延时、片选归0→段选→片选→延时、段选归0→段选→……”。为了程序效率,一般选择归0操作更简单的方式。

7.3 实验:LED点阵屏显示动画

需求:在显示屏上显示流动的飞机。

图7-4 “LED点阵显示动画”代码调用关系

我将上一节MatrixLED.c文件又优化了一下,代码如下:
- main.c

#include <REGX52.H>
#include "Matrix_LED.h"

// 定义图案数据,注意是按列循环的
// 下面这个数据如果不加"code",就会存储在片内RAM中,可能会导致存储空间不足。
// 添加"code"之后,这个数组就会存储在片外Flash上,空间很大,但不允许更改。
unsigned char code led_animation[] = 
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0x18,0x3C,0x7E,0xDB,0x99,0x18,0x18,0x18,
 0x18,0x99,0xBD,0xFF,0x18,0x24,0x42,0x00,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

void main(){
  unsigned char cur_pic[8];
  unsigned char fra,offset;//取出当前需要显示的数据
  unsigned int MAX_OFFSET = sizeof(led_animation)-8;
  unsigned int cnt_show = 0;//显示次数计数
  unsigned char MAX_CNT = 5;//控制显示速率
  MatrixLED_Init(); //LED点阵屏初始化
  while(1){
    for(offset=0;offset<MAX_OFFSET;offset++){
      cnt_show = 0;
      // 取出当前需要显示的数据
      for(fra=0;fra<8;fra++){
        cur_pic[fra]=led_animation[fra+offset];
      }
      // 重复显示以控制动画速度
      do{
        MatrixLED_ShowPic(cur_pic);
        cnt_show++;
      }while(cnt_show<MAX_CNT);
    }
  }
}

- MatrixLED.h

#ifndef __MATRIX_LED_H__
#define __MATRIX_LED_H__

void MatrixLED_Init();//LED点阵屏初始化
void MatrixLED_ShowColumn(unsigned char Column,Data); //控制LED点阵的某一列显示
void MatrixLED_ShowPic(unsigned char Data[8]); //控制LED点阵显示一副图案
  
#endif

- MatrixLED.c

#include <REGX52.H>

/*随开发板的不同,此段代码中的端口定义会有所变化,使用前注意更新*/
/**********************************************************/
// LED点阵通用,延时cycles ms,晶振@11.0592MHz
static void Delay(unsigned int cycles){
  unsigned char i, j;
  do{
    i = 2;
    j = 199;
    do{
      while (--j);
    }while (--i);
  }while(--cycles);
}

// 为了方便,先给几个引脚重新起名
sbit RCK = P3^5; // 重复了所以不叫RCLK
sbit SCK = P3^6; // SRCLK
sbit SER = P3^4;
#define MATRIX_LED_PORT P0
/*********************************************************/

/*下面的代码无需更新*/
/*********************************************************/
/**
  * @brief :LED点阵屏初始化。
  * @param :无。
  * @retval :无。
 */
void MatrixLED_Init(){
  // 对移位寄存器时钟复位
  RCK = 0;
  SCK = 0;
}

/**
  * @brief :向74HC595串行输入口输入8bit数据。
  * @param :输入的8bit数据,高位先进。
  * @retval :无。
 */
void _74HC595_WriteByte(unsigned char Byte){
  unsigned char i;
  for(i=0;i<8;i++){
    SER = Byte&(0x80>>i); // 右边只要不是0,1bit宽度的SER就为1
    SCK = 1;
    SCK = 0;
  }
  RCK = 1;
  RCK = 0;
}

/**
  * @brief :在LED点阵的指定列,输入数据。
  * @param :Column,列位置,范围0~7。
  * @param :Data,该列需要显示的数据。
  * @retval :无。
 */
void MatrixLED_ShowColumn(unsigned char Column,Data){
  _74HC595_WriteByte(Data); // 段选信号
  MATRIX_LED_PORT = ~(0x80>>Column); // 片选信号
  Delay(1);
  MATRIX_LED_PORT = 0xff; // 消影
}

/**
  * @brief :在LED点阵显示一幅图案。
  * @param :Data[8],输入数据是一维数组,长度为8,表示一幅图案。
  * @retval :无。
 */
void MatrixLED_ShowPic(unsigned char Data[8]){
  unsigned char i;
  for(i=0;i<8;i++){
      MatrixLED_ShowColumn(i,Data[i]);
  }
}
/*********************************************************/

编程感想:

  1. 做滚动动画的时候,可以在此动画前后添加空屏,就以保证动画的连续程度。
  2. 注意滚动动画,每次偏移量为1;视频动画每次偏移量为8(一帧)。
  3. 注意数组太长,片上的RAM会存不下,可以使用 code 存放在片上ROM(Flash)中,如unsigned char code led_animation[]
  4. 下面给给出一些其他动画。
//小球下落,视频动画
unsigned char code led_animation[] = 
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,
 0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,
 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,
 0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,
 0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,
 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

// 方框回缩与放大,视频动画
 unsigned char code led_animation[] = 
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0xFF,0x81,0x81,0x81,0x81,0x81,0x81,0xFF,
 0x00,0x7E,0x42,0x42,0x42,0x42,0x7E,0x00,
 0x00,0x00,0x3C,0x24,0x24,0x3C,0x00,0x00,
 0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00, //中心轴
 0x00,0x00,0x3C,0x24,0x24,0x3C,0x00,0x00,
 0x00,0x7E,0x42,0x42,0x42,0x42,0x7E,0x00,
 0xFF,0x81,0x81,0x81,0x81,0x81,0x81,0xFF,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

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

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

相关文章

前端灰度发布(定义 优点 原理 方式)

1. 什么是灰度发布&#xff1f; 灰度发布&#xff0c;又被称之为金丝雀发布&#xff0c;是指某次新发布功能特性和旧功能特性之间能够以平滑过渡的方式呈现给用户&#xff0c;就像金丝雀的羽毛一样多种颜色平滑渐变。 举个例子&#xff0c;某个已上线处于运行中的系统需要一次…

播放视频报403 forbidden的原因及解决方案

一、原因 1、原因&#xff1a;我们知道&#xff0c;在页面引入图片、JS 等资源&#xff0c;或者从一个页面跳到另一个页面&#xff0c;都会产生新的 HTTP 请求&#xff0c;浏览器一般都会给这些请求头加上表示来源的 Referrer 字段。图片服务器通过检测 Referrer 是否来自规定…

Cisco RV340命令执行漏洞(CVE-2022-20707)及关联历史漏洞分析

一、引言 本篇文章主要是对Cisco RV340命令执行漏洞(CVE-2022-20707)进行的研究分析&#xff0c;尽管利用此漏洞需要身份验证&#xff0c;但可以通过CVE-2022-20705绕过现有的身份验证机制实现无条件的命令执行。历史相关的漏洞还包括&#xff1a;CVE-2020-3451、CVE-2021-147…

客户案例 | 低代码上的西门子,工欲善其事必先利其器

关键发现 用户痛点&#xff1a;项目管理过程涉及的系统繁多&#xff0c;系统间状态不透明&#xff0c;数据查询困难&#xff1b;人工流程虽属个别&#xff0c;但易拉低总体效率并有可能出错&#xff1b;数据报告自动化程度低。 解决方案&#xff1a;利用西门子低代码开发平台开…

玩转电脑|WIN10如何添加打印机扫描到电脑

win10和win7 添加打印机扫描到电脑操作不一样&#xff0c;换了win10电脑后还是按照win7的方法进行添加&#xff0c;会发现win10系统添加京瓷6525FMP打印机的扫描地址时会出现链接错误&#xff0c;无法添加。是因为win10需要设置SMB权限之后&#xff0c;即可添加地址簿。一、配置…

OAuth2.0-授权码模式

解决问题 OAuth2.0授权码模式主要解决了信任问题&#xff1a;一个第三方网站需要访问我们Github上的数据&#xff08;例如用户头像&#xff09;&#xff0c;那Github为什么要信任该网站&#xff1f;该对网站信任到什么程度&#xff1f; 如果彻底信任该网站&#xff0c;那么将…

LeetCode链表相关解法

LeetCode链表相关解法1.移除链表元素[203. 移除链表元素](https://leetcode.cn/problems/remove-linked-list-elements/)不设置头节点设置虚拟头节点2.设计链表[707. 设计链表](https://leetcode.cn/problems/design-linked-list/)3.反转链表[206. 反转链表](https://leetcode.…

使用Java8改造模板方法模式

目录 前言 以前的模板方法 Java 8 的函数式编程 Java 8以后的模板方法 总结 前言 我们在日常开发中&#xff0c;经常会遇到类似的场景&#xff1a;当要做一件事儿的时候&#xff0c;这件事儿的步骤是固定好的&#xff0c;但是每一个步骤的具体实现方式是不一定的。 通…

Hudi(14):Hudi集成Flink之核心参数设置

目录 0. 相关文章链接 1. 去重参数 2. 并发参数 2.1. 参数说明 2.2. 案例演示 3. 压缩参数 3.1. 参数说明 3.2. 案例演示 4. 文件大小 4.1. 参数说明 4.2. 案例演示 5. Hadoop 参数 Flink可配参数官网地址&#xff1a;All Configurations | Apache Hudi 0. 相关文…

Ubuntu 18.04 安装 nvidia 显卡驱动 离线安装 禁用 nouveau

Ubuntu 18.04 安装 nvidia 显卡驱动 离线安装1 系统2 查看显卡2.1 更新 pci.ids 文件3 安装显卡驱动 510.543.1 安装 nvtop4 禁用 nouveau5 安装 cuda 11.6.15.1 设置环境变量1 系统 # lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubu…

bpflock:基于eBPF实现的Linux设备安全审计工具

关于bpflock bpflock是一款基于 eBPF驱动的Linux设备安全审计工具&#xff0c;该工具使用了eBPF来帮助广大研究人员增强Linux设备的安全性。通过限制对各种Linux功能的访问&#xff0c;bpflock能够减少攻击面并阻止一些众所周知的攻击技术。 bpflock只允许类似容器管理器、sy…

区间一维dp史上最细总结(听了绝对会了,还不会的一定要进来)

目录 那年初夏&#xff08;三&#xff09; 引入 1.动态规划是什么&#xff1f; 2.什么是区间动态规划问题&#xff1f; 定义 性质 3.为何总是要问这种问题&#xff1f; 区间动态规划基本 思考 步骤&#xff08;划重点&#xff09; 例题精讲 1.最长上升子序列 题目描…

8个 数据库性能优化方案,你知道几个?(建议收藏)

毫不夸张的说咱们后端工程师&#xff0c;无论在哪家公司&#xff0c;呆在哪个团队&#xff0c;做哪个系统&#xff0c;遇到的第一个让人头疼的问题绝对是数据库性能问题。如果我们有一套成熟的方法论&#xff0c;能让大家快速、准确的去选择出合适的优化方案&#xff0c;我相信…

IB数学AA/AI应该如何选择?

IB数学怎么选课&#xff1f;AA&#xff0c;AI&#xff0c;SL&#xff0c;HL适合哪些学生&#xff1f;如何学习&#xff1f;IB数学&#xff1a;AA与AI&#xff0c;到底应该怎么选&#xff1f;IB数学AA有多难&#xff1f;要不要学数学AA HL&#xff1f;适合学生 IB数学AA AA HL偏…

【SpringCloud复习巩固】Feign

目录 一.HTTP客户端Feign 1.1RestTemplate方式调用存在的问题 1.2Feign的介绍 1.3Feign的使用 1.4自定义Feign的配置 1.4.1配置Feign日志的两种方式 1.5Feign性能优化 1.5.1Feign的性能优化-连接池配置 1.6Feign的最佳实践 一.HTTP客户端Feign 1.1RestTemplate方式调用…

自学软件测试,现在年薪30w,我骄傲了吗?

从小老一辈的人就经常说&#xff0c;小时候不好好读书&#xff0c;长大了只能去工地搬砖。我是从小都不爱读书的人&#xff0c;但在上学时期我一直有一种优越感&#xff0c;认为自己读书很有天赋&#xff0c;读书就是比别人厉害&#xff0c;但事实证明也确实如此&#xff0c;高…

[Android Studio]Android Studio Logcat日志样式设置

&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea; Android Debug&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea; Topic 发布安卓学习过程中遇到问题解决过程&#xff0c;希望我的解决方案可以对小伙伴们有帮助。 &#x1f4cb;笔记目…

c++IO流!!!开工了!!!

1.什么是IO流 流是若干个字节组成的字节序列&#xff0c;简单来说指的是就是数据从一端到另一端 键盘到程序——>标准输入流程序到屏幕——>标准输出流程序到文件——>文件流 流类体系&#xff1a;一些体系管理输入和输出的流的操作 输入流输出流文件流 ios类 istream…

【DockerCE】使用docker配置和运行HertzBeat

HertzBeat是一款免Agent的监控平台&#xff0c;拥有强大自定义监控能力&#xff0c;可以对应用服务、中间件、数据库、操作系统、云原生等进行监控&#xff0c;配置监控告警阈值&#xff0c;以及告警通知(邮件、微信、钉钉、飞书)。关于这个软件的介绍&#xff0c;我这里就不做…

困扰多年的Docker和iptables的恩怨,今天解决了

先介绍下我的使用环境&#xff1a; 操作系统&#xff1a;CentOS7.9 Docker版本&#xff1a;20.10.21 事情是这样的&#xff0c;安装完Docker的时候&#xff0c;容器镜像都跑起来了&#xff0c;端口也放行了&#xff0c;就是无法控制系统防火墙friewalld,查看firewalld状态报错 …