成绩
课程设计报告
题 目 定时插座
课 程 名 称 单片机原理及接口技术 院 部 名 称 机电工程学院 专 业 自动化 班 级 09自动化 学 生 姓 名 吴程剑 学 号 0904105003 课程设计地点 C314 课程设计学时 一周 指 导 教 师 高峰
金陵科技学院教务处制
目录
一:概述
二:设计要求和设计思路及方案 2.1设计要求 2.2设计思路 2.3设计方案 三:硬件电路设计 3.1按键设计电路 3.2数码管显示电路
3.3 DS1302电路和AT24C02电路 3.4继电器电路 四:软件设计
五:系统调试及软件仿真 六:总结
一、概述
随着科学技术特别是微型计算机技术的高速发展,单片机微机技术也获得了飞速发展。目前,单片机已经在日常生活和控制领域等方面得到了广泛的应用,它正为我国经济的快速发展发挥着举足轻重的作用。作为自动化专业的一名工科学生应该牢牢掌握这一重要技术。而课程设计这一环节是我们提高单片机应用能力的很好机会,也是我们学好这一课程的必经环节。通过课程设计可以进一步巩固我们前面所学的理论知识,使我们对单片机理论知识有一个深刻的认识和全面的掌握。另外通过这一真正意义上的实践活动,我们可以从中发现自己的不足之处并能够在自己的深思下和老师的指导下得到及时的解决。再次,它能使我们的应用能力和科技创新能力得到较大的提高。
单片机作为嵌入式微控制器在工业测控系统,智能仪器和家用电器中得到广泛应用。虽然单片机的品种很多,但MCS-51系列单片机仍不失为单片机中的主流机型。本课程一MCS-51系列以及派生系列单片机芯片为主介绍单片机的原理及应用,其特点是由浅入深,注重接口技术和应用。
二、设计要求和设计思路及方案
2.1 设计要求
本次课程设计用STC89C52作为主控器做一个定时插座。实现
一个具有定时、按键设置及控制、定时时间显示等功能的定时开关插座,具体要求和指标如下:
(1) 可以设定三组定时时间值。 (2) 设定的定时可调整的时间范围。 (3) 具有开始/停止操作按键。 (4) 具有定时时间显示和时钟显示。 2.2设计思路
为了确定其设计方案,首先必须构思好初步的设计思路。根据设计要求和实验仿真条件,初步的设计思路可以总结如下:
(1)用DS1302芯片处理当前时间并用8位数码管显示。 (2)用AT24C02芯片存储预先设定好的密码。 (3)设置模式:常开模式、常闭模式、定时模式
(4)设置开关时间:先按设置键出现01 on,再按小时和分钟键调节时间,调节好后再按设置键出现01 off,再调节时间,按确认键,这样就设置好一组定时时间。设置其他组方法相同。 2.3设计方案
根据设计要求和设计思路,可以确定系统的设计方案,图1为该系统设计的硬件电路图设计框图。硬件主要由6部分组成,即单片机,键盘,数码管显示,DS1302芯片,AT24C02芯片,继电器。 STC89C52介绍
VCC:供电电压。 GND:接地。
P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8个TTL门电流。当P0口的管脚第一次写“1”时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。 P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4个TTL门电流。P1口管脚写入“1”后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将
输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为第八位地址接收。
P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。
P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。P3口作为AT89C51的一些特殊功能口,管脚 备选功能 P3.0 RXD(串行输入口) P3.1 TXD(串行输出口) P3.2 /INT0(外部中断0) P3.3 /INT1(外部中断1) P3.4 T0(计时器0外部输入) P3.5 T1(计时器1外部输入)
P3.6 /WR(外部数据存储器写选通) P3.7 /RD(外部数据存储器读选通)
RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。
ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。
在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。 /PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。/EA / VPP:当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。 XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。 XTAL2:来自反向振荡器的输出。
在单片机中,定时功能既可以由硬件(定时/计数器)实现,也可通过软件定时实现。硬件定时是利用单片机内定时器定时,启动以后定时器可与CPU并行工作,不占用CPU时间,CPU有较高的工作效率。采用硬件定时和软件定时比用的方式,即用T0溢出中断功能实现50ms定时,通过软件延时程序实现5s定时。定时器的TMOD用于设置定时器/计数器的工作方式,并确定用于定时还是计数。TCON只要功能是为定时器在溢出时设定标志位,并控制定时器运行或
停
止
。
数码管显示
继电器 按键
DS1302 MCU AT24C02
图1:硬件电路设计
三、硬件电路设计
3.1按键设计电路
对于按键电路的设计可以有2种方式:一种方式是独立按键设计,这种设计电路适用于按键较少的控制,具有按键电路简单,编程方便等优点;另一种方式是矩阵方式键盘的设计,它适用于对控制按键较多的电路控制,占用较少的I/O接口,但是按键电路复杂,编程比较复杂。本课题总共需要6个按键,所以采用矩阵式键盘,如图2
图2:按键电路
3.2数码管显示电路
本课题所采用的是数码管作为显示电路,用来显示当前的时间及密码门时输入的密码。硬件电路连接是单片机P0口接2片74hc573锁存芯片,两片芯片的输出端分别接数码管的段选端跟位选端。这样P0口不断送出位码跟断码锁存可以实现数码管的动态显示。连接方法如图3所示。
图3:数码管显示电路
3.3 DS1302电路和AT24C02电路
24C02的SCK,SDA,WP引脚分别接单片机的P2.0,P2.1引脚和地。DS1302的RST,SCLK,I/O引脚分别接单片机的P1.3,P1.7和P2.3引
脚
。
电
路
图
如
图
4
所
示
。
图4:DS1302和24C02连接电路
3.4继电器电路
继电器的线圈一端接电源vcc一端接ULN2003的12脚。ULN2003是8个非门,可以耐高压等,用来驱动继电器。电路连接图如图5所示。
图5:继电器连接电路
四、软件设计主程序流程图
Y
是否有键按下? 读取当前时间并显示 开始 N
按确认键 调节时间 模式循环 设置键 模式
五、系统调试和软件仿真
5.1程序调试部分:
uVsion3先新建一个工程,选择芯片为AT89C52然后点击是,然后弹出来是否加入标准启动文件,点击否,然后新建一个文件,保存为“main.c”。然后双击工程窗口的Target选择添加文件到工程,选刚才新建的文件然后点击OK,输入程序,点击工程选择,选中Output中的Creat Hex File,然后编译,连接生成Hex文件,有错误修改后再编译连接。当编译结果中不出现错误时说明已经没有语法错误,但是否能完成课题所需要的功能则需要进行仿真。 5.2软件仿真部分:
运行proteus的ISIS后进入仿真界面将所需元件选择好,根据原
理图画出仿真图,待仿真图画好后双击AT89C52导入Keil所产生的后缀名为.HEX文件。按开始键进行仿真。
实验程序: #include sbit buzz=P0^6; sbit relay=P0^4; #define uchar unsigned char #define uint unsigned int typedef struct SYSTEMTIME { }; struct SYSTEMTIME clock,time; uchar tempdata[8],temp[8],disTime[8]; uchar keynum,n,setflag,modeflag,hour_temp,min_temp; bit flag,onflag,offflag; void read_time(struct SYSTEMTIME *p) //结构体形参 { } p->hour = read_DS1302(0x85); p->min = read_DS1302(0x83); p->sec = read_DS1302(0x81); uchar min; uchar hour; uchar sec; main() { uchar i,j; buzz=0;relay=0; ULN2003_Latch(); buzz=0;relay=0; ULN2003_Latch(); DS1302_init(); //初始化,第一次下载后将其屏蔽 while(1) { read_time(&clock); disTime[0] = clock.hour>>4; //时十位 disTime[1] = clock.hour&0x0f; //时个位 disTime[2] = 10; disTime[3] = clock.min>>4; //分十位 disTime[4] = clock.min&0x0f; //分个位 disTime[5] = 10; disTime[6] = clock.sec>>4; //秒十位 disTime[7] = clock.sec&0x0f; //秒个位 hour_temp=disTime[0]*10+disTime[1]; //转换成十进制 小时 min_temp=disTime[3]*10+disTime[4]; //转换成十进制 分钟 keynum=KeyPro(); switch(keynum) { case 0:{ } case 1:{ setflag++; if(setflag==2) { wrbyte_24c02(n*2,time.hour); wrbyte_24c02(n*2+1,time.min); n++; } time.hour=0; time.min=0; flag=0; break; time.hour++; if(time.hour==24) time.hour=0; flag=1; } break; case 2:{ time.min++; } case 3:{ } case 4:{ if(time.min==60) time.min=0; flag=1; break; wrbyte_24c02(n*2,time.hour); wrbyte_24c02(n*2+1,time.min); flag=0; setflag=0; n++; break; modeflag++; if(modeflag==3) modeflag=0; break; } } case 5:{ } flag=0; setflag=0; modeflag=0; onflag=0; offflag=0; while(n!=0) { } break; wrbyte_24c02((n-1)*2,0); wrbyte_24c02((n-1)*2+1,0); n--; default:break; switch(setflag) { case 1:{ temp[0]=(n/2+1)/10; temp[1]=(n/2+1)%10; } } temp[2]=11; temp[3]=0; temp[4]=13; temp[5]=11; temp[6]=11; temp[7]=11; break; case 2:{ } temp[0]=(n/2+1)/10; temp[1]=(n/2+1)%10; temp[2]=11; temp[3]=0; temp[4]=14; temp[5]=14; temp[6]=11; temp[7]=11; break; default:break; switch(modeflag) { case 0:{ } buzz=0;relay=0; ULN2003_Latch(); break; case 1:{ } buzz=0;relay=1; ULN2003_Latch(); break; case 2:{ for(j=0;j onflag=1; offflag=0; if(hour_temp==read(4*j+2)&&min_temp==read(4*j+3)) } } { } onflag=0; offflag=1; if(onflag) { } if(offflag) { } if(!offflag&&!onflag) { } break; buzz=0;relay=0; ULN2003_Latch(); buzz=0;relay=0; ULN2003_Latch(); buzz=0;relay=1; ULN2003_Latch(); } default:break; if(!setflag&&!flag) { } if(setflag&&!flag) { } if(setflag&&flag) { tempdata[0]=time.hour/10; tempdata[1]=time.hour%10; tempdata[2]=10; tempdata[3]=time.min/10; tempdata[4]=time.min%10; tempdata[5]=10; tempdata[6]=0; tempdata[7]=0; for(i=0;i<8;i++) tempdata[i]=temp[i]; for(i=0;i<8;i++) tempdata[i]=disTime[i]; } } display(tempdata); REG52.H Header file for generic 80C52 and 80C32 microcontroller. Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc. All rights reserved. --------------------------------------------------------------------------*/ #ifndef __REG52_H__ #define __REG52_H__ /* BYTE Registers */ sfr P0 = 0x80; sfr P1 = 0x90; sfr P2 = 0xA0; sfr P3 = 0xB0; sfr PSW = 0xD0; sfr ACC = 0xE0; sfr B = 0xF0; sfr SP = 0x81; sfr DPL = 0x82; sfr DPH = 0x83; sfr PCON = 0x87; sfr TCON = 0x88; sfr TMOD = 0x89; sfr TL0 = 0x8A; sfr TL1 = 0x8B; sfr TH0 = 0x8C; sfr TH1 = 0x8D; sfr IE = 0xA8; sfr IP = 0xB8; sfr SCON = 0x98; sfr SBUF = 0x99; /* 8052 Extensions sfr T2CON = 0xC8; sfr RCAP2L = 0xCA; sfr RCAP2H = 0xCB; sfr TL2 = 0xCC; sfr TH2 = 0xCD; */ /* BIT Registers */ /* PSW */ sbit CY = PSW^7; sbit AC = PSW^6; sbit F0 = PSW^5; sbit RS1 = PSW^4; sbit RS0 = PSW^3; sbit OV = PSW^2; sbit P = PSW^0; //8052 only /* TCON */ sbit TF1 = TCON^7; sbit TR1 = TCON^6; sbit TF0 = TCON^5; sbit TR0 = TCON^4; sbit IE1 = TCON^3; sbit IT1 = TCON^2; sbit IE0 = TCON^1; sbit IT0 = TCON^0; /* IE */ sbit EA = IE^7; sbit ET2 = IE^5; //8052 only sbit ES = IE^4; sbit ET1 = IE^3; sbit EX1 = IE^2; sbit ET0 = IE^1; sbit EX0 = IE^0; /* IP */ sbit PT2 = IP^5; sbit PS = IP^4; sbit PT1 = IP^3; sbit PX1 = IP^2; sbit PT0 = IP^1; sbit PX0 = IP^0; /* P3 */ sbit RD = P3^7; sbit WR = P3^6; sbit T1 = P3^5; sbit T0 = P3^4; sbit INT1 = P3^3; sbit INT0 = P3^2; sbit TXD = P3^1; sbit RXD = P3^0; /* SCON */ sbit SM0 = SCON^7; sbit SM1 = SCON^6; sbit SM2 = SCON^5; sbit REN = SCON^4; sbit TB8 = SCON^3; sbit RB8 = SCON^2; sbit TI = SCON^1; sbit RI = SCON^0; /* P1 */ sbit T2EX = P1^1; // 8052 only sbit T2 = P1^0; // 8052 only /* T2CON */ sbit TF2 = T2CON^7; sbit EXF2 = T2CON^6; sbit RCLK = T2CON^5; sbit TCLK = T2CON^4; sbit EXEN2 = T2CON^3; sbit TR2 = T2CON^2; sbit C_T2 = T2CON^1; sbit CP_RL2 = T2CON^0; #endif INTRINS.H Intrinsic functions for C51. Copyright (c) 1988-2004 Keil Elektronik GmbH and Keil Software, Inc. All rights reserved. --------------------------------------------------------------------------*/ #ifndef __INTRINS_H__ #define __INTRINS_H__ extern void _nop_ (void); extern bit _testbit_ (bit); extern unsigned char _cror_ (unsigned char, unsigned char); extern unsigned int _iror_ (unsigned int, unsigned char); extern unsigned long _lror_ (unsigned long, unsigned char); extern unsigned char _crol_ (unsigned char, unsigned char); extern unsigned int _irol_ (unsigned int, unsigned char); extern unsigned long _lrol_ (unsigned long, unsigned char); extern unsigned char _chkfloat_(float); extern void _push_ (unsigned char _sfr); extern void _pop_ (unsigned char _sfr); #endif #ifndef __DISPLAY_H__ #define __DISPLAY_H__ #define uchar unsigned char #define uint unsigned int //0 1 2 3 4 5 6 7 8 9 - 灭 _ unsigned char code DuanMa[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0xf7,0xab,0x8e}; //共阳 unsigned char code WeiMa[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//分别对应相应的数码管点亮,即位码 #define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0替换 void SEG_Latch(void) //段码锁存子程序 { P2 |= 0xe0;//P2.7~P2.5=111,Y7=0,Y7C=1,即U7的LE=1,段码数 据选通 _nop_(); P2 &= 0x1f;//P2.7~P2.5=000,Y7=1,Y7C=0,即U7的LE=0,段码 数据被锁存 } void BIT_Latch(void) //位码锁存子程序 { P2 |= 0xC0; //P2.7~P2.5=110,Y6=0,Y6C=1,即U8的LE=1, 位码数据选通 _nop_(); P2 &= 0x1f; //P2.7~P2.5=000,Y6=1,Y6C=0,即U8的LE=0, 位码数据被锁存 } void delay_50us(uint t) //50us 延时 { uchar j; for(;t>0;t--) for(j=19;j>0;j--) ; } void display(uchar *point) { unsigned char i=0; for(i=0;i<8;i++) { DataPort=WeiMa[i]; //取位码 //数据锁存 BIT_Latch(); DataPort=DuanMa[*(point+i)]; //取显示数据,段码 SEG_Latch(); //数据锁存 delay_50us(30); // 扫描间隙延时,时间太长会闪烁,太短不 亮 DataPort=0xff; //关显示,消除重影 SEG_Latch(); //数据锁存 } } #endif #ifndef __DS1302_H__ #define __DS1302_H__ #include #define uint unsigned int #define uchar unsigned char #define nop _nop_() sbit DS1302_CLK = P1^7; sbit DS1302_IO = P2^3; sbit DS1302_RST = P1^3; uchar NowTime[8]={0x12,0x5,0x26,0x6,0x00,0x00,0x00};//年,月,日,星期,时,分,秒 /***************************************************************************** 函数功能:写DS1302一个字节子程序 入口参数: 出口参数: *****************************************************************************/ void sendbyte(uchar a) { uchar i; for(i=8;i>0;i--) { DS1302_CLK=0; nop; DS1302_IO = a & 0x01; a >>= 1; DS1302_CLK=1; nop; } } /***************************************************************************** 函数功能:读DS1302一个字节子程序 入口参数: 出口参数: *****************************************************************************/ uchar readbyte(void) { uchar i,dat=0; for(i=8;i>0;i--) { } DS1302_IO=0; return dat; DS1302_CLK=1; nop; DS1302_CLK=0; dat>>=1; if(DS1302_IO) dat|=0x80; } /***************************************************************************** 函数功能:写DS1302地址子程序 入口参数:add 入口数据:dat *****************************************************************************/ void write_DS1302(uchar address,uchar dat) { DS1302_RST=0; nop; DS1302_CLK=0; nop; DS1302_RST=1; nop; sendbyte(address); nop; sendbyte(dat); nop; DS1302_RST=0; nop; DS1302_CLK=0; } /***************************************************************************** 函数功能:读DS1302地址子程序 入口参数:add 出口参数:readtimeR[] *****************************************************************************/ uchar read_DS1302(uchar address) { uchar timer; DS1302_RST=0; nop; DS1302_CLK=0; nop; DS1302_RST=1; nop; sendbyte(address); timer=readbyte(); DS1302_RST=0; nop; DS1302_CLK=0; } /***************************************************************************** 函数功能:初始化DS1302子程序 入口参数:wr_data[](全局变量) 出口参数: return timer; *****************************************************************************/ void DS1302_init() { } //=======================时钟开启,可省略================================== void clock_start(void) { uchar val; val = read_DS1302(0x81); //读秒寄存器 val &= 0x7f; //最高位CH,振荡器工作允许 write_DS1302(0x8e,0x00); //关闭保护,若写0x80,则开启保护 write_DS1302(0x8c,NowTime[0]); write_DS1302(0x88,NowTime[1]); write_DS1302(0x86,NowTime[2]); write_DS1302(0x8A,NowTime[3]); write_DS1302(0x84,NowTime[4]); write_DS1302(0x82,NowTime[5]); write_DS1302(0x80,NowTime[6]); //年 //月 //日 //星期 //时 //分 //秒 write_DS1302(0x8e,0x80); //开写保护 write_DS1302(0x8e,0x00); //关写保护 write_DS1302(0x80,val); write_DS1302(0x90,0xa5);//使能涓电流充电,DS=01:选择一个二 极管,RS=01:R1=2k } #endif #ifndef __KEY_H__ #define __KEY_H__ #define KeyPort P3 /*------------------------------------------------ 将跳线帽套在J5的BIN针上 独立按键扫描函数,返回扫描键值 左边一列从上向下对应P30,P31,P32,P33 分别是0,1,2,3号键 ------------------------------------------------*/ void delay50us(unsigned int t) //50us 延时 { unsigned char j; for(;t>0;t--) write_DS1302(0x8e,0x80);//开写保护 for(j=19;j>0;j--) ; } unsigned char KeyScan(void) //键盘扫描函数,使用行列逐级扫描法 { unsigned char Val; KeyPort=0xf0;//高四位置高,低四位拉低 if(KeyPort!=0xf0)//表示有按键按下 { delay50us(200); //去抖 if(KeyPort!=0xf0) { //表示有按键按下 KeyPort=0xfe; //检测第一行 if(KeyPort!=0xfe) { Val=KeyPort&0xf0; Val+=0x0e; while(KeyPort!=0xfe); delay50us(200); //去抖 while(KeyPort!=0xfe); return Val; } KeyPort=0xfd; //检测第二行 if(KeyPort!=0xfd) { Val=KeyPort&0xf0; Val+=0x0d; while(KeyPort!=0xfd); delay50us(200); //去抖 while(KeyPort!=0xfd); return Val; } KeyPort=0xfb; //检测第三行 if(KeyPort!=0xfb) { Val=KeyPort&0xf0; Val+=0x0b; while(KeyPort!=0xfb); delay50us(200); //去抖 while(KeyPort!=0xfb); return Val; } KeyPort=0xf7; //检测第四行 if(KeyPort!=0xf7) { Val=KeyPort&0xf0; Val+=0x07; while(KeyPort!=0xf7); delay50us(200); //去抖 while(KeyPort!=0xf7); return Val; } } } return 0xff; } unsigned char KeyPro(void) { switch(KeyScan()) { 值 case 0x7d:return 1;break;//1 case 0x7b:return 2;break;//2 case 0x7e:return 0;break;//0 按下相应的键显示相对应的码 } } case 0x77:return 3;break;//3 case 0xbe:return 4;break;//4 case 0xbd:return 5;break;//5 case 0xbb:return 6;break;//6 case 0xb7:return 7;break;//7 case 0xde:return 8;break;//8 case 0xdd:return 9;break;//9 case 0xdb:return 10;break;//a case 0xd7:return 11;break;//b case 0xee:return 12;break;//c case 0xed:return 13;break;//d case 0xeb:return 14;break;//e case 0xe7:return 15;break;//f default:return 0xff;break; #endif #ifndef _24c02_H #define _24c02_H #include \"reg52.h\" #include \"intrins.h\" #define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();} sbit SDA = P2^1; sbit SCL = P2^0; void iic_start(void) { SDA = 1; _nop_(); SCL = 1; somenop; SDA = 0; somenop; SCL = 0; } void iic_stop(void) { SDA = 0; _nop_(); SCL = 1; somenop; SDA = 1; } void iic_ack(bit ackbit) { if(ackbit) SDA = 0; else SDA = 1; somenop; SCL = 1; somenop; SCL = 0; SDA = 1; somenop; } bit iic_waitack(void) { SDA = 1; somenop; SCL = 1; somenop; if(SDA) { SCL = 0; iic_stop(); return 0; } else { SCL = 0; return 1; } } void iic_sendbyte(unsigned char byt) { unsigned char i; for(i=0;i<8;i++) { if(byt&0x80) SDA = 1; else SDA = 0; somenop; SCL = 1; byt <<= 1; somenop; SCL = 0; } } unsigned char iic_recbyte(void) { unsigned char da; unsigned char i; for(i=0;i<8;i++) { SCL = 1; somenop; da <<= 1; if(SDA) da |= 0x01; SCL = 0; somenop; } return da; } /* void delay_50us(unsigned int t) { unsigned char j; for(;t>0;t--) for(j=19;j>0;j--) ; } */ bit ISendStr(unsigned char add1,unsigned char add2,unsigned char *s,unsigned char no) { unsigned char i; iic_start(); iic_sendbyte(add1); if(iic_waitack()==0) return 0; iic_sendbyte(add2); if(iic_waitack()==0) } return 0; for(i=0;i bit IRcvStr(unsigned char add1,unsigned char add2,unsigned char *s,unsigned char no) { unsigned char i; iic_start(); iic_sendbyte(add1); if(iic_waitack()==0) return 0; iic_sendbyte(add2); } if(iic_waitack()==0) return 0; iic_start(); iic_sendbyte(add1+1); if(iic_waitack()==0) return 0; for(i=0;i *s=iic_recbyte(); iic_ack(1); s++; delay_50us(10); unsigned char read(unsigned char add) { unsigned char temp; iic_start(); } iic_sendbyte(0xa0); iic_waitack(); iic_sendbyte(add); iic_waitack(); iic_start(); iic_sendbyte(0xa1); iic_waitack(); temp=iic_recbyte(); iic_ack(0); iic_stop(); return temp; void write(unsigned char add,unsigned char dat) { iic_start(); iic_sendbyte(0xa0); iic_waitack(); iic_sendbyte(add); iic_waitack(); iic_sendbyte(dat); iic_waitack(); } iic_stop(); void wrbyte_24c02(unsigned char add,unsigned char dat) { iic_start(); iic_sendbyte(0xa0); iic_waitack(); iic_sendbyte(add); iic_waitack(); iic_sendbyte(dat); iic_waitack(); iic_stop(); delay_50us(100); } #endif #ifndef __ULN2003_H__ #define __ULN2003_H__ //sbit buzz=P0^6; void ULN2003_Latch(void) // 锁存子程序 { P2 |= 0xa0;//P2.7~P2.5=101,Y5=0,Y5C=1,即U9的LE=1,数据选 通 _nop_(); P2 &= 0x1f;//P2.7~P2.5=000,Y5=1,Y5C=0,即U9的LE=0,数据 被锁存 } #endif 六、总结 课程设计是培养学生综合运用所学知识,发现、提出、分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程。随着科学技术发展的日新日异,单片机已经成为当今计算机应用中空前活跃的领域,在生活中可以说得是无处不在,作为二十一世纪的大学生来说掌握单片机的开发技术是十分重要的。 回想起此次课设的过程,从选题到编程,从理论到实践,在两周的日子里,我们组花了很多的心血,当然这一切都在最后得到了回报。可以说得是苦多于甜,但是从中却学到很多很多的的东西,不但巩固了以前所学过的知识,而且对单片机原理课外知识也的到了拓展。另 外,在编程过程中,由于不方便使用试验箱,仿真软件的使用也成为一项重要的验证代码的方式。在对protues的使用过程中,发现了在仿真过程中有许多需要注意的地方,比如C51芯片的最小系统的搭建,元器件的链接等等。 在最关键的程序设计过程中,我体会到了坚持不懈的恒心。为了让程序达到自己的要求,必须对一段代码数次的更改,每次更改后还要在仿真软件里实现,重复这样的操作的确是无味的,但却是必要的,只有一次次的修改代码才会让程序运行的更有效率,更人性化,更易理解,这也是我们所追求的。 在此次单片机课程设计之后,我不仅加深了对单片机理论的理解,将理论很好地应用到实际当中去,而且我们还学会了如何去培养创新精神和严谨的科学作风,从而不断地战胜自己,超越自己。更重要的是,我在这一设计过程中,学会了坚持不懈,不轻易言弃。当然,该电子钟还有很多不足之处,比如闹钟不能关闭,且只能定一个闹钟。在今后的学习过程中,我们需要继续努力,锻炼自己。 因篇幅问题不能全部显示,请点此查看更多更全内容