历史上的今天
返回首页

历史上的今天

今天是:2025年08月06日(星期三)

正在发生

2021年08月06日 | 基于51单片机的电子秒表设计

2021-08-06 来源:eefocus

设计要求:


最多可记录十组数据


可删除其中多组数据


可上下查阅所记录的数据


数据通过lcd1602显示


计时精度到0.01s


由于并没有使用24c02,导致程序去数据较大,仿真可能不行。实际验证通过


程序界面如图:

仿真界面如图:

如果编译出错,将keil按如图参数设置:

以下为程序代码:


包括两个文件,主程序里面是:


#include<1602.h>

#include





#ifndef uchar

#define uchar unsigned char

#endif



#ifndef uint 

#define uint unsigned int

#endif



/*按键定义*/

/*开始键,计数键,停止计数键或者清零键,上下查阅键,删除数据键*/



sbit key_start=P1^0;

sbit key_count=P1^1;

sbit key_stop=P1^2;

sbit key_up=P1^3;

sbit key_down=P1^4;





/*变量定义*/

int count=0;//计数器



uint i,j,state,k=0,countnum,m,delete;



/*设置标志位*/



char flag;

char maxflag;

char clearflag;

char turnflag; //

char upflag;  //为1时可以继续上翻

char minflag=0; //为0时可以继续下翻

char downflag; 



/*定义数组 */

 unsigned char str[] = "time:";

 unsigned char str2[]= "num:";

 unsigned char str3[]="...press start..";

 unsigned char str4[]="....counting....";

 unsigned char str5[]=".. press count..";

 unsigned char str6[]="press up or down";

 unsigned char str7[]="..overcounting..";





 int number[10]=0;

 int num2[5]=0;



void keyscan();

void init();





void main()

{

   

    InitLcd1602();

    init();

/*以下为调试程序段*/

   LcdShowStr(0,0,str3);

  //  LcdShowStr(0,1,str2);

//  LcdWriteCom(0x91); 

//  LcdWriteData('0'+1);

//  LcdWriteCom(0x90);

//   LcdWriteData('0'+1);

/*以上为调试程序段*/





    while(1)

{ //LcdShowStr(0,1,str4); //测试

    keyscan();

Lcd1602_Delay1ms(50);

}



}

void init()

{

IT0=0;

EX0=0;

TMOD=0x01;

TH0=(65536-10000)/256; 

TL0=(65536-10000)%256;

EA=0; //开总中断



// key_count=0;

// key_stop=0;

// key_up=0;

// key_down=0;

// key_delete=0;



flag=0;  //标志位为0时代表未计时状态,为1时代表为计时状态

i=0;

maxflag=0;//定时标志位,为1时代表定时已满

clearflag=0;//清除标志位

turnflag=0;//为1时可以上下翻页显示

downflag=0;

upflag=1;

}

void keyscan()

{

if((key_start==0)&&(flag==0)) //防抖处理

{

Lcd1602_Delay1ms(10); //防抖处理

if((key_start==0)&&(flag==0))//防抖处理

{

while((!(key_start==0)&&(flag==0)));//防抖处理

InitLcd1602();

EA=1;//检测到开始按键按下后,启动定时器

ET0=1; //计时器0开启

 TR0=1; //计时器打开

flag=1;//设置标志位为计时状态

LcdShowStr(0,0,str4);

LcdShowStr(0,1,str5);

}

}

if((key_count==0)&&(flag==1)&&(maxflag==0))

{

       Lcd1602_Delay1ms(50); 

if((key_count==0)&&(flag==1)&&(maxflag==0))

{


while(!((key_count==0)&&(flag==1)&&(maxflag==0)));


    InitLcd1602();

LcdShowStr(0,0,str);

    LcdShowStr(0,1,str2);

number[i]=count;

LcdWriteCom(0xC7); 

        LcdWriteData('0'+i+1); 

LcdWriteCom(0xC6); 

        LcdWriteData('0');

if(i==9)

LcdWriteCom(0xC7); 

LcdWriteData('0'); 

LcdWriteCom(0xC6); 

LcdWriteData('0'+1); 

}





num2[0]=number[i]/10000;

num2[1]=number[i]/1000%10;

num2[2]=number[i]/100%10;

num2[3]=number[i]/10%10;

num2[4]=number[i]%10;


LcdWriteCom(0x86); 

    LcdWriteData('0'+num2[0]);



LcdWriteCom(0x87); 

    LcdWriteData('0'+num2[1]);



LcdWriteCom(0x88); 

    LcdWriteData('0'+num2[2]);



LcdWriteCom(0x89); 

    LcdWriteData('.');



 LcdWriteCom(0x8A); 

    LcdWriteData('0'+num2[3]);



LcdWriteCom(0x8B); 

    LcdWriteData('0'+num2[4]);



LcdWriteCom(0x8D); 

    LcdWriteData('S');



i++;

state=i;



if(i==10)

{

maxflag=1;


}

}

}



if(key_stop==0)

{

Lcd1602_Delay1ms(50);


 if(key_stop==0)

{

while(!(key_stop==0));

if(clearflag==0)

{

TR0=0;  //关定时器,查阅时定时就停止

EX0=1;  //开外部中断,保证只有在上下翻阅时才能触发外部中断

count=0;//计数清零

clearflag=1;//清除标志位打开,也就是说再按一下这个按键所有制清零

turnflag=1;

minflag=0;


}

else if(clearflag==1)//此块执行清除任务

{


InitLcd1602();

number[10]=0;

clearflag=0;

LcdShowStr(0,0,str3);

turnflag=0;

maxflag=0;

flag=0;

i=0;//将数组计数给清零

}

}

}






if(key_up==0)

{

Lcd1602_Delay1ms(50);

     if(key_up==0)

{

while(!(key_up==0));

if(upflag==0)

{

InitLcd1602();

LcdShowStr(0,0,str);

LcdShowStr(0,1,str2);

 minflag=0;//只要上翻过后都可以下翻

 state++;

if(state==10)

{

LcdWriteCom(0xC7); 

LcdWriteData('0'); 

LcdWriteCom(0xC6); 

LcdWriteData('0'+1); 

}

else

{

LcdWriteCom(0xC7); 

LcdWriteData('0'+state); 

LcdWriteCom(0xC6); 

LcdWriteData('0'); 

}

m=state-1;

delete=m;

 

 /*显示时间*/

num2[0]=number[m]/10000;

num2[1]=number[m]/1000%10;

num2[2]=number[m]/100%10;

num2[3]=number[m]/10%10;

num2[4]=number[m]%10;


LcdWriteCom(0x86); 

LcdWriteData('0'+num2[0]);


LcdWriteCom(0x87); 

LcdWriteData('0'+num2[1]);


LcdWriteCom(0x88); 

LcdWriteData('0'+num2[2]);


LcdWriteCom(0x89); 

LcdWriteData('.');


LcdWriteCom(0x8A); 

LcdWriteData('0'+num2[3]);


LcdWriteCom(0x8B); 

LcdWriteData('0'+num2[4]);


LcdWriteCom(0x8D); 

LcdWriteData('S');

if(state==10)

{

upflag=1;

}

}

 

 

}


}



if(key_down==0)

{

 Lcd1602_Delay1ms(50);

 if(key_down==0)

while(!(key_down==0));

if((turnflag==1)&&(minflag==0)) 

{

InitLcd1602();

LcdShowStr(0,0,str);

LcdShowStr(0,1,str2);

/*显示组号*/

state--;

LcdWriteCom(0xC7); 

LcdWriteData('0'+state); 

LcdWriteCom(0xC6); 

LcdWriteData('0'); 

k=state-1;

delete=k;



/*显示时间*/

num2[0]=number[k]/10000;

num2[1]=number[k]/1000%10;

num2[2]=number[k]/100%10;

num2[3]=number[k]/10%10;

num2[4]=number[k]%10;


LcdWriteCom(0x86); 

LcdWriteData('0'+num2[0]);


LcdWriteCom(0x87); 

LcdWriteData('0'+num2[1]);


LcdWriteCom(0x88); 

LcdWriteData('0'+num2[2]);


LcdWriteCom(0x89); 

LcdWriteData('.');


LcdWriteCom(0x8A); 

LcdWriteData('0'+num2[3]);


LcdWriteCom(0x8B); 

LcdWriteData('0'+num2[4]);


LcdWriteCom(0x8D); 

LcdWriteData('S');


if(state==1)

minflag=1;


}

upflag=0;


}

}

 }







void timer0() interrupt 1

{

TH0=(65536-10000)/256; 

TL0=(65536-10000)%256;

count++;

if(count==6000)

{

count=0; 

ET0=0; //计时器0关闭

TR0=0; //计时器关闭

turnflag=1;

EX0=1;

InitLcd1602();

LcdShowStr(0,0,str6);

LcdShowStr(0,1,str7);

}

}



void  counter0(void) interrupt 0  using 1

{

  number[delete]=0;

LcdWriteCom(0x86); 

LcdWriteData('0');


LcdWriteCom(0x87); 

LcdWriteData('0');


LcdWriteCom(0x88); 

LcdWriteData('0');



LcdWriteCom(0x89); 

LcdWriteData('.');



LcdWriteCom(0x8A); 

LcdWriteData('0');



LcdWriteCom(0x8B); 

LcdWriteData('0');



LcdWriteCom(0x8D); 

LcdWriteData('S');


}


然后是lcd的驱动程序:




#include<1602.h>









void Read_Busy()           //忙检测函数,判断bit7是0,允许执行;1禁止

{

    unsigned char sta;      //

    LCD1602_DB = 0xff;

    LCD1602_RS = 0;

    LCD1602_RW = 1;

    do

    {

        LCD1602_EN = 1;

        sta = LCD1602_DB;

        LCD1602_EN = 0;    //使能,用完就拉低,释放总线

    }while(sta & 0x80);

}



void Lcd1602_Write_Cmd(unsigned char cmd)     //写命令

{

    Read_Busy();

    LCD1602_RS = 0;

    LCD1602_RW = 0;

    LCD1602_DB = cmd;

    LCD1602_EN = 1;

    LCD1602_EN = 0;    

}



void Lcd1602_Write_Data(unsigned char dat)   //写数据

{

      Read_Busy();

      LCD1602_RS = 1;

      LCD1602_RW = 0;

      LCD1602_DB = dat;

      LCD1602_EN = 1;

      LCD1602_EN = 0;

}



void LcdSetCursor(unsigned char x,unsigned char y)  //坐标显示

{

    unsigned char addr;

    if(y == 0)

        addr = 0x00 + x;

    else

        addr = 0x40 + x;

    

    Lcd1602_Write_Cmd(addr|0x80);

}





void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str)     //显示字符串

{

    LcdSetCursor(x,y);      //当前字符的坐标

    while(*str != '')

    {

        Lcd1602_Write_Data(*str++);

    }

}



void InitLcd1602()              //1602初始化

{

    Lcd1602_Write_Cmd(0x38);    //打开,5*8,8位数据

    Lcd1602_Write_Cmd(0x0c);

    Lcd1602_Write_Cmd(0x06);

    Lcd1602_Write_Cmd(0x01);    //清屏   

}



  

 void Lcd1602_Delay1ms(uint c)   //误差 0us

{

    uchar a,b;

for (; c>0; c--)

{

for (b=199;b>0;b--)

{

  for(a=1;a>0;a--);

}      

}

   

}

/*******************************************************************************

* 函 数 名         : LcdWriteCom

* 函数功能   : 向LCD写入一个字节的命令

* 输    入         : com

* 输    出         : 无

*******************************************************************************/

#ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时

void LcdWriteCom(uchar com)  //写入命令

{

LCD1602_EN = 0;     //使能

LCD1602_RS = 0;   //选择发送命令

LCD1602_RW = 0;   //选择写入


LCD1602_DB = com;     //放入命令

Lcd1602_Delay1ms(1); //等待数据稳定



LCD1602_EN = 1;          //写入时序

Lcd1602_Delay1ms(5);  //保持时间

LCD1602_EN = 0;

}

#else 

void LcdWriteCom(uchar com)  //写入命令

{

LCD1602_EN = 0; //使能清零

LCD1602_RS = 0; //选择写入命令

LCD1602_RW = 0; //选择写入



LCD1602_DB = com; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改

Lcd1602_Delay1ms(1);



LCD1602_EN = 1; //写入时序

Lcd1602_Delay1ms(5);

LCD1602_EN = 0;



// Lcd1602_Delay1ms(1);

LCD1602_DB = com << 4; //发送低四位

Lcd1602_Delay1ms(1);



LCD1602_EN = 1; //写入时序

Lcd1602_Delay1ms(5);

LCD1602_EN = 0;

}

#endif



/*******************************************************************************

* 函 数 名         : LcdWriteData

* 函数功能   : 向LCD写入一个字节的数据

* 输    入         : dat

* 输    出         : 无

*******************************************************************************/   

#ifndef LCD1602_4PINS   

void LcdWriteData(uchar dat) //写入数据

推荐阅读

史海拾趣

常忆科技(CHINGIS)公司的发展小趣事

为了满足不断增长的市场需求,常忆科技积极拓展国内外市场。公司通过与全球知名的电子产品制造商建立合作关系,成功将产品打入国际市场。同时,常忆科技还积极参加各类国际电子展会和技术交流活动,展示其最新的技术和产品,吸引了众多国际客户的关注。

随着国际化战略的深入实施,常忆科技的产品逐渐在全球范围内得到应用。这不仅提升了公司的品牌知名度和影响力,也为公司带来了丰厚的经济回报。

Elcos AG公司的发展小趣事

随着公司规模的扩大和业务的增长,Elcos AG面临着供应链管理的挑战。为了降低成本、提高效率和保证产品质量,公司决定对供应链进行优化。通过引入先进的供应链管理软件、加强与供应商的合作和建立严格的质量控制体系等措施,Elcos AG成功实现了供应链的优化和升级。这不仅提高了公司的运营效率和市场竞争力,还为客户提供了更加稳定可靠的产品和服务。

成都振芯/国腾(CORPRO)公司的发展小趣事

随着技术的不断进步和市场需求的不断变化,CORPRO始终保持着对创新的追求和投入。近年来,公司不仅加强了在集成电路设计、微波组件开发等领域的研发能力,还积极拓展物联网、大数据等新兴领域的应用场景。这些努力使得CORPRO在行业内获得了广泛认可,并多次荣获各类荣誉奖项。例如,在2022年5月20日,CORPRO入选了四川省拟推荐2022年度国家技术创新示范企业公示名单,这一荣誉再次证明了CORPRO在电子行业的实力和影响力。

总之,成都振芯/国腾(CORPRO)公司的发展历程充满了挑战与机遇。通过不断的努力和创新,CORPRO已经成长为电子行业中一家具有强大实力和广泛影响力的企业。未来,CORPRO将继续致力于技术创新和市场拓展,为电子行业的发展贡献更多力量。

Coors Components Inc公司的发展小趣事

在面对激烈的市场竞争时,Coors Components Inc公司果断调整市场策略,将目标市场从高端用户转向中端市场。通过优化产品线、提升服务质量以及加强品牌营销,公司成功吸引了大量中端市场的消费者。这一策略调整不仅使公司的销售额大幅提升,还为其未来的发展奠定了坚实的基础。

Avalon Photonics公司的发展小趣事

随着公司的发展,Avalon Photonics开始寻求国际合作,以进一步拓展市场。公司与欧洲一家知名的科研机构建立了战略合作关系,共同研发新一代的光子学设备。这一合作不仅带来了技术上的互补,也为Avalon打开了欧洲市场的大门。通过国际合作,Avalon的产品逐渐在国际市场上获得认可,公司规模也逐步扩大。

EPIGAP公司的发展小趣事

随着全球对环保问题的日益关注,EPIGAP公司也开始注重绿色环保和可持续发展。公司积极采用环保材料和生产工艺,减少生产过程中的污染物排放。同时,EPIGAP还加大了对可再生能源的研发力度,推动公司向绿色、低碳、循环发展的方向迈进。这一战略不仅符合全球环保趋势,也为公司赢得了良好的社会声誉。

问答坊 | AI 解惑

开关电源的抗干扰问题

摘要:在叙述电磁兼容的定义及其试验方法的基础上介绍抑制电磁干扰的一般方法及其存在的问题。最后介绍新型抗电磁干扰器件—FTS系列群脉冲对抗器与LSA系列雷击浪涌吸收器的特点。 关键词:电磁干扰电磁兼容电磁兼容试验新型抗电磁干扰器件 电磁兼容 ...…

查看全部问答>

MCS-51单片机定点浮点数值计算程序库

本帖最后由 paulhyde 于 2014-9-15 09:37 编辑 分享  …

查看全部问答>

LPCXpresso——LPC1114 & LPC1343

由于项目保密性问题,细节未详尽,若不符合申请资格,请告之购买方式。谢谢…

查看全部问答>

2010年广西大学生电子设计大赛题目

本帖最后由 paulhyde 于 2014-9-15 08:54 编辑 2010年广西大学生电子设计大赛题目   大家觉得那道题目容易点呢? ===http://866.cc    …

查看全部问答>

16最小系统

没申请到开发板的,可以看看avr16的最小系统,用万能板自己焊一个…

查看全部问答>

STM32的时钟系统透析与分析(转帖)

在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①、HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接 外部时钟源,频率范围为4MHz~16MHz。 ③、LSI是低速内部时钟,RC振荡器,频 ...…

查看全部问答>

Stellaris SafeRTOS使用

有很多人问关于SafeRTOS的使用,附件是使用的文档,以及相关的头文件.另外可以参考stellaris库例程 \\StellarisWare\\boards\\dk-lm3s9b96\\safertos_demo …

查看全部问答>

wince新手入门求指导

大概跟着TQ2440的文档做了一下wince和vs2005的安装以及镜像文件的编译和烧写,现在想更进一步的学点东西,不知道如何下手,急切请教各位指导…

查看全部问答>

有没有做NetFPGA的??

论坛里有没有朋友做NetFPGA的???  一起探讨一下!…

查看全部问答>

一款车用轮速信号调理电路

如上图是一款轮速信号调理电路,通过调整可调电阻RS,可采集不同传感器信号,其中有几点不明,望高人指点一下: 1)电路将传感器信号分为信号端和公共端,公共端是一个电压比较电路,电压信号恒定为电源电压的1/2,二极管D3 D4限幅电路有必要加 ...…

查看全部问答>