宁波大学 信息与工程学院 课程名称:姓 名:
学 号:
专
指导老师:班 级:完成时间:
单片机应用系统设计 自动化091 2012-7-12
1
目录
一、实验内容及设计要求............................................................................................................... 3
1.1、实验内容 ................................................................................................................................................. 3
1.2、设计要求 ................................................................................................................................................. 3
二、概述(课题意义及背景介绍) ............................................................................................... 3
三、硬件电路图设计及说明 ............................................................................................... 4
3.1、中枢模块简介 ......................................................................................................................................... 4
3.2、LCD显示模块 ........................................................................................................................................ 5
3.3、按键模块 ................................................................................................................................................. 5
3.3、串行实时时钟芯片S-3530A .................................................................................................................. 6
3.4、电路原理图 ............................................................................................................................................. 6
四、设计之特别篇 .......................................................................................................................... 7
五、软件流程图及说明................................................................................................................... 8
5.1、主函数与中断流程图 ............................................................................................................................. 8
5.2、I2C函数流程 .......................................................................................................................................... 8
5.3、键盘扫描子程序流程图 ......................................................................................................................... 9
5.4、软件说明..................................................................................................................................................10
六、运行与调试 ............................................................................................................................ 11
七、实训设计总结 ........................................................................................................................ 11
八、参考资料及文献 .................................................................................................................... 12
九、使用说明书 ............................................................................................................................ 12
十、实验程序及相关注解............................................................................................................. 14
2
单片机应用系统设计
一、实验内容及设计要求:
1.1、实验内容:
1.使用中文液晶128x64点阵LCD,采用16点阵字库显示当前时间“时时:分分:秒秒”
2.用4个按键设置现在时间:
K1进入设置现在时间;
K2调整小时;
K3调整分;
K4设置完成。
3.增加闹铃功能,时间到了使用音乐声
可选实验内容:
4.增加闹铃功能, 时间到发出声响并启动继电器
5.增加闹铃次数 三次闹铃
6.增加秒表计数功能 精度为0.01秒
7.增加万年历显示“年月日” 二月 28天、29天
8.增加整点闹铃 指示灯闪动5次
9.增加整点闹铃开关
10.反字
小图形
11.被设置的数字闪动
12.其他自己认为可添加的内容
1.2、设计要求
方案设计前要求完成设计报告,每个组一份;
方案实施过程中完善设计报告,每个成员独立进行;
方案实施结束,经过指导老师验收后完成设计报告,每个成员独立完成,其中设计图纸每个组只需要1份。
二、概述(课题意义及背景介绍)
单片机是一种集成在电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中 3
央处理器CPU随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计时器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的计算机系统。?凡是与控制或简单计算有关的电子设备都可以单片机来实现,如:?工业自动化:数据采集、测控技术。?智能仪器仪表:数字示波器、数字信号源、数字万用表、感应电流表等。?消费类电子产品:洗衣机、电冰箱、空调机、电视机、微波炉、手机、IC卡、汽车电子设备等。?通讯方面:调制解调器、程控交换技术、手机、小灵通等。?武器装备:飞机、军舰、坦克、导弹、航天飞机、鱼雷制导、智能武器等。?现代人类生活中所用的几乎每件电子和机械产品中都会集成有单片机。手机、电话、计算器、家用电器、电子玩具、掌上电脑以及鼠标等电脑配件中都配有1-2部单片机。而个人电脑中也会有为数不少的单片机在工作。汽车上一般配备40多部单片机,复杂的工业控制系统上甚至可能有数百台单片机在同时工作!单片机的数量不仅远超过PC机和其他计算的综合,甚至比人类的数量还要多。由于单片机技术的发展,以单片机为基础的时钟系统有着越来越广阔的开发前景。
本次单片机课程设计所述的LCD时钟控制系统主要指时钟显示、时间设置、整点报时及闹铃、万年历、秒表(可扩展功能)等控制系统。课程设计方案采用进入市场时间早,总线开放,仿真开发设备多,芯片及其开发设备价格低廉、速度较快、电磁兼容性较好的MCS-51型单片机为核心实现智能时钟控制。
三、硬件电路图及说明
LCD时钟控制系统以 MCS-51兼容单片机C8051F微处理器为核心,由MCU核心模块 、128x64液晶显示模块 、独立式键盘模块、实时时钟/日历芯片模块等电路组成。
系统实验板可按教学需要与核心模块组成目标系统,然后由核心模块中的C8051F020单片机JTAG相连接的Cygnal开放工具,实现在系统开放调试。
硬件连接及软件安装:
【1】将JTAG扁平电缆与串口适配器(EC2)连接;
【2】将JTAG扁平电缆的另一端与目标系统连接;
【3】将RS232/USB串行电缆的一端与EC2连接;
【4】连接RS232/USB串行电缆的一端到PC;
【5】给目标系统上电;
3.1、中枢模块简介:
中枢模块概述
MCU 核心模块采用可插拔更换的结构,可为用户提供两种MCU 核心模块(选配),一种为80C51
系列单片机,另一种为Cygnal 公司的高速、高性能混合信号处理C8051 系列单片机。其中C8051
核心模块选用C8051F020 芯片,此芯片为现有C8051 系列单片机中功能最为齐全的一款。模块
上设计有连接F020 单片机的JTAG 调试接口,所有I/O 全部引出,有用于扩展和应用连接的排
针、双排针座,可以和用户的外部电路搭配使用。
C8051F020 片上系统单片机片内资源
4
? 模块外设
(1)逐次逼近型8路12位ADC0
转换速率最大100ksps
可编程增益放大器PGA
温度传感器
(2)8路8位ADC1输入与P1口复用
转换速率500ksps
可编程增益放大器PGA
(3)两个12位DAC
(4)两个模拟电压比较器
(5)电压基准:内部提供2.4V,外部基准可输入
(6)精确的VDD监视器
? 高速8051微控制器内核
流水线式指令结构,速度可达25MIPS
22个矢量中断源
? 存储器
片内4352字节数据RAM
64KB Flash程序存储器可作非易失性存储
外部可扩展的64KB数据存储器接口
? 数字外设8个8位的端口I/O
I2C、SPI、2个增强型UART串口
可编程的16位计数器/定时器阵列(PCA)
? 4个通用16位计数器/定时器
专用的看门狗WD
3.2、LCD显示模块:
中文液晶128x64点阵LCD,采用16点阵字库显示当前时间“xx年xx月xx日 xx时xx分xx秒”。液晶显示模块由于具有功耗低、寿命长、价格低、接口控制方便等优点,正在各类测量及控制仪表中被极广泛地推广和应用。字符型液晶显示模块是一类专用于显示字母、数字、符号等点阵式液晶显示模块。
以HD44780(HITACHI)为主控制器及其HD44100扩展控制电路构成的液晶显示模块是以若干个5×8或5×11点阵块组成的字符块集,每一个字符块是一个字符位,字符问点距和行距都为一个点的宽度,具有字符发生器ROM 可显示192种字符和64个字节的自定义字符RAM ,可自定义8个5×8点阵字符或4个5×11点阵字符。各液晶控制器制造厂商的模块接口信号和操作指令有广泛的兼容性,并能直接与单片机接口,具有专用指令,可方便地实现各种不同操作。
3.3、按键模块:
按键分配:
P3.0口,K2控制P3.1口, K3控制P3.2口, K4控制P3.3口
5
键盘是微型计算机最常用的输入设备,用户可以通过键盘向计算机输入指令、地址和数据。一般单片机系统中采和非编码键盘,非编码键盘是由软件来识别键盘上的闭合键,它具有结构简单,使用灵活等特点,因此被广泛应用于单片机系统。按键开关的抖动问题,键盘与单片机的连接组成键盘的按键有触点式和非触点式两种,单片机中应用的一般是由机械触点构成的。在上图中,当开关K1未被按下时,P3.0输入为高电平,K1按下后,P3.0输入为低电平。而按键会有抖动现象,因此必须考虑如何去除抖动,常用的去抖动的方法有两种:硬件方法和软件方法。单片机中常用软件法。软件法其实很简单,就是在单片机获得P3.0口为低的信息后,不是立即认定S1已被按下,而是延时10毫秒或更长一些时间后再次检测P3.0口,如果仍为低,说明K1的确按下了,这实际上是避开了按键按下时的抖动时间。而在检测到按键释放后(P3.0为高)再延时5-10个毫秒,消除后沿的抖动,然后再对键值处理。
通过1/0口连接。将每个按键的一端接到单片机的I/O口,另一端接地,这是最简单的方法,如上图所示是实验板上按键的接法,四个按键分别接到P3.0 、P3.1、P3.2和P3.3。对于这种键各程序可以采用不断查询的方法,功能就是:检测是否有键闭合,如有键闭合,则去除键抖动,判断键号并转入相应的键处理。
3.3、实时时钟芯片S-3530A:
S-3530是一款低功耗的CMOS实时时钟/日历芯片,它提供二个中断输出和掉电检测器,所有的地址和数据通过I2C总线接口串行传递。最大总线速度为400Kbits/s,每次读写数据后,内嵌的字地址寄存器会自动增加。最主要的功能是芯片能够自己计算闰年,不足时没有秒表功能。
器件主要特性:
? 低工作电流:典型值为0.7μA(VDD=3.0V);
? 世纪标志;
? BCD码设置时间参数;
? 大工作电压范围:1.0~5.5V;
? 低休眠电流;典型值为0.25μA(VDD=1.8~5.5V时);
? 稳压电路
? 报警和定时器;
? 掉电检测器;
? 内部集成的振荡器电容;
? I2C总线从地址:读:0A3H;写:0A2H;
3.4、电路原理图:
6
连接说明:将JTAG扁平电缆与串口适配器(EC2)连接;将JTAG扁平电缆的另一端与目标系统连接;将RS232/USB串行电缆的一端与EC2连接;连接RS232/USB串行电缆的一端到PC;给目标系统上5v的电源;单片机C8051F020P0口中P0.6、P0.7与S3530时钟芯片相连;P2口和P1口中的P1.0、P1.1、P1.2、P1.3、P1.4、P1.5与128X64LCD相连,P1.6、P1.7与发光二极管相连,其中闹钟整点报时可通过P1.6显示,闹铃设置时间到开闹铃可通过P1.7显示;P3口中的P3.1、P3.2、P3.3、P3.4分别与K1、K2、K3、K4键相连,则K1控制P3.0口,K2控制P3.1口, K3控制P3.2口, K4控制P3.3口。
四、设计之特别篇
课程设计的主要特点主要有如下几点:
1增加三次闹铃功能,时间到LED闪烁; ○
2设置界面拥有小图形(可自行DIY图形然后提取字模); ○
3增加秒表计数功能,精度为0.01秒; ○
4增加万年历显示“年月日”○,考虑闰年与平年的情况;
5有整点闹铃功能; ○
7
五、软件流程图及说明
5.1、主函数与中断流程图:
主函数流程(main.c): 中断流程:
5.2、I2C函数流程:
8
5.3、按键扫描子程序流程图:
9
5
.4、软件说明 做本实验要用到keil c51编程软件。Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。Keil提供了包括C编译器、宏汇编、连接器、库管
10
理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成开发环境(uVision)将这些部分组合在一起。运行Keil软件需要WIN98、NT、WIN2000、WINXP等操作系统。如果你使用C语言编程,那么Keil几乎就是你的不二之选,即使不使用C语言而仅用汇编语言编程,其方便易用的集成环境、强大的软件仿真调试工具也会令你事半功倍。
六、运行与调试
1) 小表情在显示屏上无法完全显示,,经检查该表情符坐标地址不对,改正后显示正常。
2) 屏幕出现不断闪烁或按键不灵。原因:程序中调用延时时间过长,使屏幕的刷新率降低,
导致屏幕不断闪烁,修改延时时间后,调试正常。
3) 设置完成后,出现秒钟从59变成00时,分钟不进位。原因:未把设置完成的数值写到
S3530A中,在设置的最后添加写S3530程序后,调试成功。
4) 在设置闹钟时,设置闹铃的小时和分钟在屏幕上不会显示,设置完成后屏幕却可以显示
闹铃的时间。原因:闹铃设置时的显示程序所在的位置不对,对程序进行修改后,显示正常。
5) 在设置秒表功能时,用定时器1中断程序,秒表不能工作。原因:定时器1的初始化不
正确,EA,TR1,ET1未使能,对程序进行修正后,秒表正常工作。
6) 秒表计时到最大值200.99时,秒表不清0,而是继续往上加。原因:当秒表计时到200.99
时,未对其进行if条件限制,使秒表各位都清零。经加条件语句后,重新调试后,秒表正常工作。
7) 本来想在屏幕最下一行的中间显示整年闹铃开,结果发现在计数时会把这些字覆盖,经
调整发现在计数时应把最下一行未用到的坐标清空,以防发生显示冲突,影响美观
8) 在设置字模式由于本组员姓“郑”与整点闹铃的“整”拼音相同,定义字模函数的时候,
函数名一样,而字模不一样,导致内部冲突出现错误,无法编译。改正方法:只要把其中的一个函数名改掉即可。
七、实训设计总结:
单片机课程是分小组进行的,这要求每个组员都要有明确的分工和积极的团队精神。我们小组由两个人组成,在单片机课程的学习和开发过程中我们深有体会。
1、小组成员分工要明确细致,这有利于提高学习效率,加快产品开发的进度。相反,假若没有明确分工,不但做不出产品,反而会无形中增加课程的难度。同时各小组成员的分工也不能是完全独立的,要相互联系,应该坚决杜绝写软件只管软件,组装硬件的只管硬件的做法,因为最终的产品是一个有机结合体,而不是一个软硬件拼凑体,只有大家分工加合作,才能取得最终的成功。
2、在产品的开发过程中,我们切实体会到一个团队一定要有一个敢于承担义务、勇于 11
承担责任的领导者。组长的乐观精神、坚韧不拔的毅力和明确清晰的产品开发思路,不但可以在遇到困难时鼓励督促大家继续工作,同时能够保障整个产品的开发高效高质量的进行。
3、每个组员都要有高度的责任感。产品的开发不是某一个人或某几个人的事情,而是大家共同的任务。特别是在产品开发遇到困难时,每个人都应该大胆承担责任,互相鼓励,两个人协同谈合作共同想办法解决问题,而不是互相推诿,互相抱怨。
在对单片机课程的学习和产品的开发过程中,我们深刻体会到了理论和实践的巨大差别,同时也明白了理论联系实际的重要性。
在课程设计的选择过程中,一定要立足于现有的实验开发环境和各组员的能力,选择有把握实现或有实现前景的项目,切忌眼高手低。很多想法和创意具有非常好的创新性,但其中很多都无法实现,甚至可行性都不存在,所以在课程设计题目的选择上要理性。
还有一点令我们印象深刻,那就是跟硬件配套的技术资料。项目刚开始时,我们始终找不到头目,任凭大家怎样改进方法都无济于事。但回过头来研究技术资料时,我们发现,很多做法纯属自己的想法,根本不符合硬件的要求。重新按照技术资料的理论和规则,很多问题都迎刃而解。
八 、 参考资料及文献
本次实习器件资料及参考资料:
【1】S3530器件手册
【2】C8051F02器件手册
【3】单片机的C语言应用程序设计 北京航空航天大学出版社
【4】单片机的应用实例 中国邮电出版社
【5】51单片机的入门及实例 中国邮电出版社
【6】徐宏亮,艾学忠等.实现多功能电子时钟设计[J].吉林化工学院学报
【7】 Atmel Corporation.AT89C52[J].Atmel Corporation,1999,6(2):199-223.
九、使用说明书
该样品为LED时钟,具有万年历,整点报时,秒表功能,闹钟功能及闹铃开关,通过四个按键(K1,K2,K3,K4)控制功能的选择使用。
1)
经过500ms延迟后画面为
12
2)时间设置
K1键为选择功能项,按一次K1键时,进入设置日期,星期以及时间选项,这时K2键为移位键,K3键为调整键,K4键为退出键;如下图所示:
3)闹铃设置
按两次K1键时,进入设置闹铃,再按K2键时,进入设置闹铃选项,这时按K2为选择闹铃,K3键为调整小时,K4键为调整分钟,K1键为退出键;K3键为闹铃开关,闹铃系统默认为关闭,当按下K3键时,闹铃开启,再按一次K3又可关闭闹铃。如下图所示:
13
4)秒表设置 按四次K1键时,进入秒表功能;按一下K2键,秒表开始计数;再按一下K2
键,秒表停止计数,可重复进行计时;K4键为退出键。如下图所示:
5)复位设置
按两下K4键时,退出功能选项
实验程序及相关注解
MAIN.C
#include "c8051f020.h"
#include
void SYSCLK_Init (void)
14
while (us) {
_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); --us; }
{
int i; // delay counter
OSCXCN = 0x65; // start external oscillator with for (i=0; i < 256; i++) ; // Wait for osc. to start up
while (!(OSCXCN & 0x80)) ; // Wait for crystal osc. to settle OSCICN = 0x88;
}
#define PRT0CF P0MDOUT
#define PRT1CF P1MDOUT
#define PRT2CF P2MDOUT
void PORT_Init (void)
{
XBR0 = 0x07;
// XBR1 = 0x04;
XBR2 = 0x40;
// EMI0CF = 0x27;
// EMI0TC = 0x21;
EMI0TC = 0x21;
EMI0CF = 0x2f;
选择。
P74OUT = 0x3F;
P0MDOUT = 0x00;
P1MDOUT |= 0x1f;
}
void SPI0_Init (void)
{
SPI0CFG = 0x03;
SPI0CFG|=0xC0; //CKPOL =1;
SPI0CN = 0x03;
SPI0CKR = SYSCLK/2/8000000-1;
}
unsigned char Count1ms;
void Timer0_Init (void)
{
CKCON|=0x8;
TMOD|=0x1; //16Bit
Count1ms=10;
TR0 = 0;
TH0 = (-SYSCLK/1000) >> 8;
TL0 = -SYSCLK/1000;
TR0 = 1; // START Timer0
IE|= 0x2;
}
void Timer1_Init (void)
// Enable SMBus, SPI0, and UART0 // Enable crossbar and weak pull-ups // EMIF端口接到P4-P7,选择复用方式,工作模式为不带块 //P1.2-P1.5推挽输出 // data sampled on 1st SCK rising edge // Master mode; SPI enabled; fla // STOP Timer0 // set Timer0 to overflow in 1ms 15
{
CKCON|=0x8;
TMOD|=0x10;
//16Bit // set Timer0 to overflow in 1ms TR1 = 0; // STOP Timer0 TH1 =(65535-18432)/256;
TL1 =(65535-18432)%256;
ET1=1;
}
void Timer0_ISR (void) interrupt 1 //1ms {
}
void Delay1ms(unsigned char T)
{
}
void Delay1s(unsigned char T)
{
}
void TestLCD(void);
void TestI2C (void);
void main (void)
{
//
//
// WDTCN = 0xde; WDTCN = 0xad; //关看门狗 SYSCLK_Init (); //初始化时钟 Timer0_Init(); //初始化定时器 //初始化定时器 while (T) { } Delay1ms(200); Delay1ms(200); Delay1ms(200); Delay1ms(200); Delay1ms(200); T--; Count1ms=T; while (Count1ms); TH0 = (-SYSCLK/1000) >> 8; if (Count1ms) Count1ms--; TL0 = -SYSCLK/1000; Timer1_Init(); PORT_Init (); //初始化IO口 SPI0_Init (); //初始化SPI0 CPT1CN|=0x80; //使能比较器1 REF0CN = 0x03; //使能片内参考电压 16
//
//
//
}
DAC0CN |= 0x80; //使能DAC0 //开中断 Test7279(0); DAC0H=0; DAC0L=0; TestLCD(); // TestI2C(); EA=1;
7279.C
#include "c8051f020.h"
#include
sbit HD7279_DAT=P1^7;
sbit HD7279_CLK=P1^6;
#define NOSELECT7279 P5 |= 0x80
#define SELECT7279
#define Set7279DAT
#define Clr7279DAT
#define Set7279CLK
#define Clr7279CLK //SPICS4(P57)=1 //SPICS4(P57)=0; P5 &= ~(0x80) HD7279_DAT=1 HD7279_DAT=0 HD7279_CLK=1 HD7279_CLK=0 // HD7279测试/演示程序
I/O口初始化 void Delay1ms(unsigned char T);//
void Delay1s(unsigned char T);
void Delay1us(unsigned char T);
void Send7279Byte(unsigned char ch)
{
} char i; SELECT7279; //置CS低电平 Delay1us(50); for (i=0;i<8;i++) { } Clr7279DAT; //发送完毕,DATA端置低,返回 if (ch&0x80) { } else { } Set7279CLK; ch=ch<<1; Delay1us(8); Clr7279CLK; Delay1us(8); //置CLK高电平 //待发数据左移 //延时8μ //置CLK低电平 //延时50μ Clr7279DAT; Set7279DAT; //输出7位到HD7279A的DATA端 //延时50μ
17
unsigned char Receive7279Byte(void)
{
}
void FlashLED(unsigned char No)
{
}
void MoveLeft(void)
{
}
void MoveRight(void)
{
}
unsigned char code BdSeg[]={
0x7e,0x30,0x6d,0x79, // 0 1 2 3 Send7279Byte(0xA0); //发右移指令 NOSELECT7279; //置CS高电平 Send7279Byte(0xA1); //发左移指令 NOSELECT7279; //置CS高电平 char i; Send7279Byte(0x88); //发闪烁指令 i=0x1; while (No) { } Send7279Byte(~i); //1闪烁 NOSELECT7279; //置CS高电平 i=i<<1; No--; unsigned char i,ch; ch=0; //DATA端置为高电平,输入状态 //延时50μ Set7279DAT; Delay1us(50); for (i=0;i<8;i++) { } Clr7279DAT; return ch; //接收完毕,DATA端重新置成低电平(输出状态) Set7279CLK; Delay1us(8); ch=ch<<1; ch+=1; //置CLK高电平 //延时8μ //接收数据左移1位 //接收1位数据 //置CLK低电平 if (HD7279_DAT) Clr7279CLK; Delay1us(8); //延时8μ 18
{
char i,ch;
}
char GetKeyValue(void) {
} char KeyValue; ShowDot--; for (i=0;i<6;i++) { } ch=DispBuf[i]; 0x33,0x5b,0x5f,0x70, // 4 5 6 7 0x7f,0x7b,0x77,0x1f, // 8 9 a b 0x4e,0x3d,0x4f,0x47, // c d e f 0x00,0x01}; void DispLED(char *DispBuf,char ShowDot)//ShowDot 显示小数点位 if ((ch>='a') && (ch<='f')) { ch-='a';ch+=0xa; } if ((ch>='A') && (ch<='F')) { ch-='A';ch+=0xa; } Send7279Byte(0x90+5-i); //不译码 if (ch==' ') else if (ch=='-') else { } //置CS高电平 if (ShowDot==i) else Send7279Byte(BdSeg[ch&0x0f]); Send7279Byte(0x80|BdSeg[ch&0x0f]); Send7279Byte(0x01); Send7279Byte(0x00); NOSELECT7279; if (CPT1CN&0x40) return -1; KeyValue=Receive7279Byte(); NOSELECT7279; return KeyValue; //无键按下 Send7279Byte(0x15); //发读键盘指令 //置CS高电平
19
void WaitKeyOff(void)
{
}
void Test7279(bit LoopFlag)
{
char i,KeyValue; Delay1ms(25); //等待25ms复位时间 //置CS高电平 //显示123456 Send7279Byte(0xA4); //发复位指令 NOSELECT7279; if (LoopFlag==0) return; DispLED("123456",0); for (i=0;i<8;i++) { } //显示123456 //显示123456 //显示123456 DispLED("7890AB",2); DispLED("CDEF -",3); { }
//显示123456
//第一位闪烁
//第二位闪烁
//关闪烁 Delay1s(1); MoveRight(); Delay1s(1); MoveLeft(); while (!(CPT1CN&0x40)); DispLED("123456",0); for (i=0;i<6;i++) DispLED("F 1",1); FlashLED(0); Delay1s(1); FlashLED(1); Delay1s(1); FlashLED(8);
//BlankLED(0x23); //注意:执行消隐后,键盘输入中断口不能恢复. for (;;)
{ KeyValue=GetKeyValue();
if(KeyValue!=-1)
{
} Send7279Byte(0xC8); //发送键码值,按方式1译码下载显示 Send7279Byte(KeyValue%16); NOSELECT7279; WaitKeyOff(); //置CS高电平 }
20
}
LCD.C
#include "c8051F020.h"
#include
#define LCD_DATA P2
#define LCD_RS P10
#define LCD_RW P11
#define LCD_E P12
#define LCD_CS1 P13
#define LCD_CS2 P14
#define LCD_RST P15
void Delay1ms(unsigned char);
#define SELECTCS 0
void LCD_WaitReady1(void) //判断LCD控制芯片KS0108是否忙
{
}
void LCD_WaitReady2(void) //判断LCD控制芯片KS0108是否忙
{
}
void LCD_WriteCommand1(char ch) //向LCD控制芯片KS0108发送控制命令 {
LCD_WaitReady1(); LCD_CS2=SELECTCS; LCD_RW=0; LCD_RS=0; LCD_DATA=ch; LCD_E=1; LCD_E=0; LCD_DATA=0xff; _nop_(); LCD_CS1=SELECTCS; LCD_RW=1; LCD_RS=0; LCD_E=1; while (LCD_DATA&0x80); LCD_CS1=!SELECTCS; LCD_DATA=0xff; _nop_(); LCD_CS2=SELECTCS; LCD_RW=1; LCD_RS=0; LCD_E=1; while (LCD_DATA&0x80); LCD_CS2=!SELECTCS;
21
} LCD_CS2=!SELECTCS;
//向LCD控制芯片KS0108发送控制命令 void LCD_WriteCommand2(char ch)
{
}
void LCD_WriteData1(char ch)
{
}
void LCD_WriteData2(char ch)
{
} LCD_WaitReady2(); LCD_CS1=SELECTCS; LCD_RW=0; LCD_RS=1; LCD_DATA=ch; LCD_E=1; LCD_E=0; LCD_CS1=!SELECTCS; LCD_WaitReady1(); LCD_CS2=SELECTCS; LCD_RW=0; LCD_RS=1; LCD_DATA=ch; LCD_E=1; LCD_E=0; LCD_CS2=!SELECTCS; LCD_WaitReady2(); LCD_CS1=SELECTCS; LCD_RW=0; LCD_RS=0; LCD_DATA=ch; LCD_E=1; LCD_E=0; LCD_CS1=!SELECTCS; //向LCD控制芯片KS0108发送数据命令 //向LCD控制芯片KS0108发送数据命令
void LCD_WriteHZ(char x,char y,char *Dot) //显示16*16点阵汉字 {
char i;
for (i=0;i<32;i++) { if ((x+i%16)<64) { LCD_WriteCommand1(0xB8+y+i/16); LCD_WriteCommand1(0x40+x+i%16); 22
} } } else { } LCD_WriteData1(Dot[i]); LCD_WriteCommand2(0xB8+y+i/16); LCD_WriteCommand2(0x40+x-64+i%16); LCD_WriteData2(Dot[i]);
char code Number[]=
/*-- 文字: 0123456789:/ --*/
{
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x07,0x08,0x10,0x10,0x08,0x07,0x00, 0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x1F,0x10,0x10,0x00,0x00, 0x00,0x30,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x18,0x14,0x12,0x11,0x10,0x18,0x00, 0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x0C,0x10,0x10,0x10,0x11,0x0E,0x00, 0x00,0x80,0x40,0x20,0xF8,0x00,0x00,0x00,0x00,0x03,0x02,0x12,0x1F,0x12,0x12,0x00, 0x00,0xF8,0x88,0x48,0x48,0x48,0x88,0x00,0x00,0x0C,0x10,0x10,0x10,0x10,0x0F,0x00, 0x00,0xE0,0x10,0x88,0x88,0x98,0x00,0x00,0x00,0x0F,0x11,0x10,0x10,0x10,0x0F,0x00, 0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00, 0x00,0x70,0x88,0x88,0x88,0x88,0x70,0x00,0x00,0x0E,0x11,0x10,0x10,0x11,0x0E,0x00, 0x00,0xF0,0x08,0x08,0x08,0x90,0xE0,0x00,0x00,0x00,0x19,0x11,0x11,0x08,0x07,0x00, 0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00, };
void LCD_WriteChar(char x,char y,char *Dot) //显示8*16点阵字符
{
char i;
for (i=0;i<16;i++) { } if ((x+i%8)<64) { } else { } LCD_WriteCommand2(0xB8+y+i/8); LCD_WriteCommand2(0x40+x-64+i%8); LCD_WriteData2(Dot[i]); LCD_WriteCommand1(0xB8+y+i/8); LCD_WriteCommand1(0x40+x+i%8); LCD_WriteData1(Dot[i]);
23
}
void LCD_DispChar(char x,char y,char ch) //128*64 取值x=0-128 y=0-8 {
}
void InitLCD(void)
{
}
void DispBmp(char *buf)
{
int i,j;
for (j=0;j<8;j++) { LCD_WriteCommand1(0xB8+j); LCD_WriteCommand1(0x40); for (i=0;i<64;i++) LCD_WriteData1(buf[(j*2)*64+i]); LCD_WriteCommand2(0xB8+j); LCD_WriteCommand2(0x40); for (i=0;i<64;i++) //显示位图 //显示一幅位图 } LCD_WriteCommand2(0xB8+j); //清右半屏 LCD_WriteCommand2(0x40); for (i=0;i<64;i++) LCD_WriteData2(0x00); char i,j; LCD_RST=0; Delay1ms(1); LCD_RST=1; Delay1ms(1); LCD_WriteCommand1(0xc0); LCD_WriteCommand2(0xc0); LCD_WriteCommand1(0x3f); //开显示 LCD_WriteCommand2(0x3f); //清屏 { LCD_WriteCommand1(0xB8+j); //清左半屏 LCD_WriteCommand1(0x40); for (i=0;i<64;i++) LCD_WriteData1(0x00); //初始化LCD if ((ch>=0)&&(ch<=0xb)) { } LCD_WriteChar(x,y,&Number[ch*16]); for (j=0;j<8;j++)
24
}
}
LCD_WriteData2(buf[(j*2+1)*64+i]);
void Delay1s(unsigned char T); LCD2.c
#include "c8051f020.h"
//------------------------------------------------------------------------------------ // Global CONSTANTS
//------------------------------------------------------------------------------------ sbit sbit sbit sbit sbit sbit sbit #define #define #define #define #define #define #define union {
unsigned char ClockString[7]; struct RealClock
{
unsigned char Year,Month,Day,Week,Hour,Minute,Second; } RT;
SMB_BUS_ERROR 0x00 SMB_START
0x08 0x10
SMB_RP_START
// (all modes) BUS ERROR // (MT & MR) START transmitted // (MT & MR) repeated START // (MT) Slave address + W transmitted; // (MT) Slave address + W transmitte
// (MT) data byte transmitted; ACK rec'vd // (MT) data byte transmitted; NACK rec'vd // (MT) arbitration lost
K1=P3^0; K2=P3^1; K3=P3^2; K4=P3^3; K5=P3^4; P1_6=P1^6; P1_7=P1^7;
0x00
// SMBus WRITE command
// SMBus READ command 0x60 0x64
//1 ack
//8 ack year month day week hour
READ
0x01
// SFR declarations
#define WRITE
// Device addresses (7 bits, lsb is a don't care)
CLOCK3530_ADDRESS_RESET CLOCK3530_ADDRESS_STATUS
0x62
//2 ack
CLOCK3530_ADDRESS_DATEHOUR CLOCK3530_ADDRESS_HOUR CLOCK3530_ADDRESS_INT1 CLOCK3530_ADDRESS_INT2
minute second
0x66 0x68 0x6A
//4 ack hour minute second //3 ack //3 ack
} RealTime; #define #define #define #define #define #define #define #define
SMB_MTADDACK 0x18 SMB_MTADDNACK 0x20 SMB_MTDBACK
SMB_MTDBNACK 0x30 SMB_MTARBLOST 0x38
0x28
25
#define #define #define #define
SMB_MRADDACK 0x40 SMB_MRADDNACK 0x48 SMB_MRDBACK
SMB_MRDBNACK 0x58
// (MR) Slave address + R transmitted; // (MR) Slave address + R transmitted;
// (MR) data byte rec'vd; ACK transmitted // (MR) data byte rec'vd; NACK transmitted
// Used by ISR to check what data has just been
0x50
char COMMAND; // Holds the slave address + R/W bit for use in the SMBus ISR.
unsigned char *I2CDataBuff; char BYTE_NUMBER;
int n=0,i,flag=1,m=0,h,f,hm=0,s=0,bs=0,l=0,q=0,q1=1,h1,h2,f1,f2; unsigned char Hour,Minute,Year,Month,Day,Week,Second; unsigned char HIGH_ADD, LOW_ADD; bit SM_BUSY;
void SMBus_ISR (void); void ResetRealClock(void) { }
//======================写S-3530A内部实时数据寄存器程序===================== //功能:将设定年、月、日、星期、时、分、秒数据写入S-3530A | //入口:发送数据放在年、月、日、星期、时、分、秒各寄存器 | //出口:NONE |
//========================================================================== void SetRealClock(void) { }
//==================读S-3530A实时数据寄存器子程序=========================== //功能:从S-3530A读入当前时间数据 | //入口:NONE | //出口:接收数据放在年、月、日、星期、时、分、秒各寄存器 |
//==========================================================================
while (SM_BUSY); SM_BUSY = 1; SMB0CN = 0x44;
// Wait for SMBus to be free. // Occupy SMBus (set to busy)
// SMBus enabled, ACK on
while (SM_BUSY); SM_BUSY = 1; SMB0CN = 0x44;
// Wait for SMBus to be free. // Occupy SMBus (set to busy)
// SMBus enabled, ACK on
// High & Low byte for EEPROM memory address
// This bit is set when a send or receive
acknowledge cycle
BYTE_NUMBER = 0; STA = 1;
// 2 address bytes. // Chip select + READ // Start transfer
// Wait for transfer to finish
COMMAND = (CLOCK3530_ADDRESS_RESET | READ); while (SM_BUSY);
acknowledge cycle
BYTE_NUMBER = 7;
// 2 address bytes.
// Chip select + WRITE
COMMAND = (CLOCK3530_ADDRESS_DATEHOUR | WRITE); I2CDataBuff = &RealTime.ClockString[0]; STA = 1;
// Data to be writen
// Start transfer
26
void GetRealClock(void) { }
//============================写状态寄存器程序============================== //功能:读/写S-3530A状态寄存器,对S-3530A进行设置 | //入口:NONE 出口:NONE | //========================================================================== unsigned char GetRealClockStatus(void) { }
void SetRealClockStatus(unsigned char status) { }
#include "INTRINS.H"
unsigned char revolve(unsigned char val) {
while (SM_BUSY); SM_BUSY = 1; SMB0CN = 0x44;
// Wait for SMBus to be free. // Occupy SMBus (set to busy)
// Start transfer
// SMBus enabled, ACK on
unsigned char result; while (SM_BUSY); SM_BUSY = 1; SMB0CN = 0x44;
// Wait for SMBus to be free. // Occupy SMBus (set to busy)
// Start transfer
// Wait for transfer to finish
// SMBus enabled, ACK on
while (SM_BUSY); SM_BUSY = 1; SMB0CN = 0x44;
// Wait for SMBus to be free. // Occupy SMBus (set to busy)
// SMBus enabled, ACK on
acknowledge cycle
BYTE_NUMBER = 7;
// 2 address bytes.
// Chip select + READ
COMMAND = (CLOCK3530_ADDRESS_DATEHOUR | READ); I2CDataBuff = &RealTime.ClockString[0]; STA = 1;
while (SM_BUSY);
// Data to be writen
// Start transfer
// Wait for transfer to finish
acknowledge cycle
BYTE_NUMBER = 1; I2CDataBuff = &result; STA = 1; return result;
while (SM_BUSY);
COMMAND = (CLOCK3530_ADDRESS_STATUS | READ);
acknowledge cycle
BYTE_NUMBER = 1; I2CDataBuff = &status; STA = 1;
COMMAND = (CLOCK3530_ADDRESS_STATUS | WRITE);
27
char i;
unsigned char val1=0;
}
void LCD_WriteHZ(char x,char y,char *Dot);
void LCD_DispChar(char x,char y,char ch); //128*64 取值x=0-128 y=0-8 void InitLCD(void);
void Delay1ms(unsigned char T);
void TestI2C (void)
{
unsigned char var ; WDTCN = 0xde; WDTCN = 0xad; OSCICN |= 0x03; P0MDOUT |= 0x1D; SMB0CN = 0x44; SMB0CR = -80; EIE1 |= 2; EA = 1; // Enable SMBus with ACKs on acknowledge cycle // SMBus clock rate = 100kHz. // SMBus interrupt enable // Global interrupt enable // Free SMBus for first transfer. // Set internal oscillator to highest setting // disable watchdog timer for (i=0;i<8;i++) { } val1=_cror_(val1,1); return val1; if (val&0x1) val1++; val1=_crol_(val1,1); val=_cror_(val,1); SM_BUSY = 0; ResetRealClock(); var = GetRealClockStatus(); var = GetRealClockStatus(); SetRealClockStatus(0xc2); var = GetRealClockStatus(); GetRealClock(); RealTime.RT.Year=0x05; RealTime.RT.Month=0x01; RealTime.RT.Day=0x01; RealTime.RT.Week=0x06; RealTime.RT.Hour=0x00; RealTime.RT.Minute=0x00; RealTime.RT.Second=0x00; SetRealClock(); GetRealClock(); LCD_WriteHZ(32,4,wu);
28
LCD_WriteHZ(64,4,wu); LCD_WriteHZ(96,4,wu); LCD_WriteHZ(32,2,wu); LCD_WriteHZ(64,2,wu); LCD_WriteHZ(96,2,wu); LCD_WriteHZ(64,0,wu); LCD_WriteHZ(80,0,wu); LCD_WriteHZ(0,0,wu); LCD_WriteHZ(112,0,wu); LCD_WriteHZ(112,2,wu); LCD_WriteHZ(112,4,wu); LCD_WriteHZ(0,6,wu); LCD_WriteHZ(16,6,wu); LCD_WriteHZ(32,6,wu); LCD_WriteHZ(112,6,wu); LCD_WriteHZ(16,0,xiao); LCD_WriteHZ(32,0,xin); LCD_WriteHZ(48,0,xi); LCD_WriteHZ(64,0,xue); LCD_WriteHZ(80,0,yuan); LCD_WriteHZ(96,0,xiao); LCD_DispChar(0,2,0); LCD_DispChar(8,2,9); LCD_DispChar(16,2,6); LCD_DispChar(24,2,0); LCD_DispChar(32,2,4); LCD_DispChar(40,2,0); LCD_DispChar(48,2,1); LCD_DispChar(56,2,1); LCD_DispChar(64,2,4); LCD_WriteHZ(80,2,li); LCD_WriteHZ(96,2,bo); LCD_WriteHZ(112,2,dong); LCD_DispChar(0,4,0); LCD_DispChar(8,4,9); LCD_DispChar(16,4,6); LCD_DispChar(24,4,0); LCD_DispChar(32,4,4); LCD_DispChar(40,4,0); LCD_DispChar(48,4,3); LCD_DispChar(56,4,5); LCD_DispChar(64,4,8); LCD_WriteHZ(80,4,zheng); LCD_WriteHZ(96,4,zhe); 29
LCD_WriteHZ(112,4,jie);
for(i=0;i<=30;i++)
Delay1ms(500);
InitLCD();
//在0,4处显示00时00分00秒 LCD_DispChar(24,4,0); LCD_WriteHZ(32,4,Shi); LCD_DispChar(48,4,0); LCD_DispChar(56,4,0); LCD_WriteHZ(64,4,Fen); LCD_DispChar(80,4,0); LCD_DispChar(88,4,0); LCD_WriteHZ(96,4,Miao); //在0,2处显示20xx年01月01 LCD_DispChar(16,2,1); //128*64 取值x=0-128 y=0-8 LCD_DispChar(24,2,2); LCD_WriteHZ(32,2,Nian); LCD_DispChar(48,2,0); LCD_DispChar(56,2,7); LCD_WriteHZ(64,2,Yue); LCD_DispChar(80,2,0); LCD_DispChar(88,2,9); LCD_WriteHZ(96,2,Ri); LCD_WriteHZ(64,0,xing); LCD_WriteHZ(80,0,qi); LCD_WriteHZ(96,0,Yi); LCD_WriteHZ(112,0,nao); LCD_WriteHZ(112,2,ling); LCD_WriteHZ(112,4,guan); LCD_DispChar(16,4,0); //128*64 取值x=0-128 y=0-8
LCD_WriteHZ(2,6,zhong);
LCD_WriteHZ(112,6,yin);
for (;;) { GetRealClock(); if(K1==0) Delay1ms(500); if(K1==0) n++; if(n==1) { Year=RealTime.RT.Year; Day=RealTime.RT.Day; Month=RealTime.RT.Month; Week=RealTime.RT.Week; Minute=RealTime.RT.Minute; 30
Second=RealTime.RT.Second; LCD_WriteHZ(0,0,she); LCD_WriteHZ(16,0,zhi); if(K2==0) Delay1ms(500); if(K2==0) m++; if(m==1) //设置年 { } else if(m==2) { LCD_WriteHZ(0,0,she); LCD_WriteHZ(16,0,zhi); LCD_WriteHZ(32,0,Yue); if(K3==0) Delay1ms(500); if(K3==0) { Month++; if(Month==0x0a) Month=0x10; //设置月 LCD_WriteHZ(0,0,she); LCD_WriteHZ(16,0,zhi); LCD_WriteHZ(32,0,Nian); if(K3==0) Delay1ms(500); if(K3==0) { } LCD_DispChar(16,2,(Year>>4)&0x0f); LCD_DispChar(24,2,Year&0x0f); if(K2==0) Delay1ms(500); if(K2==0) m++; if(K4==0) Delay1ms(500); if(K4==0) m=0; Year++; if(Year==0x0a) Year=0x10; if(Year==0x1a) Year=0x20; if(Year==0x2a) Year=0x30; if(Year==0x3a) Year=0x40; if(Year==0x4a) Year=0x50; if(Year==0x5a) Year=0x60; if(Year==0x6a) Year=0x70; if(Year==0x7a) Year=0x80; if(Year==0x8a) Year=0x90; if(Year==0x9a) Year=0x00; //if(Year==0x10a) Year=0x110; 31
} } if(Month==0x13) Month=0x01; LCD_DispChar(48,2,(Month>>4)&0x0f); LCD_DispChar(56,2,Month&0x0f); if(K2==0) Delay1ms(500); if(K2==0) m++; if(K4==0) Delay1ms(500); if(K4==0) m=0; //设置日 else if(m==3) { LCD_WriteHZ(0,0,she); LCD_WriteHZ(16,0,zhi); LCD_WriteHZ(32,0,Ri); if(K3==0) Delay1ms(500); if(K3==0) { } LCD_DispChar(80,2,(Day>>4)&0x0f); LCD_DispChar(88,2,Day&0x0f); if(K2==0) Delay1ms(500); if(K2==0) m++; if(K4==0) Delay1ms(500); Day++; { } if(Month==0x04|Month==0x06|Month==0x09|Month==0x11) { } if(Month==0x02) { } if(Day==0x0a) Day=0x10; if(Day==0x1a) Day=0x20; if(Day==0x30) Day=0x01; if(Day==0x0a) Day=0x10; if(Day==0x1a) Day=0x20; if(Day==0x2a) Day=0x30; if(Day==0x31) Day=0x01; if(Day==0x0a) Day=0x10; if(Day==0x1a) Day=0x20; if(Day==0x2a) Day=0x30; if(Day==0x32) Day=0x01; if(Month==0x01|Month==0x03|Month==0x05|Month==0x07|Month==0x08|Month==0x10|Month==0x12) 32
} if(K4==0) m=0; //设置星期 else if(m==4) { } else if(m==5) { LCD_WriteHZ(0,0,she); LCD_WriteHZ(16,0,zhi); LCD_WriteHZ(32,0,Zhou); if(K3==0) Delay1ms(500); if(K3==0) { } if(K2==0) Delay1ms(500); if(K2==0) m++; if(K4==0) Delay1ms(500); if(K4==0) m=0; //设置时 Week++; if(Week==0x07) Week=0x00; if(Week==0x01) LCD_WriteHZ(96,0,Yi); if(Week==0x02) if(Week==0x03) if(Week==0x04) if(Week==0x05) if(Week==0x06) if(Week==0x00) LCD_WriteHZ(96,0,Er); LCD_WriteHZ(96,0,San); LCD_WriteHZ(96,0,Si); LCD_WriteHZ(96,0,W); LCD_WriteHZ(96,0,Liu); LCD_WriteHZ(96,0,Ri); LCD_WriteHZ(0,0,she); LCD_WriteHZ(16,0,zhi); LCD_WriteHZ(32,0,Shi); if(K3==0) Delay1ms(500); if(K3==0) { } LCD_DispChar(16,4,(Hour>>4)&0x03); LCD_DispChar(24,4,Hour&0x0f); if(K2==0) Delay1ms(500); if(K2==0) m++; if(K4==0) Delay1ms(500); if(K4==0) m=0; Hour++; if(Hour==0x0a) Hour=0x10; if(Hour==0x1a) Hour=0x20; if(Hour==0x24) Hour=0x00; 33
} else if(m==6) { } else if(m==7) { LCD_WriteHZ(0,0,she); LCD_WriteHZ(16,0,zhi); LCD_WriteHZ(32,0,Miao); if(K3==0) Delay1ms(500); if(K3==0) { } LCD_DispChar(80,4,(Second>>4)&0x0f); LCD_DispChar(88,4,Second&0x0f); if(K2==0) Delay1ms(1000); if(K2==0) m=1; Second++; if(Second==0x0a) Second=0x10; if(Second==0x1a) Second=0x20; if(Second==0x2a) Second=0x30; if(Second==0x3a) Second=0x40; if(Second==0x4a) Second=0x50; if(Second==0x5a) Second=0x00; //设置秒 LCD_WriteHZ(0,0,she); LCD_WriteHZ(16,0,zhi); LCD_WriteHZ(32,0,Fen); if(K3==0) Delay1ms(500); if(K3==0) { } LCD_DispChar(48,4,(Minute>>4)&0x0f); LCD_DispChar(56,4,Minute&0x0f); if(K2==0) Delay1ms(1000); if(K2==0) m++; if(K4==0) Delay1ms(500); if(K4==0) m=0; Minute++; if(Minute==0x0a) Minute=0x10; if(Minute==0x1a) Minute=0x20; if(Minute==0x2a) Minute=0x30; if(Minute==0x3a) Minute=0x40; if(Minute==0x4a) Minute=0x50; if(Minute==0x5a) Minute=0x00; //设置分 34
if(K4==0) Delay1ms(500); if(K4==0) m=0; }
else m=0;
WDTCN = 0xde;
WDTCN = 0xad;
OSCICN |= 0x03;
P0MDOUT |= 0x1D; SMB0CN = 0x44;
SMB0CR = -80;
EIE1 |= 2;
EA = 1;
SM_BUSY = 0;
var = GetRealClockStatus(); SetRealClockStatus(0xc2); var = GetRealClockStatus(); GetRealClock();
RealTime.RT.Year=Year; RealTime.RT.Month=Month; RealTime.RT.Day=Day; RealTime.RT.Week=Week; RealTime.RT.Hour=Hour; RealTime.RT.Minute=Minute; RealTime.RT.Second=Second; SetRealClock();
LCD_WriteHZ(32,4,Shi); LCD_WriteHZ(64,4,Fen); LCD_WriteHZ(96,4,Miao); LCD_WriteHZ(32,2,Nian); LCD_WriteHZ(64,2,Yue); LCD_WriteHZ(96,2,Ri); if(K4==0) Delay1ms(200); if(K4==0)
{
n=0;
LCD_WriteHZ(0,0,wu); LCD_WriteHZ(16,0,wu); LCD_WriteHZ(32,0,wu); LCD_WriteHZ(48,0,wu); }
}
else if(n==2) //设置闹铃 {
LCD_WriteHZ(0,0,she);
35
LCD_WriteHZ(16,0,zhi); LCD_WriteHZ(32,0,nao); LCD_WriteHZ(48,0,Yi); if(K2==0) Delay1ms(500); if(K2==0)
{
h++;
if(h==0x0a) h=0x10; if(h==0x1a) h=0x20; if(h==0x24) h=0x00; }
RealTime.RT.Hour=h;
if(K3==0) Delay1ms(1000); if(K3==0)
{
f++;
if(f==0x0a) f=0x10; if(f==0x1a) f=0x20; if(f==0x2a) f=0x30; if(f==0x3a) f=0x40; if(f==0x4a) f=0x50; if(f==0x5a) f=0x00; }
RealTime.RT.Minute=f; if(K4==0) Delay1ms(500); if(K4==0)
{
n=0;
LCD_WriteHZ(0,0,wu); LCD_WriteHZ(16,0,wu); LCD_WriteHZ(32,0,wu); LCD_WriteHZ(48,0,wu); }
}
else if(n==3) { LCD_WriteHZ(0,0,she); LCD_WriteHZ(16,0,zhi); LCD_WriteHZ(32,0,nao); LCD_WriteHZ(48,0,Er); if(K2==0) Delay1ms(500); //设置闹铃2
36
if(K2==0)
{
h1++;
if(h1==0x0a) h1=0x10; if(h1==0x1a) h1=0x20;
if(h1==0x24) h1=0x00; }
RealTime.RT.Hour=h1;
if(K3==0) Delay1ms(1000); if(K3==0)
{
f1++;
if(f1==0x0a) f1=0x10; if(f1==0x1a) f1=0x20; if(f1==0x2a) f1=0x30; if(f1==0x3a) f1=0x40; if(f1==0x4a) f1=0x50; if(f1==0x5a) f1=0x00; }
RealTime.RT.Minute=f1; if(K4==0) Delay1ms(500); if(K4==0)
{
n=0;
LCD_WriteHZ(0,0,wu); LCD_WriteHZ(16,0,wu); LCD_WriteHZ(32,0,wu); LCD_WriteHZ(48,0,wu); }
}
else if(n==4) { LCD_WriteHZ(0,0,she); LCD_WriteHZ(16,0,zhi); LCD_WriteHZ(32,0,nao); LCD_WriteHZ(48,0,San); if(K2==0) Delay1ms(500); if(K2==0)
{
h2++;
if(h2==0x0a) h2=0x10; if(h2==0x1a) h2=0x20;
if(h2==0x24) h2=0x00; } //设置闹铃3
37
RealTime.RT.Hour=h2;
if(K3==0) Delay1ms(1000);
if(K3==0)
{
f2++;
if(f2==0x0a) f2=0x10;
if(f2==0x1a) f2=0x20;
if(f2==0x2a) f2=0x30;
if(f2==0x3a) f2=0x40;
if(f2==0x4a) f2=0x50;
if(f2==0x5a) f2=0x00;
}
RealTime.RT.Minute=f2;
if(K4==0) Delay1ms(500);
if(K4==0)
{
n=0;
LCD_WriteHZ(0,0,wu);
LCD_WriteHZ(16,0,wu);
LCD_WriteHZ(32,0,wu);
LCD_WriteHZ(48,0,wu);
}
}
else if(n==5) //进入秒表计时
{
LCD_WriteHZ(0,0,wu);
LCD_WriteHZ(16,0,wu);
LCD_WriteHZ(32,0,wu);
LCD_WriteHZ(48,0,wu);
LCD_WriteHZ(16,6,Miao);
LCD_WriteHZ(32,6,biao);
if(K2==0) Delay1ms(200);
if(K2==0)
{
hm=0;s=0;bs=0;
TR1=1;
while(1) {
LCD_DispChar(88,6,(hm>>4)&0x0f); LCD_DispChar(96,6,hm&0x0f); LCD_DispChar(64,6,(s>>4)&0x0f); LCD_DispChar(72,6,s&0x0f); LCD_DispChar(56,6,bs&0x0f); LCD_DispChar(80,6,0x0a);
38 //秒表开始计时
GetRealClock(); LCD_DispChar(16,4,(RealTime.RT.Hour>>4)&0x03); LCD_DispChar(24,4,RealTime.RT.Hour&0x0f); LCD_DispChar(48,4,(RealTime.RT.Minute>>4)&0x0f); LCD_DispChar(56,4,RealTime.RT.Minute&0x0f); LCD_DispChar(80,4,(RealTime.RT.Second>>4)&0x0f);
LCD_DispChar(88,4,RealTime.RT.Second&0x0f);
LCD_DispChar(16,2,(RealTime.RT.Year>>4)&0x0f);
LCD_DispChar(24,2,RealTime.RT.Year&0x0f);
LCD_DispChar(48,2,(RealTime.RT.Month>>4)&0x0f); LCD_DispChar(56,2,RealTime.RT.Month&0x0f);
LCD_DispChar(80,2,(RealTime.RT.Day>>4)&0x0f);
LCD_DispChar(88,2,RealTime.RT.Day&0x0f);
if(K2==0) Delay1ms(200);
if(K2==0) {TR1=0;break;} }
}
if(K4==0) Delay1ms(200);
if(K4==0)
{
n=0;
LCD_WriteHZ(16,6,wu);
LCD_WriteHZ(32,6,wu);
LCD_WriteHZ(48,6,wu);
LCD_WriteHZ(64,6,wu);
LCD_WriteHZ(80,6,wu);
LCD_WriteHZ(96,6,wu);
}
}
else
{
n=0;
LCD_WriteHZ(0,0,wu);
LCD_WriteHZ(16,0,wu);
LCD_WriteHZ(32,0,wu);
LCD_WriteHZ(48,0,wu);
LCD_WriteHZ(16,6,wu);
LCD_WriteHZ(32,6,wu);
LCD_WriteHZ(48,6,wu);
LCD_WriteHZ(64,6,wu);
LCD_WriteHZ(80,6,wu);
LCD_WriteHZ(96,6,wu);
}
LCD_DispChar(16,4,(RealTime.RT.Hour>>4)&0x03);
39 //秒表停止计时
LCD_DispChar(24,4,RealTime.RT.Hour&0x0f); LCD_DispChar(48,4,(RealTime.RT.Minute>>4)&0x0f); LCD_DispChar(56,4,RealTime.RT.Minute&0x0f); LCD_DispChar(80,4,(RealTime.RT.Second>>4)&0x0f); LCD_DispChar(88,4,RealTime.RT.Second&0x0f); LCD_DispChar(16,2,(RealTime.RT.Year>>4)&0x0f); LCD_DispChar(24,2,RealTime.RT.Year&0x0f); LCD_DispChar(48,2,(RealTime.RT.Month>>4)&0x0f); LCD_DispChar(56,2,RealTime.RT.Month&0x0f); LCD_DispChar(80,2,(RealTime.RT.Day>>4)&0x0f); LCD_DispChar(88,2,RealTime.RT.Day&0x0f); if(RealTime.RT.Week==0x01) LCD_WriteHZ(96,0,Yi); if(RealTime.RT.Week==0x02) if(RealTime.RT.Week==0x03) if(RealTime.RT.Week==0x04) if(RealTime.RT.Week==0x05) if(RealTime.RT.Week==0x06) if(RealTime.RT.Week==0x00) GetRealClock(); if(n==0&m==0&K2==0) q++; if(q==1&&q1==1) for(i=0;i<50;i++) //整点闹铃开 LCD_WriteHZ(16,6,zheng); LCD_WriteHZ(32,6,dian); LCD_WriteHZ(48,6,nao); LCD_WriteHZ(96,0,Er); LCD_WriteHZ(96,0,San); LCD_WriteHZ(96,0,Si); LCD_WriteHZ(96,0,W); LCD_WriteHZ(96,0,Liu); LCD_WriteHZ(96,0,Ri); if(n==0&m==0&K2==0) Delay1ms(200); { { flag=0;
LCD_WriteHZ(64,6,ling);
LCD_WriteHZ(80,6,kai);
}
q1=0;
LCD_WriteHZ(16,6,wu);
LCD_WriteHZ(32,6,wu); LCD_WriteHZ(48,6,wu); LCD_WriteHZ(80,6,wu); LCD_WriteHZ(64,6,wu);
}
if(q==2) //整点闹铃关
{ q1 = 1; for(i=0;i<5;i++) flag=1; { q=0; LCD_WriteHZ(16,6,zheng);
40
LCD_WriteHZ(32,6,dian); LCD_WriteHZ(48,6,nao); LCD_WriteHZ(64,6,ling); LCD_WriteHZ(80,6,guan);
} } LCD_WriteHZ(32,6,wu); LCD_WriteHZ(48,6,wu); LCD_WriteHZ(80,6,wu); LCD_WriteHZ(16,6,wu); LCD_WriteHZ(64,6,wu);
if(flag==0)
{
if(RealTime.RT.Minute==0x00&RealTime.RT.Second==0x00) //整点报时 { } } //闹铃开关 if(n==0&m==0&K3==0) l++; if(l==1) { } if(l==2) { } if(flag==0)//闹铃 { l=0; flag=1; LCD_WriteHZ(112,0,nao); LCD_WriteHZ(112,2,ling); LCD_WriteHZ(112,4,guan); flag=0; LCD_WriteHZ(112,0,nao); LCD_WriteHZ(112,2,ling); LCD_WriteHZ(112,4,kai); for(i=0;i<5;i++) //指示灯闪动五次 { } P1_6=0; Delay1ms(100); P1_6=1; Delay1ms(100); if(n==0&m==0&K3==0) Delay1ms(200);
41
if((RealTime.RT.Hour==h&RealTime.RT.Minute==f)||
(RealTime.RT.Hour==h1&RealTime.RT.Minute==f1)||(RealTime.RT.Hour==h2&RealTime.RT.Minute==f2)) //闹铃响
{ if(RealTime.RT.Second<=0x09) //指示灯闪动十秒
{P1_7=0;
Delay1ms(100);
P1_7=1;
Delay1ms(100);}
}
}
}
}
void Timer1_ISR (void) interrupt 3
{
TH1 = (65535-18432)/256;
TL1 = (65535-18432)%256;
hm++;
if(hm==0x0a) hm=0x10;
if(hm==0x1a) hm=0x20;
if(hm==0x2a) hm=0x30;
if(hm==0x3a) hm=0x40;
if(hm==0x4a) hm=0x50;
if(hm==0x5a) hm=0x60;
if(hm==0x6a) hm=0x70;
if(hm==0x7a) hm=0x80;
if(hm==0x8a) hm=0x90;
if(hm==0x9a)
{
hm=0x00;
s++;
if(s==0x0a) s=0x10;
if(s==0x1a) s=0x20;
if(s==0x2a) s=0x30;
if(s==0x3a) s=0x40;
if(s==0x4a) s=0x50;
if(s==0x5a) s=0x60;
if(s==0x6a) s=0x70;
if(s==0x7a) s=0x80;
if(s==0x8a) s=0x90;
if(s==0x9a)
{
s=0x00;
42
} } } bs++;
//------------------------------------------------------------------------------------ // Interrupt Service Routine
//------------------------------------------------------------------------------------ void SMBUS_ISR (void) interrupt 7
{
switch (SMB0STA) { // SMBus 状态码SMB0STA 寄存器 // 主发送器/接收器起始条件已发送 SMB0DAT = COMMAND ; // 装入要访问的从器件的地址 STA = 0; break; //主发送器/接收器重复起始条件已发送 // 该状态只应在读操作期间出现在存储器地址已发送并得到确认之后 ? SMB0DAT = COMMAND; // COMMAND 中应保持从地址 + R. STA = 0; break; // 主发送器从地址 + WRITE 已发送收到ACK // 主发送器数据字节已发送收到ACK if (BYTE_NUMBER) { } else { } break; // 主发送器从地址 + WRITE 已发送收到NACK // 从器件不应答发送STOP + START 重试 STO = 1; STA = 1; STO = 1; SM_BUSY = 0; // Free SMBus SMB0DAT = revolve(*I2CDataBuff); I2CDataBuff++; BYTE_NUMBER--; // If R/W=WRITE, // 手动清除START 位 case SMB_START: case SMB_RP_START: case SMB_MTADDACK: case SMB_MTDBACK: load byte to write. case SMB_MTADDNACK: break;
43
// 主发送器数据字节已发送收到NACK // 从器件不应答发送STOP + START 重试 STO = 1; STA = 1; case SMB_MTDBNACK: break; // 主发送器竞争失败 // 不应出现如果出现重新开始传输过程 STO = 1; STA = 1; case SMB_MTARBLOST: break; // 主接收器从地址 + READ 已发送,收到ACK AA = 1; // 在应答周期ACK if (!BYTE_NUMBER) { } // 主接收器从地址 + READ 已发送收到NACK // 从器件不应答发送重复起始条件重试 STA = 1; // 收到数据字节ACK 已发送 // 该状态不应出现因为AA 已在前一状态被清0 如果出现发送停止条件 if (BYTE_NUMBER) { } if (!BYTE_NUMBER) AA= 0; // 收到数据字节NACK 已发送 // 读操作已完成读数据寄存器后发送停止条件 STO = 1; SM_BUSY = 0; // 释放SMBus // 在本应用中所有其它状态码没有意义通信复位 STO = 1; // 通信复位 *I2CDataBuff=revolve(SMB0DAT); I2CDataBuff++; BYTE_NUMBER--; STO = 1; SM_BUSY = 0; // 释放SMBus case SMB_MRADDACK: break; case SMB_MRADDNACK: break; case SMB_MRDBACK: break; case SMB_MRDBNACK: break; default: 44
} } SM_BUSY = 0; break; SI=0; // 清除中断标志 45