为了让大家更深入地了解底层的原理,在讲解时特意选择了51单片机(而非STM系列),另外16*16点阵由译码器和移位缓存器直接驱动(而非MAX系列芯片),摇杆也利用ADC功能判断方向。
那如何让单片机驱动这256个点呢?直接用IO口驱动显然不够且十分浪费。为了解决这个问题,我们要引入动态扫描的方法,它利用了人类的视觉暂留现象:如果让点阵的每一行分别轮流显示,当扫描速度足够高时,我们并不会看到一行一行地闪动,而是一幅完整的图像。
在驱动这个16*16点阵时,单片机会首先选中一行,然后将16位的数据输出以显示一行,在做短时间的停顿后接着再选择下一行输出,如此往复对这16行进行高速扫描就可以在点阵上看到要显示的图像。
先来讲解一下16*16点阵的原理。为了方便大家理解,我们先来看一下8*8点阵的电路图。它实际上由64个LED组成,每行共阴,每列共阳,当某行输出信号为低电平时,整一行LED阴极均为低电平,当在列上分别输入不同的电平信号时,交叉点的LED就会有不同的亮灭情况,以此不断循环扫描,就可以显示完整的图像。
8*8点阵的原理图
16*16点阵实质上为4个8*8点阵组合而成,对它的控制和8*8点阵也是大同小异,同样是分别扫描所有的行并输出列的数据,以此输出完整的16*16图像。
我们首先来考虑点阵行的控制,由于要节省单片机的引脚,我们使用74HC138译码器来控制不同的行,这里采用两个译码器分别对16行进行选择。
74HC138引脚图
VDD和GND分别为电源正负极,A0,A1,A2负责数据输入,Y0到Y7进行译码输出,E1,E2,E3为使能引脚,只有当E1和E2均为低电平,E3为高电平时,译码器才会正常输出,否则只会全部输出高电平。在使用时,只需要输入3位二进制加权地址,就能提供8个互斥的低有效输出。
74HC138架构图
由于2^3=8,那3位的二进制数据刚好能用于输出8位的互斥数据,我们正是借用这个特性来对点阵进行行扫描。根据译码器数据手册提供数据,我们可以得知使用3位二进制加权地址来输出8位的互斥信号的真值表。 74HC138真值表 | |||
由于译码器输出电流较低,必须借助三极管分别放大输出信号才能正常驱动LED。此处将译码器的输出接口分别连接到PNP三极管的基极,然后发射极连接点阵的行引脚,由于所有三极管的发射极均连接在VCC上,当输入低电平时,集电极就会输出高电平,否则就输出低电平,以此放大译码器的控制信号。
74HC138输出的原理图
两个74HC138的连接图对比
两个译码器的连接图稍有不同,对比一下可以发现它巧妙地利用了74HC138的使能特性,当G为高电平时,两个译码器均无输出,当G为低电平且D为低电平时,第一个译码器使能而第二个译码器关闭,反之第二个译码器使能而第一个译码器关闭;所以这里就可以直接使用A B C D对16行进行选择控制,G使能全部输出。
同样是为了节省IO口,我们使用了两个74HC595级联进行列输出,由于列输出内容是不确定的,所以我们要借助位移缓存器将串行数据转化为并行数据。
74HC595引脚图
这里VCC和GND分别为电源正负极,Q0到Q7为输出接口,DS为数据输入口,SHCP为数据输入时钟,STCP为输出存储器锁存时钟线,MR用于清零移位寄存器,OE为输出使能,Q7S可以连接到下一级位移缓存器的DS。
查阅数据手册可知,当SHCP产生一个上升沿的时候,移位寄存器读入DS上的电平信号,并且所有的数据都向后移动了一位。当数据输入完毕时,在STCP上发送一个上升沿可以让移位寄存器的数据锁存输出,由于有移位寄存器的存在,进行数据输入的时候可以有效避免“鬼影”问题。此处为了方便大家理解引入了IC的架构图。
74HC595架构图
在这个制作中我们不需要对移位缓存器进行单独操作,因此将OE接地,MR接VCC即可。把SHCP和STCP分别合并同时引出为CLK和LATCH输入线;第二个IC的DS接到第一个IC的级联输出端上,以实现多个74HC595的级联;再将第一个IC的DS端引出为DATA输入线,这样子我们用三根线就可以实现16位数据的串行输出。
两个74HC595的连接图
总结一下,这个16*16点阵需要两根电源线和八根数据线进行驱动,其中A B C D和G进行选择,DATA,CLK和LATCH串行输出16位的列显示数据。在选通一行后,74HC595输出该行数据,总共16行依次循环进行动态扫描,让16*16的点阵显示出来需要的文字或者图形。
接着,我们用摇杆来控制蛇的走向。摇杆的本质是X轴和Y轴的两个电位器,在摇杆运动的时候,通过读取两个电位器的输出电压就可以分别得到X轴和Y轴的坐标。由于得到是模拟数据,利用单片机的ADC功能来获取电压大小即可得到前后左右的运动数据。
目前国内大部分51单片机为STC的产品,因此我们选用了STC8单片机作为控制中心来驱动整个游戏。鉴于贪吃蛇程序在系统平台上编写过于简单,这里就不再赘述游戏逻辑的编程。下面的C语言代码用Keil编译后通过串口烧录进单片机即可。
头文件及常量定义
全局变量定义
定义八个数据线的引脚位置
全局初始化
向74HC595发送8bits的数据的函数
借助位运算进行行选
驱动整个点阵
对摇杆的扫描及响应
定时器中断
生成随机点
贪吃蛇的游戏逻辑
简易的main函数
以上就是整个贪吃蛇游戏的主要代码,分为从硬件上驱动IC和在软件上进行游戏的过程,虽然很简单但能让初学者了解51单片机对74系列IC的使用和ADC的读取,也能对单片机的编程加强认知。谢谢大家!
图文:林钜聪
排版:刘杨
审核:梁庆铧