找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1590|回复: 7
收起左侧

仿写金沙滩的秒表程序。编译通过,下载后数码管一闪而过,萌新求助问题在哪?普中板子

[复制链接]
ID:695565 发表于 2020-3-8 21:57 | 显示全部楼层 |阅读模式
#include<reg52.h>

typedef unsigned char u8;
typedef unsigned int u16;
sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

unsigned char code LedChar[]={                        //数码管显示字符转换表
        0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
        0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71       
};
unsigned char Ledbuff[6] = {                        //数码管显示缓冲区
        0x00,0x00,0x00,0x00,0x00,0x00
};
unsigned char KeySta[4]={                                //按键当前状态
        1,1,1,1
};

u8 T0RH = 0;
u8 T0RL = 0;
bit StopwatchRefresh=1;                                           //秒表计数刷新标志
bit StopwatchRunning=0;                                    //秒表运行标志
u8 DecimalPart = 0;                                                //小数部分定义
u16 IntegerPart = 0;                                        //整数部分定义

void ConfigTimer0(u16 ms);
void KeyDriver();
void StopwatchDisplay();
void main(void)
{
        EA=1;
        ConfigTimer0(2);                                         //定时器周期函数
        while(1)
        {
                if(StopwatchRefresh)
                {
                        StopwatchRefresh=0;                        //秒表状态位
                        StopwatchDisplay();                        //秒表显示函数
                }
                KeyDriver();                                         //按键驱动函数
        }
}

void ConfigTimer0(u16 ms)
{
        unsigned long tmp;

        tmp=12000000/12;
        tmp=(tmp*ms)/1000;
        tmp=65536-tmp;
        T0RH=(u8)(tmp>>8);
        T0RL=(u8)tmp;
        TMOD&=0XF0;
        TMOD|=0X01;
        TH0=T0RH;
        TL0=T0RL;
        ET0=1;
        TR0=1;
}

void StopwatchDisplay()
{
        signed char i;
        u8 buf[4];                                                         //数据转换的缓冲区

        //小数部分转换到低2位
        Ledbuff[0] = LedChar[DecimalPart%10];
        Ledbuff[1] = LedChar[DecimalPart/10];
        //整数部分转换到高4位
        buf[0] = IntegerPart%10;
        buf[1] = (IntegerPart/10)%10;
        buf[2] = (IntegerPart/100)%10;
        buf[3] = (IntegerPart/1000)%10;

        for(i=3;i>1;i--)                                           //整数部分高位的0 转换为空字符
        {
                if(buf[i] == 0)
                {
                        Ledbuff[i+2] = 0xfe;
                }
                else
                        break;
        }
        for(;i>0;i--)                                                 //有效数字位转换为显示字符
        {
                Ledbuff[i+2] = LedChar[buf[i]];
        }
        Ledbuff[2] &= 0x7f;                                          //点亮小数点
}

/*秒表启停函数*/
void StopwatchAction()
{
        if(StopwatchRunning)                                   //已启动则停止
                StopwatchRunning = 0;
        else                                                                  //未启动则启动
                StopwatchRunning = 1;       
}

/* 秒表复位函数 */
void StopwatchReset()
{
        StopwatchRunning = 0;                                //停止秒表
        DecimalPart = 0;                                        //清零计数值
        IntegerPart = 0;
        StopwatchRefresh =1;                                //置刷新标志
}

/* 按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用 */
void KeyDriver()
{
        u8 i;
        static u8 backup[4] = {1,1,1,1};        //按键上一次的状态

        for(i=0;i<4;i++)                                        //循环检测4个按键
        {       
                if(backup[i]!= KeySta[i])                //按键状态改变
                {
                        if(backup[i] != 0)                        //按键按下
                        {
                                if(i == 1)                                   //Key1键复位秒表
                                        StopwatchReset();
                                if( i== 2)                                   //Key2键启停秒表
                                        StopwatchAction();       
                        }
                        backup[i] = KeySta[i];                 //刷新前一次的备份值
                }
        }               
}

/* 秒表计数函数,每隔10ms 调用一次进行秒表计数累加 */
void StopwatchCount()
{
        if(StopwatchRunning)                                  //当处于运行状态时递增计数值
        {
                DecimalPart++;                                           //小数部分+1
                if(DecimalPart >= 100)                          //小数部分计到100 时进位到整数部分
                {
                        DecimalPart = 0;
                        IntegerPart++;                                //整数部分+1
                        if(IntegerPart >= 10000)       
                        {
                                IntegerPart = 0;
                        }
                }
                StopwatchRefresh = 1;
        }
}

/* 数码管动态扫描刷新函数,需在定时中断中调用 */
void LedScan()
{
        static u8 i;
        P0=0X00;
        switch(i)
        {
                case 0:LSA=0;LSB=0;LSC=0;i++;P0=Ledbuff[0];break;
                case 1:LSA=1;LSB=0;LSC=0;i++;P0=Ledbuff[1];break;
                case 2:LSA=0;LSB=1;LSC=0;i++;P0=Ledbuff[2];break;
                case 3:LSA=1;LSB=1;LSC=0;i++;P0=Ledbuff[3];break;
                case 4:LSA=0;LSB=0;LSC=1;i++;P0=Ledbuff[4];break;
                case 5:LSA=1;LSB=0;LSC=1;i++;P0=Ledbuff[5];break;
                default:break;
        }
}

/* 按键扫描函数,需在定时中断中调用 */
void KeyScan()
{
        u8 i;
        static u8 keybuf[4] = {                                //按键扫描初始化
        0xFF,0xFF,0xFF,0xFF
        };

         //按键值移入缓冲区
        keybuf[0] = (keybuf[0] << 1) | KEY1;
        keybuf[1] = (keybuf[1] << 1) | KEY2;
        keybuf[2] = (keybuf[2] << 1) | KEY3;
        keybuf[3] = (keybuf[3] << 1) | KEY4;
        //消抖后更新按键状态
        for(i=0;i<4;i++)
        {
                if(keybuf[i] == 0x00)        //连续8次扫描为0,即16ms内都是弹起状态,可认为按键已按下
                        KeySta[i]=0;
                else if(keybuf[i] == 0xFF) //连续8次扫描为1,即16ms内都是按下状态,可认为按键已按下
                        KeySta[i]=1;       
        }       
}

/*中断服务函数,完成数码管,按键扫描与秒表计数*/
void Timer0() interrupt 1
{
        static unsigned char tmr10ms;
        TH0 = T0RH;
        TL0 = T0RL;
        LedScan();                                                        //数码管显示
        KeyScan();                                                        //按键扫描

        tmr10ms++;
        if(tmr10ms >= 5)
        {
                tmr10ms = 0;
                StopwatchCount();                                 //调用秒表计数函数
        }
}


A2开发板原理图.pdf

281.54 KB, 下载次数: 4

回复

使用道具 举报

ID:695565 发表于 2020-3-8 21:59 | 显示全部楼层
附件是普中版本的,除了数码管是共阴的,就没其他大的区别了,实在不知道问题出在哪?
回复

使用道具 举报

ID:524818 发表于 2020-3-10 16:34 | 显示全部楼层
共阴和共阳数码管数组值是不一样的
回复

使用道具 举报

ID:677076 发表于 2020-3-10 19:10 | 显示全部楼层
51编程就是写驱动。你要对照线路图写代码。电路设计不一样写出来就不一样,抄过来的有些地方改一改就可以了。主要是IO口位置及电平的高低。
回复

使用道具 举报

ID:642838 发表于 2020-3-10 21:54 | 显示全部楼层
改写3处:
Ledbuff[i+2] = 0xfe;改成 Ledbuff[i+2] = 0x00;
Ledbuff[2] &= 0x7f; 改成Ledbuff[2] |= 0x80;
最重要的是switch(i)中的case 5后面的i++i++要改成i=0或者删除switch语句
改成 P0 = 0x00;            
   P2 = (P2 & 0xE3) |( i*100);  
    P0 = LedBuff[i];            
     i++;
     i %= 6;简洁多了
回复

使用道具 举报

ID:213173 发表于 2020-3-10 22:01 | 显示全部楼层
wangzhe212 发表于 2020-3-8 21:59
附件是普中版本的,除了数码管是共阴的,就没其他大的区别了,实在不知道问题出在哪?

秒表不用写那么复杂,改简单一些,发生问题也好查。
  1. #include <reg51.H>

  2. #define uint unsigned int
  3. #define uchar unsigned char

  4. sbit key=P3^3;
  5. sbit LSA=P2^2;
  6. sbit LSB=P2^3;
  7. sbit LSC=P2^4;

  8. unsigned char code LedChar[]={                  //数码管显示字符转换表
  9.         0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
  10.         0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71        
  11. };
  12. unsigned char Ledbuff[] = {                        //数码管显示缓冲区
  13.         0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00
  14. };
  15. uchar Cntus=0,Cnt10ms=0,Cnt1s=0,Cnt1min=0;//中断计时变量

  16. bit  stop=0;                                                //停止标志
  17. void display();                                                //显示程序声明
  18. void keyscan();                                                //按键扫描程序声明

  19. /***********定时器初始化程序****************/
  20. void Timer0Init(void)                                //2毫秒@12.000MHz
  21. {
  22.         TMOD |= 0x01;                                        //设置定时器模式
  23.         TL0 = 0x30;                                                //设置定时初值
  24.         TH0 = 0xF8;                                                //设置定时初值
  25.         TF0 = 0;                                                //清除TF0标志
  26.         TR0 = 1;                                                //定时器0开始计时
  27.         EA=1;                                                        //开总中断
  28.         ET0=1;                                                        //开定时器0中断
  29. }

  30. /***********按键扫描程序****************/
  31. void keyscan()       
  32. {
  33.         static uint num=0,count=0;                //计数变量                       
  34.         static bit key_sign=0;                        //按键自锁标志
  35.         if(!key)                                                //检测按键为0
  36.         {
  37.                 count++;                                        //计数延时消抖
  38.                 if((count>=100)&&(key_sign==0))//检测按键如果为0
  39.                 {                       
  40.                         key_sign=1;                                //按键自锁标志置1,防止重复响应
  41.                         num++;
  42.                         if(num>=3)
  43.                                 num=0;
  44.                         switch(num)
  45.                         {
  46.                                 case 0:        Cntus=0;Cnt10ms=0;Cnt1s=0;Cnt1min=0;break;//清0
  47.                                 case 1:        stop=1; break;//计时
  48.                                 case 2:        stop=0;        break;//停止
  49.                         }               
  50.                 }
  51.         }
  52.         else
  53.         {
  54.                 count=0;                                        //计数变量清0
  55.                 key_sign=0;                                        //按键自锁标志清0
  56.         }
  57. }

  58. void StopwatchDisplay()
  59. {
  60.         Ledbuff[0]=LedChar[Cnt10ms%10];
  61.         Ledbuff[1]=LedChar[Cnt10ms/10];
  62.         Ledbuff[3]=LedChar[Cnt1s%10];
  63.         Ledbuff[4]=LedChar[Cnt1s/10];
  64.         Ledbuff[6]=LedChar[Cnt1min%10];
  65.         Ledbuff[7]=LedChar[Cnt1min/10];
  66. }

  67. void display()//显示程序
  68. {
  69.         static uchar i=0;                        //计数变量
  70.         P0=0x00;                                                //消隐
  71.         switch(i)
  72.         {
  73.                 case 0:LSA=0;LSB=0;LSC=0;break;
  74.                 case 1:LSA=1;LSB=0;LSC=0;break;
  75.                 case 2:LSA=0;LSB=1;LSC=0;break;
  76.                 case 3:LSA=1;LSB=1;LSC=0;break;
  77.                 case 4:LSA=0;LSB=0;LSC=1;break;
  78.                 case 5:LSA=1;LSB=0;LSC=1;break;
  79.                 case 6:LSA=0;LSB=1;LSC=1;break;
  80.                 case 7:LSA=1;LSB=1;LSC=1;break;
  81.         }
  82.         P0=Ledbuff[i];
  83.         i++; i%=8;
  84. }

  85. /***************主程序****************/
  86. void main()
  87. {
  88.         Timer0Init();                                        //定时器初始化
  89.         while(1)
  90.         {
  91.                 keyscan();                                        //按键扫描
  92.                 StopwatchDisplay();
  93.                 display();                                        //显示程序

  94.         }
  95. }
  96. /**************中断服务程序*****************/
  97. void timer0() interrupt        1                //2毫秒
  98. {
  99.         TL0 = 0x30;                                                //设置定时初值
  100.         TH0 = 0xF8;                                                //设置定时初值
  101.         Cntus++;                                                        //中断变量Cntus自+1
  102.         if(Cntus>=5)                                        //10ms
  103.         {
  104.                 Cntus=0;                                                //清0
  105.                 if(stop==1)                                        //启动
  106.                         Cnt10ms++;                                //10毫秒计数
  107.                 if(Cnt10ms>=100)
  108.                 {
  109.                         Cnt10ms=0;
  110.                         Cnt1s++;                                        //秒计数
  111.                         if(Cnt1s>=60)
  112.                         {
  113.                                 Cnt1s=0;
  114.                                 Cnt1min++;                        //分计数
  115.                                 if(Cnt1min>=100)
  116.                                         Cnt1min=0;
  117.                         }
  118.                 }
  119.         }
  120. }
复制代码
回复

使用道具 举报

ID:642838 发表于 2020-3-10 23:19 | 显示全部楼层
   文中还有2点错误:
for(i=3;i>1;i--)改成for(i=3;i>=1;i--)  
for(;i>0;i--) 改成for(;i>=0;i--)
加上上贴,一共改动5处
Ledbuff[i+2] = 0xfe;改成 Ledbuff[i+2] = 0x00;
Ledbuff[2] &= 0x7f; 改成Ledbuff[2] |= 0x80;
case 5:LSA=1;LSB=0;LSC=1;i++;P0=Ledbuff[5];break;改成case 5:LSA=1;LSB=0;LSC=1;i=0;P0=Ledbuff[5];break;
回复

使用道具 举报

ID:695565 发表于 2020-3-24 00:40 来自手机 | 显示全部楼层
感谢各位的的指点,虽然我第二天找到了问题所在,但是还是给了我更好的思路
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表