> 技术文档 > 51单片机控制的8*8 LED矩阵扫描显示项目

51单片机控制的8*8 LED矩阵扫描显示项目

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:本项目着重于帮助初学者理解和实现数字电路与嵌入式系统基础知识,通过编写程序控制51单片机来驱动8*8 LED矩阵实现动态显示。项目中将介绍如何使用定时器来控制扫描速度和刷新率,以及如何通过Protues软件进行仿真。学习内容包括I/O端口控制、定时器中断设置以及如何处理显示数据。

1. 51单片机基础应用

51单片机简介

51单片机是一种经典的微控制器,广泛应用于嵌入式系统的教学与产品开发。它基于Intel 8051架构,拥有简单易学的指令集,非常适合初学者学习与实践。

开发环境搭建

开发51单片机通常需要安装Keil uVision软件,这是一个集成开发环境,提供了代码编写、编译、调试等功能。接下来,需要准备硬件如开发板、USB转串口模块和相关连线,连接开发板到电脑上。

编写第一个程序

初学者可以从点亮一个LED灯开始实践。首先,创建一个C语言项目并编写代码,如下:

#include void delay(unsigned int ms) { unsigned int i, j; for (i = ms; i > 0; i--) for (j = 110; j > 0; j--);}void main() { while(1) { P1 = 0xFF; // 点亮P1口连接的LED灯 delay(1000); // 延时大约1秒 P1 = 0x00; // 熄灭LED灯 delay(1000); // 延时大约1秒 }}

通过这段代码的编译、烧录到单片机中,并运行,即可看到P1口连接的LED灯以大约1秒的间隔闪烁。

程序烧录与调试

将编写好的程序通过编程器烧录到单片机芯片中,并通过串口助手等工具进行通信和调试,观察LED灯的闪烁情况,验证程序是否正确运行。

以上章节内容为51单片机基础应用的概述,从单片机简介到开发环境搭建、编写第一个程序,再到程序烧录与调试,为初学者提供了一个基本的了解和操作流程。接下来章节将深入讨论如何利用单片机实现更复杂的功能。

2. 8*8 LED矩阵动态扫描显示原理

2.1 LED矩阵的工作原理

2.1.1 点阵式显示的组成与特性

LED矩阵是一种显示设备,由多个LED(发光二极管)排列成矩阵形式。基本的LED点阵一般为8x8的结构,它由64个LED组成。在每个LED的行和列交叉点可以控制LED的开关,形成不同的图案或文字。点阵式显示的特性包括高对比度、低功耗、可控制性强等优点。每个LED可以通过外部电路单独控制,组合起来能够展示复杂的文字、图案甚至动画效果。

2.1.2 扫描显示的基本概念与作用

扫描显示是一种控制LED显示的方式,通过快速切换各个LED的点亮与熄灭,使得人眼感觉到这些LED始终是亮着的。扫描显示一般需要定时器来控制,通过快速而连续的刷新LED矩阵的每一行或每一列,人眼因视觉暂留效应感觉到整个矩阵是同时发光的。这种显示方式可以大幅度降低功耗,并能通过控制不同的亮度级别显示不同的灰度。

2.2 动态扫描的实现方法

2.2.1 点阵扫描的时序分析

动态点阵扫描涉及时序控制,通常需要一个快速的时钟信号来控制。实现动态扫描时,首先需要向行寄存器发送选通信号,然后向列寄存器发送相应的数据。通过逐行或逐列扫描,LED矩阵的每一行或每一列可以在短时间内依次点亮。这种快速的切换给人眼以连续显示的假象。以下是一个简单的8x8 LED矩阵动态扫描时序的示例代码。

// 示例代码:动态扫描8x8 LED矩阵for(int row = 0; row < 8; row++) { // 选中当前行 digitalWrite(rowPin, LOW); for(int col = 0; col < 8; col++) { // 根据需要点亮的列设置高低电平 digitalWrite(columnPins[col], matrix[row][col]); delayMicroseconds(1000); // 延时以调整亮度或扫描速率 } digitalWrite(rowPin, HIGH); // 关闭当前行,防止干扰}

在上述代码中, rowPin 代表行选择的引脚, columnPins 代表列的引脚数组, matrix 代表LED矩阵中每一行每一列的状态(亮或灭)。通过此代码,我们可以实现每行的快速扫描。

2.2.2 动态扫描与静态扫描的区别

动态扫描与静态扫描的主要区别在于LED矩阵的驱动方式。在静态扫描中,每一行或列的LED都需要并行驱动,并且保持点亮状态直到更新画面。这种方式需要大量的驱动电路和IO端口,且功耗较高。而动态扫描只需要一组行驱动和一组列驱动,通过快速切换来逐个点亮每个LED,大大减少了硬件资源的需求并降低了功耗。

下面是一个简单的mermaid流程图来描述动态扫描和静态扫描的区别。

graph TD; A[开始] --> B[静态扫描] B --> C[每一行/列并行控制] C --> D[高功耗] A --> E[动态扫描] E --> F[逐行/列控制] F --> G[低功耗]

通过mermaid流程图的展示,可以清楚地看到两种扫描方式的区别。在实际应用中,动态扫描因其高效性和成本效益而被广泛采用。

3. 定时器在LED控制中的作用

3.1 定时器的基本概念

3.1.1 定时器的工作原理与分类

在计算机和微控制器系统中,定时器是一种常见的硬件设备,主要用于执行计数和时间测量相关的功能。其基本原理是,在给定的时间间隔内,定时器会根据其设置的频率生成一个中断信号。这个中断信号可以用来执行周期性的任务,比如更新显示画面,计时,或者控制事件发生的时间点。

定时器通常可以分为以下几类:

  • 软件定时器 :通过软件循环和延时函数来实现,不需要硬件支持,但准确性和效率较低。
  • 硬件定时器 :由专用的硬件电路实现,可以提供更精确的时间控制,并且不会占用CPU资源。
  • 计数器定时器 :除了用于计时外,还可以用作外部事件的计数器,例如,对输入信号的上升沿或下降沿进行计数。

3.1.2 51单片机定时器的结构与功能

51单片机内置有两个定时器/计数器,分别是定时器0和定时器1。这些定时器可以用作定时或计数两种模式。在定时器模式下,它们可以用作简单的定时器,例如,用于控制LED闪烁频率。在计数器模式下,它们可以对外部事件进行计数。

定时器的结构通常包括:

  • 计数器/寄存器 :用于存储当前的计数值,这个值会随着时间推移或外部事件的变化而改变。
  • 控制寄存器 :用于配置定时器的工作模式、预分频值、中断使能等。
  • 中断请求标志位 :当定时器达到预定条件时,会设置中断请求标志位,触发CPU中断。

3.2 定时器在扫描显示中的应用

3.2.1 定时器中断的产生与控制

定时器中断的产生依赖于定时器的配置和预置值。通过设置定时器的初始值,可以在经过设定的时间间隔后产生中断。中断产生后,CPU会暂停当前的处理流程,转而去执行与中断相关联的中断服务程序。

定时器中断的控制包括:

  • 中断使能 :必须使能中断,才能允许定时器中断产生。
  • 中断优先级 :在有多个中断源时,可以设置不同中断源的优先级,确定CPU响应中断的顺序。
  • 中断服务程序 :编写中断服务程序来响应中断请求,执行必要的任务。
// 51单片机定时器中断初始化示例void Timer0_Init() { TMOD |= 0x01; // 设置定时器0为模式1(16位定时器模式) TH0 = 0xFC; // 装载定时器高位初值 TL0 = 0x66; // 装载定时器低位初值 ET0 = 1; // 使能定时器0中断 TR0 = 1; // 启动定时器0}

3.2.2 定时器精确控制扫描频率的实现

精确控制LED矩阵的扫描频率对于实现良好的显示效果至关重要。扫描频率过低会导致LED闪烁,而频率过高则可能增加系统的功耗。通过定时器中断,我们可以精确控制扫描频率,保证每个LED能够以恰当的频率点亮。

在定时器中断服务程序中,我们编写代码来刷新LED矩阵的显示内容。通过改变定时器预设值,可以灵活地调整扫描频率。

// 定时器中断服务程序示例void Timer0_ISR() interrupt 1 using 1 { TH0 = 0xFC; // 重新装载定时器高位初值 TL0 = 0x66; // 重新装载定时器低位初值 // 更新LED显示内容 UpdateLEDMatrix();}

通过合理设置定时器的初值和中断服务程序,可以实现对LED矩阵扫描频率的精确控制,从而达到高效率和良好的显示效果。

定时器的应用不仅仅局限于LED控制,还广泛应用于其他需要时间控制的场合。在51单片机这样的微控制器应用中,定时器是实现精确时间控制不可或缺的工具。随着技术的不断进步,定时器的实现方式也在不断演进,但从基本的工作原理和应用来看,其核心价值始终未变。

4. 静态与动态LED驱动技术

4.1 静态驱动技术

静态驱动技术是指每个LED或LED点阵中的每一个像素,都通过单独的I/O线进行控制,而不需要进行时间上的复用。在这种驱动方式下,一个LED可以持续亮着,直到被指令关闭。

4.1.1 静态驱动的工作方式

在静态驱动方式中,单片机对每个LED进行直接控制,无需额外的驱动器。每个LED或LED的每个单元都可以在任意时刻单独控制,这使得静态驱动在控制上非常直观和简单。具体而言,要控制一个LED的亮灭,只需将对应的I/O口设置为高电平或低电平即可。

// 伪代码示例:静态控制一个LED的亮灭void setLEDState(unsigned char ledPin, unsigned char state) { // ledPin为LED对应的I/O口,state为高电平(1)或低电平(0) if (state) { // 设置I/O口为高电平以点亮LED I/O_PORT |= (1 << ledPin); } else { // 设置I/O口为低电平以熄灭LED I/O_PORT &= ~(1 << ledPin); }}
4.1.2 静态驱动的优缺点分析

静态驱动的优点在于实现简单直接,控制逻辑易于理解,且响应速度快,因为没有额外的延时。然而,这种驱动方式需要大量的I/O口,对于一些I/O口数量有限的微控制器来说并不实用。此外,静态驱动功耗较大,因为每个LED都是直接连接到微控制器的I/O口,即使在LED关闭时,也可能会有微小的电流通过。

4.2 动态驱动技术

动态驱动技术通过在时间上快速切换来控制LED,这样就可以使用较少的I/O口控制更多的LED。动态驱动技术对于LED矩阵显示特别有用,因为它大大减少了所需的I/O线数量。

4.2.1 动态驱动的工作方式

动态驱动的实现依赖于定时器中断来快速刷新LED的状态。通过快速地轮流点亮和熄灭LED,利用人眼的视觉暂留效应,我们可以看到所有LED似乎是同时点亮的。在动态驱动中,每一行或每一列的LED会迅速交替亮起,通过这种方式,微控制器可以控制LED矩阵中的每一个LED。

// 伪代码示例:动态控制一个LED矩阵的亮灭void refreshLEDMatrix() { // 依次点亮每一行,熄灭其他行 for (int i = 0; i < NUM_ROWS; i++) { // 点亮当前行 selectRow(i); // 刷新列的状态 updateColumns(); // 延时,控制刷新频率 delay(matrixRefreshRate); }}
4.2.2 动态驱动的优势与实现方法

动态驱动最大的优势在于它能够显著降低所需的I/O口数量。例如,一个8x8 LED矩阵,采用静态驱动需要64个I/O口,而采用动态驱动则可能只需要8个I/O口(8行加8列)。此外,动态驱动还可以更有效地管理电源,因为它可以通过控制刷新频率来调整LED的亮度,从而实现节能。

在实际应用中,动态驱动技术通常需要硬件支持,如行列驱动器,以及软件控制,如定时器中断的精确时间管理,以确保LED矩阵显示的正确和稳定。动态驱动技术是目前大多数LED显示系统采用的方式。

以下是两种驱动方式的表格对比:

| 特性/驱动方式 | 静态驱动 | 动态驱动 | | -------------- | ------------------------- | ------------------------- | | 控制复杂度 | 简单 | 复杂 | | I/O口需求 | 高 | 低 | | 功耗 | 高 | 低 | | 显示效果 | 可实现高亮显示 | 易出现闪烁现象 | | 适用场合 | 需要高亮或较少LED的场合 | 需要控制多LED的场合 | | 软件控制 | 直接控制每个LED | 需要定时器中断与刷新逻辑 | | 硬件支持 | 无需额外硬件支持 | 可能需要行列驱动器 |

通过本章节的介绍,我们了解了静态和动态LED驱动技术的基本概念、工作方式及其优缺点。下一章将探讨如何利用定时器在LED控制中发挥作用,进一步深入理解定时器中断的设置与应用。

5. I/O端口控制实践

5.1 I/O端口基础知识

I/O端口的功能与分类

I/O端口,即输入/输出端口,是微控制器与外部设备进行数据交换的接口。在51单片机中,I/O端口用于发送控制信号或读取外部设备状态。这些端口通常可以被配置为输入或输出模式,以满足不同的应用场景需求。

I/O端口可以分为两大类:准双向I/O端口和真正的双向I/O端口。准双向I/O端口通常有一个固定的输入或输出功能,在读取前需要配置为输入模式,在写入前需要配置为输出模式。真正的双向I/O端口则可以在任何时候动态地改变方向,这使得它们更加灵活。

在51单片机中,I/O端口的引脚通常对应于单片机的某些特定的物理引脚,如P0、P1、P2、P3等,每个端口都有自己的特性和应用方式。

51单片机I/O端口的编程

在51单片机中,I/O端口的编程通常涉及直接操作这些端口的寄存器。例如,要将P1端口配置为输出模式,可以将该端口的所有位设置为1,因为单片机的I/O端口默认为高阻态(输入模式),输出高电平。

以下是一个简单的代码示例,演示如何操作51单片机的P1端口,点亮一个LED灯:

#include void main(void) { P1 = 0xFF; // 将P1端口所有位设置为高电平,配置为输出模式 while(1) { P1 = 0x00; // 将P1端口所有位设置为低电平,点亮LED灯 // 延时函数,控制点亮时间 P1 = 0xFF; // 将P1端口所有位设置为高电平,熄灭LED灯 // 延时函数,控制熄灭时间 }}

这段代码首先将P1端口初始化为输出模式,然后在一个无限循环中通过切换P1端口的电平状态来控制LED灯的点亮和熄灭。

参数说明与代码逻辑分析

在上述代码中, P1 是指向51单片机P1端口的指针。 P1 = 0xFF; P1 = 0x00; 分别表示将P1端口所有位设置为高电平和低电平。这样的设置是通过直接写入端口的控制寄存器来完成的。

延时函数的目的是为了能够用肉眼观察到LED灯的闪烁效果。实际应用中,我们通常会使用定时器来实现精确的延时,但为了简化本例,延时函数可以采用简单的循环来实现。

5.2 I/O端口在LED显示中的应用

I/O端口控制LED的方法

在LED显示中,I/O端口可以通过编程控制每个LED灯的亮灭,从而显示不同的图案或文字。下面的代码示例展示了如何控制一个8x8的LED点阵显示器:

#include // 假设我们有一个8x8 LED点阵的硬件连接示意图如下:// P0: D0-D7 连接到LED点阵的行// P2: A0-A7 连接到LED点阵的列// 用于控制行的数组unsigned char code row[8] = {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F};// 用于控制列的数组unsigned char code col[8] = {0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE};void delay(unsigned int ms) { // 简单的延时函数实现 while (ms--) { unsigned int i; for (i = 0; i < 123; i++); }}void display(unsigned char *row, unsigned char *col) { unsigned char i; for (i = 0; i < 8; i++) { P0 = row[i]; // 选择当前行 P2 = col[i]; // 刷新当前列 delay(1); // 维持显示一段时间 }}void main() { while(1) { display(row, col); // 循环显示图案 }}

在这段代码中,我们定义了两个数组 row col ,分别用于控制LED点阵的行和列。通过逐行扫描并选择对应的列,我们可以在LED点阵上显示图案。

提高I/O端口效率的策略

为了提高I/O端口的效率,可以采用动态扫描技术,这样可以减少I/O端口的使用数量,同时保持LED点阵的显示效果。动态扫描的基本思想是在同一时间内只点亮一行LED,但通过快速地轮换显示,使得人眼看到的是全亮的LED阵列。

此外,通过使用硬件支持的多路复用技术,可以进一步减少所需的I/O端口数量。例如,可以使用移位寄存器来扩展I/O端口,这样就可以使用较少的I/O端口来控制更多的LED。

总结来说,通过对I/O端口的深入理解与控制,可以有效地驱动LED显示,同时通过采用适当的策略,可以进一步优化资源的使用,提高系统的整体效率。在下一章节中,我们将探讨定时器中断的设置与应用,这是实现定时任务与事件响应的关键技术之一。

6. 定时器中断的设置与应用

6.1 定时器中断机制

6.1.1 中断的概念与分类

在计算机系统中,中断是硬件或软件发出的一种信号,用来通知CPU暂停当前正在执行的任务,转而去处理更重要或者紧急的事件。当中断发生时,CPU会跳转到预设的中断处理程序去执行,处理完毕后再回到原来的程序继续执行。中断可以分为硬件中断和软件中断两大类。硬件中断来自于CPU外部的设备,如键盘、鼠标、定时器等;软件中断则由运行中的程序主动发起,如系统调用指令。

6.1.2 定时器中断的初始化设置

在51单片机中,定时器中断的初始化设置是通过设置特定的寄存器完成的。这些寄存器包括定时器模式寄存器(TMOD)、定时器控制寄存器(TCON)以及定时器数据寄存器(THx 和 TLx,其中x表示定时器编号)。初始化定时器中断的主要步骤如下:

  1. 设置定时器工作模式:通过TMOD寄存器来设置定时器的工作模式(例如模式0、模式1等),这决定了定时器的计数方式和启动方法。
  2. 装载定时器初值:将定时器的初值加载到THx 和 TLx 中。这个初值决定了中断的触发时间间隔。
  3. 开启定时器中断:通过设置TCON寄存器中的相应位来开启定时器中断。
  4. 全局中断使能:设置IE寄存器,使能全局中断。

以下是一个简单的代码示例,用于初始化定时器0为模式1,并开始计数:

void Timer0_Init() { TMOD &= 0xF0; // 清除定时器0模式位 TMOD |= 0x01; // 设置定时器0为模式1(16位定时器/计数器) TH0 = (65536 - 50000) / 256; // 装载定时器初值高字节 TL0 = (65536 - 50000) % 256; // 装载定时器初值低字节 ET0 = 1; // 开启定时器0中断 EA = 1; // 开启全局中断 TR0 = 1; // 启动定时器0}

在这个示例中,定时器被配置为每经过一定时间就产生一次中断,这个时间间隔取决于初值的设置以及单片机的时钟频率。

6.2 定时器中断在程序中的应用

6.2.1 中断服务程序的设计

当中断发生时,CPU会自动跳转到对应的中断服务程序(ISR)去执行。设计一个高效的中断服务程序是确保系统稳定运行的关键。以下是设计中断服务程序时需要考虑的几点:

  1. 保证ISR尽可能短小:由于中断可能会频繁发生,所以ISR中的代码应该尽量减少,避免影响主程序的执行。
  2. 使用标志位:在ISR中设置标志位或全局变量,用于通知主程序中断已经发生。
  3. 禁用中断嵌套:如果需要的话,可以在ISR中暂时禁用其他中断,以防止其他中断打断当前中断处理。
  4. 尽量避免使用延时:在ISR中应该避免使用可能导致阻塞的延时函数。

示例代码:

void Timer0_ISR() interrupt 1 { TH0 = (65536 - 50000) / 256; // 重新装载定时器初值高字节 TL0 = (65536 - 50000) % 256; // 重新装载定时器初值低字节 // 其他操作 // ...}

在这个中断服务程序中,定时器初值被重新装载以保持定时器的周期性中断。

6.2.2 中断优先级与中断嵌套

在多中断系统中,中断优先级决定了中断处理的顺序。在51单片机中,可以通过IP寄存器来设置中断源的优先级。中断嵌套指的是在处理一个中断的时候,如果发生了更高优先级的中断,则暂停当前中断处理,先处理更高优先级的中断。

下面是一个简单的例子,说明如何设置中断优先级:

IP = 0x10; // 设置定时器0中断为高优先级

如果同时发生了定时器0中断和外部中断0(假设外部中断0的默认优先级高于定时器0),CPU将会优先处理外部中断0。

在中断嵌套的情况下,我们需要保持中断服务程序的简洁性,并且要确保中断嵌套不会导致数据不一致或逻辑错误。可以通过合理地设计数据结构和访问逻辑来避免这些问题。

通过以上的内容,我们了解了定时器中断的初始化设置和在程序中的应用。定时器中断是单片机编程中非常重要的一个概念,它使得单片机能够定时执行任务,同时处理各种外部事件,是实现动态显示等高级功能的基础。在下一章节中,我们将深入探讨数据处理与显示序列转换相关的技术细节。

7. 数据处理与显示序列转换

在实现LED显示效果时,数据处理和显示序列转换是两个关键步骤,它们确保了所要显示的内容能够以正确的形式呈现。下面,我们将深入了解这两个方面的具体实现。

7.1 数据处理技术

7.1.1 数据编码与解码

在51单片机中处理LED显示时,我们需要将所要显示的字符、图像或者动画效果转换为单片机可以理解的二进制数据。这个转换过程涉及到数据的编码和解码技术。

编码过程通常涉及到字符集(如ASCII码)和图像数据的转换。例如,要显示字符\"A\",需要将其对应的ASCII码转换为LED矩阵的点阵数据。解码则是编码的逆过程,是将存储的点阵数据转换回字符或图像以显示。

// 以ASCII字符 \"A\" 为例进行编码uint8_t encode_char(char c) { // 假设我们有一个ASCII码到LED点阵的映射表 uint8_t encoded_data = ascii_to_led[c]; return encoded_data;}

7.1.2 数据存储与缓存策略

大量数据的处理和存储对于单片机这样的资源受限平台是一个挑战。合理地管理内存,采取适当的缓存策略对于提高性能和响应速度至关重要。

在LED显示应用中,可以采用静态内存分配或者动态内存管理,同时为了提高效率,我们可能会将频繁使用的数据存放在内部RAM中,而将不常变动的静态数据放在外部存储器中。

// 内部RAM缓存数据示例uint8_t cache[CACHE_SIZE]; // 缓存区域大小void cache_data(uint8_t* data, uint8_t length) { // 将数据复制到缓存中 for (int i = 0; i < length; i++) { cache[i] = data[i]; }}

7.2 显示序列的转换方法

7.2.1 字符到LED点阵的映射

为了在LED矩阵上显示字符,需要将字符的二进制数据映射到LED点阵。这个过程包括将字符编码对应的点阵模式转换成LED驱动信号。

一个字符的点阵显示通常需要一个8x8的LED矩阵(或其倍数),每行或每列代表一个位的值。例如,\'A\'的ASCII码为01000001,需要转换成对应的LED点阵模式。

// 以字符 \"A\" 映射到LED点阵为例uint8_t char_to_led_matrix(char c) { // 查找字符对应的LED点阵数据 uint8_t matrix[LED_MATRIX_SIZE]; // 假设这里有一个函数可以进行转换 ascii_to_led_matrix(c, matrix); return matrix;}

7.2.2 动画效果的生成与实现

动画效果通常是通过连续的图像帧序列实现的。为了在LED矩阵上显示动画,需要生成这些帧序列,并快速地循环播放。

首先,确定动画的帧数和播放速度。然后,根据动画的帧序列,计算出每个帧的点阵数据,并将它们存储在一个数组或者循环链表中,以便快速访问和显示。

// 动画帧序列示例uint8_t* animation_frames[MAX_FRAMES] = {frame1, frame2, frame3, ...};void animate(uint8_t* current_frame, uint8_t* next_frame) { // 在这里更新下一帧的数据,然后切换到下一帧 // 可以使用定时器中断来控制帧切换的时机}

动画的实现依赖于对显示序列的精确控制,包括帧的生成、帧的切换时机以及帧的持续时间。这些都需要借助定时器中断来实现精确的时间控制。

以上章节内容详细地介绍了数据处理和显示序列转换的基础知识和技术应用,通过实践示例加深了理解,并提供了一些用于提高效率和实现动态效果的策略。这些内容为创建更加丰富和动态的LED显示奠定了基础。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:本项目着重于帮助初学者理解和实现数字电路与嵌入式系统基础知识,通过编写程序控制51单片机来驱动8*8 LED矩阵实现动态显示。项目中将介绍如何使用定时器来控制扫描速度和刷新率,以及如何通过Protues软件进行仿真。学习内容包括I/O端口控制、定时器中断设置以及如何处理显示数据。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif