微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 51单片机动态数码管+定时器

51单片机动态数码管+定时器

时间:10-02 整理:3721RD 点击:
我的学习板上有四个数码管,两个正置,两个是倒置的
我想实现每过一秒使数码管自动加一
但是实现不了,把代码贴上,麻烦各位指点下……


  1. #include <reg52.h>
  2. #define TIME 50000

  3. char t_time = 0;
  4. char thr_bit = 0,thou_bit = 0;                 //thr_bit是百位,thou_bit是千位
  5. int sin_bit = 0,dou_bit = 0;                 //sin_bit是个位,dou_bit是十位

  6. char code bit_chosen[]={
  7.                               0XBF,0XDF,0XEF,0XF7
  8.                            };   //choose the bit
  9.                                                                                          
  10. char code       p_digit[] ={         //positive
  11.                                                         0XC0,0XF9,0XA4,0XB0,            //0~3
  12.                                                         0X99,0X92,0X82,0XF8,            //4~7
  13.                                                         0X80,0X90,0X88,0X83,            //8~B
  14.                                                         0XC6,0XA1,0X86,0X8E                //C~F
  15.                                                         };

  16. char code      n_digit[]={                //negative
  17.                                                         0XC0,0XCF,0XA4,0X86,                 //0~3
  18.                                                         0X8B,0X92,0X90,0XC7,                //4~7
  19.                                                         0X80,0X82,0X81,0X98,                //8~B
  20.                                                         0X98,0X98,0X98,0X98,                //C~F
  21.                                                     };

  22. void delay();


  23. void main(void)
  24. {

  25.                 EA  = 1;
  26.                 ET0 = 1;
  27.                 TR0 = 1;


  28.         TH0 = (65536-TIME)/256;                   //?1
  29.         TL0 = (65536-TIME)%256;

  30.                 while(1)          //因为倒置的数码管,所以有两个需要倒置数字的code
  31.                 {                          //bit_chosen数组是位选,加了注释,尽量增加可读性了
  32.                               //如果有什么细节没讲到,我可以继续解释。
  33.                          P2 = bit_chosen[3];
  34.                             P0 = n_digit[sin_bit%10];
  35.              delay();

  36.                          P2 = bit_chosen[2];
  37.                          P0 = n_digit[dou_bit%10];
  38.              delay();

  39.                          P2 = bit_chosen[1];
  40.                          P0 = p_digit[thr_bit%10];                  
  41.                          delay();

  42.                          P2 = bit_chosen[0];
  43.                          P0 = p_digit[thou_bit%10];                  
  44.                          delay();

  45.             }
  46.                
  47.                   

  48. }

  49. void delay()
  50. {
  51.      int i,j;
  52.          for(i<50;i;i++)
  53.            for(j=1;j;j--);
  54. }


  55. void timer() interrupt 1
  56. {       
  57.         TH0 = (65536-TIME)/256;
  58.         TL0 = (65536-TIME)%256;
  59.         t_time++;
  60.        
  61.        
  62.         if(t_time ==40)                                                        //晶振24M,定时1s
  63.         {                                                                               
  64.                 sin_bit++;                                                        //过一秒加1
  65.                
  66.                 if(!(sin_bit%10))                                        //10秒,十位加1
  67.                          dou_bit++;
  68.                 if(!(sin_bit%100))                                    //100s,百位加1
  69.                          thr_bit++;
  70.                 if(!(sin_bit%1000))                                        //1000s,千位加1
  71.                          thou_bit++;
  72.                 if(!(thou_bit%10000))                                //9999之后归0
  73.                          sin_bit=0;
  74.         }
  75.        

  76. }

复制代码

用tab排版之后可移植性果然差了很多……
顺便还有几个小问题。
1、主函数里面依然需要设置
        TH0 = (65536-TIME)/256;
        TL0 = (65536-TIME)%256;
吗?
因为我不了解具体的定时器的工作,是独立于CPU的么?
那样在interrupt 1 里面已经设置了
        TH0 = (65536-TIME)/256;
        TL0 = (65536-TIME)%256;
上电之后定时器就应该开始跑了吧……那在主函数里面再初始化不是很多余么。

呃呃呃呃呃呃呃

已解决
1、delay那个函数没写对,太粗心
2、TMOD没设置
3、99~100那句,thou_bit初始为0,所以sin_bit始终是0,这是最后debug出来的

首先,你的这个代码不够规范  工程首先要有一个总的说明与描述 然后每个函数都要有说明功能返回值,还有      语句  对齐与空格  还有注释 这些都很重要 一定要养成良好的习惯 不然程序一多了 自己先乱了 找错都费劲
其次,调试时有技巧的  分步,分功能去调试,我打个比方 四个数码管弄不清楚的话就一个一个来
最后,要有耐心,这是最关键的!也是最重要的

解决了就好

看看…………。……。……。…。……。…。…。……………。

谢谢你的点评
以后我会注意你所说的细节

分享一下自己写的程序
/*==========================================================
* 开发人员:laowang
* 当前版本:V1.0
* 创建时间:11/21/2013
* 修改时间:
* 功能说明:用定时器中断实现数码管的动态扫描,大家可以对比用普通的delay()函数来实现动态扫描有什么区别
*==========================================================*/

#include <reg52.h> //单片机头文件
sbit dula = P3^4;        //段选
sbit wela = P3^5;        //位选
unsigned char num1;        //定义一个变量,用来对定时器中断进行计数
unsigned char code table1[]=        //数码管(共阴)的段选编码,范围是0-F
{
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
unsigned char code table2[]=        //数码管的位选编码,范围是1-8
{
0xfe,0xfd,0xfb,0xf7,        //例如,0xfe=1111 1110 点亮第一个数码管
0xef,0xdf,0xbf,0x7f
};
/*==========================================================   
*函数名称:Init()
*功    能:对定时器进行初始化
*入口参数:
*出口参数:
*说    明:定时器0,工作方式为1
*==========================================================*/
void Init()
{
    TMOD = 0x01; //        定时器工作方式为1
    TH0 = 63536/256;          //赋初值,此处设定的中断时间为2ms,(65536-2000)/256
    TL0 = 63536%256;
    EA = 1;        //开总中断
    ET0 = 1;        //打开定时器0中断
    TR0 = 1;          //开启定时器
}
//主函数
void main()
{         
Init();           //初始化
while(1);          //程序一直在空循环,如果有中断发生,则去执行中断(进行数码管显示),
//平时执行空循环
}
/*==========================================================   
*函数名称:Timer0()
*功    能:定时器中断服务内容
*入口参数:
*出口参数:
*说    明:
*==========================================================*/
void Timer0() interrupt 1          //中断序号为1
{
TH0 = 63536/256;        //每次中断发生后,先进行赋初值
    TL0 = 63536%256;
//以下部分为数码管的显示部分
P1=table1[num1+1];        //段选信号,将这一语句放在前面有消影的作用
dula=1;
dula=0;
P1=table2[num1];        //位选信号
wela=1;
wela=0;
num1++;          //对定时器的中断进行计数,每中断一次,数码管更换一次内容
if(num1==8)         
num1=0;
}

请问 你这个有汇编语言的吗?

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top