《手把手陪您学Python》51——数组的生成方法2

在上一篇《手把手陪您学Python》50——数组的dtype属性中,我们学习了数组的数据类型及其转换方法。

今天,我们将会利用之前学习的数组属性的相关知识,学习其他生成数组的方式。

1、reshape

array和arange是我们在《手把手陪您学Python》48——数组的生成方法1中学习的数组的生成方法。

虽然这两种方法都可以将指定序列转换为数组,但在转换的过程中,array是根据列表的长度以及嵌套层级来生成某一形状的数组,arange又只能生成一维的数组。

如果我们想根据需要,生成指定形状的数组应该怎么办呢?

非常遗憾的是,array和arange方法并没有生成指定形状的参数,所以不能使用这两种方法直接生成我们需要的形状的数组。而需要通过其他的方法,将array和arange生成的数组转换成我们需要的形状,这就是reshape方法。

reshape是将原数组转换为指定形状数组的常用方法,就是在保持原数组元素个数也就是size不变的情况下,将其转换为新的形状,间接实现生成指定形状数组的目的。

reshape的参数为要转换成的目标数组的shape属性,也就是元组,同时可以将元组的括号省略。

reshape作为一种形状转换的方法,既可以在生成数组的同时进行形状转换,也可以直接对某一数组变量进行转换。

In [1]: import numpy as np

In [2]: arr1 = np.array([1, 2, 3, 4, 5, 6, 7, 8]).reshape((2, 4))   # 一维数组转换成二维数组,参数包括元组的括号
        arr1
Out[2]: array([[1, 2, 3, 4],
               [5, 6, 7, 8]])
       
In [3]: arr2 = np.array([1, 2, 3, 4, 5, 6, 7, 8]).reshape(8,)   # 一维数组转换成一维数组,参数省略元组的括号
        arr2
Out[3]: array([1, 2, 3, 4, 5, 6, 7, 8])

In [4]: arr3 = np.array([1, 2, 3, 4, 5, 6, 7, 8]).reshape(1, 8)   # 注意:结果和arr2不同
        arr3
Out[4]: array([[1, 2, 3, 4, 5, 6, 7, 8]])

In [5]: arr4 = np.array([1, 2, 3, 4, 5, 6, 7, 8])   # 也可以先定义数组再进行转换
        arr4.reshape(2, 2, 2)   # 一维数组转换成三维数组
Out[5]: array([[[1, 2],
                [3, 4]],
        
               [[5, 6],
                [7, 8]]])
        
In [6]: arr5 = np.arange(16).reshape(2,8)   # 一维数组转换成二维数组
        arr5
Out[6]: array([[ 0,  1,  2,  3,  4,  5,  6,  7],
               [ 8,  9, 10, 11, 12, 13, 14, 15]])
       
In [7]: arr6 = np.arange(16).reshape(4, 2, 2)   # 一维数组转换成三维数组
        arr6
Out[7]: array([[[ 0,  1],
                [ 2,  3]],
        
               [[ 4,  5],
                [ 6,  7]],
        
               [[ 8,  9],
                [10, 11]],
        
               [[12, 13],
                [14, 15]]])
        
In [8]: arr7 = np.arange(16).reshape(2,2,2,2)   # 一维数组转换成四维数组
        arr7
Out[8]: array([[[[ 0,  1],
                 [ 2,  3]],
        
                [[ 4,  5],
                 [ 6,  7]]],
        
        
               [[[ 8,  9],
                 [10, 11]],
        
                [[12, 13],
                 [14, 15]]]])
         
In [9]: arr8 = np.array([[0,  1,  2,  3,  4,  5,  6,  7], [8,  9, 10, 11, 12, 13, 14, 15]]).reshape(2, 2, 2, 2)    # 二维数组转换为四维数组
        arr8
Out[9]: array([[[[ 0,  1],
                 [ 2,  3]],
        
                [[ 4,  5],
                 [ 6,  7]]],
        
        
               [[[ 8,  9],
                 [10, 11]],
        
                [[12, 13],
                 [14, 15]]]])

2、生成随机数组

在NumPy中,可以使用random模块生成多种数字类型和统计分布的随机数组。

a、random.randn

《手把手陪您学Python》47——ndarray中,我们曾经利用np.random.randn生成过随机数组用于演示。

其实更确切地说,np.random.randn生成的是指定形状和元素个数的、服从标准正态分布(以0为均数、以1为标准差)的随机数组,其参数是我们指定数组的shape属性的元组。

In [10]: arr9 = np.random.randn(8)   # 生成一维标准正态分布随机数组
         arr9
Out[10]: array([-1.30988877, -0.34601258,  0.62283548, -0.44224255,  0.59793644,
                -0.47838029,  1.3035945 ,  0.14103263])
                
In [11]: arr10 = np.random.randn(2, 4)   # 生成二维标准正态分布随机数组
         arr10
Out[11]: array([[ 0.55654086,  0.85237979, -0.30700582,  0.48221887],
                [ 0.55188505,  0.32153161,  1.58344657, -0.65548478]])

In [12]: arr11 = np.random.randn(2, 4, 3)   # 生成三维标准正态分布随机数组
         arr11
Out[12]: array([[[ 1.38638958, -0.53405764,  0.37561582],
                 [ 2.61848236, -1.85721341, -1.77189997],
                 [ 1.4103478 , -0.26590613, -1.29052235],
                 [-0.73189418, -1.55958112,  0.06913844]],
        
                [[-0.20066016, -0.20109712,  0.82133339],
                 [ 0.47940501,  0.91032056,  0.95559913],
                 [-2.61454007, -1.17736678, -0.1120787 ],
                 [-1.36175475,  0.33004381, -0.656985  ]]])

​​​​​​b、random.rand

np.random.rand用于生成指定形状和元素个数的、服从“0~1”均匀分布的随机样本值。随机样本的取值范围是[0,1),但不包括1。其参数是我们指定数组的shape属性的元组。

In [13]: arr12 = np.random.rand(1, 8)   # 生成二维均匀分布随机数组
         arr12
Out[13]: array([[0.3652795 , 0.76874897, 0.10350589, 0.69743489, 0.36096167,
                 0.6949363 , 0.52513233, 0.36615817]])

c、random.randint

np.random.randint用于生成指定范围和个数的一维随机整数数组,其格式和参数为:

numpy.random.randint(low, high=None, size=None)

其中,low和high为位置参数,不需要写参数名称,size为关键字参数,必须要写参数名称。

当low和high都写时,随机整数的取值范围为[low, high),包括low但不包括high。

当low和high只写一个时,默认为low,取值范围为[0, low),包括0但不包括low。

当size省略时,默认size=1。

由于random.randint没有形状参数,所以要生成我们指定形状的数组时,需要使用reshape方法。

In [14]: arr13 = np.random.randint(10, 20, size = 5)
         arr13
Out[14]: array([18, 18, 16, 19, 10])

In [15]: arr14 = np.random.randint(10, size = 5)
         arr14
Out[15]: array([1, 9, 5, 8, 2])

In [16]: arr15 = np.random.randint(10, 20)
         arr15
Out[16]: 14

In [17]: arr16 = np.random.randint(10)
         arr16
Out[17]: 5

In [18]: arr17 = np.random.randint(20, size = 8).reshape(2, 2, 2)
         arr17
Out[18]: array([[[ 5, 11],
                 [ 9, 15]],
         
                [[ 4, 14],
                 [13,  2]]])

以上是三种较为常用的生成随机数组的方法。在NumPy的random模块中,还有其他可以用于生成随机数组的方法,大家可以根据需要进行了解和使用。

3、生成特殊数组

所谓的特殊数组,是指指定形状,并且均由0、1或者空值组成的数组,让我们分别来看一下。

a、ones

np.ones可以生成指定形状,并且全都由1组成的数组。

In [19]: arr18 = np.ones(8)   # 生成一维数组时,元组括号可以省略
         arr18
Out[19]: array([1., 1., 1., 1., 1., 1., 1., 1.])

In [20]: arr19 = np.ones((2, 3 , 4))   # 生成多维数组时,元组括号不可以省略
         arr19
Out[20]: array([[[1., 1., 1., 1.],
                 [1., 1., 1., 1.],
                 [1., 1., 1., 1.]],
         
                [[1., 1., 1., 1.],
                 [1., 1., 1., 1.],
                 [1., 1., 1., 1.]]])

b、zeros

np.zeros可以生成指定形状,并且全都由0组成的数组。

In [21]: arr20 = np.zeros(8)
         arr20
Out[21]: array([0., 0., 0., 0., 0., 0., 0., 0.])

In [22]: arr21 = np.zeros((2, 3))
         arr21
Out[22]: array([[0., 0., 0.],
                [0., 0., 0.]])

c、empty

np.empty生成的是没有初始化的数值的数组。虽然返回的结果可能都是0(因为返回值不可能真的是空的),但是也有一定的可能返回的是没有初始化的垃圾数据,所以不能用np.empty生成全0数组。

In [23]: arr22 = np.empty((4, 2))
         arr22
Out[23]: array([[0., 0.],
                [0., 0.],
                [0., 0.],
                [0., 0.]])

d、eye

np.eye用于生成一个n×n的特征矩阵,也就是对角线的位置为1,其他位置为0的,长度和宽度都是n的数组,其参数就是n。

In [24]: arr23 = np.eye(5)
         arr23
Out[24]: array([[1., 0., 0., 0., 0.],
                [0., 1., 0., 0., 0.],
                [0., 0., 1., 0., 0.],
                [0., 0., 0., 1., 0.],
                [0., 0., 0., 0., 1.]])

以上就是另外几种生成数组的方法,结合我们在《手把手陪您学Python》48——数组的生成方法1中学习的数组生成的方法,基本上掌握了NumPy中常用的数组生成的方法。

接下来,我们将会学习几种常用的操作数组的方法,包括数组的变形、展开、翻转、拼接、拆分,以及对数组元素进行添加和删除等,敬请关注。

 

图片

 


感谢阅读本文!如有任何问题,欢迎留言,一起交流讨论^_^

要阅读《手把手陪您学Python》——NumPy系列文章的其他篇目,请关注公众号点击菜单选择,或点击下方链接直达。

《手把手陪您学Python》46——NumPy介绍

《手把手陪您学Python》47——ndarray

《手把手陪您学Python》48——数组的生成方法1

《手把手陪您学Python》49——数组的shape属性

《手把手陪您学Python》50——数组的dtype属性

 


 

《手把手陪您学Python》系列文章入门阶段的篇目已经全部完成。

为更加清晰地展示Python入门阶段的知识体系,整理了如下的鱼骨图,以方便大家查阅。

图片

如要阅读相应篇目的内容,请关注公众号点击菜单选择,或点击下方链接直达。

《手把手陪您学Python》1——为什么要学Python?

《手把手陪您学Python》2——Python的安装

《手把手陪您学Python》3——PyCharm的安装和配置

《手把手陪您学Python》4——Hello World!

《手把手陪您学Python》5——Jupyter Notebook

《手把手陪您学Python》6——字符串的标识

《手把手陪您学Python》7——字符串的索引

《手把手陪您学Python》8——字符串的切片

《手把手陪您学Python》9——字符串的运算

《手把手陪您学Python》10——字符串的函数

《手把手陪您学Python》11——字符串的格式化输出

《手把手陪您学Python》12——数字

《手把手陪您学Python》13——运算

《手把手陪您学Python》14——交互式输入

《手把手陪您学Python》15——判断语句if

《手把手陪您学Python》16——循环语句while

《手把手陪您学Python》17——循环的终止

《手把手陪您学Python》18——循环语句for

《手把手陪您学Python》19——第一阶段小结

《手把手陪您学Python》20——列表

《手把手陪您学Python》21——元组

《手把手陪您学Python》22——字典

《手把手陪您学Python》23——内置序列函数

《手把手陪您学Python》24——集合

《手把手陪您学Python》25——列表推导式

《手把手陪您学Python》26——自定义函数

《手把手陪您学Python》27——自定义函数的参数

《手把手陪您学Python》28——自定义函数的返回值

《手把手陪您学Python》29——匿名函数

《手把手陪您学Python》30——模块

《手把手陪您学Python》31——文件的打开

《手把手陪您学Python》32——文件的读取

《手把手陪您学Python》33——文件的关闭

《手把手陪您学Python》34——文件的写入

《手把手陪您学Python》35——数据的存储

《手把手陪您学Python》36——错误和异常处理

《手把手陪您学Python》37——程序的重构

《手把手陪您学Python》38——第二阶段小结

《手把手陪您学Python》39——面向对象

《手把手陪您学Python》40——类的定义、属性与实例化

《手把手陪您学Python》41——类的方法与实例方法

《手把手陪您学Python》42——类的魔法方法

《手把手陪您学Python》43——类的继承

《手把手陪您学Python》44——类的导入

《手把手陪您学Python》45——Python入门完结篇

For Fans:关注“亦说Python”公众号,回复“手51”,即可免费下载本篇文章所用示例语句。

亦说Python——Python爱好者的学习分享园地
<think>好的,我现在需要帮用户生成一个用点阵显示9到0倒计时牌的代码,参考的是宋雪松的《手把手教你51单片机——C语言版(第2版)》。首先,我得理清楚这个任务的关键点。 首先,点阵显示通常用的是8x8的LED点阵,或者可能用更大的,比如16x16?不过常见的例子可能用8x8。用户可能用的是8x8,因为教材里可能以这个为例。接下来,倒计时从9到0,每个数字需要对应的点阵数据。所以第一步是确认每个数字的显示编码,也就是字模数据。 然后,硬件连接方面,点阵的行和列需要连接到单片机的IO口。通常行是控制阳极,列是阴极,或者反过来,这取决于电路设计。可能需要用到锁存器如74HC595来扩展IO口,或者直接连接,具体得看教材里的示例。假设用户使用的是共阳型点阵,行接P0口,列由P2和P3控制,或者其他端口组合。需要确定具体的引脚连接,但如果没有具体信息,可能需要做一个通用的例子,或者参考教材里的典型接法。 接下来是代码结构。需要初始化定时器,用于动态扫描显示,因为点阵是逐行或逐列扫描的。动态扫描的原理是快速逐行显示,利用人眼的视觉暂留效果。所以定时器中断服务程序需要定期更新当前显示的行数据。 然后,每个数字对应的点阵数据需要定义成数组。比如数字0到9,每个数字8个字节,每个字节对应一行的LED状态。例如,0可能是一个环形,中间空的点阵排列。 倒计时的逻辑部分,主函数里需要控制倒计时的时间,比如每秒减一,从9到0。这里可能需要使用定时器来精确计时,或者用简单的延时函数。不过为了准确,定时器可能更合适。但考虑到代码复杂度,用户可能希望先看到基本实现,可能先用延时函数,后面再优化。 可能的步骤: 1. 定义数字0-9的点阵字模数组2. 配置定时器中断,用于动态刷新点阵显示。 3. 主函数中循环倒计时,每个数字显示1秒。 4. 中断服务函数中,逐行扫描显示当前数字的点阵数据。 需要检查点阵的扫描方向是否正确,比如行是从上到下还是下到上,列是高位在前还是低位,这会影响字模的定义是否正确。如果显示出现乱码,可能需要调整字模的顺序或扫描的方式。 此外,硬件连接可能涉及到行和列的驱动电路,比如使用上拉电阻或者晶体管来增强电流驱动能力,但代码中可能不需要处理这部分,只要正确设置IO口的高低电平即可。 现在,编写具体的代码: 首先,定义字模数据。例如,假设8x8点阵,每个数字8字节,每个字节代表一列(或一行,需要确认扫描方式)。比如数字0的字模可能是0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C,但需要确认实际排列是否正确。或者可能是行扫描,每个字节对应一行,比如第一行是0b00111100(0x3C)等。这需要根据点阵的实际连接方式确定。 假设点阵的行由P0口控制,列由P2和P3控制,共16列?不,8x8的话应该只有8行和8列。可能行用P0,列用P2或其他端口。例如,行接P0口,列接P1口,或者反过来。这可能需要查阅教材中的示例电路。比如教材中可能用P0控制列,P2控制行?或者相反。 例如,假设行选择(阳极)由P2的低8位控制,列数据(阴极)由P0口控制,共阳型。那么要显示某一行,需要将对应的行置高,然后P0输出该行的列数据取反(因为共阳的话,列是低电平点亮)。 或者,可能行列都是通过锁存器连接的,但如果没有锁存器的话,可能需要直接连接IO口。 这部分可能需要假设,比如行由P2口控制,列由P0口控制。假设行是选择哪一行,列是控制该行的哪些LED点亮。 例如,动态扫描时,依次选中每一行,输出该行对应的列数据。例如,第一行选中,P2=0x01,然后P0输出该行对应的数据,延时一段时间,然后切换到下一行。 但为了使用定时器中断,可以在中断中切换当前行,并输出对应的数据。 现在,开始编写代码结构: 1. 包含头文件,如reg52.h。 2. 定义数字的字模数组,如code unsigned char num[10][8]。 3. 声明变量:当前显示的数字(count),当前扫描的行(row)。 4. 初始化定时器,设置中断。 5. 主函数中循环倒计时,每秒减一。 6. 中断服务函数处理显示刷新。 但需要注意,点阵显示需要不断刷新,所以倒计时的延时不能使用普通的延时函数,否则会导致显示闪烁。应该利用定时器中断来管理时间,同时主函数中检测时间是否到达1秒。 可能的调整:使用定时器中断来刷新显示,同时另一个定时器或计数器来计算秒数。或者,在中断中累加计数,达到一定次数后认为1秒到了。 例如,假设定时器中断每1ms触发一次,用于刷新显示,同时每1000次中断(即1秒)后,减少倒计时的数字。 这样,代码的大致结构: - 定义字模数组。 - 全局变量:count(当前数字),row(当前行),timerCount(计时用)。 - 定时器初始化,1ms中断一次。 - 中断服务函数:刷新显示行,并累加timerCount,当达到1000时,count减一。 - 主函数初始化后,进入循环,等待count变化。 但需要注意变量在中断和主循环中的修改,可能需要使用volatile类型,并处理计数器的重置。 现在,具体代码: 首先,字模数组的定义。假设每个数字有8行,每行8位,例如: code unsigned char NumTab[10][8] = { // 0的字模 {0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C}, // 1的字模 {0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x08, 0x3E}, // ... 其他数字的字模需要正确填写 }; 但实际每个数字的字模可能需要根据点阵的排列来调整。例如,不同的扫描方向可能导致数据顺序不同。这里可能需要用户根据实际硬件调整字模,或者参考教材中的示例。 然后,硬件连接假设:行选择由P2口控制,列数据由P0口控制,共阳型。例如,行选择是P2.0到P2.7,每一行为高电平选中。列数据需要输出低电平来点亮LED。例如,当P2=0x01(选中第一行),P0输出对应的该行数据(如0x3C对应二进制00111100,即低电平的位会点亮)。 所以,在中断函数中,每次选中一行,输出对应的列数据,然后切换到下一行。 代码示例: #include <reg52.h> code unsigned char NumTab[10][8] = { // 0 {0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C}, // 1 {0x08, 0x0C, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C}, // 2 {0x3E, 0x42, 0x02, 0x0C, 0x30, 0x40, 0x40, 0x7E}, // 3 {0x3C, 0x42, 0x02, 0x1C, 0x02, 0x02, 0x42, 0x3C}, // 4 {0x04, 0x0C, 0x14, 0x24, 0x7E, 0x04, 0x04, 0x04}, // 5 {0x7E, 0x40, 0x40, 0x7C, 0x02, 0x02, 0x42, 0x3C}, // 6 {0x1C, 0x20, 0x40, 0x7C, 0x42, 0x42, 0x42, 0x3C}, // 7 {0x7E, 0x02, 0x04, 0x08, 0x10, 0x10, 0x10, 0x10}, // 8 {0x3C, 0x42, 0x42, 0x3C, 0x42, 0x42, 0x42, 0x3C}, // 9 {0x3C, 0x42, 0x42, 0x42, 0x3E, 0x02, 0x04, 0x38}, }; unsigned char count = 9; // 当前显示的数字 unsigned char row = 0; // 当前扫描的行 unsigned int timer = 0; // 计时用变量 void Timer0_Init(); void Display(unsigned char num); void main() { Timer0_Init(); EA = 1; // 开启总中断 while (1) { // 主循环中不需要其他操作,倒计时由定时器处理 } } void Timer0_ISR() interrupt 1 { TH0 = (65536 - 2000) / 256; // 2ms定时 TL0 = (65536 - 2000) % 256; Display(count); // 显示当前数字 timer++; if (timer >= 500) // 2ms * 500 = 1000ms { timer = 0; if (count > 0) { count--; } else { count = 9; // 循环倒计时 } } } void Display(unsigned char num) { // 显示指定数字 P2 = 0x01 << row; // 选中当前行 P0 = ~NumTab[num][row]; // 输出列数据(取反,因为共阳) row++; if (row >= 8) { row = 0; } } 这里可能存在的问题: 1. 字模数据是否正确。由于每个教材或点阵的排列可能不同,字模可能需要调整。例如,某些点阵的行列顺序可能相反,或者数据方向不同。 2. 定时器中断的时间设置。这里假设每2ms中断一次,每次中断显示一行,这样8行需要16ms刷新一次,刷新率约为60Hz,不会有闪烁。同时,计时到500次中断即1秒。 3. 共阳或共阴的配置是否正确。如果点阵是共阴型,那么P0的输出不需要取反,行选择也可能是低电平有效。这里假设为共阳,所以列输出低电平点亮,所以取反字模数据。 4. 硬件连接是否正确。例如,行选择由P2控制,列由P0控制,这可能需要根据实际电路调整。例如,如果列接P1口,则代码中的P0需要改为P15. 初始数字设置为9,倒计时到0后可能回到9,这里用户可能需要只进行一次倒计时,可以修改在count为0时停止,或者重新开始。 6. 另外,点阵的引脚可能需要驱动能力,比如P0口需要上拉电阻,因为P0口在51单片机是开漏输出,所以可能需要接上拉电阻才能输出高电平。或者代码中使用P2口作为行选择,而P0口作为列数据输出,并且有上拉电阻。 这些细节可能需要用户根据实际硬件调整。特别是字模数据和端口连接部分,可能需要用户根据教材中的示例电路修改。 总结:提供的代码是一个基于假设的示例,用户可能需要根据实际硬件调整端口定义和字模数据,并测试显示效果。</think>根据宋雪松教材内容,以下是基于8x8点阵的倒计时显示代码实现步骤及示例: ### 一、硬件连接假设 1. **点阵类型**:共阳型8x8 LED点阵 2. **行控制**:P2口(行选择,高电平有效) 3. **列控制**:P0口(列数据,低电平点亮) 4. **晶振频率**:11.0592MHz ### 二、代码实现 ```c #include <reg52.h> // 数字0-9的点阵字模(共阳型,列数据取反) code unsigned char NumTab[10][8] = { {0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C}, // 0 {0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x08, 0x3E}, // 1 {0x3E, 0x42, 0x02, 0x0C, 0x30, 0x40, 0x40, 0x7E}, // 2 {0x3C, 0x42, 0x02, 0x1C, 0x02, 0x42, 0x42, 0x3C}, // 3 {0x04, 0x0C, 0x14, 0x24, 0x7E, 0x04, 0x04, 0x04}, // 4 {0x7E, 0x40, 0x7C, 0x02, 0x02, 0x42, 0x42, 0x3C}, // 5 {0x3C, 0x42, 0x40, 0x7C, 0x42, 0x42, 0x42, 0x3C}, // 6 {0x7E, 0x02, 0x04, 0x08, 0x10, 0x10, 0x10, 0x10}, // 7 {0x3C, 0x42, 0x42, 0x3C, 0x42, 0x42, 0x42, 0x3C}, // 8 {0x3C, 0x42, 0x42, 0x3E, 0x02, 0x04, 0x08, 0x30} // 9 }; unsigned char count = 9; // 当前显示数字 unsigned char row = 0; // 当前扫描行 unsigned int timer = 0; // 计时变量 void Timer0_Init(); void Display(unsigned char num); void main() { Timer0_Init(); EA = 1; // 开启总中断 while (1) { // 主循环保持空转,逻辑由中断处理 } } // 定时器0初始化(2ms中断) void Timer0_Init() { TMOD = 0x01; TH0 = (65536 - 2000) >> 8; TL0 = (65536 - 2000) & 0xFF; TR0 = 1; ET0 = 1; } // 定时器0中断服务函数 void Timer0_ISR() interrupt 1 { TH0 = (65536 - 2000) >> 8; // 重新加载初值 TL0 = (65536 - 2000) & 0xFF; Display(count); // 显示当前数字 timer++; if (timer >= 500) { // 500*2ms=1s timer = 0; if (count > 0) count--; else count = 9; // 循环计数 } } // 点阵显示函数 void Display(unsigned char num) { P2 = 0x01 << row; // 行选通(P2.0~P2.7) P0 = ~NumTab[num][row]; // 列数据取反输出 row = (row + 1) % 8; // 行扫描循环 } ``` ### 三、代码说明 1. **字模数据** - 使用$8\times8$矩阵编码,每个数字对应8字节数据 - 共阳型点阵需对列数据取反(`~`操作符) 2. **定时器配置** - 定时器0每2ms中断一次,实现动态扫描 - 计算公式: $$T = \frac{12}{11.0592\text{MHz}} \times (65536 - N)$$ 设置$N=2000$实现约2ms定时 3. **动态扫描原理** - 每次中断刷新一行,8行扫描周期为$16\text{ms}$ - 扫描频率$f = \frac{1}{16\text{ms}} \approx 62.5\text{Hz}$,无闪烁 4. **倒计时逻辑** - 每500次中断(1秒)更新数字 - 倒计时到0后自动重置为9 ### 四、调试建议 1. **字模验证**:可通过Proteus仿真观察显示效果,调整编码 2. **硬件适配**:若使用共阴型点阵,需删除`P0=~`操作 3. **驱动增强**:P0口建议外接$1\text{k}\Omega$上拉电阻增强驱动能力 > 实际开发中请根据硬件电路调整行/列控制端口及字模数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值