求助!请大神指导~~~~
时间:10-02
整理:3721RD
点击:
* 利用单片机计算出1!+2!+3!+……+9!的结果。
程序:
#include <reg51.h>
#define INT8U unsigned char
#define INT16U unsigned int
code INT8U SEG_CODE[] = {0x3f,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//段码
code INT8U SEG_WEI[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位码
void delay_ms(INT16U x)
{
INT8U t; while(x--) for(t = 0; t < 120; t++);
}//延时子程序
sbit d=P1^0;//位定义(控制段码信号的"门")
sbit w=P1^1; //位定义(控制位码信号的"门")
/*unsigned int*/long sum()
{
unsigned int i , j=1 ;
long s=0 ;
for(i=1;i<=9;i++)
{
j*=i;
s+=j;
}
return s ;
}//求和子函数
void main()
{
unsigned int he;
he=sum();//在主函数中调用求和子函数
while(1)
{
P0=0xff;
w=1;
P0=SEG_WEI[7];
w=0;
d=1;
P0=SEG_CODE[he%10];
d=0;
delay_ms(5);//显示完个位
P0=0xff;
w=1;
P0=SEG_WEI[6];
w=0;
d=1;
P0=SEG_CODE[(he/10)%10];
d=0;
delay_ms(5);//显示完十位
P0=0xff;
w=1;
P0=SEG_WEI[5];
w=0;
d=1;
P0=SEG_CODE[(he/100)%10];
d=0;
delay_ms(5);//显示完百位
P0=0xff;
w=1;
P0=SEG_WEI[4];
w=0;
d=1;
P0=SEG_CODE[(he/1000)%10];
d=0;
delay_ms(5);//显示完千位
P0=0xff;
w=1;
P0=SEG_WEI[3];
w=0;
d=1;
P0=SEG_CODE[(he/10000)%10];
d=0;
delay_ms(5);//显示完万位
P0=0xff;
w=1;
P0=SEG_WEI[2];
w=0;
d=1;
P0=SEG_CODE[(he/100000)%10];
d=0;
delay_ms(5);//显示完十万位
P0=0xff;
w=1;
P0=SEG_WEI[1];
w=0;
d=1;
P0=SEG_CODE[(he/1000000)%10];
d=0;
delay_ms(5);//显示完百万位
P0=0xff;
w=1;
P0=SEG_WEI[0];
w=0;
d=1;
P0=SEG_CODE[he/10000000];
d=0;
delay_ms(5);//显示完千万位
}
}
但是在proteus中仿真却出现这样的结果:
有两个问题:
1.为什么我在调试1!+2!+...+8!时结果都是正确的,而多一个9!时却发生这样的结果?
2.百万位和十万位一直都是8,怎样修改主函数才能得到没有问题的程序?
因为积分只有一分,所以希望大神不要见怪~~~~
程序:
#include <reg51.h>
#define INT8U unsigned char
#define INT16U unsigned int
code INT8U SEG_CODE[] = {0x3f,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//段码
code INT8U SEG_WEI[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位码
void delay_ms(INT16U x)
{
INT8U t; while(x--) for(t = 0; t < 120; t++);
}//延时子程序
sbit d=P1^0;//位定义(控制段码信号的"门")
sbit w=P1^1; //位定义(控制位码信号的"门")
/*unsigned int*/long sum()
{
unsigned int i , j=1 ;
long s=0 ;
for(i=1;i<=9;i++)
{
j*=i;
s+=j;
}
return s ;
}//求和子函数
void main()
{
unsigned int he;
he=sum();//在主函数中调用求和子函数
while(1)
{
P0=0xff;
w=1;
P0=SEG_WEI[7];
w=0;
d=1;
P0=SEG_CODE[he%10];
d=0;
delay_ms(5);//显示完个位
P0=0xff;
w=1;
P0=SEG_WEI[6];
w=0;
d=1;
P0=SEG_CODE[(he/10)%10];
d=0;
delay_ms(5);//显示完十位
P0=0xff;
w=1;
P0=SEG_WEI[5];
w=0;
d=1;
P0=SEG_CODE[(he/100)%10];
d=0;
delay_ms(5);//显示完百位
P0=0xff;
w=1;
P0=SEG_WEI[4];
w=0;
d=1;
P0=SEG_CODE[(he/1000)%10];
d=0;
delay_ms(5);//显示完千位
P0=0xff;
w=1;
P0=SEG_WEI[3];
w=0;
d=1;
P0=SEG_CODE[(he/10000)%10];
d=0;
delay_ms(5);//显示完万位
P0=0xff;
w=1;
P0=SEG_WEI[2];
w=0;
d=1;
P0=SEG_CODE[(he/100000)%10];
d=0;
delay_ms(5);//显示完十万位
P0=0xff;
w=1;
P0=SEG_WEI[1];
w=0;
d=1;
P0=SEG_CODE[(he/1000000)%10];
d=0;
delay_ms(5);//显示完百万位
P0=0xff;
w=1;
P0=SEG_WEI[0];
w=0;
d=1;
P0=SEG_CODE[he/10000000];
d=0;
delay_ms(5);//显示完千万位
}
}
但是在proteus中仿真却出现这样的结果:
有两个问题:
1.为什么我在调试1!+2!+...+8!时结果都是正确的,而多一个9!时却发生这样的结果?
2.百万位和十万位一直都是8,怎样修改主函数才能得到没有问题的程序?
因为积分只有一分,所以希望大神不要见怪~~~~
keil C51中unsigned int类型是16位,最大值为65535。unsigned long为32位。long型变量与int型变量相乘是被当成int × int还是long×long,这个需要实际测试一下,这会影响计算结果。局部变量he是unsigned int型,1! + ... + 8! = 46233,< 65535可以准确表示。但+9!之后,结果是409113 > 65535,则高16位丢失,则he=15897,这与你显示的后5位一致。至于前面两个8,可能是除法运算错误导致的,这个我没验证过。
想要正确的结果,最简单的办法是把所有的变量,包括局部变量和全局变量,全部改为unsigned long类型。
将变量he改为long型试试
好像大部分的8位和16位单片机的编译器整型都是16位的。我也经常不小心弄错数据类型,特别是运算之后。如果有在线调试的功能,设置断点或单步运行,查看变量的值,一般来说会很快定位问题。