基于51单片机—多功能秒表

发布者:泉地水无痕最新更新时间:2019-02-19 来源: eefocus关键字:51单片机  多功能秒表 手机看文章 扫描二维码
随时随地手机看文章

功能介绍:


1. 三位数码管显示数据00.0~99.9


2.一次计时中可记录4个数据(按一下存一次数据),存在EEPROM中(若按了五下,则会丢失第一次按下的数据)


3.两个按键功能为,暂停,启动,存数,取数,翻页(查看下一个存的时间)




硬件连接


1.两个573控制数码管的段选,位选,573数据输入端接P0口,段选,位选分别接,P1^1,P1^0


2.P1^3,P1^4分别接EEPROM的时钟线(SCL),数据线(SDA)


3.独立按键K0.K1分别接外部中断0,1接口 P3^2,P3^3


4.使用定时器0的工作方式2


介绍


1.K0分 短按(小于2s),长按(大于2s),短按为定时器启停,长按进入读取数据程序


2.K0未长按,按一下k1存入EEPROM中一个数,最多存四个数,按五下则丢失第一个数


3.k0长按后,k1存数功能失效,变成翻页功能,按一下数码管显示下一个保存的数据


4.单片机复位键,控制程序重头执行。




下面为我编写的程序




#include


typedef unsigned int uint;   //对数据类型进行声明定义

typedef unsigned char uchar;

void delayms(uint);  //延时函数声明

void display(uchar,uchar);//数码管显示函数声明


 void delay(); //短暂延时

 void start(); //开始信号

 void stop(); //停止信号

 void respons(); //应答

 void init();   //初始化 两条线都拉高

 void write_byte(uchar); //写一个字节

 uchar read_byte();    //读一个字节,带带返回值的函数

 void write_add(uchar,uchar);//写入 指定地址 数据

 uchar read_add(uchar); //读出  指定地址 数据


uchar num0,num1;//存放eeprom中的数据 ,十分位,整数位


uint cc=0;   //定义定时器0溢出次数

uchar zant=0;   //暂停开始标志位,外部中断0控制


uchar fanye=0; //定义外部中断1 存数次数标志位,翻页次数

uchar gg=0; //定义存第几数 ,翻到第几个数

uchar qc=0; //定义长按外部中断0 取出保存的数


uchar code led1[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F} ; //定义0~9的数组

uchar code led2[]={0xbF,0x86,0xdB,0xcF,0xe6,0xeD,0xfD,0x87,0xfF,0xeF} ;//0~9有小数点

 

 uchar shi=0; // 定义数码管十位

 uchar ge=0;     //定义数码管个位


 sbit wei=P1^0; //定义位选端 

 sbit duan=P1^1; //定义段选端

 sbit int0=P3^2; //外部中断0,端口

 sbit int1=P3^3; //外部中断1,端口

  sbit  scl=P1^3; //时钟线

  sbit  sda=P1^4; //数据线


void main()

{

IT0=1; //外部0低电平触发

EX0=1; //开外部中断0


IT1=1; //外部1低电平触发

EX1=1; //开外部中断1


ET0=1; //开定时器0

EA=1; // 开总中断

 

IP=0x04; //外部1优先

TMOD=0x02;   //定义定时器0,八位自动装填

TH0=0x1a; //晶振11.0592,初值26,时间250us

TL0=0x1a;


while(1)

  {   

    if(num0>=10) //次数达到满

   {

     num0=0;

num1++;

  if(num1>=100)

    {num1=0;}

}


  display(num0,num1); //显示LED函数

  

  if(fanye==1)   //存数据 判断外部中断1是否按下

   {   

switch(gg)   //通过gg的值“按第几下”,存到不同的位置

  {

   case 1:

   init();

           write_add(0x01,num0);

           init();

           write_add(0x02,num1);

          break;

   case 2:

   init();

           write_add(0x03,num0);

           init();

           write_add(0x04,num1);

          break;

   case 3:

   init();

           write_add(0x05,num0);

           init();

           write_add(0x06,num1);

          break; 

   case 4:

   init();

           write_add(0x07,num0);

           init();

           write_add(0x08,num1);

          break; 

  }

   fanye=0; //退出存数,直到下次外部中断1到来

   }


   if(qc==1) //判断外部中断0长按键 开始读存进EEPROM的数据

   {

   while(1)  

{

switch(gg)   //通过判断外部中断1,按键次数gg实现翻页功能

{   //因为又进入到现在这个大循环 所以外部中断1中的

case 1:   //fanye=1;不能在返回上面控制 存第几个数据了,相当与无用

init();

             num0=read_add(0x01);

init();

             num1=read_add(0x02);

  break;

case 2:

init();

             num0=read_add(0x03);

init();

             num1=read_add(0x04);

break;

case 3:

init();

             num0=read_add(0x05);

init();

             num1=read_add(0x06);

  break;

case 4:

init();

             num0=read_add(0x07);

init();

             num1=read_add(0x08);

   break;

}

    display(num0,num1);   //程序将在此一直判断gg,实现翻页,显示存的数据

}   //若想再次计数,按下单片机的RST复位键,程序重头执行

}  

  }

}


void wbzd0()interrupt 0

 {

   uchar p=0;    //判断按键按下的时间

   delayms(20); //消抖

   if(int0==0)

   {

  while(!int0&&p<250) //最多按25秒

      { p++;

delayms(100);}

     if(p>15) //长按2秒 调出数据,

   {

qc=1;    //主程序开始 读eeprom数据

TR0=0;   //停止定时器工作

}

  else // 低于两秒

     {

       zant=~zant;

       TR0=zant; //来回反转实现定时器0的启停

      }

}

 }



void wbzd1()interrupt 2

  {

   delayms(20); //消抖

   if(int1==0)

   {

    fanye=1;   //主程序进入存数据,后跳出,直到下次按键按下

gg++;    //用于判断存数据位,和读数据位,在不同的位置实现的功能不同

if(gg==5)

    {gg=1;}

while(!int1); //按键不松,程序不往下执行

}

  }

void T0_time()interrupt 1 //八位自动装填

 {

    cc++;

   if(cc>=400) //0.1秒到来

{

cc=0;

num0++;   

}

 }



void display(uchar num0,uchar num1) //显示函数

{

   shi=num1/10;

   ge=num1%10;


  duan=1;

  P0=led1[num0]; //送入十分位位段选数据

  duan=0;

  P0=0xff;

  wei=1;

  P0=0xfb; //选择左侧第3位位选打开

  wei=0;

  delayms(2);


  duan=1;

  P0=led2[ge]; //送入个位段选数据

  duan=0;

  P0=0xff;

  wei=1;

  P0=0xfd; //选择左侧第2位位选打开

  wei=0;

  delayms(2);


  duan=1; //打开段选

  P0=led1[shi]; //送入段选数据 十位

  duan=0; //关闭段选

  P0=0xff;   //消影

  wei=1; // 打开位选

  P0=0xfe; // 打开最右侧位选

  wei=0; // 关闭位选

  delayms(2);    // 延时一会 便于观察

}



void delayms(uint x)   //延时函数

{

  uint p,q;

  for(p=x;p>0;p--)

for(q=110;q>0;q--);

}



 void delay()

  {;;}


 void start() //开始信号

 {

  sda=1;

  delay();

  scl=1;

  delay();

  sda=0;

  delay();

 }


  void stop() //停止信号

 {

  sda=0;

  delay();

  scl=1;

  delay();

  sda=1;

  delay();

 }


 void respons() //应答

 {

  uchar i;

  scl=1;

  delay();

  while((sda==1)&&(i<250)) //防止一直没有收到应答,程序停止

{i++;}

  scl=0;

  delay();

 }


 void init()   //初始化 两条线都拉高

 {

   sda=1;

   delay();

   scl=1;

   delayms(1); //加延时,否则用不了

 }


  void write_byte(uchar date) //写一个字节

 {

  uchar i,temp;

  temp=date;

for(i=0;i<8;i++)

  {

  temp=temp<<1;

  scl=0;

  delay();

  sda=CY; //最高位移入PSW寄存器中CY位中

  delay(); //将CY中的值赋给sda

  scl=1;

  delay();

}

  scl=0;

delay();

sda=1;

delay();

 }


 uchar read_byte()    //读一个字节,带带返回值的函数

{

  uchar i,k;

  scl=0;

  delay();

  sda=1;

  delay();

   for(i=0;i<8;i++)

   {

scl=1;

delay();

k=(k<<1)|sda; //将K左移一位后与sda进行或运算,

scl=0; //依次把8个位放入一个字节中来完成接收

delay();

}

return k;   //返回值为k

}



  void write_add(uchar address,uchar date) //写入 指定地址 数据

  {

   start();

   write_byte(0xa0);  //接下来为写操作

   respons();

   write_byte(address); //送入地址

   respons();

   write_byte(date); //写入数据

   respons();

   stop();

    delayms(1); //加延时,否则用不了

  }


  uchar read_add(uchar address) //读出  指定地址 数据

  {

uchar date;

start();

write_byte(0xa0); //接下来为写操作

   respons();

   write_byte(address);   //送入地址 ,下面读数据的地址

   respons();

   start();

   write_byte(0xa1); //接下来为读操作 存储器发送数据

   respons();

   date=read_byte(); //把SDA数据线上的数据用date存

   stop();

   return date;

   delayms(1); //加延时,

  }


关键字:51单片机  多功能秒表 引用地址:基于51单片机—多功能秒表

上一篇:基于单片机的智能密码锁
下一篇:C51 实现动态内存分配

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

51单片机 LCD12864 驱动程序 C语言 ST7920
main.c #include reg52.h #include intrins.h #include string.h #include stdio.h #include stdlib.h #include LCD12864.h void main( void ) { Ini_Lcd(); Lcd_WriteStr(0,0, QQ137712826 ); while ( 1 ) { } } lcd12864.h #include reg52.h #include intrins.h sbit RS = P2 ^ 0; sbit R
[单片机]
<font color='red'>51单片机</font> LCD12864 驱动程序 C语言 ST7920
基于51单片机的nrf24l01无线的接收和发射程序
通过灯的闪烁来判断数据的接受和发射 有接收端和发射段的程序 如果24L01用reg51那么两个设备都要用reg51,如果用reg52就都得用reg52! PC通过串口发送给单片机命令 ,单片机把命令通过24L01无线发送给另一个单片机,另一个单片机控制灯LED1,LED2,LED3,LED4闪烁。 无线发射程序: #include 2401.h #define uint unsigned int #define uchar unsigned char //1//sbit KEY1=P0^0; //发送按键 //1//sbit KEY2=P0^1; //1//sbit KEY3=P0^2
[单片机]
基于<font color='red'>51单片机</font>的nrf24l01无线的接收和发射程序
8051单片机数据说明
深入理解并应用C51对标准ANSIC的扩展是学习C51的关键之一。因为大多数扩展功能都是直接针对8051系列CPU硬件的。 具体说明如下(8031为缺省CPU)。 一、Keil C51扩展关键字 C51 V4.0版本有以下扩展关键字(共19个): _at_idata sfr16 alien interrupt small bdata large _task_ Code bit pdata using reentrant xdata compact sbit data sfr 二、内存区域(Memory Areas): 1、 Pragram Area: 由Code说明可有多达64kBytes的程序
[单片机]
51单片机的定时器中断(寄存器)
中断是为使单片机具有对外部或内部随机发生的事件进行处理而设置的。51单片机有5种中断源,即有5种对应的情况发生时会使单片机去处理中断程序(中断函数)。 此篇主要整理定时器中断笔记。采用定时器中断会涉及中断寄存器,定时器/计数器相关寄存器(TCON,TMOD),中断函数等知识点。 其中,中断寄存器,定时器/计数器相关寄存器本身或者相关位用来做初始化,中断函数的内容主要是体现发生中断后所需要的操作(在中断函数内写代码)。 1.中断允许寄存器IE 图1.中断寄存器IE 中断寄存器用来设定各个中断源的打开和关闭,IE在特殊功能寄存器中,字节地址为A8H,位地址(由低位到高位)分别是A8H~AFH,该寄存器运行位寻址,即可对该
[单片机]
<font color='red'>51单片机</font>的定时器中断(寄存器)
采用AT89C51单片机和温度变送器实现炉温控制系统的设计
1、引 言 电加热炉随着科学技术的发展和工业生产水平的提高,已经在冶金、化工、机械等各类工业控制中得到了广泛应用,并且在国民经济中占有举足轻重的地位。对于这样一个具有非线性、大滞后、大惯性、时变性、升温单向性等特点的控制对象,很难用数学方法建立精确的数学模型,因此用传统的控制理论和方法很难达到好的控制效果。 单片机以其高可靠性、高性能价格比、控制方便简单和灵活性大等优点,在工业控制系统、智能化仪器仪表等诸多领域得到广泛应用。采用单片机进行炉温控制,可以提高控制质量和自动化水平。 2、单片机炉温控制系统结构 本系统的单片机炉温控制系统结构主要由单片机控制器、可控硅输出部分、热电偶传感器、温度变送器以及被控对象组成。如图1所示
[单片机]
采用AT89C<font color='red'>51单片机</font>和温度变送器实现炉温控制系统的设计
基于51单片机的智能雨刷设计
一.硬件方案 本设计运用雨滴传感器感应雨量的大小,把感应信号输给单片机系统,然后通过软件控制雨刷电机根据相应的环境做出不同的转动。 主要由51单片机最小系统+步进电机+1602显示+湿度传感器+ADC0832芯片+按键组成;如图: 二.设计功能 (1)采用lcd1602液晶显示雨水量值。 (2)雨滴传感器检测雨水量,adc0832对雨滴传感器信号ad转换数字信号单片机处理。 (3)有手动模式和自动模式控制两种,手动模式实现开关操作,还可以通过按键调整速度。自动模式下根据雨水量自动控制步进电机的速度,低于下限步进电机停止工作,上限和下限之间步进电机1档(慢速)工作,大于上限步进电机2档(快速)工作。 (4)四个按键:设置、加
[单片机]
基于<font color='red'>51单片机</font>的智能雨刷设计
80c51是几位单片机 80c51单片机有几个中断源
  80c51是几位单片机   80C51是一种8位微处理器,也被称为8051,由Intel公司推出。它是最早的商用单片机之一,由于它的简单易用、灵活可靠,被广泛应用于许多嵌入式系统中。在80C51系列中,最常见的型号包括AT89C51和AT89S52等。   80c51单片机寻址范围有多少   80C51单片机的寻址范围取决于其具体的型号和存储器结构。在最常见的AT89C51和AT89S52型号中,其寻址范围如下:   内部RAM寻址范围:0x00-0x7F(128字节)   内部ROM寻址范围:0x0000-0xFFFF(64KB)   特殊功能寄存器(SFR)寻址范围:0x80-0xFF(128字节)   外部扩展RAM
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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