找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3916|回复: 16
打印 上一主题 下一主题
收起左侧

0~99以一秒递进的动态扫描显示程序

[复制链接]
跳转到指定楼层
楼主
ID:140769 发表于 2016-10-1 13:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
书本上的0~99显示程序都是用74LS593锁存器控制显示电路。我们的单片机可以直接驱动数码管,可以不用锁存器。
我想只用89C52单片机与四位共阳数码管写一个以一秒为递进的0~99数字显示程序。P0口控制数码管的位选,P2口控制数码管的段选。
以下是我的程序思路,运行起来一直动态显示01两个数字。我不知道问题出在哪里,恳求各位坛友给个修改思路,不胜感激!!!


# include <reg52.h>
# define uint unsigned int
# define uchar unsigned char

uchar a[10] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99,     //四位共阳数码管0~9显示代码
                       0x92, 0x82, 0xF8, 0x80, 0x90 };
uchar wei[2] = { 0xef, 0xdf };  //个位与十位选通代码
     
uchar duan[2];     //用于存储个位与十位值的数组

void delay(uchar m)
{
    uchar i, j;
    for (i=0; i<m; ++i)
    for (j=110; j>0; --j);
}

void display(uchar n, uchar k) //数码管显示函数
{
     P0 = 0xff;    //个位显示
     P2 = wei[n];
     P0 = duan[n];
     delay(5);
     P2 = 0xff;

     P0 = 0xff;     //十位显示
     P2 = wei[k];
     P0 = duan[k];
     delay(5);
     P2 = 0xff;
}

void main(void)
{
     uchar i=0, n=0, k=1, d=0;
     while (1)
   {
      ++d;
      if (d==100)
          d = 0;

      duan[0] = a[d%10];  //个位显示的值
      duan[1] = a[d/10];  //十位显示的值

      display(n, k);

      TMOD = 0X01;
      TH0 = (65536-50000)/256;
      TL0 = (65536-50000)%256;
      EA = 1;
      ET0 = 1;
      TR0 = 1;
      while(1);
     }
}

void T0_time() interrupt 1
{
     uchar num=0, n=0, k=1;

     TH0 = (65536-50000)/256;
     TL0 = (65536-50000)%256;
     num++;

     display(n, k);    //定时过程中数码管显示
   
     if (num==20)
         num = 0;   
}
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:57657 发表于 2016-10-1 20:18 | 只看该作者
中断进入了变量num都清零了,怎么可能加到20啊。
把相关变量定义在函数外试试。
回复

使用道具 举报

板凳
ID:111634 发表于 2016-10-1 22:19 | 只看该作者
593是计数器,595才是锁存器。
回复

使用道具 举报

地板
ID:111634 发表于 2016-10-1 22:23 | 只看该作者
本帖最后由 zl2168 于 2016-10-1 22:25 编辑

指出几个问题:显示与0~99递进无关;0~99只有2位,不需用动态扫描显示;若I/O端口没有他用,P0、P2口可直接控制2位显示。
回复

使用道具 举报

5#
ID:140769 发表于 2016-10-1 23:27 | 只看该作者
zl2168 发表于 2016-10-1 22:23
指出几个问题:显示与0~99递进无关;0~99只有2位,不需用动态扫描显示;若I/O端口没有他用,P0、P2口可直接 ...

我用的是单片机开发板上的数码管。
回复

使用道具 举报

6#
ID:140769 发表于 2016-10-1 23:31 | 只看该作者
npn 发表于 2016-10-1 20:18
中断进入了变量num都清零了,怎么可能加到20啊。
把相关变量定义在函数外试试。

我没有听太懂朋友可否写几行代码来指导一下小弟。
回复

使用道具 举报

7#
ID:140371 发表于 2016-10-2 07:40 | 只看该作者
原程式有多處問題..... 修改後
# include <reg52.h>
# define uint unsigned int
# define uchar unsigned char

uchar a[10] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99,     //四位共阳数码管0~9显示代码
                       0x92, 0x82, 0xF8, 0x80, 0x90 };
uchar wei[2] = { 0xef, 0xdf };  //个位与十位选通代码
     
uchar duan[2];     //用于存储个位与十位值的数组

uchar num=0,sec;


void delay(uchar m)
{
    uchar i, j;
    for (i=0; i<m; ++i)
    for (j=110; j>0; --j);
}

void display(uchar n) //数码管显示函数
{
     P0 = 0xff;    //个位显示
     P2 = wei[n]];
     P0 = a[duan[n]];   
}

void main(void)
{
     uchar i=0, n=0, k=1, d=0;

      TMOD = 0X01;
      TH0 = (65536-50000)/256;
      TL0 = (65536-50000)%256;
      EA = 1;
      ET0 = 1;
      TR0 = 1;

      while(1)
      {
      duan[0] = sec[d%10];  //个位显示的值
      duan[1] = sec[d/10];  //十位显示的值
       display(n);
        n++;
        n = n %2;
       delay(1);
      }
     
}

void T0_time() interrupt 1
{
     //uchar num=0, n=0, k=1;

     TH0 = (65536-50000)/256;
     TL0 = (65536-50000)%256;
     num++;

     //display(n, k);    //定时过程中数码管显示
   
     if (num==20)
   {
  
         num = 0;
        sec++;
        if(sec >=100)
        sec =0;      
    }  
}
回复

使用道具 举报

8#
ID:140358 发表于 2016-10-3 08:00 来自手机 | 只看该作者
没了解过这个
回复

使用道具 举报

9#
ID:140461 发表于 2016-10-3 08:36 | 只看该作者
7楼的程序不错
回复

使用道具 举报

10#
ID:141207 发表于 2016-10-3 14:20 | 只看该作者
可以参考下
回复

使用道具 举报

11#
ID:141149 发表于 2016-10-4 12:31 | 只看该作者
/*                                                                             *
*                 数码管显示秒表, 分辨率0.01s                                     *
*                 K1=P1.4---控制按钮                                           *
*                       第一次按下时, 启动开始计时                             *
*                       第二次按下时, 停止                                     *
*                       第三次按下时, 归零                                     *
*                                                                              *
*    秒单位,寄存器与数码管对应关系:                                            *
*                                                                              *
* --- 秒单位 ---------- 数码管端口 ---- 缓冲区 --------- 计时BCD码值寄存器     *
*     十万位               P20        dis_buf[7]          sec_bcd[7]           *
*     万位                 P21        dis_buf[6]          sec_bcd[6]           *
*     千位                 P22        dis_buf[5]          sec_bcd[5]           *
*     百位                 P23        dis_buf[4]          sec_bcd[4]           *
*     十位                 P24        dis_buf[3]          sec_bcd[3]           *
*     个位(1.s)            P25        dis_buf[2]          sec_bcd[2]           *
*     十分位(0.1s)         P26        dis_buf[1]          sec_bcd[1]           *
*     百分位(0.01s)        P27        dis_buf[0]          sec_bcd[0]           *
*                                                                              *
********************************************************************************
*/

#include <reg51.h>
#include <intrins.h>

unsigned char data dis_digit;
unsigned char key_s, key_v;

unsigned char code dis_code[11]={0xc0,0xf9,0xa4,0xb0,        // 0, 1, 2, 3
                                0x99,0x92,0x82,0xf8,0x80,0x90, 0xff};// 4, 5, 6, 7, 8, 9, off
unsigned char dis_buf[8];                // 显示缓冲区
unsigned char sec_bcd[8];                 // 秒计数值, BCD码
unsigned char dis_index;                //
unsigned char key_times;                // K1 按下次数                                //

void clr_time();       
void update_disbuf();
bit        scan_key();
void proc_key();
void delayms(unsigned char ms);

sbit        K1 = P1^4;


void main(void)
{
        P0 = 0xff;
        P2 = 0xff;
        TMOD = 0x11;                // 定时器0, 1工作模式1, 16位定时方式
        TH1 = 0xdc;
        TL1 = 0;

        TH0 = 0xFC;
        TL0 = 0x17;
       
        clr_time();                        //
                                           
        dis_digit = 0x7f;                // 初始显示P20口数码管
        dis_index = 0;                        //
       
        key_times = 0;
        key_v = 0x01;
       
        IE = 0x8a;                                // 使能timer0, timer1中断
       
        TR0 = 1;
        TR1 = 0;
        while(1)
        {
                if(scan_key())
                {
                        delayms(10);
                        if(scan_key())
                        {
                                key_v = key_s;
                                proc_key();
                        }
                }
               
        }
}

void clr_time()
{
        sec_bcd[0] = 0x0;
        sec_bcd[1] = 0x0;
        sec_bcd[2] = 0x0;
        sec_bcd[3] = 0x0;
        sec_bcd[4] = 0x0;
        sec_bcd[5] = 0x0;
        sec_bcd[6] = 0x0;
        sec_bcd[7] = 0x0;   
       
        update_disbuf();
       
}

bit scan_key()
{
        key_s = 0x00;
        key_s |= K1;
        return(key_s ^ key_v);       
}

void proc_key()
{
        if((key_v & 0x01) == 0)
        {
                key_times++;
                if(key_times == 1)
                {
                        TR1 = 1;
                }
                else if(key_times == 2)
                {       
                        TR1 = 0;
                }
                else
                {
                        clr_time();
                        key_times = 0;
                }
               
        }
}

void timer0() interrupt 1
// 定时器0中断服务程序, 用于数码管的动态扫描
// dis_index --- 显示索引, 用于标识当前显示的数码管和缓冲区的偏移量
// dis_digit --- 位选通值, 传送到P2口用于选通当前数码管的数值, 如等于0xfe时,
//                                选通P2.0口数码管
// dis_buf   --- 显于缓冲区基地址       
{
        TH0 = 0xFC;
        TL0 = 0x17;
       
        P2 = 0xff;                                                        // 先关闭所有数码管
        P0 = dis_buf[dis_index];                        // 显示代码传送到P0口
        P2 = dis_digit;                                                //

        dis_digit = _cror_(dis_digit,1);        // 位选通值右移(P20<-P27), 下次中断时选通下一位数码管
        dis_index++;                                                //
                                       
        dis_index &= 0x07;                        // 8个数码管全部扫描完一遍之后,再回到第一个开始下一次扫描
}

void timer1() interrupt 3
//
{       
        unsigned char i;
        TH1 |= 0xdc;
        for(i = 0; i < 8; i++)
        {
                sec_bcd[i]++;                        // 低位加1
                if(sec_bcd[i] < 10)                // 如果低位满10则向高位进1
                        break;                        // 低位未满10
                sec_bcd[i] = 0;                        // 低位满10清0
        }
        update_disbuf();                        // 更新显示缓冲区
}

void update_disbuf()
// 更新显示缓冲区
{
        dis_buf[0] = dis_code[sec_bcd[0]];
        dis_buf[1] = dis_code[sec_bcd[1]];
        dis_buf[2] = dis_code[sec_bcd[2]] & 0x7f;        // 加上小数点
        dis_buf[3] = dis_code[sec_bcd[3]];
        dis_buf[4] = dis_code[sec_bcd[4]];
        dis_buf[5] = dis_code[sec_bcd[5]];
        dis_buf[6] = dis_code[sec_bcd[6]];
        dis_buf[7] = dis_code[sec_bcd[7]];
}

void delayms(unsigned char ms)       
// 延时子程序
{                                               
        unsigned char i;
        while(ms--)
        {
                for(i = 0; i < 120; i++);
        }
}

给你个程序,你自己研究一下把
回复

使用道具 举报

12#
ID:140769 发表于 2016-10-6 19:53 | 只看该作者
zfbhjzxc 发表于 2016-10-4 12:31
/*                                                                             *
*                  ...

感谢解答
回复

使用道具 举报

13#
ID:140769 发表于 2016-10-6 20:55 | 只看该作者
a0931727149 发表于 2016-10-2 07:40
原程式有多處問題..... 修改後
# include
# define uint unsigned int

非常感谢您提供了代码,看后收获良多!您的程序运行时有一些问题,我做了如下修改。
运行中数值正常显示(0~99),但是递进的速度非常快(不是以一秒为单位),是不是定时器没起作用啊?

# include <reg52.h>
# define uint unsigned int
# define uchar unsigned char

uchar a[10] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99,     //四位共阳数码管0~9显示代码
                 0x92, 0x82, 0xF8, 0x80, 0x90 };

uchar wei[2] = { 0xef, 0xdf };  //个位与十位选通代码
      
uchar duan[2];     //用于存储个位与十位值的数组

uint num=0,sec;


void delay(uint m)
{
     uint i, j;

     for (i=0; i<m; ++i)
         for (j=110; j>0; --j);
}

void display(uint n) //数码管显示函数
{
      P0 = 0xff;    //个位显示
      P2 = wei[n];
      P0 = duan[n];   
}

void main(void)
{
      uint i=0, n=0, k=1, d=0;

       TMOD = 0X01;
       TH0 = (65536-50000)/256;
       TL0 = (65536-50000)%256;
       EA = 1;
       ET0 = 1;
       TR0 = 1;

       while(1)
       {
        duan[0] = a[d%10];  //个位显示的值
        duan[1] = a[d/10];  //十位显示的值

        display(n);

            d++;

           if (d == 100)
                      d = 0;
                          
        n++;
        n = n % 2;
        delay(1);
       }
      
}

void T0_time() interrupt 1
{
      TH0 = (65536-50000)/256;
      TL0 = (65536-50000)%256;

      ++num;
     
    if (num == 20)
    {
        num = 0;
        sec++;

        if(sec == 100)
                sec =0;      
     }  
}
回复

使用道具 举报

14#
ID:141520 发表于 2016-10-7 07:47 | 只看该作者
中断进入了变量num都清零了,怎么可能加到20啊。
回复

使用道具 举报

15#
ID:141520 发表于 2016-10-7 07:48 | 只看该作者
变量num都清零了,怎么可能加到20啊。
回复

使用道具 举报

16#
ID:140769 发表于 2016-10-7 14:16 | 只看该作者
zfbhjzxc 发表于 2016-10-4 12:31
/*                                                                             *
*                  ...

非常感谢您修改的程序,在您的基础上我再次修改后运行了如下的代码得到了我想要的结果。此次收获良多!
下列的程序是完整的代码,运行后无误。


# include <reg52.h>
# define uint unsigned int
# define uchar unsigned char

uchar a[10] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99,     //四位共阳数码管0~9显示代码
                       0x92, 0x82, 0xF8, 0x80, 0x90 };

uchar wei[2] = { 0xef, 0xdf };  //个位与十位选通代码
      
uchar duan[2];     //用于存储个位与十位值的数组

uint num=0,sec;


void delay(uint m)
{
     uint i, j;

     for (i=0; i<m; ++i)
         for (j=110; j>0; --j);
}

void display(uint n) //数码管显示函数
{
      P0 = 0xff;    //个位显示
      P2 = wei[n];
      P0 = duan[n];   
}

void main(void)
{
      uint i=0, n=0, k=1;

       TMOD = 0X01;
       TH0 = (65536-50000)/256;
       TL0 = (65536-50000)%256;
       EA = 1;
       ET0 = 1;
       TR0 = 1;

       while(1)
       {
        duan[0] = a[sec%10];  //个位显示的值
        duan[1] = a[sec/10];  //十位显示的值

        display(n);
      
        n++;
        n = n % 2;        //此语句巧妙
        delay(1);
       }  
}

void T0_time() interrupt 1
{
      TH0 = (65536-50000)/256;
      TL0 = (65536-50000)%256;

      ++num;
     
      if (num == 20)
      {
         num = 0;
         sec++;

         if(sec == 100)
         sec =0;      
      }  
}

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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