第一篇:万年历单片机综合实验
综合实验报告
实验题目: 万年历
学生班级: 学生姓名: 学生学号: 指导教师: 实验时间:
摘要
本设计是电子万年历。具备三个功能:能显示:年、月、日、时、分、秒及星期信息,并具有可调整日期和时间功能。
我选用的是单片机STC89C52来实现电子万年历的功能。该电子万年历能够成功实现时钟运行,调整,显示年月日时分秒等信息。
该电子万年历使用12MHZ晶振与单片机STC89C52相连接,通过软件编程的方法实现了以24小时为一个周期,同时显示小时、分钟和秒的要求。利用单片机定时器及计数器产生定时效果通过编程形成数字钟效果,再利用数码管动态扫描显示单片机内部处理的数据。同时通过端口读入当前外部控制状态来改变程序的不同状态,实现不同功能。
电子万年历设计与制作可采用数字电路实现,也可以采用单片机来完成。若用数字电路完成,所设计的电路相当复杂,大概需要十几片数字集成块,其功能也主要依赖于数字电路的各功能模块的组合来实现,焊接的过程比较复杂,成本也非常高。若用单片机来设计制作完成,由于其功能的实现主要通过软件编程来完成,这样一来就降低了硬件电路的复杂性,从而使得其成本降低,更适合我们大学生自主研发。所以在该设计与制作中我选用了单片机STC89C52,它是低功耗、高性能的CMOS型8位单片机。片内带有4KB的Flash存储器,且允许在系统内改写或用编程器编程。另外, 单片机STC89C52的指令系统和引脚与8051完全兼容,片内有128B 的RAM、32条I/O口线、2个16位定时计数器、5个中断源、一个全双工串行口等。
因此,采用单片机STC89C52原理制作的电子万年历,不仅仅在原理上能够成功实现计时等功能,也更经济,更适用,更符合我们实际生活的需要,对我们大学生来说也更加有用。
关键词:STC89S52,DS1302,LCD,PROTEUS
目录
一、实验要求:...............................................................................................................................3
1.1基本要求:.........................................................................................................................3 1.2拓展要求:.........................................................................................................................3
二、方案论证:...............................................................................................................................3
2.1.显示部分:...........................................................................................................................3 2.2.数字时钟:.........................................................................................................................3
三、总体方案:...............................................................................................................................4
四、系统硬件设计:.......................................................................................................................4
4.1.时间设置模块:...............................................................................................................4 4.2.时钟模块:...........................................................................................................................4 4.3.整点报时电路.....................................................................................................................5 4.4.LCD液晶显示模块:.......................................................................................................5
五、整体电路:...............................................................................................................................6
5.1.电路.....................................................................................................................................6
六、数字时钟使用说明:...............................................................................................................7
七、心得体会:...............................................................................................................................7
八、程序代码:...............................................................................................................................7
一、实验要求:
1.1基本要求:
1、能动态显示年、月、日、星期、小时、分钟、秒。
2、可用键盘进行日期时间的修改。1.2拓展要求:
3、具有闹钟功能:可设定闹钟时间,在时间到达后,发出报警时间,持续5秒。
二、方案论证:
2.1.显示部分: 显示部分是本次设计的重要部分,一般有以下两种方案: 方案一:
采用LED显示,分静态显示和动态显示。对于静态显示方式,所需的译码驱动装置很多,引线多而复杂,且可靠性也较低。而对于动态显示方式,虽可以避免静态显示的问题,但设计上如果处理不当,易造成亮度低,有闪烁等问题。方案二:
采用LCD显示。LCD液晶显示具有丰富多样性、灵活性、电路简单、易于控制而且功耗小等优点,对于信息量多的系统,是比较适合的。
鉴于上述原因,我们采用方案二。2.2.数字时钟:
数字时钟是本设计的核心的部分。根据需要可采用以下两种方案实现: 方案一:
方案完全用软件实现数字时钟。原理为:在单片机内部存储器设三个字节分别存放时钟的时、分、秒信息。利用定时器与软件结合实现1秒定时中断,每产生一次中断,存储器内相应的秒值加1;若秒值达到60,则将其清零,并将相应的分字节值加1;若分值达到60,则清零分字节,并将时字节值加1;若时值达到24,则将时字节清零。该方案具有硬件电路简单的特点,但当单片机不上电,程序将不执行。而且由于每次执行程序时,定时器都要重新赋初值,所以该时钟精度不高。
方案二:
方案采用Dallas公司的专用时钟芯片DS1302。该芯片内部采用石英晶体振荡器,其芯片精度不大于10ms/年,且具有完备的时钟闹钟功能,因此,可直接对其以用于显示或设置,使得软件编程相对简单。为保证时钟在电网电压不足或突然掉电等突发情况下仍能正常工作,芯片内部包含锂电池。当电网电压不足或突然掉电时,可使系统自动转换到内部锂电池供电系统。而且即使系统不上电,程序不执行时,锂电池也能保证芯片的正常运行,以备随 时提供正确的时间。
基于时钟芯片的上述优点,本设计采用方案二完成数字时钟的功能。
三、总体方案:
本设计采用STC89C52RC单片机作为本系统的控制模块。单片机可把由DS1302、LCD液晶显示模块中的数据利用软件来进行处理,从而把数据传输到显示模块,实现日历和修改的显示。以LCD液晶显示器为显示模块,把单片机传来的数据显示出来,并且显示多样化。在显示电路中,主要靠按键来实现日期的修改和选择。
四、系统硬件设计:
4.1.时间设置模块:
时间设置模块通过四个按键实现万年历的时间调整设置。KEY1键进入时间设置模式,KEY2键实现设置内容选择,KEY3键实现设置内容加1,KEY4键实现设置内容减1。
图1.时间设置模块
4.2.时钟模块: 时钟模块采用DS1302芯片,DS1302是DALLAS公司推出的涓流充电时钟芯片内含有一个实时时钟/日历和31字节静态RAM通过简单的串行接口与单片机进行通信实时时钟/日历电路提供秒分时日日期月年的信息每月的天数和闰年的天数可自动调整时钟操作可通过 4 AM/PM指示决定采用24或12小时格式DS1302与单片机之间能简单地采用同步串行的方式进行通信仅需用到三个口线:
RST复位、I/O数据线、SCLK串行时钟。时钟/RAM的读/写数据以一个字节或多达31个字节的字符组方式通信。DS1302工作时功耗很低,保持数据和时钟信息时功率小于1mW,其接线电路如图2所示:
图2.时钟模块
4.3.整点报时电路
整点报时电路由一个NPN三极管和蜂鸣器组成,当时间走到整点时分,会每间隔一秒发出一次报时,连响五次。
图3.报时电路
4.4.LCD液晶显示模块: LCD液晶显示模块采用LCD1602型号,具有很低的功耗,正常工作时电流仅2.0mA/5.0V。通过编程实现自动关闭屏幕能够更有效的降低功耗。LCD1602分两行显示,每行可显示多达16个字符。LCD1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,通过内部指令可实现对其显示多样的控制,并且还能利用空余的空间自定义字符。其接线如图4所示:
图4.LCD液晶显示
五、整体电路:
5.1.电路
图5.整体电路
六、数字时钟使用说明:
调整时间设定:在时间显示界面中按KEY1键后,进入时间调整,通过KEY2选择需要修改的或设定的时间。按KEY2键对应内容向右移动,KEY3键加1,KEY4键减1,设置完毕,自动退出设置功能。
七、心得体会:
通过这一周的课程设计,加深了我对于单片机和数字电路的认识,通过查阅大量的资料,我获得了以前在课堂上学不到的东西,我想这对于以后的毕业设计,或者工作也好,都是很有帮助的。在设计电路中,往往是先仿真后连接实物图,但有时候仿真和电路连接并不是完全一致的,例如仿真的连接示意图中,往往没有接高电平的16脚或14脚以及接低电平的7脚或8脚,因此在实际的电路连接中往往容易遗漏。在设计的过程中遇到了很多问题,本来自己的单片机基础就比较弱,又是第一次做这样的设计,难免会遇到过各种各样的问题。同时在设计的过程中发现了自己的不足之处,比如对以前所学过的知识理解得不够深刻,掌握得不够牢固,对单片机汇编语言掌握得不好。此次的电子万年历设计重在于仿真和接线,虽然能把电路图接出来,并能正常显示,但对于电路本身的原理并不是十分熟悉.总的来说,通过这次的设计实验更进一步地增强了实验的动手能力。
八、程序代码:
#include “reg51.h” #include “intrins.h” typedef unsigned char uint8;typedef unsigned int uint16;
#define LED_Y P2 #define LCD_DATA 1 #define LCD_COMMAND 0 #define WORDNUU 11
sbit ALARM=P2^0;sbit LCD_RS=P1^5;sbit LCD_RW=P1^6;sbit LCD_EN=P1^7;sbit RTC_SDA=P3^6;sbit RTC_SCL=P3^5;sbit RTC_RST=P3^4;sbit KEY1=P1^0;sbit KEY2=P1^1;sbit KEY3=P1^2;sbit KEY4=P1^3;
#define LCD_PORT P0 uint8 LCD_NO;uint16 i1,i2;uint8 bdata AA;sbit AA7 = AA^7;#define READ_SECOND #define WRITE_SECOND #define READ_MINE
#define WRITE_MINE
#define READ_HOUR
#define WRITE_HOUR #define READ_DAY #define WRITE_DAY #define READ_MONTH #define WRITE_MONTH #define READ_WEEK #define WRITE_WEEK #define READ_YEAR
#define WRITE_YEAR
uint8 SET;uint8 PRE_HOUR;uint8 DATE[16];uint8 TIME[16];
0x81 0x80 0x83 0x82 0x85 0x84 0x87 0x86 0x89 0x88 0x8b 0x8a 0x8d 0x8c 8
void delaynus(uint8 n){
uint8 i;
for(i=0;i } void RTC_Write(uint8 dat){ uint8 i; RTC_SCL=0; //拉低SCLK,为脉冲上升沿写入数据做好准备 delaynus(2); //稍微等待,使硬件做好准备 for(i=0;i<8;i++) //连续写8个二进制位数据 { RTC_SDA=dat&0x01; //取出dat的第0位数据写入1302 delaynus(2); //稍微等待,使硬件做好准备 RTC_SCL=1; //上升沿写入数据 delaynus(2); //稍微等待,使硬件做好准备 RTC_SCL=0; //重新拉低SCLK,形成脉冲 dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位 } } uint8 RTC_Read(){ uint8 i,dat; delaynus(2); //稍微等待,使硬件做好准备 for(i=0;i<8;i++) //连续读8个二进制位数据 { dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位 if(RTC_SDA==1) //如果读出的数据是1 dat|=0x80; //将1取出,写在dat的最高位 RTC_SCL=1; //将SCLK置于高电平,为下降沿读出 delaynus(2);//稍微等待 RTC_SCL=0; //拉低SCLK,形成脉冲下降沿 delaynus(2);//稍微等待 } return dat; //将读出的数据返回 } void RTC_Write_Byte(uint8 addr,uint8 dat){ RTC_RST=0; //禁止数据传递 RTC_SCL=0; //确保写数居前SCLK被拉低 RTC_RST=1; //启动数据传输 delaynus(2); //稍微等待,使硬件做好准备 RTC_Write(addr); //写入命令字 RTC_Write(dat); //写数据 RTC_SCL=1; //将时钟电平置于已知状态 RTC_RST=0; //禁止数据传递 } uint8 RTC_Read_Byte(uint8 addr){ uint8 dat; RTC_RST=0; //拉低RST RTC_SCL=0; //确保写数居前SCLK被拉低 RTC_RST=1; //启动数据传输 RTC_Write(addr); //写入命令字 dat=RTC_Read(); //读出数据 RTC_SCL=1; //将时钟电平置于已知状态 RTC_RST=0; //禁止数据传递 return dat; //将读出的数据返回 } typedef struct __SYSTEMTIME__ { uint8 Second;uint8 Mine;uint8 Hour;uint8 Day;uint8 Month;uint8 Week;uint8 Year;}SYSTEMTIME; static SYSTEMTIME TIMETYPE; void CurrentTime(SYSTEMTIME *dat){ uint8 TimeValue; TimeValue=RTC_Read_Byte(READ_SECOND);dat->Second=(((TimeValue&0x70)>>4)*10)+(TimeValue&0x0f); TimeValue=RTC_Read_Byte(READ_MINE);dat->Mine=(((TimeValue&0x70)>>4)*10)+(TimeValue&0x0f); TimeValue=RTC_Read_Byte(READ_HOUR);dat->Hour=(((TimeValue&0x70)>>4)*10)+(TimeValue&0x0f); TimeValue=RTC_Read_Byte(READ_DAY);dat->Day=(((TimeValue&0x70)>>4)*10)+(TimeValue&0x0f); TimeValue=RTC_Read_Byte(READ_MONTH);dat->Month=(((TimeValue&0x70)>>4)*10)+(TimeValue&0x0f); TimeValue=RTC_Read_Byte(READ_WEEK);dat->Week=(TimeValue&0x0f); TimeValue=RTC_Read_Byte(READ_YEAR);dat->Year=(((TimeValue&0x70)>>4)*10)+(TimeValue&0x0f);} bit LCD_BUSY(){ bit result;LCD_RS=0;LCD_RW=1;LCD_EN=1;_nop_();_nop_();result=(bit)(LCD_PORT&0x80);LCD_EN=0;return result;} void LCD_Write(uint8 dat,uint8 type) //LCD写字符 { uint8 i;while((LCD_BUSY()&&i<100)){i++;} if(i>99)LCD_NO=1;LCD_RS=type;LCD_RW=0;LCD_EN=0;_nop_();_nop_();_nop_();_nop_();LCD_PORT=dat;_nop_();_nop_();_nop_();_nop_();LCD_EN=1;_nop_();_nop_();_nop_();_nop_();LCD_EN=0;} void LCD_INITIALIZE() //LCD初始化 { LCD_Write(0x06,LCD_COMMAND);LCD_Write(0x38,LCD_COMMAND);LCD_Write(0x0c,LCD_COMMAND);LCD_Write(0x01,LCD_COMMAND);} void LCD_Prints(uint8 *dat,uint8 add) //LCD打印函数 { LCD_Write(add|0x80,LCD_COMMAND);while(*dat!=' ')LCD_Write((*(dat++)),LCD_DATA);} void KEY_Delay(){ uint8 i,j;for(i=0;i<200;i++)for(j=0;j<200;j++);} void SET_YEAR(){ uint8 YEAR[3];LCD_Prints(“ YEAR SETTING ”,0);LCD_Prints(“ YEAR:20 ”,0x40);if((!KEY3)&&(TIMETYPE.Year<80)){KEY_Delay();i1=i2=0;TIMETYPE.Year++;} else if(TIMETYPE.Year>79)TIMETYPE.Year=0;if((!KEY4)&&(TIMETYPE.Year>0)){KEY_Delay();i1=i2=0;TIMETYPE.Year--;} YEAR[0]=(TIMETYPE.Year/10)+'0';YEAR[1]=(TIMETYPE.Year%10)+'0';YEAR[2]=' ';LCD_Prints(YEAR,0x49);} void SET_MONTH(){ uint8 MONTH[3];LCD_Prints(“ MONTH SETTING ”,0);LCD_Prints(“ MONTH: ”,0x40);if((!KEY3)&&(TIMETYPE.Month<13)){KEY_Delay();TIMETYPE.Month++;i1=i2=0;} else if(TIMETYPE.Month>12)TIMETYPE.Month=1;if((!KEY4)&&(TIMETYPE.Month>1)){KEY_Delay();TIMETYPE.Month--;i1=i2=0;} MONTH[0]=(TIMETYPE.Month/10)+'0';MONTH[1]=(TIMETYPE.Month%10)+'0';MONTH[2]=' ';LCD_Prints(MONTH,0x48);} void SET_DAY(){ uint8 DAY[3];LCD_Prints(“ DAY SETTING ”,0);LCD_Prints(“ DAY: ”,0x40);if((!KEY3)&&(TIMETYPE.Day<32)){KEY_Delay();TIMETYPE.Day++;i1=i2=0;} else if(TIMETYPE.Day>31)TIMETYPE.Day=1;if((!KEY4)&&(TIMETYPE.Day>1)){KEY_Delay();TIMETYPE.Day--;i1=i2=0;} DAY[0]=(TIMETYPE.Day/10)+'0';DAY[1]=(TIMETYPE.Day%10)+'0';DAY[2]=' ';LCD_Prints(DAY,0x46);} void SET_WEEK(){ uint8 WEEK[2];LCD_Prints(“ WEEK SETTING ”,0);LCD_Prints(“ WEEK: ”,0x40);if((!KEY3)&&(TIMETYPE.Week<8)){KEY_Delay();TIMETYPE.Week++;i1=i2=0;} else if(TIMETYPE.Week>7)TIMETYPE.Week=1;if((!KEY4)&&(TIMETYPE.Week>1)){KEY_Delay();TIMETYPE.Week--;i1=i2=0;} WEEK[0]=TIMETYPE.Week+'0';WEEK[1]=' ';LCD_Prints(WEEK,0x47);} void SET_HOUR(){ uint8 HOUR[3];LCD_Prints(“ HOUR SETTING ”,0);LCD_Prints(“ HOUR: ”,0x40);if((!KEY3)&&(TIMETYPE.Hour<24)){KEY_Delay();TIMETYPE.Hour++;i1=i2=0;} else if(TIMETYPE.Hour>23)TIMETYPE.Hour=0;if((!KEY4)&&(TIMETYPE.Hour>0)){KEY_Delay();TIMETYPE.Hour--;i1=i2=0;} HOUR[0]=(TIMETYPE.Hour/10)+'0';HOUR[1]=(TIMETYPE.Hour%10)+'0';HOUR[2]=' ';LCD_Prints(HOUR,0x47);} void SET_MINE(){ uint8 MINE[3];LCD_Prints(“ MINE SETTING ”,0);LCD_Prints(“ MINE: ”,0x40);if((!KEY3)&&(TIMETYPE.Mine<60)){KEY_Delay();TIMETYPE.Mine++;i1=i2=0;} else if(TIMETYPE.Mine>59)TIMETYPE.Mine=0;if((!KEY4)&&(TIMETYPE.Mine>0)){KEY_Delay();TIMETYPE.Mine--;i1=i2=0;} MINE[0]=(TIMETYPE.Mine/10)+'0';MINE[1]=(TIMETYPE.Mine%10)+'0';MINE[2]=' ';LCD_Prints(MINE,0x47);} void SET_SECOND(){ uint8 SECOND[3];LCD_Prints(“ SECOND SETTING ”,0);LCD_Prints(“ SECOND: ”,0x40);if((!KEY3)&&(TIMETYPE.Second<60)){KEY_Delay();TIMETYPE.Second++;i1=i2=0;} else if(TIMETYPE.Second>59)TIMETYPE.Second=0;if((!KEY4)&&(TIMETYPE.Second>0)){KEY_Delay();TIMETYPE.Second--;i1=i2=0;} SECOND[0]=(TIMETYPE.Second/10)+'0';SECOND[1]=(TIMETYPE.Second%10)+'0';SECOND[2]=' ';LCD_Prints(SECOND,0x48);} void Write_Time(){ uint8 year,month,day,hour,mine,second,week;year=((TIMETYPE.Year/10)<<4)|(TIMETYPE.Year%10);month=((TIMETYPE.Month/10)<<4)|(TIMETYPE.Month%10);day=((TIMETYPE.Day/10)<<4)|(TIMETYPE.Day%10);week=TIMETYPE.Week;hour=((TIMETYPE.Hour/10)<<4)|(TIMETYPE.Hour%10);mine=((TIMETYPE.Mine/10)<<4)|(TIMETYPE.Mine%10);second=((TIMETYPE.Second/10)<<4)|(TIMETYPE.Second%10);RTC_Write_Byte(0x8e,0x00);//写入允许 RTC_Write_Byte(0x80,WRITE_SECOND|0x80);RTC_Write_Byte(0x8e,0x80);//禁止写入 RTC_Write_Byte(0x8e,0x00);//写入允许 RTC_Write_Byte(WRITE_YEAR,year);//写入新的秒数 RTC_Write_Byte(WRITE_MONTH,month);//写入新的秒数 RTC_Write_Byte(WRITE_DAY,day);//写入新的秒数 RTC_Write_Byte(WRITE_HOUR,hour);//写入新的秒数 RTC_Write_Byte(WRITE_MINE,mine&0x7f);//写入新的秒数 RTC_Write_Byte(WRITE_WEEK,week);//写入新的秒数 RTC_Write_Byte(WRITE_SECOND,second);RTC_Write_Byte(0x8e,0x00);//写入允许 RTC_Write_Byte(0x8e,0x80);} void SET_TIME(){ uint8 i;CurrentTime(&TIMETYPE);while(1){ switch(i) { case 0:SET_YEAR();break; case 1:SET_MONTH();break; case 2:SET_DAY();break; case 3:SET_WEEK();break; case 4:SET_HOUR();break; case 5:SET_MINE();break; case 6:SET_SECOND();break; } if(!KEY2){i++;KEY_Delay();i1=i2=0;} while(!KEY2); if(i==7){i=0;Write_Time();break;} i1++; if(i1==10){i2++;i1=0;} if(i2==100){i=0;Write_Time();break;} } SET = 1;} void TIMESETTING(){ if(!KEY1){SET_TIME();} } void LCD_DISP(){ DATE[0]='2';DATE[1]='0';DATE[4]='/';DATE[7]='/';DATE[10]='/';DATE[11]=' ';DATE[14]=' ';DATE[16]=' ';TIME[2]=':';TIME[5]=':';} void LCD_Disp_Time() //读显时间 { DATE[2]=TIMETYPE.Year/10+'0';DATE[3]=TIMETYPE.Year%10+'0';DATE[5]=TIMETYPE.Month/10+'0';DATE[6]=TIMETYPE.Month%10+'0';DATE[8]=TIMETYPE.Day/10+'0';DATE[9]=TIMETYPE.Day%10+'0';DATE[11]=TIMETYPE.Week+'0'; TIME[0]=TIMETYPE.Hour/10+'0';TIME[1]=TIMETYPE.Hour%10+'0';TIME[3]=TIMETYPE.Mine/10+'0';TIME[4]=TIMETYPE.Mine%10+'0';TIME[6]=TIMETYPE.Second/10+'0';TIME[7]=TIMETYPE.Second%10+'0'; LCD_Prints(DATE,0x02);LCD_Prints(TIME,0x44);} void main(){ uint8 INIT = 1; TMOD=0x01;TH0=(65536-45872)/256;TL0=(65536-45872)%256; EA = 1;ET0 = 1;TR0 = 1; ALARM = 0;LCD_INITIALIZE(); //LCD初始化 LCD_DISP(); //液晶显示初始值 PRE_HOUR = TIME[1]; while(1){ if((!KEY1)&&(!LCD_NO))TIMESETTING(); if(SET == 1) { SET = 0; LCD_INITIALIZE();//LCD初始化 } CurrentTime(&TIMETYPE); LCD_Disp_Time(); if(INIT == 1) { INIT = 0; PRE_HOUR = TIME[1]; } } } void timer0()interrupt 1 { uint16 i,TIM; TH0=(65536-45872)/256;TL0=(65536-45872)%256;TIM++; if(TIM == 10){ TIM = 0; if(PRE_HOUR!= TIME[1]) { i++; ALARM =~ ALARM; if(i == 10) { i = 0; PRE_HOUR = TIME[1]; } } } } 18 单片机及接口技术综合实验 ——————电子万年日历系统一、题目:电子实时时钟/万年日历系统 二、功能要求: 1. 基本要求: ⑴ 显示准确的北京时间(时、分、秒),可用24小时制式; ⑵ 随时可以调校时间。 2. 发挥要求: ⑴ 增加公历日期显示功能(年、月、日),年号只显示最后两位; ⑵ 随时可以调校年、月、日; ⑶ 允许通过转换功能键转换显示时间或日期。 三、方案考虑: 1、硬件方案: ⑴ 显示器采用6位LED数码管(共阳),可分别显示时间或日期;(通过KB键可切换)⑵ 显示器的驱动采用动态扫描电路形式,以达到简化电路的目的。但要注意所需的驱动电流比静态驱动时要大,因此要增加驱动电路。可采用74LS244或者晶体管;其中74ls244是用来驱动段选码,晶体管是驱动位选码!⑶采用“一键多用方案”,以减少按键数目。本方案只采用了两个按键 ⑷ 整体上要考虑:结构简单、布局美观、操作方便、成本低廉。 2、设计电路图如下: 3、元件清单: ⑴ 89C51 1个 ⑵ IC座(40脚) 3个(其中1个用于接插89C51、2个用于接插LED段数码管)。⑶ 74LS244 1个(用于驱动6个共阳的LED段数码管)。⑷ IC座(20脚) 1个(用于接插74LS244)。(5)显示器:LED_8段数码管(共阳型)6个三极管: (6)PNP(8550) 6个(用于驱动6个共阳型LED段数码管)。 (7)微型开关: 3个(其中1个用于复位电路、其它用于键盘)。(8)晶体振荡器(12MHz):1个(用于振荡电路)。(9)电阻器: ⑴ 3KΩ 1个(用于系统复位电路)。 ⑵ 1KΩ 6个(用作PNP三极管基极电阻)。⑶ 100Ω 7个(驱动器用作74LS244输出限流电阻)。(10)电容器: ⑴ 10μF 1个(用于系统复位电路)。⑵ 30 pF 2个(用于系统振荡电路)。(11)其它: ⑴ 万能电路板(10×15): 1块 ⑵ 焊锡条: 2米 ⑶ 带插头、座的电源端子: 1条 ⑷ 各种颜色外皮的导线: 各1米(12)工具: 1.电烙铁: 1把 2.剪钳: 1把 3.镊子: 1把 4.万用表: 1个(13)设备: 编程器(MEP300或TOP851) 6个 4、软件方案: 只使用第一组工作寄存器,功能分布如下: ⑴ “时钟”基准时间由单片机内部定时中断来提供,定时时间应该乘以一个整数得到“秒”,且不宜太长或太短,最长不能超过16位定时器的最长定时时间,最短不能少于定时中断服务程序的执行时间。一般来说,基准时间越短,越有利于提高时钟运行的精确度。本实验定时5mS。乘以一个整数200得到“1秒”.⑵ 用一个计数器(R4)对定时中断的次数进行计数,从而可以实现“秒”定时,同理可以实现“分”定时和“时”定时,甚至于“日”、“月”、“年”定时。 ⑶ 显示器采用动态驱动时要注意到:LED的 “启辉时间”和 “余辉时间”。驱动信号的维持时间必须大于启辉时间;而驱动信号的间歇时间必须小于余辉时间。“启辉时间”和 “余辉时间”与驱动电流的大小有关,驱动电流越大,启辉时间越短,而余辉时间越长。但是,驱动电流的大小受到驱动电路的驱动能力和LED极限功耗的限制。本实验采用了74ls244和晶体管8550驱动,并进行适当的延时3ms解决上述问题。 ⑷ LED的余辉时间使动态驱动显示得到保证,但也要注意到它在更新显示内容时,可能造成显示字符的混乱模糊。为此,在把“更新显示内容”写入显示器之前,必须把所有的LED熄灭,即要把一个“熄灭驱动信号”先写入显示器。 ⑸对于按键的处理,采用中断。产生中断后先判有无按键被按下,还要考虑到“去抖动影响”问题,可采用软件延迟法解决这个问题,延迟时间至少10mS。而单纯进行软件延时的话会令到显示管产生断续的情况,故调用显示程序作为延时时间。这样就合理地处理好这两者的矛盾了。 ⑹ 把键盘的按键分两种情况来处理,操作简单。 ① 调整时间时,先按下KA键,(KA键为选择调整位置的键,如选调整秒或分),而此时的KB键只是用来加一操作。在调整时间状态下,若在十秒内检测到没有任何按键按下,则返回正常显示时钟状态。 ② 而不调整时间,即不按下KA键,KB的键只用来切换显示日期和时钟。⑺ 对于自动识别“月大、月小”和“平年、闰年”的问题,主要考虑: ① 月大、月小: 1~7月:逢单月为31天;逢双月为30天,其中2月另行处理。8~12月:逢单月为30天;逢双月为31天。②平年、闰年: 仅仅处理2月份的天数:平年的2月份天数为28天,闰年的2月份天数为29天。 5、程序流程图如下:(1)电子时钟计算程序图 (2)调整流程图 程序编写如下: ;///////////////////////////////////////////////////////// ORG 0000H LJMP START ORG 0003H LJMP PROINT0 ;int0用来切换时钟调整位置 ORG 0013H ;用来调整时间,只加不减 LJMP PROINT1 ORG 001BH ;5ms的延迟,计数200次则为1秒 LJMP PROTIME ORG 0030H ;主程序 TABLE: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H ;0 1 2 3 4 5 6 7 8 9 ORG 0050H START: MOV TCON,#05H ;中断初始化 MOV IE ,#8DH MOV TMOD,#10H MOV TH1,#0eCH ;定时器初始化 MOV TL1,#78H MOV 31H,#0AH ;10秒 MOV 32H,#1EH;30分 MOV 33H,#09H;9点 MOV 34H,#0AH MOV 35H,#06H MOV 36H,#05H MOV 37H,#14H ;10号;6月;2005年 ;R7 存放切换标志 0 NORMAL , 1 HOUR ,2 MINUTE ,3 SECOND ,4 YEAR,5 MONTH,6 DAY MOV R1,#00H ;确定在调时不按键的最长时间,10秒后返回normal状态 MOV R7,#00H ;切换标志 MOV 40H,#00H ;十六进制转换BCD的高位 MOV 41H,#00H ;十六进制转换BCD的低位 MOV R6,#00H ;调时的位闪烁的时间间隔 MOV R4,#00H ;用来计数5ms的中断次数,200次则一秒 mov r3,#00h SETB TR1 ;开始计时 AGAIN: ACALL PROSHOW ;显示 AJMP AGAIN PROSHOW: CJNE R3,#00H,SHOWDATE ;如果r3等于1就显示日期,等于0就显示时钟 CJNE R7,#04H,DATE1 ;显示程序 AJMP SHOWDATE ;showdate显示年月日 AJMP SHOWDATE DATE1: CJNE R7,#05H,DATE2 DATE2: CJNE R7,#06H,SHOWCLOCK AJMP SHOWDATE showCLOCK: MOV R0,33H ;showclock显示时分秒,先显示时 ACALL PROHTOD CJNE R7,#01H,CLK1 INC R6 CJNE R6,#03H,CLK2 ;若处于调时状态,则该位闪烁 MOV R6 ,#00H CLK1: clr P2.4 mov a,41H MOV P0, a ;显示时的低位 ACALL DELAY3MS CLK2: SETB P2.4 CLR P2.5 mov a,40H MOV P0,a ;显示时的高位 ACALL DELAY3MS SETB P2.5 MOV R0,32H ;显示分 ACALL PROHTOD CJNE R7,#02H,CLK3 INC R6 CJNE R6,#03H,CLK4 ;若处于调时状态,则该位闪烁 MOV R6,#00H CLK3: CLR P2.2 mov a,41H MOV P0, a ;显示分的低位 ACALL DELAY3MS CLK4: SETB P2.2 CLR P2.3 mov a,40h MOV P0,a ;显示分的高位 ACALL DELAY3MS SETB P2.3 MOV R0,31H ;显示秒 ACALL PROHTOD CJNE R7,#03H,CLK5 INC R6 CJNE R6,#03H,CLK6 MOV R6,#00H CLK5: CLR P2.0 mov a,41H MOV P0, a ACALL DELAY3MS CLK6: SETB P2.0 CLR P2.1 mov a,40h MOV P0,a ACALL DELAY3MS SETB P2.1 RET SHOWDATE: MOV R0,36H ACALL PROHTOD CJNE R7,#04H,DAY1 INC R6 CJNE R6,#03H,DAY2 MOV R6,#00H DAY1: CLR P2.4 MOV P0,41H ACALL DELAY3MS DAY2: SETB P2.4 CLR P2.5 MOV P0,40H ACALL DELAY3MS SETB P2.5 MOV R0,35H ACALL PROHTOD CJNE R7,#05H,MONTH1 ;若处于调时状态,则该位闪烁 ;显示秒的低位 ;显示秒的高位 ;显示年 ;若处于调时状态,则该位闪烁;显示年的低位 ;显示年的高位 ;显示月 INC R6 CJNE R6,#03H,MONTH2 ;若处于调时状态,则该位闪烁 MOV R6,#00H MONTH1: CLR P2.2 MOV P0,41H ;显示月的低位 ACALL DELAY3MS MONTH2: SETB P2.2 CLR P2.3 MOV P0,40H ;显示月的高位 ACALL DELAY3MS SETB P2.3 MOV R0,34H ACALL PROHTOD CJNE R7,#06H,YEAR1 INC R6 CJNE R6,#03H,YEAR2 MOV R6,#00H YEAR1: CLR P2.0 MOV P0,41H ACALL DELAY3MS YEAR2: SETB P2.0 CLR P2.1 MOV P0,40H ACALL DELAY3MS SETB P2.1 RET PROHTOD:PUSH ACC MOV A,R0 MOV B,#0AH DIV AB MOV DPTR,#0030H MOVC A,@A+DPTR MOV 40H,A MOV A,B MOVC A,@A+DPTR MOV 41H,A POP ACC RET ;显示日 ;若处于调时状态,则该位闪烁 ;十六进制数转换成bcd码,且可以直接输出p0口 DELAY3MS: ;DELAY3MS MOV 45H,#08H DELAY1: MOV 46H,#0FFH DELAY2: DJNZ 46H,DELAY2 DJNZ 45H,DELAY1 RET PROINT0: CLR EX0 ;切换键中断程序 MOV R3,#00H ACALL PROSHOW MOV C,P3.2 JC IEXIT0 MOV R1,#00H INC R7 CJNE R7,#07H,IEXIT0 MOV R7,#00H INT01: MOV C,P3.2 JC INT02 ACALL PROSHOW AJMP INT01 INT02: ACALL PROSHOW IEXIT0: SETB EX0 RETI PROINT1:CLR EX1 ACALL PROSHOW MOV C,P3.3 JC IEXIT1 LCALL ISYEAR ;判断平年闰年 LCALL ISMONTH ;判断月份,确定最大日数 MOV R1,#00H CJNE R7,#00H,NEXT1 ;若不是调时状态,按此键就是切换显示日期、时钟 INC R3 CJNE R3,#02H,IEXIT1 MOV R3,#00H AJMP IEXIT1 NEXT1: mov r3,#00h CJNE R7,#03H,NEXT2 ;修改秒位 INC 31H MOV A,31H CJNE A,#3CH,INT11 ;遇60变0 MOV 31H,#00H AJMP IEXIT1 NEXT2: CJNE R7,#02H,NEXT3 ;修改分位 INC 32H MOV A,31H CJNE A,#3CH,INT11 ;遇60变0 MOV 31H,#00H AJMP IEXIT1 NEXT3: CJNE R7,#01H,NEXT4 ;修改时位 INC 33H MOV A,33H CJNE A,#18H,INT11 ;遇24变0 MOV 33H,#00H AJMP IEXIT1 NEXT4: CJNE R7,#06H,NEXT5 ;修改日 INC 34H MOV A,34H CJNE A,49H,INT11 ;到月底就返回月初 MOV 34H,#01H AJMP IEXIT1 NEXT5: CJNE R7,#05H,NEXT6 ;修改月 INC 35H MOV A,35H CJNE A,#0DH,INT11 ;十二月过后就跳回1月 MOV 35H,#01H AJMP IEXIT1 NEXT6: CJNE R7,#04H,INT11 ;修改年 INC 36H MOV A,36H CJNE A,#64H,INT11 MOV 36H,#00H MOV C,P3.3 INT11: JC INT12 ACALL PROSHOW AJMP INT11 INT12: ACALL PROSHOW IEXIT1: setb EX1 RETI PROTIME: MOV TMOD,#10H MOV TH1,#3CH ;定时器初始化 MOV TL1,#60H setb tr1 INC R4 CJNE R4,#0c8H,EXIT MOV R4,#00H ;计满1秒则清零 CJNE R7,#00H,DIAOSHI AJMP NORMAL DIAOSHI:INC R1 ;调时不按键的最长时间为10秒,在此期间又键按下重新计时 CJNE R1,#0AH,EXIT MOV R7,#00H ;到10秒则返回正常显示状态 MOV R1,#00H AJMP EXIT NORMAL:ACALL ISYEAR ;判断平闰年,返回标志48h,0为平年,1为闰年 ACALL ISMONTH ;判断哪个月,返回该月的最大日数,存放在49h INC 31H MOV A,31H ;秒加一 CJNE A,#3CH,EXIT MOV 31H,#00H INC 32H ;分加一 MOV A,32H CJNE A,#3CH,EXIT MOV 32H,#00H INC 33H ;时加一 MOV A,33H CJNE A,#18H,EXIT MOV 33H,#00H INC 34H MOV A,34H CJNE A,49H,EXIT MOV 34H,#01H INC 35H MOV A,35H CJNE A,#0DH,EXIT MOV 35H,#01H INC 36H MOV A,36H CJNE A,#64H,EXIT MOV 36H,#00H;年加一;月加一;日加一 EXIT: RETI ISYEAR: MOV A,36H;判断平闰年 MOV B,#04H DIV AB MOV A,B CJNE A,#00H,EXITYEAR1 MOV 48H,#01H ;闰年 SJMP EXITYEAR MOV 48H,#00H ;平年 EXITYEAR1: EXITYEAR: RETI ISMONTH: MOV A,35H ;开始检查月份 CJNE A,#02H,NEXTMON1 ;判断二月 MOV R2,48H CJNE R2,#00H,RUNNIAN MOV 49H,#1DH ;平年为28天,赋29给49h AJMP EXITMONTH RUNNIAN:MOV 49H,#1EH ;闰年为29天,赋30天给49h AJMP EXITMONTH NEXTMON1: CJNE A,#04H,NEXTMON2 AJMP XIAOYUE NEXTMON2:CJNE A,#06H,NEXTMON3 AJMP XIAOYUE NEXTMON3:CJNE A,#09H,NEXTMON4 AJMP XIAOYUE NEXTMON4:CJNE A,#0BH,DAYUE XIAOYUE: MOV 49H,#1FH ;四,六,九,十一月是小月,30天,但应该赋31天给比较值49h,AJMP EXITMONTH DAYUE: MOV 49H,#20H ;其他月份为大月,31天,赋32天给49h EXITMONTH: RETI END 课程设计报告 任务和设计要求 首先要学会安装软件,要熟悉会使用。系统设计 系统框图 硬件设计 3.1 电路原理图 课程设计报告 课程设计报告 课程设计报告 3.2 主要单元电路 3.3 元件清单 软件设计 4.1 程序流程图 课程设计报告 4.2程序清单 TIME_WEEK DATA 52H TIME_YEAR DATA 5DH TIME_MONTH DATA 5EH TIME_DATA DATA 5FH YEARH DATA 36H YEAR DATA 35H MONTH DATA 34H DAY DATA 33H HOUR DATA 32H MINUTE DATA 31H SEC DATA 30H 课程设计报告 AAA BIT P3.0 BBB BIT P3.1 AA BIT P3.3 BB BIT P3.4 CC BIT P3.5 BL BIT P3.2 BZ1 BIT 21H.0 TIMES DATA 20H COM DATA P1 ORG 0000H LJMP START ORG 0003H RETI ORG 000BH LJMP INTT0 ORG 0013H RETI ORG 001BH RETI ORG 0023H RETI START: 课程设计报告 MOV R0,#30H MOV R7,#9 CLEETE: MOV @R0,#00H INC R0 DJNZ R7,CLEETE MOV TIMES,#00H MOV TMOD,#01H MOV TL0,#0C0H MOV TH0,#63H MOV SEC,#0 MOV MINUTE,#0H MOV HOUR,#0H MOV DAY,#01H MOV MONTH,#01H MOV YEAR,#01H MOV YEARH,#20H SETB EA SETB ET0 SETB TR0 MOV R4,#19 START1: 课程设计报告 CALL DISP JNB AA,SETMM1 JMP START1 SETMM1: CALL SETMM JMP START1 SETMM: CALL DISP CALL DISP JB AA,SETMM0 SETMM2: JNB AA,SETMM3 CLR ET0 CLR TR0 MOV SEC,#0 MOV TIMES,#01H MOV R0,#MINUTE SETMM4: NOP INC22: CALL OFFL CALL INC11 课程设计报告 CALL DISP JB AA,INC22 CALL DISP JB AA,INC22 INC R0 MOV A,TIMES RL A MOV TIMES,A JNB TIMES.5, SETMM4 SETMM12: JNB AA , SETMM11 SETMM0: SETB TR0 SETB ET0 RET SETMM11: CALL DISP JMP SETMM12 SETMM3: CALL DISP JMP SETMM2 INC11: 课程设计报告 MOV R3,#40 INC111: MOV A,@R0 JB BB,INC17 ADD A,#1 DA A CALL INC000 INC13: JNB BB , INC14 INC17: MOV @R0,A CALL DISP DJNZ R3,INC111 RET INC14: CALL DISP JMP INC13 OFFL: MOV 22H,@R0 MOV R6,#10 OFF1: MOV R7,#10 课程设计报告 OFF2: MOV @ R0, # 0AAH CALL DISP DJNZ R7 , OFF2 DJNZ R6 , OFF1 MOV @ R0 , 22H RET INC000: JB TIMES.0, INC001 JB TIMES.1, INC002 JB TIMES.2, INC003 JB TIMES.3, INC004 JB TIMES.4, INC005 JMP INCOUT INC005: CJNE A, #99H, INCOUT MOV A,#00H JMP INCOUT INC004: CJNE A, # 13H, INCOUT MOV A,#01H JMP INCOUT 课程设计报告 INC003: CJNE A,# 32H ,INCOUT MOV A,#01H JMP INCOUT INC002: CJNE A,#24H,INCOUT MOV A,#00H JMP INCOUT INC001: CJNE A,# 60H , INCOUT MOV A,#00H INCOUT: RET INTT0: PUSH ACC PUSH PSW ORL TL0,#0C0H MOV TH0,#63H DJNZ R4 , CLKE111 JMP LOOP11 CLKE111: JMP CLKE 课程设计报告 LOOP11: MOV R4,#19H MOV A,SEC ADD A,#1 DA A MOV SEC,A CJNE A, #60H , CLKE99 MOV SEC,#0 MOV A,MINUTE ADD A,#1 DA A MOV MINUTE,A CLK0: CJNE A, # 60H, CLKE MOV MINUTE,#0 MOV A,HOUR ADD A,#1 DA A MOV HOUR,A CJNE A, # 24H, CLKE MOV HOUR,#0 MOV A,DAY 课程设计报告 ADD A,#1 DA A MOV DAY,A MOV A,MONTH INC A MOVC A, @A + PC SJMP CLK1 DB 31H,28H,31H DB 30H,31H,30H DB 31H,31H,30H DB 00H,00H,00H DB 00H,00H,00H DB 31H,30H,31H CLK1: CLR C SUBB A,DAY JNC CLKE MOV A,MONTH CJNE A,#2,CLK3 MOV A,YEAR ANL A,#13H JNB ACC.4,CLK2 课程设计报告 ADD A,#2 CLK2: ANL A,#3 JNZ CLK3 MOV A,DAY XRL A,#29H JZ CLKE CLK3: MOV DAY,#1 MOV A,MONTH ADD A,#1 DA A MOV MONTH,A CJNE A,#13H,CLKE MOV MONTH,#1 MOV A,YEAR ADD A,#1 DA A MOV YEAR,A CLKE99: CALL CONVERT CLKE: 课程设计报告 POP PSW POP ACC RETI DISP: PUSH PSW PUSH ACC MOV 23H,R0 DISP99: MOV R1,#40H MOV R0,#30H MOV R2,#9 DISP1: MOV A,@R0 ANL A,#0FH MOV @R1,A MOV A,@R0 SWAP A ANL A,#0FH INC R1 MOV @R1,A DJNZ R2,DISP2 CALL DISPLAY 课程设计报告 MOV R0,23H POP ACC POP PSW RET DISP2: INC R1 INC R0 JMP DISP1 DISPLAY: MOV R1,#40H MOV R5,#19 SETB AAA PLAY: SETB BBB NOP CLR BBB CLR AAA MOV A,@R1 MOV DPTR,#TAB MOVC A,@A+DPTR MOV COM,A CALL DL1MS 课程设计报告 MOV COM,#0FFH DJNZ R5,PLAY1 CLR BBB SETB AAA RET PLAY1: INC R1 JMP PLAY TAB: DB 0C0H,0F9H,0A4H, 0B0H,99H,92H,82H,0F8H,80H,90H,0FFH,0A3H,8EH,0ABH DL1MS: MOV 25H,R7 MOV 24H,R6 MOV R7,#20 DS1: MOV R6,#10 DJNZ R6,$ DJNZ R7,DS1 MOV R7,25H MOV R6,24H RET 课程设计报告 START_YEAR EQU 01 CONVERT_YEAR DATA 5CH CONVERT_MONTH DATA 38H CONVERT_DATE DATA 37H TEMP_BYTE1 DATA 57H TEMP_BYTE2 DATA 58H TEMP_BYTE3 DATA 59H TEMP_BYTE4 DATA 5AH TEMP_BYTE5 DATA 5BH CONVERT: MOV A, YEAR MOV TIME_YEAR,A MOV A,MONTH MOV TIME_MONTH,A MOV A,DAY MOV TIME_DATA,A MOV A,TIME_YEAR MOV B,#16 DIV AB MOV CONVERT_YEAR,B MOV B,#10 MUL AB 课程设计报告 ADD A,CONVERT_YEAR MOV CONVERT_YEAR,A MOV A,TIME_MONTH JNB ACC.4,CON_02 CLR ACC.4 ADD A,#10 CON_02:MOV CONVERT_MONTH,A MOV A,TIME_DATA MOV B,#16 DIV AB MOV CONVERT_DATE,B MOV B,#10 MUL AB ADD A,CONVERT_DATE MOV CONVERT_DATE,A MOV DPTR,#MONTH_DATA MOV A,CONVERT_YEAR CON_06:CLR C SUBB A,#START_YEAR MOV B,#3 MUL AB ADD A,DPL 课程设计报告 MOV DPL,A MOV A,B ADDC A,DPH MOV DPH,A MOV A, #2 MOVC A, @A+DPTR CLR ACC.7 MOV B, #32 DIV AB MOV TEMP_BYTE1,A MOV TEMP_BYTE2,B MOV TEMP_BYTE3,#0 MOV A,CONVERT_MONTH CJNE A,#10,CON_08 CON_08:JC CON_09 MOV TEMP_BYTE3,#1 CON_09:MOV A,CONVERT_YEAR ANL A,#03H JNZ CON_10 MOV A,CONVERT_MONTH LCALL GET_RUN_DAYS_LOW SJMP CON_12 课程设计报告 CON_10:MOV A,CONVERT_MONTH LCALL GET_DAYS_LOW CON_12:MOV B,CONVERT_DATE DEC B ADD A,B MOV TEMP_BYTE4,A JNC CON_14 INC TEMP_BYTE3 CON_14:MOV A,TEMP_BYTE1 LCALL GET_DAYS_LOW DEC A ADD A,TEMP_BYTE2 MOV TEMP_BYTE5,A MOV A,CONVERT_MONTH CJNE A,TEMP_BYTE1,CON_20 MOV A,CONVERT_DATE CJNE A,TEMP_BYTE2,CON_20 CON_20:JC CON_22 LJMP CON_60 CON_22:MOV A,CONVERT_YEAR JNZ CON_24 MOV A,#100 课程设计报告 CON_24:DEC A MOV CONVERT_YEAR,A MOV A,DPL CLR C SUBB A,#3 MOV DPL,A JNC CON_26 DEC DPH CON_26:MOV A,TEMP_BYTE5 CLR C SUBB A,TEMP_BYTE4 MOV TEMP_BYTE3,A MOV CONVERT_MONTH,#12 CLR F0 CLR A MOVC A,@A+DPTR ANL A,#0F0H SWAP A;MOV TEMP_BYTE4,A JZ CON_30 MOV A, #2 MOVC A , @A+DPTR 课程设计报告 MOV C, ACC.7 MOV A, #1 MOVC A, @A+DPTR RLC A SJMP CON_34 CON_30:MOV A, #1 MOVC A, @A+DPTR CON_34:MOV TEMP_BYTE5, A CON_40:MOV A, TEMP_BYTE5 RRC A MOV TEMP_BYTE5, A JC CON_42 MOV B, #29 SJMP CON_44 CON_42:MOV B, #30 CON_44:MOV A, TEMP_BYTE3 CLR C SUBB A, B JZ CON_46 JNC CON_50 CPL A INC A 课程设计报告 CON_46: INC A MOV B, #10 DIV AB SWAP A ORL A, B MOV CONVERT_DATE, A MOV A, CONVERT_MONTH MOV B, #10 DIV AB SWAP A ORL A, B MOV CONVERT_MONTH, A MOV A, CONVERT_YEAR MOV B, #10 DIV AB SWAP A ORL A, B MOV CONVERT_YEAR, A CALL WEEK RET CON_50:MOV TEMP_BYTE3, A JB F0, CON_52 课程设计报告 DEC CONVERT_MONTH CON_52:MOV A, CONVERT_MONTH CJNE A, TEMP_BYTE4, CON_54 CPL F0 CON_54:SJMP CON_40 CON_60:MOV A, TEMP_BYTE4 CLR C SUBB A, TEMP_BYTE5 MOV TEMP_BYTE4, A JNC CON_62 DEC TEMP_BYTE3 CON_62:MOV CONVERT_MONTH, #1 CLR A MOVC A, @A+DPTR MOV TEMP_BYTE5, A ANL A, #0F0H SWAP A XCH A, TEMP_BYTE5 CLR F0 ANL A, #0FH MOV TEMP_BYTE1, A MOV A, #1 课程设计报告 MOVC A, @A+DPTR MOV TEMP_BYTE2, A ANL A, #0F0H ORL A, TEMP_BYTE1 SWAP A MOV TEMP_BYTE1, A MOV A, #2 MOVC A, @A+DPTR MOV C, ACC.7 MOV A, TEMP_BYTE2 ANL A, # 0FH SWAP A MOV ACC.3, C MOV TEMP_BYTE2, A CON_70:MOV A, TEMP_BYTE2 RLC A MOV TEMP_BYTE2, A MOV A, TEMP_BYTE1 RLC A MOV TEMP_BYTE1, A JC CON_72 MOV B, #29 课程设计报告 SJMP CON_74 CON_72:MOV B, #30 CON_74:MOV A, TEMP_BYTE4 CLR C SUBB A,B JNC CON_78 MOV B, A MOV A, TEMP_BYTE3 JZ CON_76 DEC TEMP_BYTE3 MOV TEMP_BYTE4, B SJMP CON_80 CON_76:MOV A, TEMP_BYTE4 LJMP CON_46 CON_78:MOV TEMP_BYTE4, A CON_80:MOV A, CONVERT_MONTH CJNE A, TEMP_BYTE5, CON_82 CPL F0 JNB F0, CON_82 SJMP CON_70 CON_82:INC CONVERT_MONTH SJMP CON_70 课程设计报告 GET_DAYS_LOW: MOVC A, @A+PC RET DB 0,31,59,90,120,151,181,212,243,17,48,78 GET_RUN_DAYS_LOW: MOVC A, @A+PC RET DB 0,31,60,91,121,152,182,213,244,18,49,79 MONTH_DATA: DB 04DH,04AH,0B8H;2001 DB 00DH,04AH,04CH;2002 DB 00DH,0A5H,041H;2003 DB 025H,0AAH,0B6H;2004 DB 005H,06AH,049H;2005 DB 07AH,0ADH,0BDH;2006 DB 002H,05DH,052H;2007 DB 009H,02DH,047H;2008 DB 05CH,095H,0BAH;2009 DB 00AH,095H,04EH;2010 DB 00BH,04AH,043H;2011 课程设计报告 DB 04BH,055H,037H;2012 DB 00AH,0D5H,04AH;2013 DB 095H,05AH,0BFH;2014 DB 004H,0BAH,053H;2015 DB 00AH,05BH,048H;2016 DB 065H,02BH,0BCH;2017 DB 005H,02BH,050H;2018 DB 00AH,093H,045H;2019 DB 047H,04AH,0B9H;2020 DB 006H,0AAH,04CH;2021 DB 00AH,0D5H,041H;2022 DB 024H,0DAH,0B6H;2023 DB 004H,0B6H,04AH;2024 DB 069H,057H,03DH;2025 DB 00AH,04EH,051H;2026 DB 00DH,026H,046H;2027 DB 05EH,093H,03AH;2028 DB 00DH,053H,04DH;2029 DB 005H,0AAH,043H;2030 DB 036H,0B5H,037H;2031 DB 009H,06DH,04BH;2032 DB 0B4H,0AEH,0BFH;2033 课程设计报告 DB 004H,0ADH,053H;2034 DB 00AH,04DH,048H;2035 DB 06DH,025H,0BCH;2036 DB 00DH,025H,04FH;2037 DB 00DH,052H,044H;2038 DB 05DH,0AAH,038H;2039 DB 00BH,05AH,04CH;2040 DB 005H,06DH,041H;2041 DB 024H,0ADH,0B6H;2042 DB 004H,09BH,04AH;2043 DB 07AH,04BH,0BEH;2044 DB 00AH,04BH,051H;2045 DB 00AH,0A5H,046H;2046 DB 05BH,052H,0BAH;2047 DB 006H,0D2H,04EH;2048 DB 00AH,0DAH,042H;2049 DB 035H,05BH,037H;2050 DB 009H,037H,04BH;2051 DB 084H,097H,0C1H;2052 DB 004H,097H,053H;2053 DB 006H,04BH,048H;2054 DB 066H,0A5H,03CH;2055 课程设计报告 DB 00EH,0A5H,04FH;2056 DB 006H,0B2H,044H;2057 DB 04AH,0B6H,038H;2058 DB 00AH,0AEH,04CH;2059 DB 009H,02EH,042H;2060 DB 03CH,097H,035H;2061 DB 00CH,096H,049H;2062 DB 07DH,04AH,0BDH;2063 DB 00DH,04AH,051H;2064 DB 00DH,0A5H,045H;2065 DB 055H,0AAH,0BAH;2066 DB 005H,06AH,04EH;2067 DB 00AH,06DH,043H;2068 DB 045H,02EH,0B7H;2069 DB 005H ,02DH, 04BH;2070 DB 08AH, 095H, 0BFH;2071 DB 00AH, 095H, 053H;2072 DB 00BH, 04AH, 047H;2073 DB 06BH, 055H, 03BH;2074 DB 00AH, 0D5H, 04FH;2075 DB 005H, 05AH, 045H;2076 DB 04AH, 05DH, 038H;2077 课程设计报告 DB 00AH, 05BH, 04CH;2078 DB 005H, 02BH, 042H;2079 DB 03AH, 093H, 0B6H;2080 DB 006H, 093H, 049H;2081 DB 077H, 029H, 0BDH;2082 DB 006H, 0AAH, 051H;2083 DB 00AH, 0D5H, 046H;2084 DB 054H, 0DAH, 0BAH;2085 DB 004H, 0B6H, 04EH;2086 DB 00AH, 057H, 043H;2087 DB 045H, 027H, 038H;2088 DB 00DH, 026H, 04AH;2089 DB 08EH, 093H, 03EH;2090 DB 00DH, 052H, 052H;2091 DB 00DH, 0AAH, 047H;2092 DB 066H, 0B5H, 03BH;2093 DB 005H, 06DH, 04FH;2094 DB 004H, 0AEH, 045H;2095 DB 04AH, 04EH, 0B9H;2096 DB 00AH, 04DH, 04CH;2097 DB 00DH, 015H, 041H;2098 DB 02DH, 092H, 0B5H;2090 课程设计报告 DB 00DH, 053H, 049H;2100 TIME_WEEK1 DATA 52H WEEK: MOV A, TIME_YEAR MOV B, #16 DIV AB MOV TEMP_BYTE1, B MOV B, #10 MUL AB ADD A, TEMP_BYTE1 MOV TEMP_BYTE1, A MOV A, TIME_MONTH JB ACC.7, GETW02 MOV A, #100 ADD A, TEMP_BYTE1 MOV TEMP_BYTE1, A MOV A, TIME_MONTH CLR ACC.7 GETW02: JNB ACC.4, GETW04 ADD A , #10 CLR ACC.4 GETW04: MOV TEMP_BYTE2,A 课程设计报告 MOV A, TIME_DATA MOV B, #16 DIV AB MOV TEMP_BYTE3, B MOV B, #10 MUL AB ADD A, TEMP_BYTE3 MOV TEMP_BYTE3, A MOV A ,TEMP_BYTE1 ANL A, #03H JNZ GETW10 MOV A, TEMP_BYTE2 CJNE A, #3,GETW06 GETW06: JNC GETW10 DEC TEMP_BYTE3 GETW10: MOV A,TEMP_BYTE2 LCALL GET_CORRECT ADD A, TEMP_BYTE1 MOV B, #7 DIV AB MOV A, TEMP_BYTE1 课程设计报告 ANL A, #0FCH RR A RR A ADD A, B ADD A, TEMP_BYTE3 MOV B, #7 DIV AB MOV A, B CJNE A, #0,OUTOUT MOV B, #8 OUTOUT: MOV TIME_WEEK, B RET GET_CORRECT: MOVC A, @A+PC RET DB 0,3,3,6,1,4,6,2,5,0,3,5 END 系统仿真及调试 课程设计报告 仿真结果及分析 课程设计报告 上图为运行时的显示,左边两个数码管显示器显示的是年、月、日,中间的显示的是时、分、秒,右边显示的是农历日期以及星期。若想要调试时间,可通过右下方两个并联开关调试,左边开关调试数码管显示位置,右边的调试增1。此刻是2013年11月29日下午15:02,星期五,时间准确。训练体会 在整个单片机课程设计中,想要做出这个完整的设计过程,必须突破几个难点: 1、元件得找准却,6路驱动可以用74LS244代替。 2、连线不能连错,对应的输入输出端标上序号。 3、程序代码不能敲错。 4、由于单管显示的星期数不稳定,可以采用双管显示。参考文献:单片机课程设计指导。 单片机万年历实训报告 系 部:电气自动化系 班 级:13电信2班 姓 名:周祝福 指导老师:黄丽英、侯聪玲 实训时间:2015年1月19日~23日 用AT89C51与LCD1602设计 的可调式电子日历时钟 一、总体设计 1.1、设计目的 为巩固所学的单片机知识,把所学理论运用到实践中,用LCD1602与AT89C51 设计可调式电子日历时钟。 1.2、设计要求 (1)显示:年、月、日、时、分、秒和星期; (2)设置年、月、日、时、分、秒和星期的初始状态; (3)能够用4个按键调整日历时钟的年、月、日、时、分、秒和星期 ; 完成可调式电子日历时钟的硬件和软件的设计,包括单片机的相关内容;日历时钟模块的设计,液晶显示模块的设计,按键模块的设计。控制程序的编写等。 1.3、系统基本方案选择和论证 1.3.1、单片机芯片的选择方案 方案一: 采用89C51芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容。方案二: 采用STC12C5A60S2系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换(250K/S),针对电机控制,强干扰场合。但造价较高。1.3.2、显示模块选择方案和论证: 方案一: 采用点阵式数码管显示,点阵式数码管是由八行八列的发光二极管组成,对于显示文字比较适合,如采用显示数字显得太浪费,且价格也相对较高。所以不用此种作为显示。方案二: 采用LED数码管动态扫描,虽然LED数码管价格适中,但要显示多个数字所需要的个数偏多,功耗较大,显示出来的只是拼音,而不是汉字。所以也不用此种作为显示。方案三: 采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量字符,且视觉效果较好,外形美观。LCD1602可实现显示2行十六个字符。1.3.4、电路设计最终方案决定 综上各方案所述,对此次作品的方案选定:采用80C51作为主控制系统; LCD1602液晶带汉字库显示屏作为显示部分。 二、硬件设计 2.1、电路设计模块图如图 AT89C51 块按键控制模LCD162 2.3、用proteus仿真软件仿真并抓图。 三、软件设计 3.1、画出各个函数流程图。 3.1.1、LCD1602液晶显示控制流程图如图 入口 对1602初始化写入显示设置命令 延时一段时间 检查忙标志 BF= 7>? 设置字符显示位置 延时一段时间 向1602中写入数据 LCD显示内容 返回主程序 是 3.1.2、调时函数控制流程如图 开始 控制键有效,调整年 控制键有效,调整月 等待按键程序 等待按键程序 加有效 减有效 加有效 减有效 年加 1 年减 1 月加 1 月减 1 控制键有效,调整日 控制键有效,调整星期 等待按键程序 等待按键程序 加有效 减有效 加有效 减有效 日加 1 日减 1 星期加 1 星期减 1 控制键有效,调整时 等待按键程序 加有效 时加 1 减有效 时减 1 控制键有效,调整分 等待按键程序 加有效 分加 1 减有效 分减 1 按键有效跳出调时程序,进入主循环 实训心得:通过为期一周的单片机实训,是我们对这门课有了许多新的了解,弥补了在课堂上学习的不足。相信这对我们以后的学习和工作都会有很大的帮助。我们一定要在最短的时间里对这些不足加以改正!在试训中有苦有甜,当我们为一个很难攻破的程序找出路时,心情烦躁,感觉自己很不可理喻,当程序一点一点编好后,自己从心底感觉到一点小小的安慰,看着自己的成果。感觉很欣慰。总而言之,单片机课程设计对于我们有很大的帮助,我们从中受益匪浅。 程序代码。 #include uchar a,count,S1num,xqnum;uchar yue,ri,shi,fen,miao;uint nian; sbit lcdrs=P2^5;sbit lcdrw=P2^4;sbit lcden=P2^3; sbit S1=P3^0; //定义键--进入设置 sbit S2=P3^1; //定义键--增大 sbit S3=P3^2; //定义键--减小 sbit S4=P3^3; //定义键--退出设置 uchar code table0[]=“2015-01-11 SUN”;uchar code table1[]=“00:00:00”;uchar code xingqi[][3]={“MON”,“TUE”,“WED”,“THU”,“FRI”,“SAT”,“SUN”}; void delay(uint z){ uint x,y;for(x=z;x>0;x--) for(y=110;y>0;y--);} /************************************************** 1602液晶显示器模块 *************************************************/ void write_com(uchar com) //液晶写指令 { lcdrw=0;lcdrs=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;} void write_data(uchar dat) //液晶写数据 { lcdrw=0;lcdrs=1;P0=dat;delay(5);lcden=1;delay(5);lcden=0;} /******************************************** 年月日写入1602函数 ********************************************/ void write_sfm(uchar add,uchar dat) //写时分秒函数 { uchar shi,ge;shi=dat/10;ge=dat%10;write_com(0x80+0x40+add);write_data(0x30+shi);write_data(0x30+ge);} void write_yr(uchar add,uchar dat) //写月日函数 { uchar shi,ge;shi=dat/10;ge=dat%10;write_com(0x80+add);write_data(0x30+shi);write_data(0x30+ge);} void write_nian(uchar add,uint dat) //写年函数 { uint qian,bai,shi,ge;qian=dat/1000;bai=dat%1000/100;shi=dat%100/10;ge=dat%10;write_com(0x80+add);write_data(0x30+qian);write_data(0x30+bai);write_data(0x30+shi);write_data(0x30+ge);} /*************************************************** 1602初始化 ***************************************************/ void init_lcd() //液晶初始化 { lcden=0; nian=2015;yue=1;ri=11;shi=0; //初始shi、fen、miao fen=0;miao=0; write_com(0x38); //设置16x2显示,5x7点阵,8位数据口 write_com(0x0c); //设置开显示,不显示光标 write_com(0x06); //写一个字符后地址指针加1 write_com(0x01); //显示清0,数据指针清0 } void init() //初始化函数 { init_lcd(); //液晶初始化 write_com(0x80); //设置显示初始坐标 for(a=0;a<14;a++) //显示年月日初始值 { write_data(table0[a]); delay(5);} write_com(0x80+0x40); //设置显示初始坐标 for(a=0;a<8;a++) //显示时分秒初始值 { write_data(table1[a]); delay(5);} write_nian(0,nian);write_sfm(6,miao); //分别将shi、fen、miao送去液晶显示 write_sfm(3,fen);write_sfm(0,shi); count=0;xqnum=0;S1num=0; //初始化全局变量count TMOD=0x01; //设置定时器0工作模式1 TH0=(65535-50000)/256; //定时器装初始值 TL0=(65535-50000)%256;EA=1; //开总中断 ET0=1; //开定时器0中断 TR0=1; //启动定时器0 } /************************************************** 独立键盘 *************************************************/ void keyscan(){ if(S1==0){ delay(5); //确认定义键被按下 if(S1==0) { S1num++; //定义键S1按下次数记录 while(!S1); //释放按键确认 if(S1num==1)//S1按下一次时 { TR0=0; //关闭定时器 write_com(0xc0+7);//光标定位到秒位置 write_com(0x0f);//光标闪烁 } if(S1num==2) //S1按下两次时 { write_com(0xc0+4);//光标定位到分位置 } if(S1num==3) //S1按下三次时 { write_com(0xc0+1); //光标定位到时位置 } if(S1num==4) //S1按下四次时 { write_com(0x80+13); //光标定位到星期位置 } if(S1num==5) //S1按下五次时 { write_com(0x80+9); //光标定位到日位置 } if(S1num==6) //S1按下六次时 { write_com(0x80+6); //光标定位到月位置 } if(S1num==7) //S1按下七次时 { write_com(0x80+3); //光标定位到年位置 } if(S1num==8) //S1按下八次时 { S1num=0; //S1记录按键次数清零 TR0=1; //开启定时器 write_com(0x0c); //取消光标闪烁 } } } if(S1num!=0) //只有定义键按下后S2、S3、S4才有效 { if(S2==0){ delay(5); //防抖 if(S2==0) //确认按键被按下 { while(!S2); //释放按键确认 if(S1num==1)//S1按下一次时 { miao++; //调整秒加1 if(miao==60)//满60清零 miao=0; write_sfm(6,miao); //每调节一次送液晶显示一次 write_com(0x80+0x40+6); //显示位置重新回到调节处 } if(S1num==2) //S1按下两次时 { fen++; //调整分加1 if(fen==60) fen=0;write_sfm(3,fen);write_com(0x80+0x40+3);} if(S1num==3) //S1按下三次时 { shi++; //调整时加1 if(shi==24) shi=0;write_com(0x80+0x40);write_sfm(0,shi);} if(S1num==4) { xqnum++;if(xqnum==7) xqnum=0;write_com(0x80+0x0b);for(a=0;a<3;a++){ write_data(xingqi[xqnum][a]); delay(5);} } if(S1num==5) { ri++;if(yue==2){ if(nian%400==0) { if(ri==30) { ri=1; } } if(nian%400!=0) { if(ri==29) { ri=1; } //星期加调整 //日加调整 } } else if(yue<=7){ if(yue%2==0&yue!=2) { if(ri==31) { ri=1; } } else if(yue%2!=0&yue!=2) { if(ri==32) { ri=1; } } } else if(yue>=8){ if(yue%2==0) { if(ri==32) { ri=1; } } else if(yue%2!=0) { if(ri==31) { ri=1; } } } write_yr(8,ri);} if(S1num==6) { yue++;if(yue==13) yue=1;write_yr(5,yue); //月加调整 } if(S1num==7) //年加调整 { nian++; if(nian==2019) nian=2014; write_nian(0,nian); } } } if(S3==0){ delay(5);if(S3==0) //确认按键被按下 { while(!S3); if(S1num==1) { miao--; //调整秒减1 if(miao==-1) //减到00后再减重新设置为59 miao=59; write_sfm(6,miao); write_com(0x80+0x40+6); } if(S1num==2) { fen--; //调整分减1 if(fen==-1) fen=59; write_sfm(3,fen); write_com(0x80+0x40+3); } if(S1num==3) { shi--; //调整时减1 if(shi==-1) shi=23; write_sfm(0,shi); write_com(0x80+0x40); } if(S1num==4) { xqnum--; //调整星期减一 if(xqnum==-1) xqnum=6;write_com(0x80+0x0b);for(a=0;a<3;a++){ write_data(xingqi[xqnum][a]); delay(5);} } if(S1num==5) //调整日 { ri--; if(yue==2){ if(nian%400==0) { if(ri==0) { ri=29; } } if(nian%400!=0) { if(ri==0) { ri=28; } } } else if(yue<=7) { if(yue%2==0&yue!=2) { if(ri==0) { ri=30; } } else if(yue%2!=0&yue!=2) { if(ri==0) { ri=31; } } } else if(yue>=8) { if(yue%2==0) { if(ri==0) { ri=31; } } else if(yue%2!=0) { if(ri==0) { ri=30; } } } write_yr(8,ri); } if(S1num==6) { yue--; if(yue==0) yue=12; write_yr(5,yue); } if(S1num==7) { nian--; if(nian==2013) nian=2018; write_nian(0,nian); } } } if(S4==0) { delay(5);if(S4==0){ S1num=0; TR0=1; write_com(0x0c); //调整月 //调整年 //退出设置、开启中断 } } } } /************************************************** 定时器0 *************************************************/ void timer0()interrupt 1 //定时器0中断服务程序 { TH0=(65535-50000)/256; //重装定时器初始值 TL0=(65535-50000)%256;count++; //中断次数累加 if(count==20) //20次50毫秒即一秒 { count=0; miao++; if(miao==60) //秒加到60时分进位 { miao=0; fen++; if(fen==60) //分加到60时时进位 { fen=0; shi++; if(shi==24) //时加到24时清0 { shi=0; xqnum++; ri++; if(yue==2) //如果是二月 { if(nian%400==0) //闰年判断 { if(ri==30) { ri=1; yue++; write_yr(5,yue); } } if(nian%400!=0) //平年判断 { if(ri==29) { ri=1; yue++; write_yr(5,yue); } } } else if(yue<=7&yue!=2) //一月到七月 { if(yue%2==0)//偶数月(除二月) { if(ri==31) { ri=1; yue++; } } else if(yue%2!=0) //奇数月 { if(ri==32) { ri=1; yue++; } } write_yr(5,yue); } else if(yue>=8) //八月到12月 { if(yue%2==0)//偶数月(除二月) { if(ri==32) { ri=1; yue++; if(yue==13) //如果判断月份为12月,则加一后重新定义月份为1 { yue=1; nian++; write_nian(0,nian); } write_yr(5,yue); } } else if(yue%2!=0) //奇数月 { if(ri==31) { ri=1; yue++; write_yr(5,yue); } } } write_yr(8,ri); if(xqnum==7) //星期写入 xqnum=0; write_com(0x80+0x0b); for(a=0;a<3;a++) { write_data(xingqi[xqnum][a]); delay(5); } } write_sfm(0,shi); //重新写入数据 } write_sfm(3,fen); //重新写入数据 } write_sfm(6,miao); //重新写入数据 } } /************************************************* 主函数 *************************************************/ void main(){ init();while(1){ keyscan(); //不停的检测按键是否被按下 } } 实验报告 姓名:文可鑫学号:20072121010专业:电子信息工程 1编写一个秒表程序,使用查询方式。 listp=16f877a include“p16f877a.inc” include countequ20h count_sequ21h org000h startnop callInitSPI bankselOPTION_REG movlw04h movwfOPTION_REG bankselINTCON movlw00h movwfINTCON movlw06h movwfTMR0 movlwd'131' movwfcount movlw00h movwfcount_s mainbtfssINTCON,T0IF goto$-1 movlw06h movwfTMR0 bcfINTCON,T0IF incfcount,f btfssSTATUS,Z gotomain movlwd'131' movwfcount incfcount_s,f movfcount_s,w sublwd'60' btfscSTATUS,Z clrfcount_s movfcount_s,w callBin2BCD movfDIS_TEMP2,w callCHAR_CODE1 movwfDIS_TEMP2movfDIS_TEMP1,wcallCHAR_CODE1movwfDIS_TEMP1callLEDlightnop gotomain CHAR_CODE1;共阴极字符表 ADDWF PCL,F RETLW 3fh;0RETLW 06h;1RETLW 5bh;2RETLW 4fh;3RETLW 66h;4RETLW 6dh;5RETLW 7dh;6RETLW 07h;7RETLW 7fh;8RETLW 6fh;9 Bin2BCD CLRF DIS_TEMP1MOVWF DIS_TEMP2 Ttenth MOVLW.10SUBWF DIS_TEMP2,WBTFSS STATUS,CGOTO OUT MOVWF DIS_TEMP2INCF DIS_TEMP1,FGOTO Ttenth OUT RETURN end 2编写一个秒表程序,使用中断方式。listp=16f877a include“p16f877a.inc” include gotointp startnop callInitSPIbankselOPTION_REGmovlw44h movwfOPTION_REGbankselINTCONmovlw0a0hmovwfINTCONmovlw06hmovwfTMR0movlwd'131'movwfcountmovlw00hmovwfcount_s heregotohere intp btfssINTCON,T0IFgoto$-1movlw06hmovwfTMR0 bcfINTCON,T0IFincfcount,fbtfssSTATUS,Zgotointpmovlwd'131'movwfcountincfcount_s,fmovfcount_s,wsublwd'60'btfscSTATUS,Zclrfcount_smovfcount_s,wcallBin2BCDmovfDIS_TEMP2,wcallCHAR_CODE1movwfDIS_TEMP2movfDIS_TEMP1,wcallCHAR_CODE1movwfDIS_TEMP1callLEDlightnop RETFIE CHAR_CODE1;共阴极字符表 ADDWF PCL,F RETLW 3fh;0RETLW 06h;1RETLW 5bh;2RETLW 4fh;3RETLW 66h;4RETLW 6dh;5RETLW 7dh;6RETLW 07h;7RETLW 7fh;8RETLW 6fh;9 Bin2BCD CLRF DIS_TEMP1MOVWF DIS_TEMP2 TtenthMOVLW.10SUBWF DIS_TEMP2,WBTFSS STATUS,CGOTO OUT MOVWF DIS_TEMP2INCF DIS_TEMP1,FGOTO Ttenth OUT RETURN end CHAR_CODE1;共阴极字符表 ADDWF PCL,F RETLW 3fh;0RETLW 06h;1RETLW 5bh;2RETLW 4fh;3RETLW 66h;4RETLW 6dh;5RETLW 7dh;6RETLW 07h;7RETLW 7fh;8RETLW 6fh;9 Bin2BCD CLRF DIS_TEMP1MOVWF DIS_TEMP2 Ttenth MOVLW.10SUBWF DIS_TEMP2,WBTFSS STATUS,CGOTO OUT MOVWF DIS_TEMP2INCF DIS_TEMP1,FGOTO Ttenth OUT RETURN end listp=16f877a include“p16f877a.inc” include callInitSPIbankselOPTION_REGmovlw04h movwfOPTION_REGbankselINTCONmovlw00hmovwfINTCONmovlw06hmovwfTMR0movlwd'131'movwfcountmovlw00hmovwfcount_s heregotohere intpbtfssINTCON,T0IFgoto$-1movlw06hmovwfTMR0 bcfINTCON,T0IFincfcount,fbtfssSTATUS,Zgotointpmovlwd'131'movwfcountincfcount_s,fmovfcount_s,w sublwd'60'btfscSTATUS,Zclrfcount_smovfcount_s,wcallBin2BCDmovfDIS_TEMP2,wcallCHAR_CODE1movwfDIS_TEMP2movfDIS_TEMP1,wcallCHAR_CODE1movwfDIS_TEMP1callLEDlightnop RETFIE CHAR_CODE1;共阴极字符表 ADDWF PCL,F RETLW 3fh;0RETLW 06h;1RETLW 5bh;2RETLW 4fh;3RETLW 66h;4RETLW 6dh;5RETLW 7dh;6RETLW 07h;7RETLW 7fh;8RETLW 6fh;9 Bin2BCD CLRF DIS_TEMP1MOVWF DIS_TEMP2 Ttenth MOVLW.10SUBWF DIS_TEMP2,WBTFSS STATUS,CGOTO OUT MOVWF DIS_TEMP2INCF DIS_TEMP1,FGOTO Ttenth OUT RETURN end第二篇:单片机课程设计-电子万年历
第三篇:万年历单片机课程设计报告
第四篇:单片机万年历实训报告
第五篇:基于PIC单片机电子万年历实验报告