基于51单片机设计的带有测温功能的电子时钟汇总_第1页
基于51单片机设计的带有测温功能的电子时钟汇总_第2页
基于51单片机设计的带有测温功能的电子时钟汇总_第3页
基于51单片机设计的带有测温功能的电子时钟汇总_第4页
基于51单片机设计的带有测温功能的电子时钟汇总_第5页
已阅读5页,还剩43页未读 继续免费阅读

下载本文档

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

文档简介

1、职业技能训练之 电子技术课程设计报告 学 院 电子与信息学院 设计题目 基于 51 单片机设计的带有测温功能的电子时钟 班 级 XXX 姓 名 XXX 学 号 XXX 指导教师 XXX 时 间 2012年 06月 25日 目录 设计要求 课程设计的方案、目的及意义 三、硬件设计方案 四、软件设计方案 五、总结 六、参考资料 设计要求 用 51 单片机设计带温度显示的电子时钟,具体要求如下: 1、利用 DS1302 时钟芯片实现时钟功能模块。 2、时钟要求可以调节时间:年、月、日、时、分、秒。 3、利用 LCD1602 显示。 4、利用 DS18B20 芯片实现温度功能模块。 5、利用按键完成各

2、项功能。 二、课程设计方案、目的及意义 1、总体方案: 用 STC89C51单片机作为 CPU 主控制器,DS1302时钟芯片提供准确时钟信 号, DS18B20 温度传感器采集温度信息,三个按键进行加减调整、功能切换作 用,通过 LCD1602 对外多功能显示。 2、具体方案: CPU 控制所有模块,通过循环反复从 DS1302 中读取时钟信息,传送至 LCD1602 显示,得到基本时钟功能。 当分为 59,秒为 56 时开始, 每隔一秒 LED 灯点亮 240毫秒, 0分0秒时 LED 灯点亮 700毫秒。从而实现整点光报时。 定时循环从 DS18B20中读取温度信息, 传送至 LCD16

3、02 显示,得到基本温 度计功能。当温度高于 30度(包括 30度)时,点亮红色 LED 灯,提醒当天为 高温天气。低于 0度时,点亮蓝色 LED 灯,提醒当天为冰冻天气。 键盘使用扫面方式, MENU 键控制功能切换,完成时钟和温度间的转换。 OK 键控制时间调整与确定, UP、DOWN 键调节时间, R、L 键选择调整对象。 进入调整时,暂停 DS1302 数据读取,并将改变的时间数据写入 DS1302,并送 LCD1602 显示,同时,启动 LCD1602 光标闪烁, 确定调整对象, 完成人机对话。 退出调整时,停止写入数据,重新读取 DS1302 时钟信息。从而完善时钟功能。 3、目的

4、及意义 可作为产品生产,作为居家的时钟显示与温度计。 三、硬件设计方案 1、原理图 2、 PCB 图 3、各功能模块分析 (一)、主控制器: STC 单片机 89C51 功能: 程序存储器 16K、RAM 数字存储器 1280、可直接通过串口下载程序,单 一 +5V 电源供电, 五个中断源的中断控制系统, 片内振荡器和时钟产生电路, 石 英晶体和微调电容需要外接。 CPU:由运算和控制逻辑组成, 同时还包括中断系统和部分外部特殊功能寄 存器。 RAM :用以存放可以读写的数据,如运算的中间结果、最终结果以及欲显 示的数据。 ROM:用以存放程序、一些原始数据和表格。 I/O 口:四个 8 位并

5、行 I/O 口,既可用作输入,也可用作输出。 P0 口做 I/O 口需接上拉电阻。 T/C :两个定时 /记数器,既可以工作在定时模式,也可以工作在记数模式。 (二 )、LCD1602 显示模块 介绍:工业字符型液晶,能够同时显示16x02 即 32个字符( 16列 2行) 管脚信息: 显示模式设置: 显示开关及功能设置: 数据指针设置: 写时序: 注: R3 调节显示屏对比度 三)、 DS1302 时钟芯片 管脚信息: VCC :Vcc1 为后备电源, VCC2 为主电源。在主电源关闭的情况下,也能 保持时钟的连续运行。 DS1302 由 Vcc1 或 Vcc2 两者中的较大者供电。当 Vc

6、c2 大于 Vcc10.2V 时, Vcc2 给 DS1302供电。当 Vcc2 小于 Vcc1 时, DS1302由 Vcc1 供电。 X1、X2:X1 和 X2 是振荡源,外接 32.768kHz 晶振。 RST:RST 是复位/片选线,通过把 RST 输入驱动置高电平来启动所有的数 据传送。 RST 输入有两种功能:首先, RST 接通控制逻辑,允许地址 /命令序列 送入移位寄存器; 其次,RST提供终止单字节或多字节数据的传送手段。 当 RST 为高电平时,所有的数据传送被初始化,允许对 DS1302 进行操作。如果在传送 过程中 RST置为低电平,则会终止此次数据传送, I/O 引脚

7、变为高阻态。上电运 行时,在 Vcc2.0V 之前, RST必须保持低电平。只有在 SCLK 为低电平时,才 能将RST置为高电平。 I/O为串行数据输入输出端 (双向),后面有详细说明。 SCLK :SCLK 为时钟输入端。 日历寄存器: 注: (1):小时寄存器的位 7 用于定义 DS1302是运行于 12 小时模式还是 24 小时模 式。当为高时,选择 12 小时模式。在 12 小时模式下,位 5为低时为 AM,高时 为 PM。在 24小时模式下,位 5 是第二个 10小时位。 (2)、秒寄存器的位 7定义为时钟暂停标志。 当该位置为 1 时,时钟振荡器停止, DS1302处于低功耗状态

8、;该位置 0 是,时钟开始运行。 ( 3)、控制寄存器的位 7 是写保护位,其他 7 位均置为 0。在任何的对时钟和 RAM 的写操作之前, WP位必须为 0。当 WP位 1时,写保护位防止对任一寄存 器的写操作。 控制字节: 注:控制字节的最高有效位 (位 7)必须是逻辑 1,如果它为 0,则不能把数据写入 DS1302中,位6如果为0,则表示存取日历时钟数据, 为1表示存取 RAM 数据; 位 5 至位 1 指示操作单元的地址 ; 最低有效位 ( 位 0) 如为 0 表示要进行写操作,为 1表示进行读操作,控制字节总是从最低位开始输出。 数据读写及时序: 在控制指令字输入后的下一个 SCL

9、K 时钟的上升沿时,数据被写入 DS1302,数 据输入从低位即位 0开始。同样,在紧跟 8位的控制指令字后的下一个 SCLK 脉 冲的下降沿读出 DS1302的数据,读出数据时从低位 0 位到高位 7。 四)、DS18B20温度传感器 管脚信息: GND:接地 DQ: 数据 I/O VDD :电源 存储器: 控制字节: Skip ROM CCh :允许总线控制器不用提供 64 位 ROM 编码就使用存储器操作 命令,在单点总线情况下右以节省时间。 Convert T44h:开始温度转换。 Read ScratchpadBEh: 读取暂存器和 CRC 字节,知道 9 字节 时序: 读时间隙:

10、当从 DS12B20 读取数据时,主机生成读时间隙。当主机把数据线从逻辑高 电平拉到逻辑低电平的时候,写时间隙开始。数据线必须保持至少1s,从 DS18B20 输出的数据在读时间隙的下降沿出现后 15s 内有效。因此,主机在 读时间隙开始后必须停止把 I/O 脚驱动为低电平 15s,以读取 I/O 脚状态。在 读时间隙的结尾, I/O 引脚将被外部上拉电阻拉到高电平。所有读时间隙必须最 少 60s,包括两个读周期间至少 1s 的恢复时间。 写时间隙: 当主机把数据线从逻辑高电平拉到逻辑低电平的时候, 写时间隙开始。 所有 写时间隙必须最少持续 60s,包括两个写周期间至少 1s 的恢复时间。

11、I/O 线 电平变低后, DS18B20 在一个 15 s 到 60s 的窗口内对 I/O 线采样。如果线 上是高电平,就是写 1,如果线上是低电平,就是写 0。 主机要生成一个写时间隙, 必须把数据线拉到低电平然后释放, 在写时间隙 开始后的 15s 内允许数据线拉到高电平 主机要生成一个写 0 时间隙,必须把数据线拉到低电平并保持 60 s。 六)、按键部分 原理: 键盘扫描,先将 P3.6 口置零,此时扫描 S5S8,如果 P3.0P3.3中有为 0,则说 明有对应键按下。然后将 P3.7 口置零,此时扫描 S1S4,如果 P3.0P3.3中有为 0,则说明有对应键按下。 四、软件设计方

12、案 部分程序代码 (一)主程序: #include #includelcd1602.h /包含头文件,直接引用显示文件 #includeds18b20.h #include DS1302.h #define uchar unsigned char #define uint unsigned int #define TIMER0_COUNT 0 xEE11 sbit mode=P30;/设定修改位数 sbit plus=P31;/ 加键 sbit dec=P32;/减键 uchar count,s1num,timer0_tick,count=0; typedef struct char hour

13、; char minute; char second; time; typedef struct uint year; char month; char day; date; time now=11,20,7; / 显示时间初始值 date today=12,6,16; char code dayofmonth=31,28,31,30,31,30,31,31,30,31,30,31; / 设定月份数组, 用以判定 12 个月的最大值 char code weekday710=Week1 ,Week2 ,Week3 ,Week4 ,Week5 ,Week6 ,Week7 ; /设定行星期显示数

14、uchar monthday(uchar year,uchar month) if(month=2 else return(28); /非闰年时的该月份天数 28 void display_week() /由年月日计算星期,用以显示星期数 char days; days=(today.day+1+2*today.month+3*(today.month+1)/5+today.year+today.year/4-to day.year/100+today.year/400)%7; display_string( static void timer0_initialize(void) /timer

15、0 initialize EA=0; timer0_tick=0; /设置不接受所有中断 TR0=0; / 关闭 Timer0 TMOD=0X01; /设置 Timer0 为模式 2,16 位工作模式 TL0=(TIMER0_COUNT / 设置 Timer0 低八位数值 TH0=(TIMER0_COUNT 8); / 设置 Timer0 高八位数值 PT1=1; /设置 Timer0 的优先级为最高 ET0=1; /设置接受 Timer0 的中断 TR0=1; / 启动 Timer0 EA=1; /设置系统接受中断 void write_time(uchar add,uchar number

16、) /写时间 gotoxy(2,add); display_data(number); void write_riqi(uchar add,uchar number)/写日期 gotoxy(1,add); display_data(number); void keyscan()/按键扫描程序 uchar mode_num; / 设 定 mode_num, 来 判 断 是 哪 一 位 要 修 改 , 当 mode_num为零时,为非修改模式 if(mode=0) /修改位 的选择 delay(5);/ 延时 if(mode=0) /当外部按键 mode 没按下一次时,都使 mode_num 自加

17、, 即 mode_num表示为按键 mode 按下的次数 mode_num+; while(!mode); TR0=0; write_com(0 x0f); if(mode_num=1) gotoxy(1,1); /当 mode_num为 1时,为年份改变位, 光标移到( 1,2) if(mode_num=2) gotoxy(1,4); /当 mode_num为 2 时,为月份 改变位,光标移到( 1,5) if(mode_num=3) gotoxy(1,7); /当 mode_num 为 3 时,为日期改 变位,光标移到( 1, 8) if(mode_num=4) gotoxy(2,1);/

18、当 mode_num 为 4 时,为小 时改变位,光标移到( 2,2) if(mode_num=5) gotoxy(2,4);/当 mode_num为 5 时,为分 钟改变位,光标移到( 2,5) if(mode_num=6) gotoxy(2,7); /当 mode_num 为 6 时,为秒数改 变位,光标移到( 2, 8) if(mode_num=7)/当 mode_num为 7 时,退出修改模式 mode_num=0; / 非修改模式时,将 mode_num 置零,有助 于判断是否为修改模式 write_com(0 x0c); TR0=1; if(mode_num!=0)/ 为修改模式时

19、,加减键的处理子程序 if(plus=0)/当加键为零,即外部触发一次时,进行以下处理 delay(5); / 延时 if(plus=0) /延时再次判断加键,防止抖动 if(mode_num=1) /当为年份改变时,年份自加一,并且 显示修改后的日期 today.year+; write_riqi(1,today.year); / 因为年份主要是最后两位在改 变,所以除以 100 来计算年份值,除以 100 求得的商值为十位 gotoxy(1,14); display_week(); /因为改变日期都会改变周数, 所以要重 新显示 if(mode_num=2) /以下处理同上 today.m

20、onth+; if(today.month=13) today.month=1; / 特 别 注 意,月份不能超过 12,当为 13 时,要将月份置 1 write_riqi(4,today.month); / 除以 10 来计算月份值,除以 10 求得的商值为十位 gotoxy(1,14); display_week(); if(mode_num=3) /以下处理同上 today.day+; if(today.daymonthday(today.year,today.month) / 特别要判断每个月份的最大值,不能超过此数,超过后要将天数置一 today.day=1; write_riqi

21、(7,today.day); /除以 10 来计算月份值, 除以 10 求 得的商值为十位 gotoxy(1,14); display_week(); if(mode_num=4) /以下处理同上 now.hour+; if(now.hour=24) now.hour=0; /小时不能超过 24 write_time(1,now.hour); if(mode_num=5)/以下处理同上 now.minute+; if(now.minute=60) now.minute=0; write_time(4,now.minute); if(mode_num=6)/ 以下处理同上 now.second+

22、; if(now.second=60) now.second=0; write_time(7,now.second); if(dec=0) /减键的处理和加键处理处理相反 delay(5); if(dec=0) if(mode_num=1) today.year-; write_riqi(1,today.year); gotoxy(1,14); display_week(); if(mode_num=2) today.month-; if(today.month=0) today.month=12; /要注意月份的 最小值为 1,当减为零时,要讲月份置为 12 write_riqi(4,tod

23、ay.month); / 除以 10 来计算月份值,除以 10 求得的商值为十位 gotoxy(1,14); display_week(); if(mode_num=3) today.day-; if(today.day=0) /当天数减为 0 时,要重新赋值, 为上一个月的最大值 today.day=monthday(today.year,today.month); write_riqi(7,today.day); / 除以 10 来计算月份值,除以 10 求得的商值为十位 gotoxy(1,14); display_week(); if(mode_num=4) now.hour-; if(

24、now.hour0) now.hour=23; /当小时数小于 0 时,要重新赋 值,置为 23 write_time(1,now.hour); if(mode_num=5) now.minute-; if(now.minute0) now.minute=59; /注意点同上 write_time(4,now.minute); if(mode_num=6) now.second-; if(now.second 8);/ 设置 Timer0 高八位数值 TR0=1; count+; if(count=30) display_temp(); /延时,当 count=30 时,显示温度,并延时 if

25、(count=200) /当 count 自加到 200 时,开始判断此时时、 分、秒的值, 并进行转换 count=0; now.second+; if(now.second=60) /当秒达到 60 时,向分进位,且秒数置零 now.second=0; now.minute+; if(now.minute=60) /当分达到 60 时,向时进位,且分数置零 now.minute=0; now.hour+; if(now.hour=24) /当时达到 24 时,向天进位,且时数置 零 now.hour=0; today.day+; if(today.daymonthday(today.yea

26、r,today.month) /判断天数,当超过本月最大天数时,向月份进位,且天数置一 today.day=1; today.month+; if(today.month=13) /判断月份, 当月 份超过 12 时,向年份进位,月份置一 today.month=1; today.year+; write_riqi(4,today.month); / 在位置 4 处, 向 lcd 写月份 write_riqi(7,today.day); /在位置 7 处,向 lcd 写 天数 gotoxy(1,14); display_week(); write_time(1,now.hour); /在位置

27、1 处,向 lcd 写时数 write_time(4,now.minute); /在位置 4处,向 lcd 写分数 write_time(7,now.second); /在位置 7 处,向 lcd 写秒数 void main() SYSTEMTIME CurrentTime; LcdInitiate(); / 初始化 lcd timer0_initialize(); / 初始化内部定时器 Initial_DS1302(); /初始化 DS1302 DateToStr( /从 DS1302 读取日期 TimeToStr( /从 DS1302 读取时间 gotoxy(1,1); display_s

28、tring(CurrentTime.DateString); / 显示日期 gotoxy(1,10); display_week(); / 显示周几 gotoxy(2,1); display_string(CurrentTime.TimeString); / 显示时间 gotoxy(2,10); display_string(00.0C);/显示温度 while(1) keyscan(); (二) DS1302时钟模块 #include #include #ifndef _REAL_TIMER_DS1302_2003_7_21 #define _REAL_TIMER_DS1302_2003_7

29、_21 sbit DS1302_CLK = P16; sbit DS1302 _IO = P17; sbit DS1302 _RST = P15; sbit ACC0 = ACC0; sbit ACC7 = ACC7; /实时时钟时钟线引脚 /实时时钟数据线引脚 /实时时钟复位线引脚 typedef struct _SYSTEMTIME_ unsigned char Second; unsigned char Minute; unsigned char Hour; unsigned char Week; unsigned char Day; unsigned char Month; unsig

30、ned char Year; unsigned char DateString9; unsigned char TimeString9; SYSTEMTIME;/定义的时间类型 #define AM(X) X #define PM(X) (X+12) #define DS1302_SECOND 0 x80 0 x80 放的的秒数 #define DS1302_MINUTE 0 x82 / 转成 24 小时制 /时钟芯片的寄存器位置 ,存放时间 ,如 #define DS1302_HOUR 0 x84 #define DS1302_WEEK 0 x8A #define DS1302_DAY 0

31、x86 #define DS1302_MONTH 0 x88 #define DS1302_YEAR 0 x8C #define DS1302_RAM(X) (0 xC0+(X)*2) /用 于计 算 DS1302_RAM 地 址的宏 RAM 命令控制字地址: 0 xC0-0 xFD void DS1302InputByte(unsigned char d) /实时时钟写入一字节 (内部函数 ) unsigned char i; ACC = d; for(i=8; i0; i-) /将 IO 线上的数据存放在 ACC 中 /特别注意, DS1302 写一数据时, /每次移位一位 DS1302_

32、IO = ACC0; DS1302_CLK = 1; CLK 要产生一负脉冲 DS1302_CLK = 0; ACC = ACC 1; unsigned char DS1302OutputByte(void) /实时时钟读取一字节 (内部函数 ) unsigned char i; for(i=8; i0; i-) ACC = ACC 1;/将前一个下降沿读出的数据右 移一位从而读出该次读出的数放入 ACC7 ACC7 = DS1302_IO; /SCLK 下降沿读出 DS1302 的数 DS1302_CLK = 1; DS1302_CLK = 0; return(ACC); void Writ

33、e1302(unsigned char ucAddr, unsigned char ucDa) /其/ 中 Addr 为 DS1302 地址, ucData为要写的数据 DS1302_RST = 0; 沿, CLK 为低电平 DS1302_CLK = 0; DS1302_RST = 1; DS1302InputByte(ucAddr); DS1302InputByte(ucDa); DS1302_CLK = 1; DS1302_RST = 0; /写数据时,要注意 RST 产生一上升 / 地址,命令 / 写 1 字节数据 unsigned char Read1302(unsigned char

34、 ucAddr) / 读取 DS1302 某地址的数据 unsigned char ucData; DS1302_RST = 0; DS1302_CLK = 0; DS1302_RST = 1; DS1302InputByte(ucAddr|0 x01); ucData = DS1302OutputByte(); / 地址,命令 / 读 1 字节数据DS1302_CLK = 1; DS1302_RST = 0; return(ucData); /是否写保护 void DS1302_SetProtect(bit flag) if(flag) Write1302(0 x8E,0 x80); /0

35、x8E 控制字节地址,bit7=WP WP=1 禁止数据 写入 DS1302 else Write1302(0 x8E,0 x00); /WP=0 允许写入 DS1302 void DS1302_SetTime(unsigned char Address, unsigned char Value)/ 设置 时间函数 DS1302_SetProtect(0); Write1302(Address, (Value/10)Second = (ReadValue /将 ReadValue数据的第 4、5、6 位取出,实际上就是秒数的十位,但是以二进制的 形式表示,所以要进行移位,向右移四位, 在乘以

36、10,在加上 ReadValue变量中 秒数的,将十六进制的数化成十进制数表示,并放在 Time-Second 中 ReadValue = Read1302(DS1302_MINUTE); Time-Minute = (ReadValue/ 同上 ReadValue = Read1302(DS1302_HOUR); Time-Hour = (ReadValue /同上 ReadValue = Read1302(DS1302_DAY); Time-Day = (ReadValue / 同上 ReadValue = Read1302(DS1302_WEEK); Time-Week = (ReadV

37、alue /同上 ReadValue = Read1302(DS1302_MONTH); Time-Month = (ReadValue / 同上 ReadValue = Read1302(DS1302_YEAR); Time-Year = (ReadValue / 同上 void DateToStr(SYSTEMTIME *Time)/年份转换成可供 lcd 显示的字段子程 序 Time-DateString0 = Time-Year/10 + 0; /Time-DateString0 中存放的就 是要显示年的十位 Time-DateString1 = Time-Year%10 + 0; /

38、Time-DateString1 中存放的就 是要显示年的个位 Time-DateString2 = -;/年和月份之间用 -分开 Time-DateString3 = Time-Month/10 + 0; /Time-DateString3 中存 放的 就是要显示月份的十位 Time-DateString4 = Time-Month%10 + 0; /Time-DateString4 中存 放的 就是要显示月份的个位 Time-DateString5 = -; Time-DateString6 = Time-Day/10 + 0; /Time-DateString6 中存放的就 是要显示日的

39、十位 Time-DateString7 = Time-Day%10 + 0; /Time-DateString7 中存放的 就是要显示日的个位 Time-DateString8 = 0; /记住,结束时要添加 0,以作为 结束标志 void TimeToStr(SYSTEMTIME *Time)/时间转换成可供 lcd 显示的字段子程序 Time-TimeString0 = Time-Hour/10 + 0; Time-TimeString1 = Time-Hour%10 + 0; Time-TimeString2 = :; Time-TimeString3 = Time-Minute/10

40、+ 0; Time-TimeString4 = Time-Minute%10 + 0; Time-TimeString5 = :; Time-TimeString6 = Time-Second/10 + 0; Time-TimeString7 = Time-Second%10 + 0; Time-TimeString8 = 0; void Initial_DS1302(void)/DS1302 的初始化程序 unsigned char Second=Read1302(DS1302_SECOND); if(Second #endif (三) DS18B20温度模块 #include #inclu

41、de #define uchar unsigned char #define uint unsigned int uint temp; / 温度变量 sbit DS=P10;/ 定义数据传输接口 void delay1(uchar count) /延时 while(count0) count-; void reset(void)/ 送初值和初始命令 DS=0; delay1(100); DS=1; delay1(4); delay1(200); bit read_bit(void)/读一比特,特别注意对于 18b20,要读数据时,一定要 产生 DS 正脉冲,然后才传送数据 bit temp;

42、DS=0; _nop_(); DS=1; _nop_(); temp=DS; delay1(200); return temp; uchar read_byte(void) /读一字节的数据 uchar i,byte=0; bit j; for(i=0;i8;i+) byte=_cror_(byte ,1); /将 byte 数据向右循环一位,每次都取出最高位 j=read_bit(); / 设定 j 为读取进来的一比特数 if(j=0) byte=byte|0 x00; /当 j=0 时,即读取一字节数完毕,取出次字 节数 else byte=byte|0 x80;/每次取出最高位 retu

43、rn byte;/ 返回字节数 void write_byte(uchar command) /写一字节到 18b20 uchar i; for(i=0;i8;i+) /用 i 来设定一字节的数据 if(command delay1(8); DS=1; _nop_(); else /否则产生一上升沿 DS=0; _nop_(); DS=1; delay1(8); command=_cror_(command,1); void tmpchange(void) / 启动 18b20 reset(); write_byte(0 xcc); /直接向 18b20 发送温度变换命令 write_byte

44、(0 x44); /启动 18b20 进行温度转换 uint tmp() /获取温度 float tt; uchar a,b; reset(); write_byte(0 xcc); /直接向 18b20 发送温度变换命令 write_byte(0 xbe); /读取温度寄存器的温度值 a=read_byte();/读低八位 b=read_byte();/读高八位 temp=b; temp=8; /因为 18b20 处理接受到的数据要进行处理, 先将高八位左移 4 位 temp=temp|a; /在和低八位相或,整合取得的数据 tt=temp*0.0625; temp=tt*10+0.5; r

45、eturn temp; (四) LCD1602 显示模块 #include /包含单片机寄存器的头文件 #include /包含 _nop_()函数定义的头文件 #define uchar unsigned char #define uint unsigned int sbit rs=P20;/寄存器选择信号 sbit rw=P21;/读写控制信号线 sbit lcden=P22; /使能信号线 sbit BF=P07;/忙碌标志位,将 BF 位定义为 P0.7引脚 #define lcd_mode 0 x38 #define display_cursor 0 x0f #define undi

46、splay_cursor 0 x0c char code int_to_char=0,1,2,3,4,5,6,7,8,9; /* void delay(uint x)/延时程序 uint a,b; for(a=x;a0;a-) for(b=10;b0;b-); /* unsigned char BusyTest(void) bit result; rs=0;/根据规定, RS为低电平, RW为高电平时,可以读状态 rw=1; lcden=1; /E=1 ,才允许读写 _nop_(); / 空操作 _nop_(); _nop_(); _nop_(); / 空操作四个机器周期,给硬件反应时间 re

47、sult=BF; / 将忙碌标志电平赋给 result lcden=0; return result; /* 函数功能:将模式设置指令或显示地址写入液晶模块 入口参数: dictate */ void WriteInstruction (unsigned char dictate) while(BusyTest()=1); /如果忙就等待 rs=0; /根据规定, RS 和 R/W 同时为低电平时,可以 写入指令 rw=0; lcden=0;/E置低电平(根据表 8-6,写指令时, E为高 脉冲, / 就是让 E从 0到 1发生正跳变,所以应先 置0 _nop_(); _nop_();/空操作

48、两个机器周期,给硬件反应时间 /将数据送入 P0 口,即写入指令或地址 P0=dictate; _nop_(); _nop_(); _nop_(); _nop_(); /空操作四个机器周期,给硬件反应时间 lcden=1; /E 置高电平 _nop_(); _nop_(); _nop_(); _nop_();/空操作四个机器周期,给硬件反应时间 lcden=0;/当 E 由高电平跳变成低电平时,液晶模块开 始执行命令 void write_com(uchar com) /写命令 P0=com;/写命令,记住时序问题 rs=0; /rs 要为低电平 lcden=0; /使 lcd 使能端产生一个

49、正脉冲 delay(10); lcden=1; delay(10); lcden=0; void WriteAddress(unsigned char x) WriteInstruction(x|0 x80); / 显示位置的确定方法规定为 80H+地址码 x void write_date(unsigned char y) /写数据 while(BusyTest()=1); rs=1;/RS为高电平, RW为低电平时,可以写入数据 rw=0; lcden=0;/E 置低电平(根据表 8-6,写指令时, E为高脉冲, P0=y;/将数据送入 P0 口,即将数据写入液晶模块 _nop_(); _

50、nop_(); _nop_(); _nop_(); /空操作四个机器周期,给硬件反应时间 lcden=1; /E 置高电平 _nop_(); _nop_(); _nop_(); _nop_();/空操作四个机器周期,给硬件反应时间 lcden=0;/当 E 由高电平跳变成低电平时, 液晶模块开始执行 命令 /* void LcdInitiate(void) delay(15);/ 延时 15ms,首次写指令时应给 LCD 一段较长的反应 时间 WriteInstruction(0 x38); /显示模式设置: 162 显示, 57 点阵, 8 位数据接 口 delay(5); /延时 5ms

51、WriteInstruction(0 x38); delay(5); WriteInstruction(0 x38); delay(5); WriteInstruction(0 x0d); /显示模式设置:显示开,有光标,光标闪烁 delay(5); WriteInstruction(0 x0c); /显示模式设置:光标右移,字符不移 delay(5); WriteInstruction(0 x01); /清屏幕指令,将以前的显示内容清除 delay(5); void display_string(char *p) / 写字符串 while(*p) write_date(*p); delay(

52、20); p+; /* void gotoxy(uchar x,uchar y) /设置移动坐标 if(x=1) write_com(0 x80+y); else write_com(0 xc0+y); /* void display_data(char number) / 显示数据 uchar x,y; x=number/10; /将取得的数据转换成十进制 y=number%10; write_date(int_to_charx); write_date(int_to_chary); (五)键盘扫描部分 char fun,flag,flag2,adjust,wei,adt;/按键功能标志位

53、sbit rr=P37; sbit ll=P36; sbit anjian=P16;/按键灯光提醒 sbit right=P33; sbit left=P32; sbit up=P31; sbit down=P30; sbit menu=P33; sbit ok=P32; void keyscan()/调整时间按键程序 uchar i; ll=0; if(fun=1)/功能 1,时钟情况下 if(ok=0)/ 判断 OK 键摁下 delay_MS(5);/去抖动 if(ok=0) while(!ok);/松手监测 anjian=0;/提示灯点亮 delay_MS(240); anjian=1;

54、 flag+;/按键计数 ds1302_write_byte(write_wp,0 x00); /DS1302 暂停 ds1302_write_byte(write_sec,0 x80); ds1302_write_byte(write_wp,0 x80); if(flag=2)/调整时间完毕,退出调整 wei=0; adt=0; ds1302_write_time(); flag=0; adjust=1;/ 允许调整时间标志位 lcd1602_write_command(0 x0d); lcd1602_write_command(0 x80+0 x03); ll=1; rr=0; if(ad

55、just=1) if(right=0)/判断左移按键 delay_MS(5); if(right=0) while(!right); anjian=0; delay_MS(240); anjian=1; wei+;/移动位置标志 adt=1; if(wei=1) lcd1602_write_command(0 x0d); / 显示光标 lcd1602_write_command(0 x80+0 x03); if(wei=8)/ 循环移动 wei=1; lcd1602_write_command(0 x0d); lcd1602_write_command(0 x80+0 x03); if(adt=1) if(up=0)/时间加 1 delay_MS(5); if(up=0) w

温馨提示

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

评论

0/150

提交评论