Whr4477 2018-04-05 03:32 采纳率: 0%
浏览 2062
已结题

C语言 单片机秒表程序

本人是一个新手 对于下边的c程序每一个子函数能看懂,但是像这么多子函数放到一起
就晕了,想请亲们帮我把这个程序的流程梳理梳理中断是何时工作,各个子函数怎么在这个整体里运行 越详细越好,本人十分感谢!

/* 设计的秒表计数到小数点后两位,(ms)用到六个数码管一个小数点加两位小数*/
#include<reg52.h>

sbit ADDR3=P1^3;
sbit ENLED=P1^4;
sbit KEY1=P2^4;
sbit KEY2=P2^5;
sbit KEY3=P2^6; 
sbit KEY4=P2^7;

unsigned char code LedChar[] = {  //数码管显示字符转换表
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
unsigned char LedBuff[6]={
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF  //数码管显示缓存区
};
unsigned char KeySta[4]={1,1,1,1};

bit StopwatchRunning=0;
bit StopwatchRefresh=1;
unsigned char IntegerPart=0;//整数部分
unsigned char DecimalPart=0;//小数部分

void ConfigTimer0(unsigned int ms);
void StopwatchDisplay();
void KeyDriver();

void main()
{
    EA=1;
    ENLED=0;
    ADDR3=1;
    P2=0XFE;//P2.0置零选第四行按键
    ConfigTimer0(2);//T0定时2ms

    while(1)
    {
      if(StopwatchRefresh)       //如果刷新需要调用显示函数
          StopwatchRefresh=0;
          StopwatchDisplay();
      KeyDriver();
    }
}

/*配置并启动T0 ms就是T0的定时时间*/
void ConfigTimer0(unsigned int ms)
{
    unsigned long tmp;
    tmp=11059200/12;//   1/T=f频率
    tmp=(tmp*ms)/1000; //    ms/1000=1s   f*T=机械周期个数
    tmp=65536-tmp;
    tmp=tmp+18;
    T0RH=(unsigned char)(tmp>>8);
    T0LH=(unsigned char)tmp;
    TMOD&=0xF0;
    TMOD|=0x01;
    TH0=T0RH;
    TL0=T0RL;
    ET0=1;
    TR0=1;

}
/*秒表计数显示函数*/
void StopwatchDisplay()
{
       signed char i;                         
       unsigned char buf[4];//同理数据转换的缓冲区

    /*小数部分转换到低2位*/
    LedBuf[0]=LedChar[DecimalPart%10];
    LedBuf[1]=LedChar[DecimalPart/10];  
    /*整数部分换到高4位 注意这里和小数部分区别是要用到缓存*/
    buf[0]= IntegerPart%10;
    buf[0]= IntegerPart/10%10;
    buf[0]= IntegerPart/100%10;
    buf[0]= IntegerPart/1000%10;
    for(i=3;i>=1;i++)//把高位为零的换成空字符
    {
        if(buf[i]==0)
           LedBuf[i+2]=0xFF;//置空
        else
          break;
    }
    for(;i>=0;i--)
    {
           LedBuf[i+2]=LedChar[buf[i]];
    }
        LedBuf[i+2]=0x7F;//运行到整数的最后一位上顺便点亮小数点
}
/*秒表复位*/
void  StopwatchReset()
{
    StopwatchRunning=0; //停止秒表
    IntegerPart=0;
    DecimalPart=0;
    StopwatchReset=1//重置刷新标志
}
/*秒表启停函数*/
void StopwatchAction()
{
     if(StopwatchRunning)//若是已经启动则停止
        StopwatchRunning=0;
     else
        StopwatchRunning=1;//若是已经停止则启动 
}
/*按键驱动函数,检测到有按键动作,调度相应动作函数,只有两个按键另外四个。注意:需要在主函数调用*/
void KeyDriver()
{
   unsigned char i;
   static unsigned char backup[4]=[1,1,1,1];
   for(i=0;i<4;i++)
   {
           if(backup[i]!=KeySta[i])
           {
              if(backup[i]!=0)
              {
                 if(i==1)
                    StopwatchReset();
            else if(i==2)
                    StopwatchAction();
              }
                backup[i]=KeySta[i];
           }
   }

}
/*数码管动态扫描刷新函数,注意:需在定时中断中调用*/
void  LedScan()
{
   static unsigned char i=0;

   P0=0XFF;
   P1=(P1&0xF8)|i;
   P0=LedBUF[i];
   if(i<5)         //在C里,i>5 i=0 继续走!!!
       i++;
   else
       i=0;
}
void KeyScan()
{
  unsigned char i;
  static unsigned char keybuff[4]={
      0xFF,0xFF,0xFF,0xFF
  };
    keybuff[0]=(keybuff[0]<<1)| KEY1;
    keybuff[1]=(keybuff[1]<<1)| KEY1;
    keybuff[2]=(keybuff[2]<<1)| KEY1;
    keybuff[3]=(keybuff[3]<<1)| KEY1;

    for(i=0;i<4;i++)
    {
      if(keybuff[i]==0x00)//连续8次扫描为0, 2ms*8(得移动8位上面才能有结果)
      {
          KeySta[i]=0;
      }
      else if(keybuff[i]==0xFF)
      {
          KeySta[i]=1;
      }
    }
}
/* 秒表计数函数,每隔10ms调用一次进行秒表计数累加 */
void StopwatchCount()
{
    if (StopwatchRunning)  //当处于运行状态时递增计数值
    {
        DecimalPart++;           //小数部分+1
        if (DecimalPart >= 100)  //小数部分计到100时进位到整数部分
        {
            DecimalPart = 0;
            IntegerPart++;       //整数部分+1
            if (IntegerPart >= 10000)  //整数部分计到10000时归零
            {
                IntegerPart = 0;
            }
        }
        StopwatchRefresh = 1;    //设置秒表计数刷新标志
    }
}
/*T0中断函数,完成数码管扫描、按键扫描与秒表计数*/
void InterruptTimer0() interrupt 1
{
  static unsigned char tmr10ms =0;
  TH0=T0RH;
  TL0=T0RL;
  LedScan();
  KeyScan();
//定时10ms进行一次秒表计数
    tmr10ms++;
    if(tmr10ms>=5)   //2ms一次 2*5=10ms
    {
      tmr10ms=0;
      StopwatchCount();
    }  
}

  • 写回答

9条回答

  • 小七小琪 2018-04-05 11:36
    关注

    定时器呀 使用定时器计时数码管显示

    评论

报告相同问题?

悬赏问题

  • ¥15 opencv 无法读取视频
  • ¥15 用matlab 实现通信仿真
  • ¥15 按键修改电子时钟,C51单片机
  • ¥60 Java中实现如何实现张量类,并用于图像处理(不运用其他科学计算库和图像处理库))
  • ¥20 5037端口被adb自己占了
  • ¥15 python:excel数据写入多个对应word文档
  • ¥60 全一数分解素因子和素数循环节位数
  • ¥15 ffmpeg如何安装到虚拟环境
  • ¥188 寻找能做王者评分提取的
  • ¥15 matlab用simulink求解一个二阶微分方程,要求截图