有关51单片机的问题

我用定时器扫描数码管,编写一个时钟的程序时,数码管上只有那个秒的个位是亮的,而其它都是很暗,这是什么原因???求大神。。。。下面是代码:
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar code wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
uchar duan[8];
uchar h,m,s;
/*void delay(uint t)
{
while(t--);
} */
void T_0()
{
TMOD|=0x01;
//TH0=0x00;
//TL0=0x00;
EA=1;
ET0=1;
TR0=1;
}
main()
{
void display(uchar f,uchar n);
T_0();
while(1)
{
duan[0]=table[h/10];
duan[1]=table[h%10];
duan[2]=0x40;
duan[3]=table[m/10];
duan[4]=table[m%10];
duan[5]=0x40;
duan[6]=table[s/10];
duan[7]=table[s%10];
}
}
void display(uchar f,uchar n)
{
uchar i;
for(i=0;i<n;i++)
{
P0=0x00;
P1=wei[i+f];
P0=duan[i];
}
}
void Te_0() interrupt 1
{
static uint t;
TH0=(65536-2000)/256; //2ms
TL0=(65536-2000)%256;
display(0,8);
t++;
if(t==500)
{
t=0;
s++;
if(s==60)
{
s=0;
m++;
if(m==60)
{
m=0;
h++;
if(h==24)
h=0;
}
}
}
}

1、8位二进制补码表示十六位进制的范围是多少?是-80H~7FH么
是。
----
2、“8051单片机的外部拓展EEPROM程序存储器进行适当的连接可以作为数据存储器使用,而8051单片机的外部拓展数据存储器也可以作为程序存储器进行程序调试”
前一句懂,后一句为什么是对的呢?如果外部数据存储器没有连接方式的话,MOVC这种查表指令该怎么办呢?数据存储和程序存储器的指令不是不同吗?还有我们编写KEILC程序时,指令是存在单片机哪里的?是外部程序存储器还是内部程序存存储器里?(可能存在外部数据存储器么)

这些话,是否正确,要看硬件电路。
如果把 PSEN 和 RD 相与,外部拓展数据存储器,也可以作为程序存储器。

前一句:外部拓展EEPROM程序存储器进行适当的连接可以作为数据存储器使用,
这里已经说了,需要适当的连接。

就是说,电路进行了改动,什么事情,都是可能发生的。
不要再提出疑问。
----
3、“能够用于寄存器寻址的寄存器有:Rn、Ri、DPTR、A、B、CY",
DPTR为毛也行啊,有MOV A,DPTR这种指令吗?徐汉斌单片机教材上就DPTR有关的指令只有4个,MOVX A,@DPTR;MOVX @DPTR,A;MOV DPTR,#addr16;MOVC A,@DPTR+A

你复习考试,要选定一本教材,不同的作者,说法不一。
----
4、“MSC 51单片机定时\计数器对外部脉冲进行计数时,要求输入的计数脉冲的高电平或低电平的持续时间不少于一个机器周期”,这句话哪里有错,实在没看出来

有错吗?
----
5、两数相减用补码运算时,是不是CY等于0表示第一个数小于第二个数,CY等于1表示第一个数大于第二个数

单片机的计算,是按照无符号数进行的,Cy,可以反应出无符号数的大小。
想像成补码,并不这么简单,补码是有正负的。
----
6、单片机怎样区别BCD码与16进制数?比如说计算BCD码的补码时,其模9AH与16进制相同,单片机怎么区分这是BCD码的100?

单片机不区别这个,需要编程人,编写程序来解决 BCD 码的问题。
----
这样可以么?
温馨提示:答案为网友推荐,仅供参考
第1个回答  2014-08-16
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar code wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
uchar duan[8];
uchar h,m,s;
void delay(uint t)
{
while(t--);
}
main()
{
uchar i;
TMOD|=0x01;
EA=1;
ET0=1;
TR0=1;

while(1) {
duan[0]=table[h/10];
duan[1]=table[h%10];
duan[2]=0x40;
duan[3]=table[m/10];
duan[4]=table[m%10];
duan[5]=0x40;
duan[6]=table[s/10];
duan[7]=table[s%10];
for(i = 0; i < 8; i++){
P1 = wei[i];
P0 = duan[i];
delay(100);
P0 = 0x00;
}
}
}
void Te_0() interrupt 1
{
static uint t;
TH0=(65536-2000)/256; //2ms
TL0=(65536-2000)%256;
t++;
if(t==500){ t=0;s++;
if(s==60) { s=0;m++;
if(m==60) { m=0;h++;
if(h==24) h=0;
}
}
}
}追问

在那里加延时是可以解决问题,但是那个秒好像就变化很慢了。。不是真正的一秒了???

追答

晶振频率,如果是 12MHz,不会很慢的。

晶振频率,如果是 11.0592MHz,会慢一点。

晶振频率,如果是 6MHz,会慢很多。

……
void Te_0() interrupt 1
{
static uint t;
TH0=(65536-2000)/256; //2ms--初始值,要根据晶振,认真选定
TL0=(65536-2000)%256;
t++;
if(t==500){ t=0;s++;
……

追问

为什么在定时器初始化时没有赋初值???

追答

这是尊重你的原来的程序。

你原来,就没有写。

追问

我不知道为什么不用写?

追答

初始化时写上,只是对第一次定时,起作用。
对以后的定时,无影响。

写上,第一次定时,就定时 2ms。
不写,第一次定时,就定时 65.535ms。

以后,只要在中断函数中,重写初值,就能准确定时。

本回答被提问者采纳
第2个回答  2014-08-16
数字都显示出来了吗?是暗而已还是完全没有显示?有没有闪烁?追问

都显示了,就是比较暗,没有闪烁。

追答

有可能是数码管驱动电流不足。你电路自己做的吗,贴出来我看看。

追问

不是,我买的单片机开发板。

追答

那你把开发板数码管部分的电路我看看。有显示了就不应该是程序的问题。如果是STC的单片机,数码管未加驱动电路的话,IO可能要开强推挽。

追问

我在display里面加一个延时就可以正常显示,但是那样的话 秒就变化很慢,不是一秒了

追答

不对啊,暗的部分数字是不是显示8

追问

不是,都是正确的显示了,只是除了秒的个位很亮,其它都很暗。。

追答

for(i=0;i<n;i++)
{
P0=0x00;
P1=wei[i+f];
P0=duan[i];
}
你看你的位扫描,几乎没有时间间隔。 在定时器溢出后才扫一次,也就是定时器溢出的时候一瞬间扫了完了全部数码管。这是不对的,你应该将每一位扫描的时间间隔连续均匀。

追问

那个定时器初始化时为什么不用给TH0赋初值???

追答

TH0=(65536-2000)/256; //2ms
TL0=(65536-2000)%256;
你定时器中断溢出程序里有啊。。。程序刚运行时,由于不赋初值时,定时器从0开始计数直到溢出,进入定时器中断程序里面。而中断程序里面有赋初值。 说白了,就是定时器除了第一次溢出时间长点,以后每次都是按初值的设定的时间来溢出。这对你的程序没影响,所以赋不赋都无所谓。

相关了解……

你可能感兴趣的内容

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 非常风气网