历史上的今天
返回首页

历史上的今天

今天是:2025年02月19日(星期三)

正在发生

2019年02月19日 | 基于51单片机—多功能秒表

2019-02-19 来源:eefocus

功能介绍:


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); //加延时,

  }


推荐阅读

史海拾趣

Hi-Tron Semiconductor Corp公司的发展小趣事

机顶盒,全称为数字视频变换盒,是现代家庭娱乐中不可或缺的重要设备。从广义上讲,任何与电视机连接的网络终端设备均可视为机顶盒,其发展历程涵盖了从模拟频道增补器到数字卫星、地面及有线电视机顶盒的广泛范畴。而从狭义角度看,机顶盒特指那些具备数字处理能力的设备,如IPTV机顶盒、DVB-S卫星机顶盒、DVB-T地面机顶盒及DVB-C有线电视机顶盒等。

机顶盒的核心功能在于接收并转换数字电视信号,使之能在传统或智能电视上播放。它不仅能接收来自有线电缆、卫星天线及宽带网络的信号,还能提供电子节目指南、网页浏览等增值服务。通过机顶盒,用户能够享受到高清乃至4K超高清的电视节目,体验更为细腻的画面和震撼的音效。此外,机顶盒还具备网络交互能力,支持在线购物、观看网络视频、玩游戏等多元化活动,使电视机从单向接收信息的设备转变为智能互动终端。

随着技术的不断进步,机顶盒正朝着高清化、智能化方向发展。未来,机顶盒将不仅限于基本的信号接收与解码功能,还将融入更多智能推荐、语音识别等先进技术,为用户提供更加个性化、便捷的娱乐体验。总之,机顶盒作为连接电视与互联网的桥梁,正以其丰富的功能和广泛的应用场景,不断满足用户日益增长的娱乐需求。

Cicoil公司的发展小趣事

随着计算机技术的飞速发展,处理器成为了电子设备的核心部件。Cicoil公司看到了这一趋势,开始与处理器制造商展开合作。他们为处理器提供高质量的连接电缆,确保处理器能够稳定、高效地运行。这一合作使得Cicoil公司的电缆产品进一步深入到计算机领域,也为其带来了更多的商业机会。

Everbuild公司的发展小趣事

为了进一步扩大市场份额,Everbuild开始积极拓展国际市场。公司派遣专业的团队参加国际电子产品展览会,与国际知名厂商进行技术交流和合作。同时,Everbuild还针对不同国家和地区的市场需求,推出了定制化的电子产品解决方案。这些努力使Everbuild的产品逐渐进入国际市场,并赢得了越来越多客户的信任和支持。

比亚迪(BYD)公司的发展小趣事

进入21世纪,新能源汽车市场逐渐兴起。比亚迪凭借在电池领域的深厚积累,果断转型进入新能源汽车领域。2000年,比亚迪推出了全球第一款纯电动乘用车——比亚迪e6,这一创新产品引起了市场的广泛关注。此后,比亚迪不断加大对新能源汽车的研发和生产投入,推出了多款具有竞争力的新能源汽车产品。同时,比亚迪还积极涉足光伏和LED照明等其他领域,不断拓展其电子业务版图。

Hokuriku公司的发展小趣事

在20世纪70年代,电子行业正处于快速发展期,对高精度、高稳定性的电子元器件需求激增。Hokuriku Electric凭借其深厚的技术积累,成功研发出新一代高精度金属板电阻器。这款电阻器不仅具有极低的温度系数和出色的长期稳定性,还大幅提升了电子设备的性能和可靠性。这一技术突破迅速赢得了市场的广泛认可,使Hokuriku Electric在电阻器领域崭露头角,为后续发展奠定了坚实基础。

安美通(APPCON)公司的发展小趣事

随着市场的不断变化和客户需求的升级,安美通意识到只有不断创新才能在竞争中立于不败之地。因此,公司加大了对研发的投入,积极引进高端人才,并与多所高校和研究机构建立了紧密的合作关系。通过持续的技术创新,安美通成功推出了一系列具有自主知识产权的新产品,进一步巩固了其在行业内的领先地位。

问答坊 | AI 解惑

智能车资料下载

本帖最后由 paulhyde 于 2014-9-15 09:15 编辑 顶顶!!!  …

查看全部问答>

s3c2410触摸屏程序中对外接晶体管控制的问题

《ARM Linux入门与实践》一书当中,关于触摸屏的那一节有几个地方不理解。 该程序的说明是:“代码并没有使用S3C2410A中的触摸屏控制器,而是通过直接控制FPIO的4个晶体管的导通和截止” P220: void Wait_Touch(void) {     XMON_O ...…

查看全部问答>

dll库加载的问题

自己写了一个实现tapi的库 怎么加载到windows ce中呢? 用的编译环境是EVC…

查看全部问答>

我的最新充电原理图提交

上次提交的原理图,由于美信没有提供MAX17005B充电管理芯片,导致无法进行下去。为此,重新在美信网站溜达一圈,按照以下原则,确定该次芯片选型和原理图设计。   1。 芯片没有停产,可以继续使用,美信提供样品。   2。 封装不能是QFN ...…

查看全部问答>

关于工业以太网问题请教

组建一个简单的工业以太网,一台x86工控机当服务器,用网线联一台工业以太网交换机,交换机再连一台PLC,PLC 连接底层设备。 假设服务器上我装的就是普通的windows XP操作系统,上面运行我的工控软件。 请问我这个算是工业以太网吗?工业以太网不 ...…

查看全部问答>

请问能否仅通过430的串口往里面烧写程序?

请问能否仅通过430的串口往里面烧写程序? 谢谢! 搜了一下,有很多卖BSL的,除了需要TXD、RXD外,还需要一些别的脚。 有没有这么一种软件?当430的串口与计算机串口通过MAX232之类的芯片一接,在电脑上运行这个软件,直接就把程序烧进去了。…

查看全部问答>

LPC1114控制18B20程序

如题,我最近在学习LPC1114,照着51编写了一个LPC1114控制18b20的程序,可是怎样都不能成功,希望那个大仙能分享下自己的成功的程序,在此谢谢啦…

查看全部问答>

12864中文显示乱码!!!

是这样的,我是用串行方式写的代码,上电后发现显示中文字符会乱码。英文和数字则显示正常,不知道怎么回事 [ 本帖最后由 冷板凳 于 2012-9-25 15:50 编辑 ]…

查看全部问答>

【晒心得】TI EZ430-CHRONOS-433 无线手表

昨天收到手表,今天戴了一整天,现在说说我的体验心得。(写的比较乱,跟大家交流分享)     这么大一个联邦快递,同事都说这个快递费都要好贵,再加上整个套件不单单只有一个手表,还有个MSP-eZ430仿真器(该仿真器只支持二线仿真)和 ...…

查看全部问答>