河北科技大学数电课设实验报告摇摇棒.docx
《河北科技大学数电课设实验报告摇摇棒.docx》由会员分享,可在线阅读,更多相关《河北科技大学数电课设实验报告摇摇棒.docx(14页珍藏版)》请在冰豆网上搜索。
河北科技大学数电课设实验报告摇摇棒
科技大学
课程设计报告
学生:
学号:
专业班级:
课程名称:
数字电子技术基础
学年学期:
2013—2014学年第2学期
指导教师:
高观望
2014年6月
一、作品说明
摇摇棒是如今流行的一种玩具,在各种聚会、节日中均见得到它的身影。
本设计也追随着摇摇棒的原理,利用人眼的视觉暂留特性,通过STC12单片机对16只高亮度LED发光二极管进行控制,配合手的左右摇晃就可呈现一幅完整的画面。
该摇摇棒具有如下功能:
1)显示“生日快乐”;
2)显示“o(∩_∩)o”微笑图案;
3)显示心形图案;
4)显示“LOVE”;
5)可以通过开关实现转换,轮流显示并循环。
二、系统总体设计
1、总体方案比较与论证
所谓的“摇摇棒”,其实就是一个循环的LED显示,利用人的视觉滞留产生静态显示的现象。
要实现这个目标,就要求延时部分做的比较小,所以采用石英晶体振荡器。
本作品本着制作方便、降低成本的原则,采用单片机控制。
由水银开关的闭合对单片机产生外部中断,继而对中断进行采集。
到达一定数量便进行图象的转换。
整个系统由单片机控制模块,开关及电源模块和输出显示模块三个部分构成。
系统框图如下:
输出显示LED
单片机
水银开关
2、主要部件原理
(1)单片机控制模块
用单片机想要控制LED显示只需要定时输出就可以,但每个人摇动的速度不一样,如何准确的并稳定的变换图案呢?
这就需要用到外部中断。
将水银开关的两个引脚一端接VCC,一端接GND,这样的话,当摇棒向一边运动时LED按照程序编辑好的规律显示,而向另一边运动时LED全灭,此时一个周期就会产生一个下降沿的信号,信号传递给单片机的INT0端口产生中断,然后对中断的数量计数,当计到10时便转换显示的图案,当依次显示完后便回到初始状态进行循环。
由于人的视觉滞留时间长达0.1s,所以在每显示完一列LED后应加入一段合适的延时,如5ms,每个字之间加入延时如15ms,这样,我们就能看到静态的稳定的字,并且每个字之间是有空隙的。
为了让字能够在空间的中部显示,在启动中断显示后延时一段合适的时间,使棒在半圆轨迹的大约1/4处开始显示,这样看到的字方向上才比较正。
(2)水银开关
水银开关,又称倾侧开关,是电路开关的一种,以一接着电极的小巧容器储存著一小滴水银,容器中多数注入惰性气体或真空
水银开关是由一个封闭的玻璃管,和两个分开着的导线和一段水银球组成。
当玻璃管的平衡位置变化时,水银球会来回移动,当水银球移动到两根导线时,因水银是金属-导体,故电路变为通路,此时接收器处于工作状态;反之,水银球远离两根导线时为断路,此时接收器处于非工作状态。
3、系统设计
本系统包括单片机控制模块,开关及电源模块和输出显示模块三个部分。
单片机控制模块由Keil4进行编写,显示程序用C语言编写,实现起来较简单。
主要有三部分构成,主程序、中断服务部分还有字符点阵。
开关及电源模块采用4.5伏(即3节1.5伏电池)电源并配合水银开关使用。
输出显示模块采用16个LED灯,在板上一字排开。
三、硬件设计
硬件连接上用水银开关产生的电平转换引发中断,传递给单片机,再由单片机调用点阵文件输出到LED上。
考虑到运算效率,我们采用STC12系列单片机,即51系列单片机的增强版。
实际验证后发现,STC12作为主控芯片显示效果更好。
摇摇棒设计电路图
STC12C5A32S2单片机作为控制器,在它的P0、P2口接有16只以共阳的方式连接的高亮度LED,由单片机输出低电平点亮。
P0口处接上拉电阻RA1。
串在LED公共端的二极管D1会产生一定的压降,用来保护LED。
K1是画面切换开关,用于切换显示不同容;S1为水银开关。
系统电源VCC为5V,实际使用时用3节干电池串联4.5V即可。
16只LED发光管作为画面每一列的显示,左右摇晃起到了扫描的作用,人眼的视觉暂留现象使得看到的是一幅完整的画面。
水银开关的作用:
棒在摇动时,只能在朝某一方向摇动时显示,否则会出现镜像字或镜像画面,所以通过接一只水银开关来控制,使摇摇棒从左向右摇动时将容显示出来。
四、软件设计
软件部分包括主函数程序、中断服务程序、延时子程序以及四个显示子程序。
软件设计流程如下:
五、系统调试与分析
主要测试单片机的工作情况,能否正常用LED显示出各图案,并且记录各图案持续的时间和稳定显示度以及一个循环周期所用的时间。
并且检查LED的发光亮度,使之可以明显的分辩出来。
图案
稳定程序
生日快乐
较稳定
心形
较稳定
笑脸
较稳定
LOVE
较稳定
经过测试,当摆动的幅度和速度适当时,各个画面均可以明显的显示出来。
整体来说,本方案设计比较成功。
六、课程作品制作体会
刚开始学习单片机知识的时候就听说过摇摇棒,也曾经在网上查过有关资料,但是一直没有机会把实物做出来。
所以趁着数电课设的机会,我们组决定制作摇摇棒项目。
首先,我们打算使用AltiumDesignerRelease10软件绘制出项目原理图和pcb版图,然后使用腐蚀液手工制版。
这样焊接出来的板子会很漂亮。
前期的工作都很顺利,PCB板也成功的画出来
但是腐蚀出来板子后才发现输出比例和实物比例不相符,最后经全组讨论后决定使用万用板焊接。
这次小挫折也告诉我们科学的严谨性,电子制作中的每一步都应该深思熟虑,不然前期的一个小失误就可能使整个项目功亏于溃。
硬件很快就按照电路图焊好了,我们吸取上次的教训,仔细认真地焊接,最终焊接完成后硬件测试一次性通过。
大大鼓舞了团队的士气。
接下来就是调试程序了。
中间还有一个小插曲,本来我们决定使用51系列的单片机,但经过测试后感觉不如12系列的效果好,所以最后选择了STC12C5A32S2。
(12系列单片机是51系列的升级版,不仅包含了51单片机的所有功能并在此基础上有所扩展,而且运算速度也比51单片机快。
)程序是使用keil4平台编写的C语言代码,在程序框架写好后,需要调试的就只剩下延时函数的时间参数。
通过一次又一次的调试,终于使图像显示居中并且大小合适。
完成并实现了项目的预期功能和效果。
调试期间的过程无疑是枯燥而单调的,但是看着自己的作品时刻朝着心中预期的方向改善,那种心情上的愉悦可以冲散身体的疲劳。
我想这正是我执着的热爱着电子制作的原因吧,同时这份感情上的慰藉会是鼓励我在这条路上走的更远的不竭动力。
附:
一、硬件电路图
二、源程序
#include
#defineucharunsignedchar
#defineuintunsignedint//宏定义
sbitKEY=P3^7;//定义画面切换按键
ucharKY;//KY作用在后面说明
uchardisp;//显示汉字指针
ucharpic=0,num=0;//pic为按键次数;num为中断次数
ucharcodelove[]={
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*/
};
ucharcodeloveyou[]={
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,/*心形图案*/
};
ucharcodehehe[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x01,0x40,0x01,0xC0,0x01,0x00,0x00,0x00,0x00,
0xF0,0x0F,0x08,0x10,0x04,0x20,0x00,0x00,0x00,0x00,0xF0,0x3F,0x08,0x00,0x04,0x00,
0x04,0x00,0x04,0x00,0x08,0x00,0xF0,0x3F,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x20,
0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x00,0x00,0x00,0xF0,0x3F,0x08,0x00,0x04,0x00,
0x04,0x00,0x04,0x00,0x08,0x00,0xF0,0x3F,0x00,0x00,0x00,0x00,0x04,0x20,0x08,0x10,
0xF0,0x0F,0x00,0x00,0x00,0x00,0xC0,0x01,0x40,0x01,0xC0,0x01,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*呵呵o(∩_∩)o图案*/
};
unsignedcharcodehanzi[]={
0x00,0x01,0x80,0x40,0x60,0x40,0x1E,0x41,
0x10,0x41,0x10,0x41,0x10,0x41,0x10,0x41,
0xFF,0x7F,0x12,0x41,0x10,0x41,0x10,0x41,
0x98,0x41,0x10,0x61,0x00,0x40,0x00,0x00,/*"生",0*/
0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x3F,
0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,
0x42,0x10,0x42,0x10,0x42,0x10,0xFE,0x3F,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"日",1*/
0x70,0x00,0x00,0x00,0xFF,0xFF,0x08,0x00,
0xB0,0x80,0x88,0x40,0x88,0x30,0x88,0x0E,
0xFF,0x01,0x88,0x06,0x88,0x08,0x88,0x30,
0xF8,0x60,0x80,0xC0,0x80,0x40,0x00,0x00,/*"快",2*/
0x00,0x00,0x00,0x20,0x40,0x18,0xFC,0x0C,
0x44,0x07,0x44,0x12,0x44,0x20,0x46,0x40,
0xFA,0x3F,0x42,0x00,0x43,0x00,0x43,0x02,
0x42,0x0C,0x40,0x38,0x00,0x10,0x00,0x00,/*"乐",3*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
/*****函数声明*****/
voiddisplay1_ltor(void);
voiddisplay2_ltor(void);
voiddisplay2_rtol(void);
voiddisplay3(void);
voiddisplay4(void);
/*****n(us)延时子程序*****/
voidDelayUs(uintN)
{
uintx;
for(x=0;x<=N;x++);
}
/*****中断服务程序*****/
voidintersvr0(void)interrupt0
{
;
KY=~KY;//每个摇动来回水银开关会在摆幅两端分别产生下降沿中断,只提取其中一次(从左向右摇才显示)
if(KY==0)
{
num++;//计算中断次数
switch(pic)//选择画面
{
case0:
{display1_ltor();}break;
case1:
{display2_ltor();}break;
case2:
{display3();}break;
case3:
{display4();}break;
default:
{display1_ltor();}
}
}
}
/*****显示子程序1(汉字)*****/
voiddisplay1_ltor(void)
{
uchari;
//if(num>10){disp++;num=0;}//12个汉字分为3次显示完(每次显示4个),每中断10次切换
//if(disp>2)disp=0;
DelayUs(4000);//此处延时时间依各硬件差别而各不相同,试着调整使得显示容居中即可
for(i=0;i<64;i++)
{
P0=~hanzi[disp*128+i*2];
P2=~hanzi[disp*128+i*2+1];
DelayUs(600);
}
}
/*****显示子程序2(LOVE)*****/
voiddisplay2_ltor(void)
{
uchari;
DelayUs(3500);
for(i=0;i<64;i++)
{
P0=~love[i*2];
P2=~love[i*2+1];
DelayUs(1200);
}
}
/*****显示子程序3(心形图案)*****/
voiddisplay3(void)
{
uchari;
DelayUs(4000);
for(i=0;i<64;i++)
{
P0=~loveyou[i*2];
P2=~loveyou[i*2+1];
DelayUs(1200);
}
}
/*****显示子程序4(呵呵o(∩_∩)o图案)*****/
voiddisplay4(void)
{
uchari;
DelayUs(3500);
for(i=0;i<64;i++)
{
P0=~hehe[i*2];
P2=~hehe[i*2+1];
DelayUs(1000);
}
}
/*****主函数*****/
voidmain(void)
{
IT0=1;
EX0=1;
EA=1;//开中断,下降沿中断
KY=0;
KEY=1;
while
(1)//主程序中只检测按键
{
if(KEY==0)//画面切换键按下
{
DelayUs(10000);//按键去抖
if(KEY==0)
{
pic++;
}
while(!
KEY);
}
if(pic>3)pic=0;
}
}
/*****END*****/