单片机设计报告(共21页).doc
精选优质文档-倾情为你奉上51单片机课程设计报告学 院: 物理与信息工程 专业班级: B(电信111) 学 号: 姓 名: 指导教师: 王 莉 专心-专注-专业目 录1、 设计任务与要求-2(1) 概述-2(2) AT89C52介绍-2(3) 引脚功能说明-22、 总原理图及元器件清单-3(1) 总原理图-3(2) 元器件清单-33、 硬件模块分析-4(1)74LS245引脚结构及功能-4(2)LED显示模块-4(3)数码管显示模块-5(4)蜂鸣器模块-64、系统硬件结构图及程序流程图-7(1)系统硬件结构图-7(2)程序流程图-75、调试及结论-8(1)单元调试-8(2)整体调试-86、实验结果-8(1)数码管倒计时及流水灯-9(2)8个LED灯同步闪烁-9(3)数码管显示HELLO-10(4)播放音乐-107、心得体会-108、参考文献-129、附录:C源程序代码-121、设计任务与要求(1)概述 通过自选课题课程设计,将理论知识和实际操作结合起来,熟悉STC89C52的工作原理,运用所学知识,完成设计。本次课程设计选用比较常用的AT89C52单片机,显示模块分为三个:LED灯;数码管;蜂鸣器。利用定时器控制数码管倒计时的时间间隔和LED流水灯的时间间隔,以及蜂鸣器播放音乐时音律的调节,以实现数码管倒计时、LED闪烁、音乐播放的功能。使用uVision软件,利用汇编语言编写程序,并用Protues软件进行硬件仿真,掌握这两款软件的基本使用方法,熟悉掌握汇编语言的编写,提高动手和思维能力。(2)AT89C52介绍·与MCS-51 产品指令和引脚完全兼容 ·8K字节可重擦写flash闪速存储器 ·1000次擦写周期·数据保留时间:10年·全静态工作:0Hz-24MHz·三级程序存储器锁定·256*8位内部RAM·32可编程I/O线·3个16位定时器/计数器·8个中断源 ·可编程串行UART通道·低功耗的闲置和掉电模式(3)引脚功能说明(1).电源引脚 Vcc(40脚):典型值5V。 Vss(20脚):接低电平。(2).外部晶振 X1、X2分别与晶体两端相连接。当采用外部时钟信号时,X2接振荡信号,X1接地。(3).输入输出口引脚: P0口:I/O双向口。作输入口时,应先软件置“ 1”。 P1口:I/O双向口。作输入口时,应先软件置“ 1”。 P2口:I/O双向口。作输入口时,应先软件置“ 1”。 P3口:I/O双向口。作输入口时,应先软件置“ 1”。(4).控制引脚: RST/Vpd、ALE/-PROG、-PSEN、-EA/Vpp组成了MSC-51的控制总线。 RST/Vpd(9脚):复位信号输入端(高电平有效)。 第二功能:加+5V备用电源,可以实现掉电保护RAM信息不丢失。ALE/-PROG(30脚):地址锁存信号输出端。 第二功能:编程脉冲输入。-PSEN(29脚):外部程序存储器读选通信号。-EA/Vpp(31脚):外部程序存储器使能端。 第二功能:编程电压输入端(+21V)。2、总原理图及元器件清单(1)基于Proteus 7.8的总原理图(2)元器件清单(1) 控制部分:AT29C52单片机1个,弹跳式开关1个。(2) 显示部分:8个发光二极管(LED灯),1个6位七段数码管。(3) 声音部分:蜂鸣器1个。(4) 收发器:74LS245芯片1个。3、硬件模块分析(1)74LS245引脚结构及功能 74LS245是我们常用的芯片,用来驱动led或者其他的设备,用法很简单如上图,这里简单的给出一些资料,他是8路同相三态双向总线收发器,可双向传输数据。 74LS245还具有双向三态功能,既可以输出,也可以输入数据。 当8051单片机的P0口总线负载达到或超过P0最大负载能力时,必须接入74LS245等总线驱动器。 当片选端/CE低电平有效时,DIR=“0”,信号由 B 向 A 传输;(接收) *DIR=“1”,信号由 A 向 B 传输;(发送)当/CE为高电平时,A、B均为高阻态。(2)LED显示模块(实现闪烁功能) 图(1)发光二极管实物图 图(2)发光二极管原理图 LED显示模块包括控制参数调整显示模块和交叉口倒计时显示模块两部分,此两部分的8位LED均采用动态显示方式,采用共阳极连接方式,将所有二极管的阳极端连在一起,阴极接到P0口,通过AT89C52对各个LED进行控制从而实现对LED的定时选通。(3)数码管显示模块(实现倒计时功能) 图(1)引脚图 图(2)六位7段数码管实物图 这类数码管可以分为共阳极与共阴极两种,共阳极就是把所有LED的阳极连接到共同接点com,而每个LED的阴极分别为a、b、c、d、e、f、g及dp(小数点);共阴极则是把所有LED的阴极连接到共同接点com,而每个LED的阳极分别为a、b、c、d、e、f、g及dp(小数点),如下图所示。图中的8个LED分别与上面那个图中的ADP各段相对应,通过控制各个LED的亮灭来显示数字。(4)蜂鸣器模块(实现播放音乐功能) 蜂鸣器发声原理是电流通过电磁线圈,使电磁线圈产生磁场来驱动振动膜发声的,因此需要一定的电流才能驱动它,单片机IO引脚输出的电流较小,单片机输出的TTL电平基本上驱动不了蜂鸣器,因此需要增加一个电流放大的电路。常见的一种了解方式如右图。 本设计通过已编好的C语言源程序控制AT89C52单片机来驱动蜂鸣器,C程序中包含的音乐代码,能让蜂鸣器播放出音乐生日快乐歌。4、 系统硬件结构图和程序流程图(1)系统硬件结构图(2)程序流程图5、调试及结论(1)单元调试a 显示模块的测试:显示模块包括LED显示和数码管计数器的显示。 刚开始将显示模块的程序编译后进行仿真,开始仿真时数码管显示英文的同时,8个LED没有同步闪烁。分析程序后,经检查发现时间参数设置错误,导致二者没能同步显示。经过修改程序并再次编译运行、仿真,发现数码管和LED灯都按程序预定规则正常显示。 开始的时候,使用的是AT89C51单片机,由于本次课程设计中数码管倒计时、LED流水灯和音乐播放程序都需要用到定时器,而AT89C51只有两个定时器可同时使用,难以满足设计要求。经过小组讨论,我们决定使用AT89C52代替AT89C51,以满足定时要求。数码管显示模块:当8位LED同步闪烁三次后熄灭的同时,6位七段数码管显示出英文单词“HELLO”。但是开始的时候最后一位数码管并不是空白,而是有杂乱的显示。经分析后,我们将最后一位接入低电平,使之固定为完全不显示,再次编译运行并仿真,得到预期的“HELLO”英文字幕显示。调试成功。b 声音模块的测试:声音模块由蜂鸣器组成,将开关按下后,蜂鸣器会播放生日快乐歌。刚开始的时候,音乐虽然可以正常播放,但是声音有点嘈杂,分析之后,我们在单片机上加了一个晶体振荡器,然后重新仿真,这次播放出来的音乐相比之前而言就清晰了很多。(2)整体调试 课程设计的整体测试是希望得到实现要求的功能,将总体设计程序进行编译运行,生成.hex文件后,加载到硬件仿真系统,开始仿真,单片机的运行不仅可以按显示模块的程序正常运行,也可以通过按键控制音乐播放,声音模块和按键模块同样可行。通过几个循环并无发现错误,由此我们便可以得出,编出来的程序符合我们的设计要求。6、实验结果(1)数码管倒计时+流水灯(2)倒计时完成后,8个LED灯同步闪烁:(3)闪烁完成后,所有LED灯灭,同时数码管显示“HELLO”:(4)按下开关后,数码管熄灭,同时蜂鸣器播放音乐生日快乐歌。7、课程设计收获与总结这学期我们开了单片机的C语言程序设计与应用的课程,这也是第一次与“单片机”接触。说实话刚开始听到这个课程真是一头雾水。“单片机”是什么的?做什么用的?都不知道。学了单片机这门课程后我明白了:单片机是一块在集成电路芯片上集成了一台有一定规模的微型计算机。简称为单片微型计算机或单片机。片机的应用到处可见,应用领域广泛,主要应用在智能仪表、实时控制、通信、家电等方面。在单片机这门课中我们学C51,毕竟C51和我书上讲的C语言,有些类似,编程的思想可以说是相通的。而且C51还有更大的优点就是编写大程序时的优越性更不言而喻,当然在那时,我并没有想的那么深远,C51的特点,还是在后来的实践过程中,渐渐体会到了! 在学完了这门课之后,我们不考试,只做一个课程设计就行。我们这组共有三名成员,我们这一小组足足花了两个星期才将这个课程设计所有的工作完成,包过选题,画流程图,程序设计,仿真运行。当然这设计期间我们也遇到了很多的困难,比喻在设计流水灯这一模块,流水灯经常有一个不亮,而且不能和数码管同步,经过反复的调试和运行,我们发现是因为定时器0的时间初值没有算正确,重新计算初值后,这一问题就解决了。在数码管这一模块中,我们选择的是数码管的动态显示倒计时。但是最仿真初运行的 结果是变成了静态显示单个数字和我们预期的效果不一样,通过查看程序我们发现是因为我们延时的时间太长了,将延时的时间缩短就解决了这一问题。因为数码管动态动态驱动是将所有数码管的8个显示笔划"a,b,c,d,e,f,g,dp"的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,位选通由各自独立的I/O线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是那个数码管会显示出字形,取决于单片机对位选通COM端电路的控制,所以我们只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的的COM端,就使各个数码管轮流受控显示,这就是动态驱动。在轮流显示过程中,每位数码管的点亮时间为12ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感。 最后我们还用一个用开关来控制一首歌曲的播放,但是由于AT89C51芯片只有两个定时器,在前面的流水灯和数码管倒计时中你都用了。为了将这首歌曲能够添加进去,我们是想尽了各种办法,但是由于定时器不能共用,最后都失败了。实在是没有办法,我们就该用了AT89C52这个芯片,因为AT89C52芯片有三个定时器,刚好能够满足我们的要求。最后终于达到了我们的预期效果。在这次的单片机课程设计的中,我感受颇深,收获颇多。第一,必须要有学习单片机的热情,不是说今天去图书馆看了一个下午关于单片机的书,而明天玩上半天,后天就不知道那个本书在讲什么东西了。还是先说说我吧,我在从学校出来之前,正如上面所说的:我知道有种芯片叫单片机,但是具体长成什么样子,却一点也不知道!而我对单片机的痴迷更是常人所不能想象的地步,虽然有很多不懂,但是我还是坚持了下来,当时我就想过,为了单片机值不值得我这样去付出,不过我还是横下一条心,坚持看我的书和资料。 第二,既然我们想学好单片机,除了上课认真听讲之外,那就要多看下课本和资料书更重要的是还要多在仿真软件上面调试和运行一下,看一下仿真结果。因为理论联系实际才是最重要的。即使你每天捧着本书,把那本书翻烂,也永远学不会单片机的! 第三,想学单片机的必需工具-电脑PC。因为写程序,编译或者是仿真都是通过PC完成的。如果没有PC,什么也做不了!有了PC最好还要可以上网,因为如果你没有可以和你交流单片机的人,遇到自己解决不了的问题,一直都想不通,那么估计你学习单片机的热情就会随着时间的推移而慢慢耗尽。如果你能上网通过论坛或者QQ群,问题就很快得到解决。这样的学习效率一定很高!真正的高手是从论坛中泡出来的!总之,在本次课程设计中我感觉我学到的东西比一个学期学的东西还多,软件绘图技巧在平常的学习中是学不到,我希望以后能够有更多的这种上机的机会,这两个月感觉过的很充实,我也真正的融入到了学习当中去,别无他思,一切都还不错,而且在绘图时耐心和细心是必不可少的,感觉非常好!我达到了我自己的预期目标和要求,受益匪浅!同时我也感觉到了一个团队,一个小组,必须要有团队精神,必须要有团结协作的能力,不然就是一盘散沙。只有大家团结协作,目标一致,共同努力,才能够高效率的解决做课程设计时所遇到的困难,才能在最短的时间里完成老师布置的任务。因为成功的团队没有失败的个人,失败的个人没有成功的团队,因为重要的不是我,重要的是我们8、参考文献(1)单片机的C语言程序设计与应用基于Proteus仿真(第2版),姜志海、赵艳雷、陈松(编著),电子工业出版社。(2)单片微型计算机原理及应用,张毅坤(编著),西安电子科技大学出版社 1998 。(3)微型计算机原理与接口技术(第4版),周荷琴、吴秀清(编著),中国科学技术大学出版社。(4)单片机C语言程序设计,侯殿有(编著),人民邮电出版社 2010 。9、附录:C源程序代码#include<reg52.h> /52单片机头文件#include <intrins.h> /包含有左右循环移位子函数的库#define uint unsigned int /宏定义#define uchar unsigned char /宏定义/sbit dula=P26;/sbit wela=P27;sbit speaker=P27;uchar code table= /显示数据编码0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x76,0x79,0x38,0x3f,0x00;uchar temp,t0,t1,bai,shi,ge,flag,flag1,flag3; unsigned char k,i;uint shu;void init(); /函数声明void display(uchar aa,uchar bb,uchar cc,uchar bai,uchar shi,uchar ge);void delay(uint z) /延时子函数uint x,y;for(x=z;x>0;x-)for(y=110;y>0;y-); unsigned char timer2h,timer2l,time; /生日歌code unsigned char sszymmh=5,1,1, 5,1,1, 6,1,2, 5,1,2, 1,2,2, 7,1,4, 5,1,1, 5,1,1, 6,1,2, 5,1,2, 2,2,2, 1,2,4, 5,1,1, 5,1,1, 5,2,2, 3,2,2, 1,2,2, 7,1,2, 6,1,2, 4,2,1, 4,2,1, 3,2,2, 1,2,2, 2,2,2, 1,2,4; / 音阶频率表 高八位code unsigned char FREQH= 0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8, 0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,0xFC, /1,2,3,4,5,6,7,8,i 0xFC,0xFD,0xFD,0xFD,0xFD,0xFE, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF, ; / 音阶频率表 低八位code unsigned char FREQL= 0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6, 0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,0x8F, /1,2,3,4,5,6,7,8,i 0xEE,0x44, 0x6B,0xB4,0xF4,0x2D, 0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16, ;void delay2(unsigned char t) unsigned char t7; unsigned long t2; for(t7=0;t7<t;t7+) for(t2=0;t2<8000;t2+) ; TR2=0; void t0int() interrupt 5 TF2=0; TR2=0; speaker=!speaker; TH2=timer2h; TL2=timer2l; TR2=1; void song() TH2=timer2h; TL2=timer2l; TR2=1; delay2(time); / unsigned char k,i; /T2CON=0x00; /置CT0定时工作方式1 /EA=1; /ET2=1;/IE=0x82 /CPU开中断,CT0开中断 /* T2CON = 0x00; RCAP2H = (uint8)(65536UL - SYS_MCLK/1000) >> 8); RCAP2L = (uint8)(65536UL - SYS_MCLK/1000); TH2 = (uint8)(65536UL - SYS_MCLK/1000) >> 8); TL2 = (uint8)(65536UL - SYS_MCLK/1000); ET2 = 1; TR2 = 1; */void main() /主函数init();while(1)if(flag1!=1) /如果flagi不再等于1则显示数据display(7,6,5,bai,shi,ge);elsedisplay(16,17,18,18,19,20);if(flag3) i=0; while(i<75) /音乐数组长度 ,唱完从头再来 k=sszymmhi+7*sszymmhi+1-1; timer2h=FREQHk; timer2l=FREQLk; time=sszymmhi+2; i=i+3; song(); flag3=0; /否则显示hellovoid init() /初始化函数shu=432;temp=0xfe;P1=temp;TMOD=0x11;TH0=(65536-50000)/256; /定时器初始化TL0=(65536-50000)%256;TH1=(65536-50000)/256;TL1=(65536-50000)%256;EA=1;ET0=1;ET1=1;TR0=1;TR1=1;T2CON=0x00;ET2=1; TR2=1;EX0=1;IT0=1;void timer0() interrupt 1 /定时器0中断TH0=(65536-50000)/256;TL0=(65536-50000)%256;t0+;if(flag!=1) /flag不等于1时进行流水灯if(t0=10)t0=1;temp=_crol_(temp,1);P1=temp;else /否则进行灯闪烁if(t0%4=0) /小灯每200毫秒变化一次P1=P1;/if(t0=60)if(t0=25)TR0=0; /3秒后关闭定时器0,关闭灯,并置flag=1P1=0xff;flag1=1;void timer1() interrupt 3 /定时器1中断函数TH1=(65536-50000)/256;TL1=(65536-50000)%256;t1+;if(t1=2)t1=0;shu-;bai=shu/100;shi=shu%100/10;ge=shu%10;if(shu=398) /当到398时把原来T0中的数清除,重新加裁初值让小灯闪烁TR0=0;TH0=(65536-50000)/256;TL0=(65536-50000)%256;TR0=1;flag=1;t0=0;P1=0xff;TR1=0;void display(uchar aa,uchar bb,uchar cc,uchar bai,uchar shi,uchar ge) /显示子函数 uchar bitcode;bitcode=0xfe; P0=tableaa;P2=bitcode;delay(10) ;P2=0xff;bitcode=bitcode<<1;bitcode=bitcode|0x01;P0=tablebb;P2=bitcode;delay(10) ;P2=0xff;bitcode=bitcode<<1;bitcode=bitcode|0x01;P0=tablecc;P2=bitcode;delay(10) ;P2=0xff;bitcode=bitcode<<1;bitcode=bitcode|0x01;P0=tablebai;P2=bitcode;delay(10) ;P2=0xff;bitcode=bitcode<<1;bitcode=bitcode|0x01; P0=tableshi;P2=bitcode;delay(10) ;P2=0xff;bitcode=bitcode<<1;bitcode=bitcode|0x01;P0=tablege;P2=bitcode;delay(10) ;P2=0xff;bitcode=bitcode<<1;bitcode=bitcode|0x01; void TOISR(void) interrupt 0 flag3=1;