高级单片机开发技术与应用_第1页
高级单片机开发技术与应用_第2页
高级单片机开发技术与应用_第3页
高级单片机开发技术与应用_第4页
高级单片机开发技术与应用_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、单片机课程设计报告系 部: 自动控制系 专 业: 工业电气自动化 班 级: 自044 姓 名: 张元元 学 号: 0431437 日 期 : 2006年12月16日河南机电高等专科学校封面一. 前言:二. 系统总体设计:三. 硬件设计:四. 软件设计:五. 总结与展望:高级单片机项目开发总结一前言:项目的意义:随着电子技术的迅速发展,特别是随着大规模集成电路的出现,给人类生活带来了根本性的改变。尤其是高级单片机开发技术的应用产品已经走进了千家万户。电子万年历的出现给人们的生活带来了诸多方便。该万年历具有时间定时,显示年月日星期的功能。开机后可以设置年月日星期及显示定时设置时间和闹钟是否开启,若

2、开启的话一旦时间到则发出一阵声响。本系统以单片机的C语言进行软件设计,高级单片机开发的万年历控制实现了对时间控制的智能化,摆脱了传统中由人来控制时间长短的不便,实现了在生活中必不可少的设备。万年历能控制闹铃启停的时间、能够循环显示家人的姓名、能够随意的调整时间且星期回随着日期的变化而变化。使用液晶显示器来显示现在的时间,显示格式为“年月日时分秒”,由LED闪动来作秒计数表示,具有4个按键来作功能设置,可以设增加了程序的可读性和可移植性,为了便于扩展和更改,软件的设计采用模块化结构,使程序设计的逻辑关系更加简洁明了。系统通过点阵式液晶为载体显示数据,所以具有人性化的操作和美观的页面效果。可以显示

3、时间、日期、星期和家人姓名,并有闹铃功能。 二系统总体设计:1.总体功能:多功能数字万年历可以显示时间、年、日期、星期和家人姓名,并有闹铃功能。2.主要软件设计:时钟是通过单片机的时间中断的应用,从而得到一定的时基,然后通过一定的循环得到一秒,最后得到了一分钟和一个小时,中间有运用了平、闰年的判断及星期自动处理程序,自动对年月日的转换。闹钟的开启也是通过另一个中断开启的,键盘的输入的同样是通过外部中断向程序输入一定量的数据的。3.主要硬件设计:系统应用一个单片机的最小系统,加上一些外围电路组成的,例如小键盘,蜂鸣器驱动电路,电源指示灯,还有一个重要的显示模块LCD液晶显示等等。 三硬件设计:1

4、. 最小系统:该最小系统的复位电路是上电复位,复位电路有一个10k的电阻,和一个10Uf的电解电容组成,晶振是11.0592m的,加上两个30pf的电容,最后CPU选择了AT89C51,它们在现实的应用生活比较普遍,并且价格低,应用环境也比较广,优点是很多的,它具有算术运算功能强,软件编程灵活,自由度大,可用软件编程实现各种算符合逻辑控制,并且由于其功耗低,体积小,技术成熟和成本低等优点,使其在各个领域应用广泛,所以选择这些阻件。2. 显示部分:显示部分我选择了LCD1602液晶,它具有相对成本低,如果用数码管的话成本要高点,它还具有轻薄短小,地耗电量,无辐射危险,平面直角显示以及影像不闪烁等

5、优势可视面积大,画面效果好,分辨率高,接线简单,抗干扰强等等的优点。这可是数码管所不可比拟的,从现在看来,它(液晶显示)可能成为以后主流的显示设备。因此选择了LCD1602液晶显示,对我们以后掌握其他元件有很大的帮助。下面就是对其的介绍:这里介绍的字符型液晶模块是一种用5x7点阵图形来显示字符的液晶显示器,根据显示的容量可以分为1行16个字、2行16个字、2行20个字等等,这里以常用的2行16个字的1602液晶模块来介绍它的编程方法。  1602采用标准的16脚接口,其中:第1脚:VSS为地电源,第2脚:VDD接5V正电源,第3脚:V0为液晶显示器对比度调整端,接正电源时对

6、比度最弱,接地使用时可以通过一电源时对比度最高,对比度过高时会产生“鬼影”,个10K的电位器调整对比度,第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。,第5脚:RW为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和RW共同为低电平时可以写入指令或者显示地址,当RS为低电平RW为高电平时可以读忙信号,当RS为高电平RW为低电平时可以写入数据。第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。第714脚:D0D7为8位双向数据线。第1516脚:空脚1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,如表

7、1所示,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,     1602液晶模块内部的控制器共有11条控制指令,如表2所示,    它的读写操作、屏幕和光标的操作都是通过指令编程来实现的。(说明:1为高电平、0为低电平) ,指令1:清显示,指令码01H,光标复位到地址00H位置,指令2:光标复位,光标返回到地址00H ,指令4:显示开关控制。 D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示 C:控制光标的开与关,高电平表示有光标,低电平表示无光标 B

8、:控制光标是否闪烁,高电平闪烁,低电平不闪烁 ,指令5:光标或显示移位 S/C:高电平时移动显示的文字,低电平时移动光标,指令6:功能设置命令 DL:高电平时为4位总线,低电平时为8位总线 N:低电平时为单行显示,高电平时双行显示 F: 低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符 (有些模块是 DL:高电平时为8位总线,低电平时为4位总线),指令7:字符发生器RAM地址设置 指令8:DDRAM地址设置 ,指令9:读忙信号和光标地址 BF:为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。 指令10:写数据,指令11:读数据。   

9、;  DM-162液晶显示模块可以和单片机AT89C51直接接口,电路如图1所示。 液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,表3是DM-162的内部显示地址.M-162的内部显示地址.    比如第二行第一个字符的地址是40H,那么是否直接写入40H就可以将光标定位在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位D7恒定为高电平1所以实际写入的数据应该是01000000B(40H)+1

10、0000000B(80H)=11000000B(C0H)3. 驱动部分:驱动电压我们应用了比较容易从电脑USB接口采集的5伏电压,其他部分没有什么驱动芯片。4. 独立式键盘:键盘使用,独立式键盘是指直接用I/O 口线加上几个上拉电阻构成的单个按键电路。它的配置灵活,软件结构简单。因此该万年历系统有结构简单,成本低,用广的优点。5. 原理图:四软件设计:#include <reg51.h>#include <intrins.h>unsigned char code dis_week="SUN,MON,TUE,WED,THU,FRI,SAT"unsign

11、ed char code para_month13=0,0,3,3,6,1,4,6,2,5,0,3,5; /星期月参变数unsigned char data dis_buf116; /lcd 上排显示缓冲区unsigned char data dis_buf216; /lcd 下排显示缓冲区unsigned char data year,month,date,week;/年、月、日、星期unsigned char data armhour,armmin,armsec;/闹钟时、分、秒unsigned char data hour,min,sec,sec100; /时、分、秒、百分之一秒unsi

12、gned char data flag,vkey,skey;/设置状态计数标志、按键先前值、按键当前值unsigned int s=0;bit alarm; /标识是否启用闹钟,1-启用,0-关闭sbit rs = P20; /LCD 数据/命令选择端(H/L)sbit rw = P21; /LCD 读/写选择端(H/L)sbit ep = P22; /LCD 使能控制sbit PRE = P11; /调整键(k3)sbit SET = P12; /调整键(k4)sbit SPK = P13;void delayms(unsigned char ms); /延时程序bit lcd_busy()

13、; /测试LCD 忙碌状态程序void lcd_wcmd(char cmd); /写入指令到LCD 程序void lcd_wdat(char dat); /写入数据到LCD 程序void lcd_pos(char pos); /LCD 数据指针位置程序void lcd_init(); /LCD 初始化设定程序void pro_timedate(); /时间日期处理程序void pro_display(); /显示处理程序void pro_key(); /按键处理程序void time_alarm(); /定时闹铃功能(闹钟)unsigned char scan_key(); /按键扫描程序un

14、signed char week_proc(); /星期自动计算与显示函数bit leap_year(); /判断是否为闰年void lcd_sef_chr(); /LCD 自定义字符程序void update_disbuf(unsigned char t1,unsigned char t2,unsigned char dis_h,unsigned char dis_m,unsigned char dis_s);/更新显示缓冲区函数/ 延时程序void delay(unsigned char ms) while(ms-) unsigned char i;for(i = 0; i< 250

15、; i+)_nop_(); /执行一条_nop_()指令为一个机器周期_nop_();_nop_();_nop_();/测试LCD 忙碌状态bit lcd_busy()bit result;rs = 0;rw = 1;ep = 1;_nop_();_nop_();_nop_();_nop_();result =(bit)(P0&0x80); /LCD 的D0-D7 中,D7=1 为忙碌,D7=0 为空闲ep = 0;return result;/写入指令到LCDvoid lcd_wcmd(char cmd)while(lcd_busy(); /当lcd_busy为1 时,再次检测LCD

16、忙碌状态,lcd-busy 为0 时,开始写指令rs = 0;rw = 0;ep = 0;_nop_();_nop_();P0 = cmd;_nop_();_nop_();_nop_();_nop_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep = 0;/写入数据到LCDvoid lcd_wdat(char dat)while(lcd_busy(); /当lcd_busy为1 时,再次检测LCD忙碌状态,lcd-busy 为0 时,开始写数据rs = 1;rw = 0;ep = 0;P0 = dat;_nop_();_nop_();_nop_();_n

17、op_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep = 0;/LCD 数据指针位置程序void lcd_pos(char pos)lcd_wcmd(pos|0x80); /数据指针=80+地址码(00H27H,40H67H)/设定二个自定义字符,(注意:LCD1602 中自定义字符的地址为0x00-0x07,即可定义8个字符)/这里我们设定把一个自定义字符放在0x00 位置(000),另一个放在0x01 位子(001)void lcd_sef_chr() /第一个自定义字符lcd_wcmd(0x40); /"01 000 000"

18、 第1 行地址(D7D6 为地址设定命令形式D5D4D3 为字符存放位置(0-7),D2D1D0 为字符行地址(0-7))lcd_wdat(0x1f); /"XXX 11111" 第1 行数据(D7D6D5为XXX,表示为任意数(一般用000),D4D3D2D1D0 为字符行数据(1-点亮,0-熄灭)lcd_wcmd(0x41); /"01 000 001" 第2行地址lcd_wdat(0x11); /"XXX 10001" 第2 行数据lcd_wcmd(0x42); /"01 000 010" 第3行地址lcd_

19、wdat(0x15); /"XXX 10101" 第3 行数据lcd_wcmd(0x43); /"01 000 011" 第4行地址lcd_wdat(0x11); /"XXX 10001" 第4 行数据lcd_wcmd(0x44); /"01 000 100" 第5行地址lcd_wdat(0x1f); /"XXX 11111" 第5 行数据lcd_wcmd(0x45); /"01 000 101" 第6行地址lcd_wdat(0x0a); /"XXX 01010&q

20、uot; 第6 行数据lcd_wcmd(0x46); /"01 000 110" 第7行地址lcd_wdat(0x1f); /"XXX 11111" 第7 行数据lcd_wcmd(0x47); /"01 000 111" 第8行地址lcd_wdat(0x00); /"XXX 00000" 第8 行数据/第二个自定义字符lcd_wcmd(0x48); /"01 001 000" 第1行地址lcd_wdat(0x01); /"XXX 00001" 第1 行数据lcd_wcmd(0

21、x49); /"01 001 001" 第2行地址lcd_wdat(0x1b); /"XXX 11011" 第2 行数据lcd_wcmd(0x4a); /"01 001 010" 第3行地址lcd_wdat(0x1d); /"XXX 11101" 第3 行数据lcd_wcmd(0x4b); /"01 001 011" 第4行地址lcd_wdat(0x19); /"XXX 11001" 第4 行数据lcd_wcmd(0x4c); /"01 001 100"

22、第5行地址lcd_wdat(0x1d); /"XXX 11101" 第5 行数据lcd_wcmd(0x4d); /"01 001 101" 第6行地址lcd_wdat(0x1b); /"XXX 11011" 第6 行数据lcd_wcmd(0x4e); /"01 001 110" 第7行地址lcd_wdat(0x01); /"XXX 00001" 第7 行数据lcd_wcmd(0x4f); /"01 001 111" 第8行地址lcd_wdat(0x00); /"XX

23、X 00000" 第8 行数据/LCD 初始化设定void lcd_init()lcd_wcmd(0x38); /设置LCD 为16X2 显示,5X7 点阵,八位数据借口delay(1);lcd_wcmd(0x0c); /LCD 开显示及光标设置(光标不闪烁,不显示"-")delay(1);lcd_wcmd(0x06); /LCD 显示光标移动设置(光标地址指针加1,整屏显示不移动)delay(1);lcd_wcmd(0x01); /清除LCD 的显示内容delay(1);/闰年的计算bit leap_year()bit leap;if(year%4=0&

24、&year%100!=0)|year%400=0)/闰年的条件leap=1;elseleap=0;return leap;/星期的自动运算和处理unsigned char week_proc() unsigned char num_leap;unsigned char c;num_leap=year/4-year/100+year/400;/自00 年起到year 所经历的闰年数if( leap_year()&& month<=2 ) /既是闰年且是1 月和2月c=5;elsec=6;week=(year+para_monthmonth+date+num_leap

25、+c)%7;/计算对应的星期return week;/更新显示缓冲区void update_disbuf(unsigned char t1,unsigned char t2,unsigned char dis_h,unsigned char dis_m,unsigned char dis_s) dis_buf10=t1; /dis_buf11=0x20; /空格dis_buf12=50; /'2'dis_buf13=48; /'0'dis_buf14=year/10+48;dis_buf15=year%10+48;dis_buf16=0x2d;dis_buf17

26、=month/10+48;dis_buf18=month%10+48;dis_buf19=0x2d; /'-'dis_buf110=date/10+48;dis_buf111=date%10+48;dis_buf112=0x20;dis_buf113=dis_week4*week;dis_buf114=dis_week4*week+1;dis_buf115=dis_week4*week+2;dis_buf20=t20;dis_buf21=t21;dis_buf22=t22;dis_buf23=t23;dis_buf24=t24;dis_buf25=t25;dis_buf26=0

27、x20; /空格if (alarm)dis_buf27=0x01; /alarm=1,显示闹钟启用标致(第二个自定义字符)elsedis_buf27=0x20; /alarm=0,不显示闹钟启用标致dis_buf28=dis_h/10+48;dis_buf29=dis_h%10+48;dis_buf210=0x3a; /':'dis_buf211=dis_m/10+48;dis_buf212=dis_m%10+48;dis_buf213=0x3a;dis_buf214=dis_s/10+48;dis_buf215=dis_s%10+48;/时间和日期处理程序void pro_t

28、imedate()sec+;if(sec > 59)sec = 0;min+;if(min>59)min=0;hour+;if(hour>23)hour=0;date+;if (month=1|month=3|month=5|month=7|month=8|month=10|month=12)if (date>31) date=1;month+; /大月31 天if (month=4|month=6|month=9|month=11)if (date>30) date=1;month+; /小月30 天if (month=2)if( leap_year() /闰年

29、的条件if (date>29) date=1;month+; /闰年2 月为29 天elseif (date>28) date=1;month+; /平年2 月为28 天if (month>12) month=1;year+;if (year>99) year=0;week_proc();if (sec=armsec && min=armmin && hour=armhour)if (alarm)TR1=1; /闹钟启用时,闹铃时间到,启动Timer1/显示处理程序void pro_display() unsigned char i;lc

30、d_pos(0x00);for (i=0;i<=15;i+)lcd_wdat(dis_buf1i);lcd_pos(0x40);for (i=0;i<=15;i+)lcd_wdat(dis_buf2i);/Timer0 中断处理程序,秒的产生void timer0() interrupt 1TH0=0xdc; /Timer0 置10ms 定时初值dc00H(216=65536D,dc00H=56320D)TL0=0x00; /定时时间=(65536-56320)*(1/11.0592)*12=10ms (f0=11.0592Mhz)sec100+;if(sec100 >= 1

31、00) /1 秒时间(100*10ms=1000ms=1s)sec100 = 0;switch(s)case 0: update_disbuf(0x00," pei ",hour,min,sec); break;/0x00 表示显示00 位置的自定义字符case 1: update_disbuf(0x00," lu ",hour,min,sec); break;case 2: update_disbuf(0x00," yuan ",hour,min,sec); break;default : break; s+; /每秒轮流显示我们的

32、姓名pro_timedate();/调用时间和日期处理程序if (s=3) s=0 ;pro_display(); /调用显示处理函数/按键扫描程序unsigned char scan_key()skey=0x00; /给变量vkey置初值skey|=PRE; /读取PRE 键的状态skey=skey<<1; /将PRE 键的状态存于skey 的B1 位skey|=SET; /读取SET 键的状态,并存于skey 的B0 位return skey; /返回skey的键值(即PRE,SET 的状态)/外部中断INT0 中断处理程序void int0() interrupt 0TR0=

33、0; /禁止Timer0IE=0; /禁止中断lcd_wcmd(0x0e); /显示光标"_",整个光标不闪烁alarm=1;update_disbuf(0x50,"alarm:",armhour,armmin,armsec); /更新显示数据,0x50 表示要显示"P"pro_display(); /调用显示处理程序lcd_pos(0x47); /使光标位于第一个调整项下flag=0;vkey=0x03;while(flag0x0a)skey = scan_key(); /扫描按键状态if (skeyvkey) /若skey与vke

34、y相同,跳出循环,相异执行循环体 delay(10); /去按键抖动skey = scan_key(); /转回扫描按键状态if (skeyvkey) /若skey与vkey相同,跳出循环,相异执行循环体 vkey=skey; /将skey的值付给vkeyif (skey=0x01) /PRE 键按下 flag+; /调整标志位加1switch (flag) /将光标置于相应调整位置case 1: lcd_pos(0x49);break; /光标置小时闹铃设置位置case 2: lcd_pos(0x4c);break; /光标置分钟闹铃设置位置case 3: lcd_pos(0x4f);bre

35、ak; /光标置秒时闹铃设置位置case 4: update_disbuf(0x50,"time: ",hour,min,sec);pro_display();lcd_pos(0x05);break; /光标置年调整位置case 5: lcd_pos(0x08);break; /光标置月调整位置case 6: lcd_pos(0x0b);break; /光标置日调整位置case 7: lcd_pos(0x49);break; /光标置时调整位置case 8: lcd_pos(0x4c);break; /光标置分调整位置case 9: lcd_pos(0x4f);break;

36、 /光标置秒调整位置default:break;if (skey=0x02) /SET 键按下 pro_key(); /转设置按键处理程序lcd_wcmd(0x0c); /设置LCD 开显示及光标不闪烁,不显示"-"lcd_wcmd(0x01); /清除LCD 的显示内容IE=0x8f; /CPU 开中断,INT0,INT1,开中断TR0=1; /Timer0 启动/主程序,初始化及初值设定void main()lcd_init(); /初始化LCDlcd_sef_chr(); /写入自定义字符号hour=10;min=0;sec=0; /开机时的时,分,秒显示armhou

37、r=10;armmin=0;armsec=0; /开机时的时,分,秒闹铃初值year= 6; month=12;date=14; /开机时的年,月,日,星期显示week_proc();alarm=1; /初始开机,启用闹钟IE = 0x8f; /CPU 开中断,INT0,INT1,Timer0,Timer1 开中断IP = 0x04; /设置INT0 为中断最高优先级IT0=0;IT1=0; /外部INT0,INT1 设置为电平触发方式(注意,触发不要选边沿方式)TMOD = 0x11; /Timer0,Timer1 工作于模式1, 16 位定时方式TH0 = 0xdc;TL0 = 0x00;

38、 /Timer0 置10ms 定时初值TH1 = 0xff;TL1 = 0x00; /Timer1 置初值TR0 = 1; /Timer0 启动TR1 = 0;while(1);/设置按键处理程序void pro_key()switch (flag)case 0:alarm=!alarm; /启用或关闭闹钟(alarm=1:启用,alarm=0:关闭)update_disbuf(0x50,"alarm:",armhour,armmin,armsec); /更新显示数据pro_display(); /调用显示处理lcd_pos(0x47);break; /光标回到原调整位置c

39、ase 1:armhour+;if (armhour>23) armhour=0;update_disbuf(0x50,"alarm:",armhour,armmin,armsec); /更新显示数据pro_display(); /调用显示处理lcd_pos(0x49);break; /光标回到原调整位置case 2:armmin+;if (armmin>59) armmin=0;update_disbuf(0x50,"alarm:",armhour,armmin,armsec);pro_display();lcd_pos(0x4c);bre

40、ak;case 3:armsec+;if (armsec>59) armsec=0;update_disbuf(0x50,"alarm:",armhour,armmin,armsec);pro_display();lcd_pos(0x4f);break;case 4:year+;if (year> 99) year= 0;week_proc(); /星期自动运算update_disbuf(0x50,"time: ",hour,min,sec);pro_display();lcd_pos(0x05);break;case 5:month+;if

41、 (month>12) month=1;week_proc(); /星期自动运算update_disbuf(0x50,"time: ",hour,min,sec);pro_display();lcd_pos(0x08);break;case 6:date+;if (month=1|month=3|month=5|month=7|month=8|month=10|month=12)if (date>31) date=1; /大月31 天if (month=4|month=6|month=9|month=11)if (date>30) date=1; /小月30 天if (month=2)if(leap_year() /闰年的条件if (date>29) date=1; /闰年2 月为29 天elseif (date&

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论