51基于单片机的电子时钟设计课程设计(完整)_第1页
51基于单片机的电子时钟设计课程设计(完整)_第2页
51基于单片机的电子时钟设计课程设计(完整)_第3页
51基于单片机的电子时钟设计课程设计(完整)_第4页
51基于单片机的电子时钟设计课程设计(完整)_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

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

文档简介

1、 课程设计报告课程设计报告 题题 目目 基于单片机的电子时钟设计 课课 程程 名名 称称 单片机原理及应用 院院 部部 名名 称称 机电工程学院 专专 业业 电气工程及其自动化 班班 级级 12 电气工程及其自动化(单) 学学 生生 姓姓 名名 钱 凯 学学 号号 1205202032 课程设计地点课程设计地点 工科楼 c304 课程设计学时课程设计学时 20 指指 导导 教教 师师 李国利 金陵科技学院教务处制成绩目录目录一、概述.41.1 设计任务与要求:.41.2 设计目的:.4二、总体设计方案及说明.4三、系统硬件电路设计.53.1 at89c51 单片机最小系统.53.2ds1302

2、 实时时钟芯片模块.63.3 ds18b20 温度传感器模块.73.4 lcd1602 液晶显示模块 .83.5 4*4 矩阵按键 .9四、系统软件部分设计.104.1 软件流程图.104.2 系统源程序.13五、系统仿真过程与结果.295.1 proteus仿真软件简介.295.2 keil软件简介.295.3 结合proteus仿真软件与 keil软件编译过程.29六、制作过程与功能实现.336.1 实物制.336.2 功能实现.34七、总结.35八、参考文献.36附录一:.36附录二:.38摘摘 要要基于at89c51单片机设计了电子,系统主要包括单片机最小系统、温度采集电路、显示电路、

3、时钟电路等等。系统采用ds18b20温度传感器对室内进行温度测量,加上ds1302实时时钟芯片内置时间,同时将当前温度信息和时间发送到lcd进行显示。画出了系统原理图,进行了软件设计,给出了系统流程图,并编写了系统程序。最后进行了系统仿真,仿真结果表明,所设计的系统能够满足要求。本系统具有成本低,可靠性高和安全实用等特点,广泛应用于社会生活的各个领域。 关键词:关键词:at89c51 单片机;ds18b20;ds1302 手动时间调整; 一、概述一、概述1.1 设计任务与要求:设计任务与要求:设计一个基于单片机并采用 lcd 显示的日历电子钟,要求:1)系统功能:可进行秒分时、天月年计时、温度

4、;可进行手动时间调整。2)给出系统设计方案,画出硬件连线图,并说明工作原理;3)画出程序框图并编写程序。1.2 设计目的:设计目的:通过本课程设计,使学生掌握控制系统设计的一般步骤,掌握系统总体控制方案的设计方法。使学生进一步掌握微型计算机应用系统的硬、软件开发方法,输入/输出(i/o)接口技术,应用程序设计技术,并能结合专业设计简单实用的单片机应用系统。针对课堂重点讲授内容使学生加深对单片机硬件原理的理解及提高 c51 语言程序设计的能力,为以后的毕业设计搭建了单片机系统应用平台,提高学生的开发创新能力。二、总体设计方案及说明二、总体设计方案及说明本方案以at89c51 单片机为控制核心,由

5、 ds18b20 温度传感器模块,ds1302实时时钟芯片模块,lcd1602 液晶显示模块, 4*4 矩阵按键以及上拉电阻和下拉电阻构成。通过 lcd1602 液晶显示模块显示时间及温度,通过按键可以设置年月日、分时秒。本设计采用 5v 电源,程序主要是通过单片机下载的软件来完成。stc89c52rc单片机ds18b20温度模块ds1302s时钟模块4*4按键模块lcd1602显示模块图 2-1 系统框图三、系统硬件电路设计三、系统硬件电路设计3.13.1 at89c51at89c51 单片机最小系统单片机最小系统(1)时钟电路单片机工作时,从取指令到译码再进行微操作,必须在时钟信号控制下才

6、能有序地进行,时钟电路就是为单片机工作提供基本时钟的。单片机的时钟信号通常有两种产生方式:内部时钟方式和外部时钟方式。内部时钟方式的原理电路如图所示。在单片机xtal1 和 xtal2 引脚上跨接上一个晶振和两个稳频电容,可以与单片机片内的电路构成一个稳定的自激振荡器。晶振的取值范围一般为 024mhz,常用的晶振频率有6mhz、12 mhz、11.0592 mhz、24 mhz 等。本次设计采用 11.0592mhz。一些新型的单片机还可以选择更高的频率。外接电容的作用是对振荡器进行频率微调,使振荡信号频率与晶振频率一致,同时起到稳定频率的作用,一般选用 2030pf 的瓷片电容。外部时钟方

7、式则是在单片机 xtal1 引脚上外接一个稳定的时钟信号源,它一般适用于多片单片机同时工作的情况,使用同一时钟信号可以保证单片机的工作同步。时序是单片机在执行指令时 cpu 发出的控制信号在时间上的先后顺序。at89c51 单片机的时序概念有 4 个,可用定时单位来说明,包括振荡周期、时钟周期、机器周期和指令周期。振荡周期:是片内振荡电路或片外为单片机提供的脉冲信号的周期。时序中 1 个振荡周期定义为 1 个节拍,用 p 表示。时钟周期:振荡脉冲送入内部时钟电路,由时钟电路对其二分频后输出的时钟脉冲周期称为时钟周期。时钟周期为振荡周期的2 倍。时序中 1 个时钟周期定义为 1 个状态,用 s

8、表示。每个状态包括 2 个节拍,用 p1、p2表示。机器周期:机器周期是单片机完成一个基本操作所需要的时间。一条指令的执行需要一个或几个机器周期。一个机器周期固定的由6 个状态s1s6 组成。指令周期:执行一条指令所需要的时间称为指令周期。一般用指令执行所需机器周期数表示。 at89c51 单片机多数指令的执行需要 1 个或 2 个机器周期,只有乘除两条指令的执行需要 4 个机器周期。(2)复位电路无论是在单片机刚开始接上电源时,还是运行过程中发生故障都需要复位。复位电路用于将单片机内部各电路的状态恢复到一个确定的初始值,并从这个状态开始工作。单片机的复位条件:必须使其 rst 引脚上持续出现

9、两个(或以上)机器周期的高电平。单片机的复位形式:上电复位、按键复位。上电复位电路中,利用电容充电来实现复位。在电源接通瞬间,rst 引脚上的电位是高电平( vcc) ,电源接通后对电容进行快速充电,随着充电的进行,rst 引脚上的电位也会逐渐下降为低电平。只要保证rst 引脚上高电平出现的时间大于两个机器周期,便可以实现正常复位。按键复位电路中,当按键没有按下时,电路同上电复位电路。如在单片机运行过程中,按下 reset 键,已经充好电的电容会快速通过 4.7k 电阻的回路放电,从而使得 rst 引脚上的电位快速变为高电平,此高电平会维持到按键释放,从而满足单片机复位的条件实现按键复位。图

10、3-1 单片机复位电路3.2 ds1302 实时时钟芯片模块实时时钟芯片模块ds1302 是美国 dallas 公司推出的一种高性能、低功耗的实时时钟芯片,附加 31 字节静态 ram,采用 spi 三线接口与 cpu 进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和 ram 数据。实时时钟可提供秒、分、时、日、星期、月和年,一个月小与 31 天时可以自动调整,且具有闰年补偿功能。工作电压宽达 2.55.5v。采用双电源供电(主电源和备用电源) ,可设置备用电源充电方式,提供了对后背电源进行涓细电流充电的能力。ds1302 的外部引脚分配如图,ds1302 用于数据记录,特别是对某些

11、具有特殊意义的数据点的记录上,能实现数据与出现该数据的时间同时记录,因此广泛应用于测量系统中。 1.各引脚的功能为: 图 3-4 时钟芯片外部引脚vcc1:主电源;vcc2:备份电源。当 vcc2vcc1+0.2v 时,由 vcc2 向ds1302 供电,当 vcc2 vcc1 时,由 vcc1 向 ds1302 供电。 sclk:串行时钟,输入,控制数据的输入与输出; i/o:三线接口时的双向数据线; ce:输入信号,在读、写数据期间,必须为高。该引脚有两个功能:第一,ce开始控制字访问移位寄存器的控制逻辑;其次,ce 提供结束单字节或多字节数据传输的方法。图 3-5 时钟芯片3.3 ds1

12、8b20 温度传感器模块温度传感器模块ds18b20 工作原理:ds18b20 的温度检测与数字数据输出全集成于一个芯片之上,从而抗干扰力更强。其一个工作周期可分为两个部分,即温度检测和数据处理。在讲解其工作流程之前我们有必要了解 18b20 的内部存储器资源。18b20 共有三种形态的存储器资源,它们分别是: rom 只读存储器,用于存放 ds18b20id 编码,其前 8 位是单线系列编码(ds18b20 的编码是 19h) ,后面 48 位是芯片唯一的序列号,最后 8 位是以上56 的位的 crc 码(冗余校验) 。数据在出产时设置不由用户更改。ds18b20 共64 位 rom。ram

13、 数据暂存器,用于内部计算和数据存取,数据在掉电后丢失,ds18b20共 9 个字节 ram,每个字节为 8 位。第 1、2 个字节是温度转换后的数据值信息,第 3、4 个字节是用户 eeprom(常用于温度报警值储存)的镜像。在上电复位时其值将被刷新。第 5 个字节则是用户第 3 个 eeprom 的镜像。第 6、7、8 个字节为计数寄存器,是为了让用户得到更高的温度分辨率而设计的,同样也是内部温度转换、计算的暂存单元。第 9 个字节为前 8 个字节的 crc 码。eeprom 非易失性记忆体,用于存放长期需要保存的数据,上下限温度报警值和校验数据,ds18b20 共 3 位 eeprom,

14、并在 ram 都存在镜像,以方便用户操作。图 3-3 温度传感器模块3.4 lcd1602 液晶显示模块液晶显示模块lcd1602 可以显示 16*2=32 个字符,也可以用来显示一些汉字图片(利用取模软件提取) ,原理图中的可调电阻是用来调节字符显示的亮度的,调节是要有耐心,应为用到的是精密可调电阻,这个需要转很多圈,不容易显示出来,注意不能跳到太亮,要不很容易烧掉液晶,下面为接口说明,一般不显示很可能是程序的问题和可调电阻没有调节好。 图 3-6 lcd1602 液晶的原理图3.5 4*4 矩阵按键矩阵按键矩阵键盘又称为行列式键盘,它是用 4 条 i/o 线作为行线,4 条 i/o 线作为

15、列线组成的键盘。在行线和列线的每一个交叉点上,设置一个按键。这样键盘中按键的个数是 4*4 个。这种行列式键盘结构能够有效地提高单片机系统中i/o 的利用率。图 3-7 矩阵按键电路四、系统软件部分设计四、系统软件部分设计4.1 软件流程图软件流程图系统初始化采集温度采集时间lcd显示开始图 4-1 主函数系统流程图程序开始,首先先进行系统初始化。然后先进行温度的采集,时间的采集,最后将温度和时间送至 lcd 显示数据。开始复位跳过序列号识别跳过序列号识别启动温度转换读取温度值结束复位图 4-2 ds18b20 温度传感器的读取流程图单片机向 ds18b20 温度传感器发送数据采集温度,温度传

16、感器首先进行系统的初始化 ds18b20 温度传感器每 1 秒钟进行一次温度采集,如果温度有变化则读取温度,若温度没有变化将继续返回上一步循环。开始ds1302初始化读取时间是否=200ms时间是否变化返回yesyesnono图 4-3 ds1302 读取系统流程图单片机向 ds1302 时钟芯片发送数据采集时间,ds1302 时钟芯片首先进行系统初始化。ds1302 时钟芯片是 200ms 进行一次时间的数据采集。如果时间变化,则读取时间,如果没有变化,则返回上一步继续循环。 开始lcd1602初始化读取温度和时间是否有按键按下lcd显示返回按键设置时间是否结束yesyesnono图 4-4

17、 lcd 显示器系统流程图单片机向 lcd 显示器发送数据要求显示温度和时间,lcd 显示器首先进行初始化。然后读取温度和时间。下一步判断按键是否按下,如果按下就将设置时间送至 lcd 显示器进行显示。如果没有设置则返回上一步,然后送至 lcd 显示器进行显示。4.2 系统源程序系统源程序#include struct stime /日期时间结构体定义日期时间结构体定义 unsigned int year; unsigned char mon; unsigned char day; unsigned char hour; unsigned char min; unsigned char sec

18、; unsigned char week;bit flag1s = 0; /1s 定时标志定时标志bit flag200ms = 1; /200ms 定时标志定时标志struct stime buftime; /日期时间缓冲区日期时间缓冲区unsigned char setindex = 0; /时间设置索引时间设置索引unsigned char t0rh = 0; /t0 重载值的高字节重载值的高字节unsigned char t0rl = 0; /t0 重载值的低字节重载值的低字节void configtimer0(unsigned int ms);void refreshtimeshow

19、();void getshowtemp();extern void initds1302();extern void getrealtime(struct stime *time);extern void setrealtime(struct stime *time);extern void keyscan();extern void keydriver();extern void initlcd1602();extern void lcdshowstr(unsigned char x, unsigned char y, unsigned char *str);extern void lcds

20、etcursor(unsigned char x, unsigned char y);extern void lcdopencursor();extern void lcdclosecursor();extern bit start18b20();extern bit get18b20temp(int *temp);void main() unsigned char psec=0 xaa; /秒备份,初值秒备份,初值 aa 确保首次读取时间后会刷新确保首次读取时间后会刷新显示显示 ea = 1; /开总中断开总中断 configtimer0(1); /t0 定时定时 1ms start18b2

21、0(); /启动启动 ds18b20 initds1302(); /初始化实时时钟初始化实时时钟 initlcd1602(); /初始化液晶初始化液晶 /初始化屏幕上固定不变的内容初始化屏幕上固定不变的内容 lcdshowstr(3, 0, 20 - -); lcdshowstr(1, 1, : : -c); while (1) keydriver(); /调用按键驱动调用按键驱动 if (flag200ms & (setindex = 0) /每隔每隔 200ms 且未处于设置状态时,且未处于设置状态时, flag200ms = 0; getrealtime(&buftime); /获取当前

22、时间获取当前时间 if (psec != buftime.sec) /检测到时间有变化时刷新显示检测到时间有变化时刷新显示 refreshtimeshow(); psec = buftime.sec; /用当前值更新上次秒数用当前值更新上次秒数 if (flag1s & (setindex = 0) /每隔每隔 1s 读取并显示温度读取并显示温度 flag1s = 0; getshowtemp(); /* 将一个将一个 bcd 码字节显示到屏幕上,码字节显示到屏幕上,(x,y)-屏幕起始坐标,屏幕起始坐标,bcd-待显示待显示 bcd 码码 */void showbcdbyte(unsigne

23、d char x, unsigned char y, unsigned char bcd) unsigned char str4; str0 = (bcd 4) + 0; str1 = (bcd&0 x0f) + 0; str2 = 0; lcdshowstr(x, y, str);/* 获取并显示温度获取并显示温度 */void getshowtemp() int temp; unsigned char str4; if (get18b20temp(&temp) /读取当前温度并判断是否成功读取当前温度并判断是否成功 /读取成功时,刷新当前温度显示读取成功时,刷新当前温度显示 temp =

24、4; /右移右移 4 位以舍弃小数位位以舍弃小数位 str0 = temp/10 + 0; /显示为两位十进制数字显示为两位十进制数字 str1 = temp%10 + 0; str2 = 0; lcdshowstr(11, 1, str); else /读取失败时,提示错误信息读取失败时,提示错误信息 lcdshowstr(11, 1, -); start18b20(); /重新启动下一次转换重新启动下一次转换/* 刷新日期时间的显示刷新日期时间的显示 */void refreshtimeshow() showbcdbyte(5, 0, buftime.year); showbcdbyte(

25、8, 0, buftime.mon); showbcdbyte(11, 0, buftime.day); showbcdbyte(1, 1, buftime.hour); showbcdbyte(4, 1, buftime.min); showbcdbyte(7, 1, buftime.sec);/* 刷新当前设置位的光标指示刷新当前设置位的光标指示 */void refreshsetshow() switch (setindex) case 1: lcdsetcursor(5, 0); break; case 2: lcdsetcursor(6, 0); break; case 3: lcd

26、setcursor(8, 0); break; case 4: lcdsetcursor(9, 0); break; case 5: lcdsetcursor(11, 0); break; case 6: lcdsetcursor(12, 0); break; case 7: lcdsetcursor(1, 1); break; case 8: lcdsetcursor(2, 1); break; case 9: lcdsetcursor(4, 1); break; case 10: lcdsetcursor(5, 1); break; case 11: lcdsetcursor(7, 1);

27、 break; case 12: lcdsetcursor(8, 1); break; default: break; /* 递增一个递增一个 bcd 码的高位码的高位 */unsigned char incbcdhigh(unsigned char bcd) if (bcd&0 xf0) 0 x90) bcd += 0 x10; else bcd &= 0 x0f; return bcd;/* 递增一个递增一个 bcd 码的低位码的低位 */unsigned char incbcdlow(unsigned char bcd) if (bcd&0 x0f) 0 x00) bcd -= 0 x1

28、0; else bcd |= 0 x90; return bcd;/* 递减一个递减一个 bcd 码的低位码的低位 */unsigned char decbcdlow(unsigned char bcd) if (bcd&0 x0f) 0 x00) bcd -= 0 x01; else bcd |= 0 x09; return bcd;/* 递增时间当前设置位的值递增时间当前设置位的值 */void incsettime() switch (setindex) case 1: buftime.year = incbcdhigh(buftime.year); break; case 2: buf

29、time.year = incbcdlow(buftime.year); break; case 3: buftime.mon = incbcdhigh(buftime.mon); break; case 4: buftime.mon = incbcdlow(buftime.mon); break; case 5: buftime.day = incbcdhigh(buftime.day); break; case 6: buftime.day = incbcdlow(buftime.day); break; case 7: buftime.hour = incbcdhigh(buftime.

30、hour); break; case 8: buftime.hour = incbcdlow(buftime.hour); break; case 9: buftime.min = incbcdhigh(buftime.min); break; case 10: buftime.min = incbcdlow(buftime.min); break; case 11: buftime.sec = incbcdhigh(buftime.sec); break; case 12: buftime.sec = incbcdlow(buftime.sec); break; default: break

31、; refreshtimeshow(); refreshsetshow();/* 递减时间当前设置位的值递减时间当前设置位的值 */void decsettime() switch (setindex) case 1: buftime.year = decbcdhigh(buftime.year); break; case 2: buftime.year = decbcdlow(buftime.year); break; case 3: buftime.mon = decbcdhigh(buftime.mon); break; case 4: buftime.mon = decbcdlow(b

32、uftime.mon); break; case 5: buftime.day = decbcdhigh(buftime.day); break; case 6: buftime.day = decbcdlow(buftime.day); break; case 7: buftime.hour = decbcdhigh(buftime.hour); break; case 8: buftime.hour = decbcdlow(buftime.hour); break; case 9: buftime.min = decbcdhigh(buftime.min); break; case 10:

33、 buftime.min = decbcdlow(buftime.min); break; case 11: buftime.sec = decbcdhigh(buftime.sec); break; case 12: buftime.sec = decbcdlow(buftime.sec); break; default: break; refreshtimeshow(); refreshsetshow();/* 右移时间设置位右移时间设置位 */void rightshifttimeset() if (setindex != 0) if (setindex 1) setindex-; el

34、se setindex = 12; refreshsetshow(); /* 进入时间设置状态进入时间设置状态 */void entertimeset() setindex = 2; /把设置索引设置为把设置索引设置为 2,即可进入设置状态,即可进入设置状态 leftshifttimeset(); /再利用现成的左移操作移到位置再利用现成的左移操作移到位置 1 并完成显示刷新并完成显示刷新 lcdopencursor(); /打开光标闪烁效果打开光标闪烁效果/* 退出时间设置状态,退出时间设置状态,save-是否保存当前设置的时间值是否保存当前设置的时间值 */void exittimeset

35、(bit save) setindex = 0; /把设置索引设置为把设置索引设置为 0,即可退出设置状态,即可退出设置状态 if (save) /需保存时即把当前设置时间写入需保存时即把当前设置时间写入 ds1302 setrealtime(&buftime); lcdclosecursor(); /关闭光标显示关闭光标显示/* 按键动作函数,根据键码执行相应的操作,按键动作函数,根据键码执行相应的操作,keycode-按键键码按键键码 */void keyaction(unsigned char keycode) if (keycode=0) & (keycode8); /定时器重载值拆分

36、为高低字节定时器重载值拆分为高低字节 t0rl = (unsigned char)tmp; tmod &= 0 xf0; /清零清零 t0 的控制位的控制位 tmod |= 0 x01; /配置配置 t0 为模式为模式 1 th0 = t0rh; /加载加载 t0 重载值重载值 tl0 = t0rl; et0 = 1; /使能使能 t0 中断中断 tr0 = 1; /启动启动 t0/* t0 中断服务函数,执行按键扫描和中断服务函数,执行按键扫描和 200ms 定时定时 */void interrupttimer0() interrupt 1 static unsigned char tmr2

37、00ms = 0; static unsigned int tmr1000ms = 0; th0 = t0rh; /重新加载重载值重新加载重载值 tl0 = t0rl; keyscan(); /按键扫描按键扫描 tmr200ms+; if (tmr200ms = 200) /定时定时 200ms tmr200ms = 0; flag200ms = 1; tmr1000ms+; if (tmr1000ms = 1000) /定时定时 1000ms tmr1000ms = 0; flag1s = 1; /* 文件名:文件名:lcd1602.c* 描描 述:述:1602 字符液晶驱动模块字符液晶驱动

38、模块* 版本号:版本号:v1.0.0* 备备 注:注:*/#include #define lcd1602_db p0sbit lcd1602_rs = p10;sbit lcd1602_rw = p11;sbit lcd1602_e = p15;/* 等待液晶准备好等待液晶准备好 */void lcdwaitready() unsigned char sta; lcd1602_db = 0 xff; lcd1602_rs = 0; lcd1602_rw = 1; do lcd1602_e = 1; sta = lcd1602_db; /读取状态字读取状态字 lcd1602_e = 0; wh

39、ile (sta & 0 x80); /bit7 等于等于 1 表示液晶正忙,重复检测直到其等于表示液晶正忙,重复检测直到其等于 0 为为止止/* 向向 lcd1602 液晶写入一字节命令,液晶写入一字节命令,cmd-待写入命令值待写入命令值 */void lcdwritecmd(unsigned char cmd) lcdwaitready(); lcd1602_rs = 0; lcd1602_rw = 0; lcd1602_db = cmd; lcd1602_e = 1; lcd1602_e = 0;/* 向向 lcd1602 液晶写入一字节数据,液晶写入一字节数据,dat-待写入数据值待

40、写入数据值 */void lcdwritedat(unsigned char dat) lcdwaitready(); lcd1602_rs = 1; lcd1602_rw = 0; lcd1602_db = dat; lcd1602_e = 1; lcd1602_e = 0;/* 设置显示设置显示 ram 起始地址,亦即光标位置,起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标对应屏幕上的字符坐标 */void lcdsetcursor(unsigned char x, unsigned char y) unsigned char addr; if (y = 0) /由输入的屏幕坐标

41、计算显示由输入的屏幕坐标计算显示 ram 的地址的地址 addr = 0 x00 + x; /第一行字符地址从第一行字符地址从 0 x00 起始起始 else addr = 0 x40 + x; /第二行字符地址从第二行字符地址从 0 x40 起始起始 lcdwritecmd(addr | 0 x80); /设置设置 ram 地址地址/* 在液晶上显示字符串,在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,对应屏幕上的起始坐标,str-字符串指针字符串指针 */void lcdshowstr(unsigned char x, unsigned char y, unsigned char

42、*str) lcdsetcursor(x, y); /设置起始地址设置起始地址 while (*str != 0) /连续写入字符串数据,直到检测到结束符连续写入字符串数据,直到检测到结束符 lcdwritedat(*str+); /* 打开光标的闪烁效果打开光标的闪烁效果 */void lcdopencursor()lcdwritecmd(0 x0f);/* 关闭光标显示关闭光标显示 */void lcdclosecursor()lcdwritecmd(0 x0c);/* 初始化初始化 1602 液晶液晶 */void initlcd1602() lcdwritecmd(0 x38); /1

43、6*2 显示,显示,5*7 点阵,点阵,8 位数据接口位数据接口 lcdwritecmd(0 x0c); /显示器开,光标关闭显示器开,光标关闭 lcdwritecmd(0 x06); /文字不动,地址自动文字不动,地址自动+1 lcdwritecmd(0 x01); /清屏清屏/* 文件名:文件名:keyboard.c* 描描 述:述:4*4 矩阵按键驱动模块矩阵按键驱动模块* 版本号:版本号:v1.0.0* 备备 注:注:*/#include sbit key_in_1 = p24;sbit key_in_2 = p25;sbit key_in_3 = p26;sbit key_in_4

44、= p27;sbit key_out_1 = p23;sbit key_out_2 = p22;sbit key_out_3 = p21;sbit key_out_4 = p20;unsigned char code keycodemap44 = /矩阵按键编号到标准键盘键码的映射矩阵按键编号到标准键盘键码的映射表表 1, 2, 3, 0 x26 , /数字键数字键 1、数字键、数字键 2、数字键、数字键 3、向上键、向上键 4, 5, 6, 0 x25 , /数字键数字键 4、数字键、数字键 5、数字键、数字键 6、向左键、向左键 7, 8, 9, 0 x28 , /数字键数字键 7、数字键

45、、数字键 8、数字键、数字键 9、向下键、向下键 0, 0 x1b, 0 x0d, 0 x27 /数字键数字键 0、esc 键、键、 回车键、回车键、 向右键向右键;unsigned char pdata keysta44 = /全部矩阵按键的当前状态全部矩阵按键的当前状态 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1;extern void keyaction(unsigned char keycode);/* 按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用 */vo

46、id keydriver() unsigned char i, j; static unsigned char pdata backup44 = /按键值备份,保存前一次的值按键值备份,保存前一次的值 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; for (i=0; i4; i+) /循环检测循环检测 4*4 的矩阵按键的矩阵按键 for (j=0; j4; j+) if (backupij != keystaij) /检测按键动作检测按键动作 if (backupij != 0) /按键按下时执行动作按键按下时执行动作 keyaction(

47、keycodemapij); /调用按键动作函数调用按键动作函数 backupij = keystaij; /刷新前一次的备份值刷新前一次的备份值 /* 按键扫描函数,需在定时中断中调用,推荐调用间隔按键扫描函数,需在定时中断中调用,推荐调用间隔 1ms */void keyscan() unsigned char i; static unsigned char keyout = 0; /矩阵按键扫描输出索引矩阵按键扫描输出索引 static unsigned char keybuf44 = /矩阵按键扫描缓冲区矩阵按键扫描缓冲区 0 xff, 0 xff, 0 xff, 0 xff, 0 x

48、ff, 0 xff, 0 xff, 0 xff, 0 xff, 0 xff, 0 xff, 0 xff, 0 xff, 0 xff, 0 xff, 0 xff ; /将一行的将一行的 4 个按键值移入缓冲区个按键值移入缓冲区 keybufkeyout0 = (keybufkeyout0 1) | key_in_1; keybufkeyout1 = (keybufkeyout1 1) | key_in_2; keybufkeyout2 = (keybufkeyout2 1) | key_in_3; keybufkeyout3 = (keybufkeyout3 1) | key_in_4; /消抖

49、后更新按键状态消抖后更新按键状态 for (i=0; i4; i+) /每行每行 4 个按键,所以循环个按键,所以循环 4 次次 if (keybufkeyouti & 0 x0f) = 0 x00) /连续连续 4 次扫描值为次扫描值为 0,即,即 4*4ms 内都是按下状态时,可认为按内都是按下状态时,可认为按键已稳定的按下键已稳定的按下 keystakeyouti = 0; else if (keybufkeyouti & 0 x0f) = 0 x0f) /连续连续 4 次扫描值为次扫描值为 1,即,即 4*4ms 内都是弹起状态时,可认为按内都是弹起状态时,可认为按键已稳定的弹起键已稳

50、定的弹起 keystakeyouti = 1; /执行下一次的扫描输出执行下一次的扫描输出 keyout+; /输出索引递增输出索引递增 keyout &= 0 x03; /索引值加到索引值加到 4 即归零即归零 switch (keyout) /根据索引,释放当前输出引脚,拉低下次的输出引脚根据索引,释放当前输出引脚,拉低下次的输出引脚 case 0: key_out_4 = 1; key_out_1 = 0; break; case 1: key_out_1 = 1; key_out_2 = 0; break; case 2: key_out_2 = 1; key_out_3 = 0; b

51、reak; case 3: key_out_3 = 1; key_out_4 = 0; break; default: break; /* 文件名:文件名:ds1302.c* 描描 述:实时时钟芯片述:实时时钟芯片 ds1302 驱动模块驱动模块* 版本号:版本号:v1.0.0* 备备 注:注:*/#include sbit ds1302_ce = p17;sbit ds1302_ck = p35;sbit ds1302_io = p34;struct stime /日期时间结构体定义日期时间结构体定义 unsigned int year; /年年 unsigned char mon; /月月

52、 unsigned char day; /日日 unsigned char hour; /时时 unsigned char min; /分分 unsigned char sec; /秒秒 unsigned char week; /星期星期;/* 发送一个字节到发送一个字节到 ds1302 通信总线上通信总线上 */void ds1302bytewrite(unsigned char dat) unsigned char mask; for (mask=0 x01; mask!=0; mask=1) /低位在前,逐位移出低位在前,逐位移出 if (mask&dat) != 0) /首先输出该位数

53、据首先输出该位数据 ds1302_io = 1; else ds1302_io = 0; ds1302_ck = 1; /然后拉高时钟然后拉高时钟 ds1302_ck = 0; /再拉低时钟,完成一个位的操作再拉低时钟,完成一个位的操作 ds1302_io = 1; /最后确保释放最后确保释放 io 引脚引脚/* 由由 ds1302 通信总线上读取一个字节通信总线上读取一个字节 */unsigned char ds1302byteread() unsigned char mask; unsigned char dat = 0; for (mask=0 x01; mask!=0; mask=1)

54、 /低位在前,逐位读取低位在前,逐位读取 if (ds1302_io != 0) /首先读取此时的首先读取此时的 io 引脚,并设置引脚,并设置 dat 中的对应中的对应位位 dat |= mask; ds1302_ck = 1; /然后拉高时钟然后拉高时钟 ds1302_ck = 0; /再拉低时钟,完成一个位的操作再拉低时钟,完成一个位的操作 return dat; /最后返回读到的字节数据最后返回读到的字节数据/* 用单次写操作向某一寄存器写入一个字节,用单次写操作向某一寄存器写入一个字节,reg-寄存器地址,寄存器地址,dat-待写入字待写入字节节 */void ds1302singl

55、ewrite(unsigned char reg, unsigned char dat) ds1302_ce = 1; /使能片选信号使能片选信号 ds1302bytewrite(reg1)|0 x80); /发送写寄存器指令发送写寄存器指令 ds1302bytewrite(dat); /写入字节数据写入字节数据 ds1302_ce = 0; /除能片选信号除能片选信号/* 用单次读操作从某一寄存器读取一个字节,用单次读操作从某一寄存器读取一个字节,reg-寄存器地址,返回值寄存器地址,返回值-读到的读到的字节字节 */unsigned char ds1302singleread(unsign

56、ed char reg) unsigned char dat; ds1302_ce = 1; /使能片选信号使能片选信号 ds1302bytewrite(reg1)|0 x81); /发送读寄存器指令发送读寄存器指令 dat = ds1302byteread(); /读取字节数据读取字节数据 ds1302_ce = 0; /除能片选信号除能片选信号 return dat;/* 用突发模式连续写入用突发模式连续写入 8 个寄存器数据,个寄存器数据,dat-待写入数据指针待写入数据指针 */void ds1302burstwrite(unsigned char *dat) unsigned cha

57、r i; ds1302_ce = 1; ds1302bytewrite(0 xbe); /发送突发写寄存器指令发送突发写寄存器指令 for (i=0; i8; i+) /连续写入连续写入 8 字节数据字节数据 ds1302bytewrite(dati); ds1302_ce = 0;/* 用突发模式连续读取用突发模式连续读取 8 个寄存器的数据,个寄存器的数据,dat-读取数据的接收指针读取数据的接收指针 */void ds1302burstread(unsigned char *dat) unsigned char i; ds1302_ce = 1; ds1302bytewrite(0 xb

58、f); /发送突发读寄存器指令发送突发读寄存器指令 for (i=0; iyear = buf6 + 0 x2000; time-mon = buf4; time-day = buf3; time-hour = buf2; time-min = buf1; time-sec = buf0; time-week = buf5;/* 设定实时时间,时间结构体格式的设定时间转换为数组并写入设定实时时间,时间结构体格式的设定时间转换为数组并写入 ds1302 */void setrealtime(struct stime *time) unsigned char buf8; buf7 = 0; buf

59、6 = time-year; buf5 = time-week; buf4 = time-mon; buf3 = time-day; buf2 = time-hour; buf1 = time-min; buf0 = time-sec; ds1302burstwrite(buf);/* ds1302 初始化,如发生掉电则重新设置初始时间初始化,如发生掉电则重新设置初始时间 */void initds1302() unsigned char dat; struct stime code inittime = /2013 年年 10 月月 8 日日 12:30:00 星期二星期二 0 x2013,

60、0 x10,0 x08, 0 x12,0 x30,0 x00, 0 x02 ; ds1302_ce = 0; /初始化初始化 ds1302 通信引脚通信引脚 ds1302_ck = 0; dat = ds1302singleread(0); /读取秒寄存器读取秒寄存器 if (dat & 0 x80) != 0) /由秒寄存器最高位由秒寄存器最高位 ch 的值判断的值判断 ds1302 是否已是否已停止停止 ds1302singlewrite(7, 0 x00); /撤销写保护以允许写入数据撤销写保护以允许写入数据 setrealtime(&inittime); /设置设置 ds1302 为默

温馨提示

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

评论

0/150

提交评论