实验7 利用51单片机的定时器设计一个时钟
1.利用实验板和配件,设计一个时钟,时间显示在LCD1602上,并按秒更新,能够在实验板上设计3个按键调整时,分,秒。其功能为:功能选择键,数值增大和数值减小键。利用板上AT24C02设计实现断电保护显示数据的功能。
=============Clock.h=============
#ifndef __CLOCK_H__
#define __CLOCK_H__
//========全局变量区============================================
unsignedchar T_High_50ms=(65536-45872)/256;
unsignedint T_Low_50ms=(65536-45872)%256;
unsignedchar Count,Count_T1,Count_1s;//Count用来记录每50ms的计数,Count_T1用来记
//========全局变量区结束============================================
#endif
=============I2C.H=============
#ifndef __I2C_H__
#define __I2C_H__
#include<reg51.h>
sbit sda=P2^0;
sbit scl=P2^1;
//========函数区============================================
void nop();
void initI2C();
externvoid I2C_start(); //开始信号
externvoid I2C_stop(); //停止
externvoid I2C_respons(); //应答
externvoid I2C_write_byte(unsignedchar date);
externunsignedchar I2C_read_byte();
externvoid I2C_write_address(unsignedchar address,unsignedchar date);
externunsignedchar I2C_read_address(unsignedchar address);
//========函数区结束============================================
#endif
=============OrphanKey.h=============
#ifndef __ORPHANKEY_H__
#define __ORPHANKEY_H__
sbit FUNCTION_KEY=P3^2;//功能键 --按下暂停,再按开始
sbit Key_ADD=P3^3;//加1
sbit KEY_MINUS=P3^4;//减1
const bit PRESSED=0;//按下
bit SUSPEND=0;//0的时候运行,1的时候暂停
#endif
=============I2C.C=============
#include "head/I2C.h"
//=========全局变量区============================================
#define uchar unsigned char
#define uint unsigned int
bit I2C_write=0; //写24C02的标志;
unsignedchar sec,tcnt;
//=========全局变量区结束============================================
void nop()
{;;}
/***********************************************************
I2C的初始化
***********************************************************/
void initI2C(){
sda=1;
nop();
scl=1;
nop();
}
void I2C_start() //开始信号
{
sda=1;
nop();
scl=1;
nop();
sda=0;
nop();
}
void I2C_stop() //停止
{
sda=0;
nop();
scl=1;
nop();
sda=1;
nop();
}
void I2C_respons() //应答
{
uchar i;
scl=1;
nop();
while((sda==1)&&(i<250))i++;
scl=0;
nop();
}
void I2C_write_byte(uchar date)
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
scl=0;
nop();
sda=CY;
nop();
scl=1;
nop();
}
scl=0;
nop();
sda=1;
nop();
}
uchar I2C_read_byte()
{
uchar i,k;
scl=0;
nop();
sda=1;
nop();
for(i=0;i<8;i++)
{
scl=1;
nop();
k=(k<<1)|sda;
scl=0;
nop();
}
return k;
}
void I2C_write_address(uchar address,uchar date)
{
I2C_start();
I2C_write_byte(0xa0);
I2C_respons();
I2C_write_byte(address);
I2C_respons();
I2C_write_byte(date);
I2C_respons();
I2C_stop();
}
uchar I2C_read_address(uchar address)
{
uchar date;
I2C_start();
I2C_write_byte(0xa0);
I2C_respons();
I2C_write_byte(address);
I2C_respons();
I2C_start();
I2C_write_byte(0xa1);
I2C_respons();
date=I2C_read_byte();
I2C_stop();
return date;
}
=============lab8_1.c=================
#include<reg51.h>
#include "head/Clock.h"
#include "head/OrphanKey.h"
#include "head/I2C.H"
/*
1.利用实验板和配件,设计一个时钟,时间显示在LCD1602上,并按秒更新,能够在实验板上设计3个按键调整时,分,秒。其功能为:功能选择键,数值增大和数值减小键。利用板上AT24C02设计实现断电保护显示数据的功能。
*/
/*
步骤:
1、设计一个中断,用来计时
2、设计一个字符生成函数,用来生成所需的时间
3、独立按键监测功能,用来监测按下了什么键
4、一个外部中断
5、一个断点保护的功能,其实就是通过I2C写入,读取数值
*/
//=========全局变量区============================================
#define uchar unsigned char
#define uint unsigned int
uchar code table[]="12:23:12";
uchar code table1[]="I am a boy!";
sbit lcden=P2^7; //液晶使能端
sbit lcdrs=P2^6; //数据或命令控制(0代表命令,1代表数据)
sbit LCDWR=P2^5; //读写控制(0代表写,1代表读)
uchar num;
uchar FIRST_LINE=0x80;
uchar SECOND_LINE=0xc0;
uchar Current_Time[9];
uchar Hour,Minute,Second=0;//时、分、秒
sbit beer = P1 ^4; //蜂鸣器
// sbit led1=P1^3;
//=========全局变量区结束============================================
//=========函数区============================================
/***********************************************************
延时函数
参数说明:
z代表要延时z ms
***********************************************************/
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/***********************************************************
写命令或数据
参数说明:
isRs=1代表写数据,isRs=0代表写命令
***********************************************************/
void write(uchar mdata, uchar isRs)
{
lcdrs=isRs;
P0=mdata;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
/***********************************************************
写命令
参数说明:
data代表要写的命令
***********************************************************/
void write_command(uchar com)
{
write(com,0);
}
/***********************************************************
写数据
参数说明:
data代表要写的数据
***********************************************************/
void write_data(uchar mdata)
{
write(mdata,1);
}
/***********************************************************
初始化时钟
***********************************************************/
void InitTime(){
// 时间的转换
Current_Time[0]=Hour/10+'0';
Current_Time[1]=Hour%10+'0';
Current_Time[2]=':';
Current_Time[3]=Minute/10+'0';
Current_Time[4]=Minute%10+'0';
Current_Time[5]=':';
Current_Time[6]=Second/10+'0';
Current_Time[7]=Second%10+'0';
Current_Time[8]='\0';
}
/***********************************************************
保存时钟的值
***********************************************************/
void KeepClockValue(){
I2C_write_address(2,Second);
delay(10);
I2C_write_address(3,Minute);
delay(10);
I2C_write_address(4,Hour);
}
/***********************************************************
改变时间
***********************************************************/
void changeTime()
{
// 时间的转换
if(Second>=60){
Second=0;
Minute++;
}else{
++Second;
}
if(Minute==60){
Hour++;
Minute=0;
}
if(Hour==24){
Second=0;
Minute=0;
Hour=0;
}
KeepClockValue();
}
/**
初始化
**/
void InitClockInterrupt(){//初始化中断
TMOD=0x11; // 对TMOD赋值,以确定T0和T1的工作方式。
TH0=T_High_50ms;// 计算初值,并将其写入TH0、TL0或TH1、TL1。
TL0=T_Low_50ms;
EA =1;//开启中断总允许
ET0 =1;
IT0 =1; //开启定时器0,1中断允许
TR0=1; // 使TR0或TR1置位,启动定时/计数器定时或计数
Count=Count_T1=Count_1s=0;//计数
}
/***********************************************************
初始化按钮中断
***********************************************************/
void initButtonInterupt(){
IT0 =0;
//EA = 1; //开启中断总允许
EX0 =1; //外部中断0允许位
}
void init()
{
InitTime();
lcden=0;
LCDWR=0;
write_command(0x38);//设置16X2显示,5X7点阵,8位数据接口
write_command(0x0c);//设置开显示,不显示光标
write_command(0x06);//写一个字符后地址指针加1
write_command(0x01);//显示清零,数据指针清零
}
void WriteStringToLCD(uchar *dat)
{
while(*dat!='\0')
{
write_data(*dat);
dat++;
delay(5);
}
}
/***********************************************************
向LCD整体左移动
***********************************************************/
void LCD_MoveToLeft(){
int num;
for(num=0;num<16;num++)
{
write_command(0x18);
delay(200);
}
}
/***********************************************************
向LCD打印字符串
***********************************************************/
void PrintToLCD(){
//write_command(FIRST_LINE);
//WriteStringToLCD(table);
write_command(SECOND_LINE);
WriteStringToLCD(Current_Time);
}
/***********************************************************
是否加1
***********************************************************/
void IsAdd(){
if(PRESSED==Key_ADD){ //当加1按键按下
delay(10); //去抖动
if(PRESSED==Key_ADD){ //当加1按键按下
changeTime();
InitTime();
PrintToLCD();
while(!Key_ADD);
}
}
}
/***********************************************************
是否减1
***********************************************************/
void IsMinus(){
if(PRESSED==KEY_MINUS){ //当减1按键按下
delay(10); //去抖动
if(PRESSED==KEY_MINUS){ //当减1按键按下
if(Second>0){ //防止按下减1按钮的时候,被减成负数
Second--;
InitTime();
PrintToLCD();
while(!KEY_MINUS);
}
}
}
}
/***********************************************************
是否运行
***********************************************************/
void IsRun(){
if(PRESSED==FUNCTION_KEY){ //当减1按键按下
delay(10); //去抖动
if(PRESSED==FUNCTION_KEY){ //当减1按键按下
SUSPEND=~SUSPEND;
// led1=SUSPEND;
while(!KEY_MINUS);
}
}
}
/***********************************************************
是否暂停
***********************************************************/
void IsSuspend(){
IsRun();
IsMinus(); //监测是否需要减1
IsAdd(); //监测是否需要加1
}
/***********************************************************
重新计数
***********************************************************/
void ReCount(){
Count=0; //开始下一轮1s的计时
TH0=T_High_50ms;// 计算初值,并将其写入TH0、TL0或TH1、TL1。
TL0=T_Low_50ms;
}
/***********************************************************
初始化时钟的值
***********************************************************/
void initClockValue(){
Second=I2C_read_address(2); //读出保存的数据赋于Second
Minute=I2C_read_address(3);
Hour=I2C_read_address(4);
}
void main()
{
init();
InitClockInterrupt();
initButtonInterupt();
initClockValue();
if(Second>100) //防止首次读取出错误数据
Second=0;
while(1){
IsSuspend();
if(Count>=20&&(!SUSPEND)){//定时器0 1s时间到
ReCount();
changeTime();
InitTime();
PrintToLCD();
}
}
}
//=========函数区结束============================================
//=========中断函数区============================================
/**
初始化按钮外部中断
**/
void intButton() interrupt 0//外部中断0
{
}
/**
用定时0实现8个发光二极管以1s间隔闪烁
**/
void int0() interrupt 1//定时/计数器T0中断
{
Count++;
}
//=========中断函数区结束============================================
作者:kissazi2
出处:http://www.cnblogs.com/kissazi2/
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。