实验7 利用51单片机的定时器设计一个时钟

发布者:blq0681最新更新时间:2016-05-31 来源: eefocus关键字: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
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
#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++;
}
 
 
//=========中断函数区结束============================================
关键字:51单片机  定时器  时钟 引用地址:实验7 利用51单片机的定时器设计一个时钟

上一篇:51单片机STC89C54波特率以及双时钟探讨
下一篇:51单片机驱动步进电机(双四拍和八拍)

推荐阅读最新更新时间:2024-03-16 14:55

使用C51单片机的一些误区和注意事项
1) C忌讳绝对定位。 常看见初学者要求使用_at_,这是一种谬误,把C当作ASM看待了。在C中变量的定位是编译器的事情,初学者只要定义变量和变量的作 用域,编译器就把一个固定地址给这个变量。怎么取得这个变量的地址?要用指针。比如unsigned char data x;后,x的地址就是&x, 你只要查看这个参数,就可以在程序中知道具体的地址了。所以俺一看见要使用绝对定位的人,第一印象就是:这大概是个初学者。 2) 设置SP的问题。 原因和1差不对,编译器在把所有变量和缓冲区赋予地址后,自动把最后一个字节开始的地方,作为SP的开始位置,所以初学者是不必 要去理会的。这体现C的优越性,很多事情C编译时候做了。 3) 用C的主程序结构
[单片机]
STM32的通用定时器的知识及其配置
通用定时器大致有3个需要配置 1.时基配置 TIM_TimeBaseStructInit 2.外设输出PWM配置 TIM_OCStructInit 一般用来输出PWM的 3.外设输入捕捉配置 TIM_ICStructInit 对于来自与外面的信号进行输入捕捉,可以捕捉电平变化。 内容较多,本文不在叙述
[单片机]
51单片机对SAA7113初始化和控制的程序
  用51单片机对7113初始化和控制   SAA7113的初始化就是对寄存器配置合适的参数,使其能够有符合要求的输出。寄存器配置通过I2C总线来进行,很多可以控制I2C总线的器件都可以作为主器件对7113进行初始化,这里介绍用51单片机初始化7113的例子。   51单片机和7113的硬件连接非常简单,只要把单片机的两个I/O口(如P1.0、P1.0)直接和7113的SCL、SDA管脚相连,再加上上拉电阻即可。   用单片机初始化7113的主要任务是程序的编写,首先要熟悉I2C总线协议,根据I2C总线的原理写出启动、停止、应答信号等的子程序,由子程序再写出发送、接收1个字节的程序,然后根据7113的寄存器操作格式写出读写寄
[单片机]
西门子博图 :如何读取CPU时钟的本地时间
说明 使用该指令从 CPU 时钟读取当前本地时间,并将此时间在 OUT 输出中输出。在输出本地时间时,会用到夏令时和标准时间的时区和开始时间(已在 CPU 时钟的组态中设置)的相关信息。 参数 下表列出了“RD_LOC_T”指令的参数: 参数 声明 数据类型 存储区 说明 S7-1200 S7-1500 RET_VAL Return INT INT I、Q、M、D、L、P 指令的状态 OUT Output DTL DT, LDT, DTL I、Q、M、D、L、P * 本地时间 * 数据类型 DT 和 DTL 无法用于以下存储区:输入、输出和位存储器。 参数 RET_VAL 错误代码* (W#16#....
[嵌入式]
西门子博图 :如何读取CPU<font color='red'>时钟</font>的本地时间
STM32普通定时器(TIM2-7)的时钟源疑问
【问题】 STM32F103的APB1最大总线时钟是AHB总线时钟的1/2,最大为36MHz,在用ST的库函数(v2.0)的时候,TIM2(普通定时器)的时钟频率为72MHz,不知道原因何在? 【问题分析】 STM32中有多达8个定时器,其中TIM1和TIM8是能够产生三对PWM互补输出的高级定时器,常用于三相电机的驱动,它们的时钟由APB2的输出产生。其它6个为普通定时器,时钟由APB1的输出产生。 下图是STM32参考手册上时钟分配图中,有关定时器时钟部分的截图: 从图中可以看出,定时器的时钟不是直接来自APB1或APB2,而是来自于输入为APB1或APB2的一个倍频器,图中的蓝色部分。 下面以定时器2~7的时钟说明这
[单片机]
STM32普通<font color='red'>定时器</font>(TIM2-7)的<font color='red'>时钟</font>源疑问
51单片机16X16点阵上移C语言程序
前面已经分享了,点阵汇编语言,想信大家大部分用C语言较多了,下面我就将16X16点阵上移C语言程序分享出来,希望能帮到需要的朋友!本人此程序有经过实物测试的。并非随意弄出来的。并且有配视频效果,可以点击查看的视频祥见: http://www.tudou.com/programs/view/D0SCJyO4RBQ/ 下面是原理图,请大家祥细看看,不懂的帖子留言! #include reg52.h #define uchar unsigned char #define uint unsigned int #define LINE P0//定义行线IO口,即74HC154控制端 #define shudu 20//字移动的
[单片机]
<font color='red'>51单片机</font>16X16点阵上移C语言程序
51单片机P0口的特性及使用方法解析
一、P0口特性: P0口为三态双向I/O口。对于内部有程序存贮器的单片机基本系统(如定制的8051),P0口可以作为输入/输出口使用,直接连外部的输入/输出设备;也可以作为系统扩展的地址/数据总线口。对于内部没有程序存贮器的单片机(如8031),P0口只能作为地址/数据总线口使用。 1、P0口的输出驱动器中也有一个多路电子开关。输出驱动器转接至口锁动器的Q端时,P0口作为双向I/O口使用。 这时,CPU发来的控制信号为低电平,使输出驱动电路的上拉场效应管T1截止。P0口的锁存器为“1”时,输出驱动器中的两个场效应管均截止,引脚浮空;由于P0口输出电路是漏极开路的电路,必须外接10kΩ拉高电阻才能有高电平输出。而写入“0”时,下
[单片机]
<font color='red'>51单片机</font>P0口的特性及使用方法解析
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved