一:基本原理与硬件电路设计:
16 只 LED 发光管作为画面每一列的显示,左右摇晃起到了扫描的作用,人眼的视觉暂留现象使得看到的是一幅完整的画面。与 LED 点阵的显示有几分相仿。
1. 系统电源 VCC 为 5V,下载程序和调试时一定要保证 5V 电压,实际使用时用 3 节干电池 串联4.5V 即可。
2. STC89C52RC 单片机作为控制器,在它的P0、P2 口接有 16 只以共阳的方式连接的高亮 度LED,由单片机输出低电平点亮。
3. P0 口的上拉电阻排不能少,最好是10K 的。上拉电阻可以提高单片机驱动能力。
4. 经实测 LED点亮时两端电压为 3V 左右,在 LED 的安全承受范围内。画面切换开关,用 于切换显示不同内容;
水银开关的作用:棒在摇动时,只能在朝某一方向摇动时显示,否则会出现镜像字或镜像画面, 所以通过接一只水银开关来控制,使摇摇棒从左向右摇动时将内容显示出来。
由于P0口内部无上拉电阻,所以P0口在用作输入输出时必须要接上拉电阻,一般为10K其他口可以不接上拉电阻 。
protel电路图:
STC89C52RC 实物引脚图:
注意:上电复位电路中的电解电容是 10uF,电阻为 10K,晶振电路中两个瓷片电容最好是:
22、30、33、47pF,晶振一般是 11.0592MHz
二:硬件制作:
使用的是直径 5mm 的红色高亮 LED,感觉太大了些,远看效果很好但近看时字不够连贯。建议 使用直径为 3mm 的高亮LED,颜色可根据个人喜好选择。
水银开关里的水银珠很活跃,导致在接通时容易产生抖动,所以将水银开关斜向上放置(尖尖 朝斜上方45°角),靠水银珠自身重力的作用减少抖动:
IC 座里面隐藏元件,既美观又能保护元件:
关于电源接法:电源用 3 节干电池串联成 4.5V,正极作为 VCC,负极作为GND!
三:关于开关按钮的接法:
轻触开关/微动开关:
按下去 连通 松开 又断开
相对的两个脚是连在一起的,即 1 和 2 连一起 3 和 4 连 一起,
连线时,只需将一端连到 1/2,另一端连到 3/4 即可
自锁开关:
可以中间对应的两个脚 接一端 , 左侧/右侧对应的两个脚 接另一端!
四:程序:
/**********************************************************
程序名称:LED摇摇棒显示64*16像素
简要说明:外部中断方式INT0显示;取模方式:纵向取模、字节倒序
(取点方式:纵向8点下高位,字节排列:上到下左到右)
**********************************************************/
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int //宏定义
sbit KEY=P3^3; //定义画面切换按键
uchar KY; //防止重影的控制变量
uchar pic=0; //pic为按切换键次数
uchar code love[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x3F,0x00,0x20,0x00,0x20,0x00,0x20,
0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x0F,
0x04,0x10,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x04,0x10,0xF8,0x0F,0x00,0x00,
0x00,0x00,0x00,0x00,0xFE,0x07,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x20,0x00,0x10,
0x00,0x08,0xFE,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x3F,0x82,0x20,0x82,0x20,
0x82,0x20,0x82,0x20,0x82,0x20,0x82,0x20,0x82,0x20,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00/*LOVE*/
};
uchar code loveyou[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x78,0x00,0xFC,0x00,0xFE,0x01,0xFE,0x03,0xFE,0x07,0xFE,0x0F,0xFE,0x1F,0xFC,0x3F,
0xF8,0x7F,0xFC,0x3F,0xFE,0x1F,0xFE,0x0F,0xFE,0x07,0xFE,0x03,0xFE,0x01,0xFC,0x00,
0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*心形图案*/
};
uchar code hanzi[] = {
/*生 CC9FA */
0x80,0x40,0xC0,0x40,0x70,0x42,0x3E,0x42,
0x1E,0x42,0x10,0x42,0x10,0x42,0xFF,0x7F,
0xFF,0x7F,0x10,0x42,0x10,0x42,0x10,0x42,
0x10,0x42,0x10,0x42,0x10,0x40,0x00,0x40,
/*日 CC8D5 */
0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,
0xFE,0xFF,0x82,0x40,0x82,0x40,0x82,0x40,
0x82,0x40,0x82,0x40,0x82,0x40,0xFE,0xFF,
0xFE,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
/*快 CBFEC */
0x00,0x01,0xE0,0x01,0x00,0x00,0xFF,0xFF,
0x10,0x00,0x30,0x81,0x28,0xC1,0x08,0x71,
0x08,0x3D,0xFF,0x0F,0xFF,0x0F,0x08,0x3D,
0xF8,0x71,0xF8,0xC1,0x00,0x81,0x00,0x81,
/*乐 CC0D6 */
0x00,0x00,0x00,0x20,0xE0,0x30,0xFC,0x18,
0x9C,0x0E,0x84,0x46,0x84,0x80,0xF4,0xFF,
0xF6,0x7F,0x82,0x00,0x83,0x02,0x83,0x06,
0x82,0x0C,0x80,0x38,0x80,0x30,0x00,0x00
};
/*函数声明*/
void display1(void);
void display2(void);
void display3(void);
void display4(void);
/*延时子程*/
void DelayUs(uint N)
{
uint x;
for(x=0; x<=N;x++);
}
/*中断服务程序*/
void intersvr0(void) interrupt 0 using 1
{
KY=~KY; //每个摇动来回水银开关会在摆幅两端分别产生下降沿中断,只提取其中一次(从左向右摇才显示)
//当从右向左摇时,产生中断,KY取反变为1,此时不显示,不运行下面的语句
if(KY==0)
{
switch(pic) //选择画面
{
case 0:{display1();}break;
case 1:{display2();}break;
case 2:{display3();}break;
default:{display1();}//其他情况
}
}
}
/*显示子程序1(汉字)*/
void display1(void)
{
uchar i,n;
DelayUs(4000); //此处延时时间依各硬件差别而各不相同,试着调整使得显示内容居中即可
for(n=0;n<4;n++) //每次显示一个字 留点间隔 再显示第二个, 总共显示四个字
{
for(i=0;i<16;i++)
{
P0=~hanzi[n*32+i*2];//LED灯是置0时亮,故这里要取反,下同
P2=~hanzi[n*32+i*2+1];
DelayUs(70);
}
}
}
/*显示子程序2(LOVE)*/
void display2(void)
{
uchar i;
DelayUs(4000);
for(i=0;i<64;i++)
{
P0=~love[i*2];
P2=~love[i*2+1];
DelayUs(70);
}
}
/*显示子程序3(心形图案)*/
void display3(void)
{
uchar i;
DelayUs(4000);
for(i=0;i<64;i++)
{
P0=~loveyou[i*2];
P2=~loveyou[i*2+1];
DelayUs(70);
}
}
/*主函数*/
void main(void)
{
IT0=1;
EX0=1;
EA=1; //开中断,下降沿中断
KY=0;
while(1) //主程序中只检测按键
{
if(KEY==0) //画面切换键按下
{
DelayUs(10000); //按键去抖
if(KEY==0)
pic++;
if(pic>2)pic=0;
}
}
}