找回密码
 立即注册

QQ登录

只需一步,快速开始

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

怎么用单片机定时器做数码管动态显示?我的程序仿真不出来

[复制链接]
跳转到指定楼层
楼主
我想用定时器做数码管刷新,这个程序不知道哪里错了,用protues仿真不出来。


#include"reg52.h"
#define uchar unsigned char
#define uint unsigned int


code uchar led_7d_seg[]={0xc0,0xf9,0xa4,0xb0,0x99,
                         0x92,0x82,0xf8,0x80,0x90,
                                               0x88,0x83,0xc6,0xa1,0x86,0x8e};
code uchar led_7d_dig[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar disp_buff[8]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
void disp_led(void);
uchar num=0;
void main()
{  uchar cnt=0;
   uint sec=0;
   TMOD=0x01;//设置T0为方式一
   TH0=0xFC;//给T0赋初值,定时1ms
   TL0=0x67;
   TR0=1;
   while(1)
    {disp_led();
         if(TF0==1)
           {TF0=0;         //T0溢出后,清零标志位重新赋初值
            TH0=0xFC;
                TL0=0x67;
                cnt++; //T0溢出次数
            }
                if (cnt>=1000)//定时1s
                 {cnt=0;
                  sec++;//1s后数码管计数加一
                  disp_buff[0]=led_7d_seg[sec%10];
                  disp_buff[1]=led_7d_seg[sec/10%10];
                  disp_buff[2]=led_7d_seg[sec/100%10];
                  disp_buff[3]=led_7d_seg[sec/1000%10];
                  disp_buff[4]=led_7d_seg[sec/10000%10];
                  disp_buff[5]=led_7d_seg[sec/100000%10];
                  disp_buff[6]=led_7d_seg[sec/1000000%10];
                  disp_buff[7]=led_7d_seg[sec/10000000%10];
                  }

         }
}
void disp_led(void)
{P2=0;
P0=disp_buff[num];
P2=led_7d_dig[num];
num++;
num=num%8;
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2018-12-4 20:54 | 只看该作者

你对此一下就知道哪里错了
#include"reg52.h"
#define uchar unsigned char
#define uint unsigned int
code uchar led_7d_seg[]={0xc0,0xf9,0xa4,0xb0,0x99,
                         0x92,0x82,0xf8,0x80,0x90,
                         0x88,0x83,0xc6,0xa1,0x86,0x8e};
code uchar led_7d_dig[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar disp_buff[8];
void disp_led(void);
uchar num=0;

void main()
{
        uint cnt=0;
        unsigned long sec=0;
        TMOD=0x01;//设置T0为方式一
        TH0=0xFC;//给T0赋初值,定时1ms
        TL0=0x67;
        TR0=1;
        while(1)
        {
                if(TF0==1)
                {
                        TF0=0;         //T0溢出后,清零标志位重新赋初值
                        TH0=0xFC;
                        TL0=0x67;
                        cnt++; //T0溢出次数
                        if (cnt>=1000)//定时1s
                        {
                                cnt=0;
                                sec++;//1s后数码管计数加一
                                disp_buff[0]=sec%10;
                                disp_buff[1]=sec/10%10;
                                disp_buff[2]=sec/100%10;
                                disp_buff[3]=sec/1000%10;
                                disp_buff[4]=sec/10000%10;
                                disp_buff[5]=sec/100000%10;
                                disp_buff[6]=sec/1000000%10;
                                disp_buff[7]=sec/10000000%10;
                        }
                        disp_led();
                }
        }
}
void disp_led(void)
{
        P0=0xff;
        P2=led_7d_dig[num];
        P0=led_7d_seg[disp_buff[num]];
        num++;
        num=num%8;
}

回复

使用道具 举报

板凳
ID:354168 发表于 2018-12-4 22:26 | 只看该作者
本帖最后由 牧阿木 于 2018-12-4 22:57 编辑

谢谢你帮我改程序啊!我还是有点不明白的地方,
这个位选的接法不太懂,
还有就是为什么不能这样写disp_buff[0]=led_7d_seg[sec%10];,而是disp_buff[0]=sec%10;然后让P0=led_7d_seg[disp_buff[num]];
也不太明白这个“num”,为什么位选和段选赋值都用到了num。对数码管赋值的时候是不是不用把1到15都写出来啊?
如果你有空闲的时候就告诉我吧,麻烦你啦!
回复

使用道具 举报

地板
ID:213173 发表于 2018-12-5 09:30 | 只看该作者
牧阿木 发表于 2018-12-4 22:26
谢谢你帮我改程序啊!我还是有点不明白的地方,
这个位选的接法不太懂,
还有就是为什么不能这样写disp_bu ...

1.位驱动的接法与硬件的物理结构相关,如果位码这样写led_7d_dig[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};就可以按照你的接法。否则显示的数是反序的。
2.为了用多位数码管正常显示一个大数字,往往将该数分解为个、十、百......的方法分别保存在缓存数组中。P0输出的不是真实的数字,而是代表这个数字的图形----段码,也就是译码。所以P0=段码数组[缓存数组[下标num]]。
3.由于变量num限制在0~7范围循环,在这里num是作为位码和缓存两个数组的下标公用。
4.不是对数码管赋值!是对P0赋值驱动数码管。在实物中8个数码管的段接点是连接在一起的,某时间段某个数码管亮灭是由位码确定的。
5.你的程序其他错误:uint sec=0;,uint 类型最大65535,uchar cnt=0;,uchar 类型最大255.uchar disp_buff[8]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};,这样定义会造成加电初始全显示8.8.8......,还有显示程序放在 if(TF0==1)外,在实际应用中会因为刷新速度太快而无法正常显示。
回复

使用道具 举报

5#
ID:354168 发表于 2018-12-5 11:38 | 只看该作者
哇!你能回复我我太开心啦!哈哈哈哈。谢谢你啊!
你给我讲的我能明白一点,但是有的地方还不太懂。
uchar disp_buff[8]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};我这样定义缓存区是想让它初始化全不亮,因为这个是共阳极接法嘛,0xFF是全为高电平,数码管都是灭的。
可是在定义输出显示的时候你把P0=0xff,这样它不就什么都不显示嘛,为什么仿真的时候它的八位都显示0啊?
还有一个问题是主函数里并没有对P2口的led_7d_dig[num]进行延时设置,为什么数码管还可以以1ms的速度刷新呢?
回复

使用道具 举报

6#
ID:213173 发表于 2018-12-5 14:13 | 只看该作者
本帖最后由 wulin 于 2018-12-5 14:44 编辑
牧阿木 发表于 2018-12-5 11:38
哇!你能回复我我太开心啦!哈哈哈哈。谢谢你啊!
你给我讲的我能明白一点,但是有的地方还不太懂。
ucha ...

1.因为你定义的是缓存数组里的初始数据都是0xff,也就是255,因导入数码管数组的数据只限制在0~15范围,溢出无效,系统默认0x00,所以显示8.8.8.8.8.8.8.8.,如果想在加电初始不显示,可以在数码管数组中增加第16个元素0xff,缓存数组里的初始数据都设置0x10,才能使P0=0xff。我定义缓存数组用的是缺省设置,系统默认0x00,所以开机全显0.
2.显示程序里的P0=0xff,是消隐语句,不加此句在实际电路中数码管会有鬼影(不该亮的笔画微亮)。
3.把显示程序放在if(TF0==1)里就是为了以1ms的速度刷新。再加延时就画蛇添足了。
回复

使用道具 举报

7#
ID:354168 发表于 2018-12-7 15:26 来自手机 | 只看该作者
wulin 发表于 2018-12-5 14:13
1.因为你定义的是缓存数组里的初始数据都是0xff,也就是255,因导入数码管数组的数据只限制在0~15范围, ...

谢谢你啊!哈哈我还是不太明白缓存数组和数码管数组这里为什么我的数码管全亮,而你的就只显示0。num在0-7循环,它就用不到定义的数码管里边后六位了(数码管里我定义了从0-F)那为什么后边再加0xff它就全都不显示了啊?
回复

使用道具 举报

8#
ID:213173 发表于 2018-12-7 20:46 | 只看该作者
牧阿木 发表于 2018-12-7 15:26
谢谢你啊!哈哈我还是不太明白缓存数组和数码管数组这里为什么我的数码管全亮,而你的就只显示0。num在0- ...

P0=led_7d_seg[disp_buff[num]];在这里num值表示缓存的下标0~7,如果缓存数组里的初始数据都设置0x10就是16,这时等效P0=led_7d_seg[16],因数码管数组第16元素是增加的0xff,所以这时等效P0=0xff,数码管全都不显示。我这样解释已经比教科书还详细,如果还不能理解就只能在今后实践中逐渐理解了。

评分

参与人数 1黑币 +8 收起 理由
牧阿木 + 8 谢谢你啊!是我没有理解数组的含义。我现在.

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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