|
|
|
| 恳请电脑圈圈,程序匠人,XWJ大师出来帮忙一下。 |
|
新闻出处:21ic 发布时间:2007-05-30
|
xzhenggen 发布于 2007-5-24 8:14:00
尝试了几种if…else…方式,还是没能解决以下问题…… 在C51里面如何使用C语言写判零及小数点消隐的子程序?? #define AD_Loop_PickVol_PER 0.0024414 unsigned char idata serial_buff[12];
void display(uint v) { unsigned char row, count; float tt; unsigned long tmp ; signed long value; tt=v*AD_Loop_PickVol_PER;//AD采样数值 value = tt * 1000000000;//取小数点后9位 tmp = value; if(value<0)tmp*=-1;//取负数 for(count=0;count<11;count++) { if(tmp !=0) { serial_buff[10-count]=tmp%10; tmp/=10; } else { serial_buff[10-count]=0; } } draw_bmp(0,1,8,ELAPHT[12]);//显示"Pi" for(count = 0; count != 11; count++) { draw_bmp(8+row*8,1,8,num[serial_buff][count]]);//显示读数 row++; if((count == 1))//定位小数位 { draw_bmp(8+row*8,1,8,num[10]);//设置小数点 row++; } } row=0; draw_bmp(112+row*8,1,8,ELAPHT[11]);//显示"W" } 此时正确吗? if(value<0)tmp*=-1;//取负数 上面的子程序是使用在12232LCD上显示的AD采集的数值,格式为PiXX. XXXXXXXXXW(保留小数点后9位数值,但显示格式须作如下修改)。 为了显示单位方便直观所以要在LCD上自动切换显示格式,同时小数点也自动移位切换显示。现要求更改12232LCD上的显示格式为如下几种方式: 1, 如果小数点前两位数值不等于零,则LCD上显示格式自动切换为PiXX.XXX W显示,其余后面的六位数值消掉(留下空格)。而如果此时的数值显示为Pi 0X.XXX W则前面的0自动消掉不显示。更改显示方式为:Pi X.XXX W
2, 如果小数点前两位数值都等于零,则LCD上显示格式自动切换为Pi XXX.XXX mW显示,即把前面小数点两位为零的数值去掉(留下空格)及其余后面的六位数值消掉(留下空格)。而如果此时的数值显示为Pi 0XX.XXX mW或者为Pi 00X.XXX mW则前面的0都自动消掉不显示。更改显示方式为:Pi XX.XXX mW或者Pi X.XXX mW 3, 如果小数点前两位及后面三位都等于零,则LCD上显示格式自动切换为Pi XXX.XXX uW显示,即把前面小数点两位为零的数值和小数点后面三位为零的数值去掉(留下空格)。而如果此时的数值显示为Pi 0XX.XXX uW或者为Pi 00X.XXX uW则前面的0都自动消掉不显示。更改显示方式为:Pi XX.XXX uW或者Pi X.XXX uW 4, 如果小数点前两位数值及后面六位数值都等于零,则LCD上显示格式自动切换为Pi XXX nW显示,即把前面小数点两位为零的数值和小数点后面六位为零的数值去掉(留下空格)。而如果此时的数值显示为Pi 0XX nW或者为Pi 00X nW则前面的0都自动消掉不显示。更改显示方式为:Pi X X nW或者Pi X nW 5, 在void display(uint v)函数加入if…else…的什么语法?是否可以实现上述四种功能在LCD上显示出来,各位高手请出招啊,多谢!多谢!
zhaoyu2005 发布于 2007-5-24 8:25:00 你编不出来只能是你的逻辑出错了,其实你描述的判断逻辑很清楚了,剩下的就是编程实现了,你就按照你描述的判断条件编写,可能麻烦点、庞大点,但是编完了你理清了思路可以优化
infree 发布于 2007-5-24 15:25:00 因为long型是装不下11位有效数字的,所以使用浮点数来直接判断和打印。 给这个函数一个浮点数,它会按你要求的格式输出应该显示的字符串到val_buf中,你可以添加将一个字符串显示到LCD上的处理过程。 我在串口打印输出的结果见附图。 仅供测试!!! void display_format(float fvalue) { INT8U val_buf[20]; INT8U i;
if(fvalue>=1)//W { sprintf(val_buf,"Pi%12.9fW",fvalue); } else { if(fvalue>=0.001)//mW { fvalue*=1000; sprintf(val_buf,"Pi%8.3f mW",fvalue); } else { if (fvalue>=0.000001)//uW {fvalue*=1000000; sprintf(val_buf,"Pi%8.3f uW",fvalue); } else//nW {//fvalue>=0.000000001 fvalue*=1000000000; sprintf(val_buf,"Pi%8.0f nW",fvalue); } } } #ifdef SERIAL_DEBUG SBUF='\n'; Delay_ms(1); for(i=0;i<16;i++) { SBUF=val_buf[i]; Delay_ms(1); } #endif }

computer00 发布于 2007-5-24 21:05:00 事实上,楼主要的只是六位精度而已。你可以写一个转换为6位结果的子函数,然后按照 测试结果的范围,放大适当的倍数来显示。
void display(float v) { tmp = v * 1000;//取小数点后3位
if(value<0) //如果是负数则取相反数,并设置‘-’号,否则显示空格 { tmp*=-1; serial_buff[0]='-'; //负号在你字库中的位置,下面的空格同样 } else { serial_buff[0]=' '; //or '+' } serial_buff[7]=tmp%10; tmp/=10; serial_buff[6]=tmp%10; tmp/=10; serial_buff[5]=tmp%10; tmp/=10; serial_buff[4]='.'; //小数点在你字库中的位置 serial_buff[3]=tmp%10; tmp/=10; serial_buff[2]=tmp%10; tmp/=10; serial_buff[1]=tmp%10; if(serial_buff[1]==0) { serial_buff[1]=' '; if(serial_buff[2]==0) { serial_buff[2]=' '; } } draw(serial_buff); }
main() { if(result>=1) { display(result); draw(" W"); } else if(result>=0.001) { display(result*1000); draw("mW"); } else if(result>=1e-6) { display(result*1e6); draw("uW"); } }
infree 发布于 2007-5-25 8:31:00 打印W级的数据应改为:sprintf(val_buf,"Pi%6.3f W",fvalue); 数据和W之间留下6个空格。
另:看题目中的要求,应该是不会有负数的,所以也不必考虑符号问题吧!
xzhenggen 发布于 2007-5-27 8:12:00 感谢computer00(电脑圈圈)鼎力的帮助,及各位大侠热心帮助。
xzhenggen 发布于 2007-5-27 16:34:00 是不是就是 tt=v*AD_Loop_PickVol_PER;//AD采样数值
xzhenggen 发布于 2007-5-28 11:24:00 我现在用你们提供的子函数可以达到我的显示要求了,但是还想再请电脑圈圈帮我完成最后一步。显示nW级时,只显示前面有效的两,三位或者一位有效数。我指的有效数是指小数点前面为零消掉,同时小数点也消掉。只显示nW级三位有效数,同理前面为零也消掉。多谢了!!! 修改电脑圈圈的子程序如下:简洁明朗,优化代码,实实在在用得舒服,顺畅。 void display_Temp() { unsigned char row, count; unsigned int tmp; int v; v=getTmpValue(); tmp =v; if(v<0) { tmp*=-1; serial_buff_T[0]='-'; } else { serial_buff_T[0]='+';//num[12] } for(count=1;count<6;count++) { if(tmp !=0) { serial_buff_T[6-count]=tmp%10; tmp/=10; } else { serial_buff_T[6-count]=0; } } draw_bmp(0,0,8,ELAPHT[8]);// 显示"T" draw_bmp(8,0,8,num[15]);//显示":" for(count = 1; count != 6; count++) { draw_bmp(56+row*8,0,8,num[serial_buff_T][count]]);//显示读数 row++; if(serial_buff_T[1]==0) { draw_bmp(56,0,8,num[12]);//显示" " if(serial_buff_T[2]==0) { draw_bmp(64,0,8,num[12]);//显示" " } } if(count == 3)//定位小数位 { draw_bmp(56+row*8,0,8,num[10]);//设置小数点 row++; } } if(serial_buff_T[0]=='+') { draw_bmp(40,0,8,num[13]);//显示"+" } else if(serial_buff_T[0]=='-') { draw_bmp(40,0,8,num[14]);//显示"-" } row=0; draw_bmp(112,0,8,num[11]);//显示"℃" } void display_Pi() { unsigned char line, cout; unsigned long stmp; unsigned int vt; float pow,plt; vt=read7896(); pow=vt*AD_Loop_PickVol_PER;//AD采集数值 if(pow>=1) { plt=pow; draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=0.001) { plt=pow*1000; draw_bmp(104,1,8,ELAPHT[11]);//显示"m" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=1e-6) { plt=pow*1e6; draw_bmp(104,1,8,ELAPHT[10]);//显示"u" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } stmp = plt * 1000;//取小数点后3位 for(cout=1;cout<7;cout++) { if(stmp!=0) { serial_buff[7-cout]=stmp%10;//显示读数 stmp/=10; } else { serial_buff[7-cout]=0; } } for(cout = 1; cout <7; cout++) { draw_bmp(40+row1*8,1,8,num[serial_buff][cout]]);//显示读数 line++; if(serial_buff[1]==0) { draw_bmp(40,1,8,num[12]);//显示" " if(serial_buff[2]==0) { draw_bmp(48,1,8,num[12]);//显示" " } } if(count1 == 3)//定位小数位 { draw_bmp(40+line*8,1,8,num[10]);//设置小数点 line++; } } line=0; draw_bmp(0,1,8,ELAPHT[13]);//显示"Pi" }
computer00 发布于 2007-5-29 3:53:00 你应该将数据全部写到一个数组里面,然后用一个函数用个for语句全部一次显示.
//将值转化为串并保存在serial_buff中 void change(unsigend long temp) { unsigend char i; serial_buffer[4]=10; //小数点 for(i=1;i<8;i++) { if(i==4)continue; //跳过小数点的位置 if(temp!=0) { serial_buff[8-i]=temp%10; temp/=10; } else { serial_buff[8-i]=0; } }
if(serial_buff[1]==0) { serial_buff[1]=12; //空格 if(serial_buff[2]==0) { serial_buff[2]=12; //空格 } } } //////////////////////////////////////////////////////////////
void display_Pi() { unsigned int vt; float pow; unsigned char i;
vt=read7896(); pow=vt*AD_Loop_PickVol_PER;//AD采集数值 if(pow>=1) { change(pow*1e3); draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=1e-3) { change(pow*1e6); draw_bmp(104,1,8,ELAPHT[11]);//显示"m" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=1e-6) { change(pow*1e9); //将前面的3位结果放到后面 serial_buff[7]=serial_buff[3]; serial_buff[6]=serial_buff[2]; serial_buff[5]=serial_buff[1]; //前面4位改为空格 for(i=1;i<5;i++)serial_buff[i]=12; draw_bmp(104,1,8,ELAPHT[10]);//显示"u" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" }
//显示读数 for(i = 1; i <8; i++) { draw_bmp(40+i*8,1,8,num[serial_buff][i]]); } //??? line=0; draw_bmp(0,1,8,ELAPHT[13]);//显示"Pi" }
xzhenggen 发布于 2007-5-29 12:11:00
但会出现以下问题: 前面两位数值会被零不断地覆盖,后面的三位数值即serial_buff[7],serial_buff[6],serial_buff[5],有时会被serial_buff[3],serial_buff[2],serial_buff[1]所覆盖.数值覆盖是不断循环的,而且读数好像都有问题. 我在主函数里面是循环调用子程序的. main() { ...
while(1) { display_Pi(); } } 我现在有点纳闷的是为啥??加入 void change(unsigend long temp)函数,读AD数值有问题.
xzhenggen 发布于 2007-5-29 13:30:00 。。。。。。。。
void change(unsigned long temp) { unsigned char i; serial_buff[4]=10; for(i=1;i<8;i++) { if(i==4)continue; if(temp!=0) { serial_buff[8-i]=temp%10; temp/=10; } else { serial_buff[8-i]=0; } } }
void display_Pi() { unsigned int vt; float pow; unsigned char i; vt=read7896(); pow=vt*AD_Loop_PickVol_PER;//AD采集数值 if(pow>=1) { change(pow*1e3); draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=1e-3) { change(pow*1e6); draw_bmp(104,1,8,ELAPHT[11]);//显示"m" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=1e-6) { change(pow*1e9); serial_buff[7]=serial_buff[3]; serial_buff[6]=serial_buff[2]; serial_buff[5]=serial_buff[1]; for(i=1;i<5;i++)draw_bmp(40+i*8,1,8,num[12]);//显示" " draw_bmp(104,1,8,ELAPHT[10]);//显示"u" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } draw_bmp(0,1,8,ELAPHT[13]);//显示"Pi" draw_bmp(8,1,8,num[15]);//显示":" for(i=1;i<8;i++) { draw_bmp(40+i*8,1,8,num[serial_buff][i]]);//显示读数} if(serial_buff[1]==0) { draw_bmp(48,1,8,num[12]);//显示" " if(serial_buff[2]==0) { draw_bmp(56,1,8,num[12]);//显示" " } } if(serial_buff[4]==10) { draw_bmp(72,1,8,num[10]);//设置小数点 } } }
void logo(void) { uchar i,j,h; TR0 = 1; lcd_clr(); draw_bmp(0,0,112,welcome_1); draw_bmp(0,1,104,welcome_2); for(i=0;i<10;i++)for(j=0;j;j++)for(h=1;h;h++); lcd_clr(); draw_bmp(0,0,112 ,welcome_3); for(i = 0;i<5;i++)for(j = 1;j;j++)for(h = 1;h;h++); } void main (void) { //uint i; P0 =0xff; P1 =0xff; P2 =0xff; P3 =0xff; delay(255); lcd_init(); lcd_init(); lcd_init(); lcd_clr(); logo(); delay(120); lcd_clr(); //lcd_clr(); //sendChangeCmd(); //TMOD:GATE|C/! T|M1|MO|GATE|C/! T|M1|M0 // 0 0 1 0 0 0 0 1 TMOD = 0x21; TH0 = 0X4C; TL0 = 0x00; //SCON:SM0|SM1|SM2|REN|TB8|RB8|TI|RI // 0 1 0 0 0 0 0 0 ET0 = 1; ES = 1; EA = 1; while(1) { display_Pi(); //display_amp(1); //display_Temp(); //sendChangeCmd(); } }
mybao 发布于 2007-5-29 13:37:00 注意身体啊
computer00 发布于 2007-5-29 15:22:00 if(serial_buff[1]==0) { draw_bmp(48,1,8,num[12]);//显示" " if(serial_buff[2]==0) { draw_bmp(56,1,8,num[12]);//显示" " } } if(serial_buff[4]==10) { draw_bmp(72,1,8,num[10]);//设置小数点 }
?????????????????????????????????????????????????????????????
原本放在change里面不是好好的吗?在change里面处理好了,然后显示的时候, 一下全部显示不就行了?你要显示一个空格,就是num[12],那让serial_buff[1]=12就OK了. 小数点也是同样的道理.
for(i = 1; i <8; i++) { draw_bmp(40+i*8,1,8,num[serial_buff][i]]); }
xzhenggen 发布于 2007-5-30 8:46:00 没仔细看以为电脑圈圈又是提供两个思维方式的子程序。想当然地误改,真是越改越乱。真得感谢21IC平台,使我幸运地认识了computer00(电脑圈圈)这样的好心人,感谢电脑圈圈耐心细致的指点和帮助。自学单片机真的好难啊!!光有恒心和毅力还是不够的,还要有高手贵人的指点和帮助。就像是学武功一样,光有武功秘籍是不够的,还须有高手指点和帮助。幸运地是我第一次单独做项目,就得到了电脑圈圈这样的好心高手帮助,今天收获成功喜悦,心存感激溢于言表。假如没有遇到认识电脑圈圈这样有耐心,细致热心助人的高手,我的项目到目前还是处于摸索状态,停滞不前。不可能这么快走向成功的第一步。前面得到电脑圈圈地帮助很多很多。。。电脑圈圈真得是我的良师益友。。。以下两个子程序加入进去,直接调用就OK了!!。 void change(unsigned long temp) { unsigned char i;
serial_buff[4]=10; //小数点 for(i=1;i<8;i++) { if(i==4)continue; //跳过小数点的位置 if(temp!=0) { serial_buff[8-i]=temp%10; temp/=10; } else { serial_buff[8-i]=0; } }
if(serial_buff[1]==0) { serial_buff[1]=12; //空格 if(serial_buff[2]==0) { serial_buff[2]=12; //空格 } } } //////////////////////////////////////////////////////////////
void display_Pi() { unsigned int vt; float pow; unsigned char i; vt=read7896(); pow=vt*AD_Loop_PickVol_PER;//AD采集数值 if(pow>=1) { change(pow*1e3); draw_bmp(104,1,8,num[12]);//显示" "加入此句,是因为测试时显示mW转W时,有时m没消掉。 draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=1e-3) { change(pow*1e6); draw_bmp(104,1,8,ELAPHT[11]);//显示"m" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=1e-6) { change(pow*1e9); //将前面的3位结果放到后面 serial_buff[7]=serial_buff[3]; serial_buff[6]=serial_buff[2]; serial_buff[5]=serial_buff[1]; //前面4位改为空格 for(i=1;i<5;i++)serial_buff[i]=12; draw_bmp(104,1,8,ELAPHT[10]);//显示"u" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } //显示读数 for(i = 1; i <8; i++) { draw_bmp(40+i*8,1,8,num[serial_buff][i]]); } //??? line=0; //此句在我前面的子程序里如果不加入时,小数点会出现三位,数值循环左移。 draw_bmp(0,1,8,ELAPHT[13]);//显示"Pi" }
computer00 发布于 2007-5-30 10:48:00 其实你没必要将数字和字符分开做字库,完全可以把它们做成一个表。就像你那些"-","+","."等,也可以把"u","W"等放到num(或者换个名字)里。然后再使用宏定义,就更方便了。当然,你现在的程序已经可以了,懒得改也无妨了。
#define A_u 20 /*20表示它在数组中的位置,根据你的情况定*/ #define A_m 21 #define A_W 22 //自己决定上面这些值,最好按次序来
//然后就可以把它们放到buff中去处理了
serial_buff[9]=A_W;//显示"W",反正每次都要显示,一次赋值就够了
if(pow>=1) { change(pow*1e3); serial_buff[8]=12;//显示" "加入此句,是因为测试时显示mW转W时,有时m没消掉。 } else if(pow>=1e-3) { change(pow*1e6); serial_buff[8]=A_m;//显示"m" } ................... ................... ...................
//一次将数字和单位都显示出来 for(i = 1; i <10; i++) { draw_bmp(40+i*8,1,8,num[serial_buff][i]]); }
xzhenggen 发布于 2007-5-24 8:14:00
尝试了几种if…else…方式,还是没能解决以下问题…… 在C51里面如何使用C语言写判零及小数点消隐的子程序?? #define AD_Loop_PickVol_PER 0.0024414 unsigned char idata serial_buff[12];
void display(uint v) { unsigned char row, count; float tt; unsigned long tmp ; signed long value; tt=v*AD_Loop_PickVol_PER;//AD采样数值 value = tt * 1000000000;//取小数点后9位 tmp = value; if(value<0)tmp*=-1;//取负数 for(count=0;count<11;count++) { if(tmp !=0) { serial_buff[10-count]=tmp%10; tmp/=10; } else { serial_buff[10-count]=0; } } draw_bmp(0,1,8,ELAPHT[12]);//显示"Pi" for(count = 0; count != 11; count++) { draw_bmp(8+row*8,1,8,num[serial_buff][count]]);//显示读数 row++; if((count == 1))//定位小数位 { draw_bmp(8+row*8,1,8,num[10]);//设置小数点 row++; } } row=0; draw_bmp(112+row*8,1,8,ELAPHT[11]);//显示"W" } 此时正确吗? if(value<0)tmp*=-1;//取负数 上面的子程序是使用在12232LCD上显示的AD采集的数值,格式为PiXX. XXXXXXXXXW(保留小数点后9位数值,但显示格式须作如下修改)。 为了显示单位方便直观所以要在LCD上自动切换显示格式,同时小数点也自动移位切换显示。现要求更改12232LCD上的显示格式为如下几种方式: 1, 如果小数点前两位数值不等于零,则LCD上显示格式自动切换为PiXX.XXX W显示,其余后面的六位数值消掉(留下空格)。而如果此时的数值显示为Pi 0X.XXX W则前面的0自动消掉不显示。更改显示方式为:Pi X.XXX W
2, 如果小数点前两位数值都等于零,则LCD上显示格式自动切换为Pi XXX.XXX mW显示,即把前面小数点两位为零的数值去掉(留下空格)及其余后面的六位数值消掉(留下空格)。而如果此时的数值显示为Pi 0XX.XXX mW或者为Pi 00X.XXX mW则前面的0都自动消掉不显示。更改显示方式为:Pi XX.XXX mW或者Pi X.XXX mW 3, 如果小数点前两位及后面三位都等于零,则LCD上显示格式自动切换为Pi XXX.XXX uW显示,即把前面小数点两位为零的数值和小数点后面三位为零的数值去掉(留下空格)。而如果此时的数值显示为Pi 0XX.XXX uW或者为Pi 00X.XXX uW则前面的0都自动消掉不显示。更改显示方式为:Pi XX.XXX uW或者Pi X.XXX uW 4, 如果小数点前两位数值及后面六位数值都等于零,则LCD上显示格式自动切换为Pi XXX nW显示,即把前面小数点两位为零的数值和小数点后面六位为零的数值去掉(留下空格)。而如果此时的数值显示为Pi 0XX nW或者为Pi 00X nW则前面的0都自动消掉不显示。更改显示方式为:Pi X X nW或者Pi X nW 5, 在void display(uint v)函数加入if…else…的什么语法?是否可以实现上述四种功能在LCD上显示出来,各位高手请出招啊,多谢!多谢!
zhaoyu2005 发布于 2007-5-24 8:25:00 你编不出来只能是你的逻辑出错了,其实你描述的判断逻辑很清楚了,剩下的就是编程实现了,你就按照你描述的判断条件编写,可能麻烦点、庞大点,但是编完了你理清了思路可以优化
infree 发布于 2007-5-24 15:25:00 因为long型是装不下11位有效数字的,所以使用浮点数来直接判断和打印。 给这个函数一个浮点数,它会按你要求的格式输出应该显示的字符串到val_buf中,你可以添加将一个字符串显示到LCD上的处理过程。 我在串口打印输出的结果见附图。 仅供测试!!! void display_format(float fvalue) { INT8U val_buf[20]; INT8U i;
if(fvalue>=1)//W { sprintf(val_buf,"Pi%12.9fW",fvalue); } else { if(fvalue>=0.001)//mW { fvalue*=1000; sprintf(val_buf,"Pi%8.3f mW",fvalue); } else { if (fvalue>=0.000001)//uW {fvalue*=1000000; sprintf(val_buf,"Pi%8.3f uW",fvalue); } else//nW {//fvalue>=0.000000001 fvalue*=1000000000; sprintf(val_buf,"Pi%8.0f nW",fvalue); } } } #ifdef SERIAL_DEBUG SBUF='\n'; Delay_ms(1); for(i=0;i<16;i++) { SBUF=val_buf[i]; Delay_ms(1); } #endif }

computer00 发布于 2007-5-24 21:05:00 事实上,楼主要的只是六位精度而已。你可以写一个转换为6位结果的子函数,然后按照 测试结果的范围,放大适当的倍数来显示。
void display(float v) { tmp = v * 1000;//取小数点后3位
if(value<0) //如果是负数则取相反数,并设置‘-’号,否则显示空格 { tmp*=-1; serial_buff[0]='-'; //负号在你字库中的位置,下面的空格同样 } else { serial_buff[0]=' '; //or '+' } serial_buff[7]=tmp%10; tmp/=10; serial_buff[6]=tmp%10; tmp/=10; serial_buff[5]=tmp%10; tmp/=10; serial_buff[4]='.'; //小数点在你字库中的位置 serial_buff[3]=tmp%10; tmp/=10; serial_buff[2]=tmp%10; tmp/=10; serial_buff[1]=tmp%10; if(serial_buff[1]==0) { serial_buff[1]=' '; if(serial_buff[2]==0) { serial_buff[2]=' '; } } draw(serial_buff); }
main() { if(result>=1) { display(result); draw(" W"); } else if(result>=0.001) { display(result*1000); draw("mW"); } else if(result>=1e-6) { display(result*1e6); draw("uW"); } }
infree 发布于 2007-5-25 8:31:00 打印W级的数据应改为:sprintf(val_buf,"Pi%6.3f W",fvalue); 数据和W之间留下6个空格。
另:看题目中的要求,应该是不会有负数的,所以也不必考虑符号问题吧!
xzhenggen 发布于 2007-5-27 8:12:00 感谢computer00(电脑圈圈)鼎力的帮助,及各位大侠热心帮助。
xzhenggen 发布于 2007-5-27 16:34:00 是不是就是 tt=v*AD_Loop_PickVol_PER;//AD采样数值
xzhenggen 发布于 2007-5-28 11:24:00 我现在用你们提供的子函数可以达到我的显示要求了,但是还想再请电脑圈圈帮我完成最后一步。显示nW级时,只显示前面有效的两,三位或者一位有效数。我指的有效数是指小数点前面为零消掉,同时小数点也消掉。只显示nW级三位有效数,同理前面为零也消掉。多谢了!!! 修改电脑圈圈的子程序如下:简洁明朗,优化代码,实实在在用得舒服,顺畅。 void display_Temp() { unsigned char row, count; unsigned int tmp; int v; v=getTmpValue(); tmp =v; if(v<0) { tmp*=-1; serial_buff_T[0]='-'; } else { serial_buff_T[0]='+';//num[12] } for(count=1;count<6;count++) { if(tmp !=0) { serial_buff_T[6-count]=tmp%10; tmp/=10; } else { serial_buff_T[6-count]=0; } } draw_bmp(0,0,8,ELAPHT[8]);// 显示"T" draw_bmp(8,0,8,num[15]);//显示":" for(count = 1; count != 6; count++) { draw_bmp(56+row*8,0,8,num[serial_buff_T][count]]);//显示读数 row++; if(serial_buff_T[1]==0) { draw_bmp(56,0,8,num[12]);//显示" " if(serial_buff_T[2]==0) { draw_bmp(64,0,8,num[12]);//显示" " } } if(count == 3)//定位小数位 { draw_bmp(56+row*8,0,8,num[10]);//设置小数点 row++; } } if(serial_buff_T[0]=='+') { draw_bmp(40,0,8,num[13]);//显示"+" } else if(serial_buff_T[0]=='-') { draw_bmp(40,0,8,num[14]);//显示"-" } row=0; draw_bmp(112,0,8,num[11]);//显示"℃" } void display_Pi() { unsigned char line, cout; unsigned long stmp; unsigned int vt; float pow,plt; vt=read7896(); pow=vt*AD_Loop_PickVol_PER;//AD采集数值 if(pow>=1) { plt=pow; draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=0.001) { plt=pow*1000; draw_bmp(104,1,8,ELAPHT[11]);//显示"m" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=1e-6) { plt=pow*1e6; draw_bmp(104,1,8,ELAPHT[10]);//显示"u" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } stmp = plt * 1000;//取小数点后3位 for(cout=1;cout<7;cout++) { if(stmp!=0) { serial_buff[7-cout]=stmp%10;//显示读数 stmp/=10; } else { serial_buff[7-cout]=0; } } for(cout = 1; cout <7; cout++) { draw_bmp(40+row1*8,1,8,num[serial_buff][cout]]);//显示读数 line++; if(serial_buff[1]==0) { draw_bmp(40,1,8,num[12]);//显示" " if(serial_buff[2]==0) { draw_bmp(48,1,8,num[12]);//显示" " } } if(count1 == 3)//定位小数位 { draw_bmp(40+line*8,1,8,num[10]);//设置小数点 line++; } } line=0; draw_bmp(0,1,8,ELAPHT[13]);//显示"Pi" }
computer00 发布于 2007-5-29 3:53:00 你应该将数据全部写到一个数组里面,然后用一个函数用个for语句全部一次显示.
//将值转化为串并保存在serial_buff中 void change(unsigend long temp) { unsigend char i; serial_buffer[4]=10; //小数点 for(i=1;i<8;i++) { if(i==4)continue; //跳过小数点的位置 if(temp!=0) { serial_buff[8-i]=temp%10; temp/=10; } else { serial_buff[8-i]=0; } }
if(serial_buff[1]==0) { serial_buff[1]=12; //空格 if(serial_buff[2]==0) { serial_buff[2]=12; //空格 } } } //////////////////////////////////////////////////////////////
void display_Pi() { unsigned int vt; float pow; unsigned char i;
vt=read7896(); pow=vt*AD_Loop_PickVol_PER;//AD采集数值 if(pow>=1) { change(pow*1e3); draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=1e-3) { change(pow*1e6); draw_bmp(104,1,8,ELAPHT[11]);//显示"m" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=1e-6) { change(pow*1e9); //将前面的3位结果放到后面 serial_buff[7]=serial_buff[3]; serial_buff[6]=serial_buff[2]; serial_buff[5]=serial_buff[1]; //前面4位改为空格 for(i=1;i<5;i++)serial_buff[i]=12; draw_bmp(104,1,8,ELAPHT[10]);//显示"u" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" }
//显示读数 for(i = 1; i <8; i++) { draw_bmp(40+i*8,1,8,num[serial_buff][i]]); } //??? line=0; draw_bmp(0,1,8,ELAPHT[13]);//显示"Pi" }
xzhenggen 发布于 2007-5-29 12:11:00
但会出现以下问题: 前面两位数值会被零不断地覆盖,后面的三位数值即serial_buff[7],serial_buff[6],serial_buff[5],有时会被serial_buff[3],serial_buff[2],serial_buff[1]所覆盖.数值覆盖是不断循环的,而且读数好像都有问题. 我在主函数里面是循环调用子程序的. main() { ...
while(1) { display_Pi(); } } 我现在有点纳闷的是为啥??加入 void change(unsigend long temp)函数,读AD数值有问题.
xzhenggen 发布于 2007-5-29 13:30:00 。。。。。。。。
void change(unsigned long temp) { unsigned char i; serial_buff[4]=10; for(i=1;i<8;i++) { if(i==4)continue; if(temp!=0) { serial_buff[8-i]=temp%10; temp/=10; } else { serial_buff[8-i]=0; } } }
void display_Pi() { unsigned int vt; float pow; unsigned char i; vt=read7896(); pow=vt*AD_Loop_PickVol_PER;//AD采集数值 if(pow>=1) { change(pow*1e3); draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=1e-3) { change(pow*1e6); draw_bmp(104,1,8,ELAPHT[11]);//显示"m" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=1e-6) { change(pow*1e9); serial_buff[7]=serial_buff[3]; serial_buff[6]=serial_buff[2]; serial_buff[5]=serial_buff[1]; for(i=1;i<5;i++)draw_bmp(40+i*8,1,8,num[12]);//显示" " draw_bmp(104,1,8,ELAPHT[10]);//显示"u" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } draw_bmp(0,1,8,ELAPHT[13]);//显示"Pi" draw_bmp(8,1,8,num[15]);//显示":" for(i=1;i<8;i++) { draw_bmp(40+i*8,1,8,num[serial_buff][i]]);//显示读数} if(serial_buff[1]==0) { draw_bmp(48,1,8,num[12]);//显示" " if(serial_buff[2]==0) { draw_bmp(56,1,8,num[12]);//显示" " } } if(serial_buff[4]==10) { draw_bmp(72,1,8,num[10]);//设置小数点 } } }
void logo(void) { uchar i,j,h; TR0 = 1; lcd_clr(); draw_bmp(0,0,112,welcome_1); draw_bmp(0,1,104,welcome_2); for(i=0;i<10;i++)for(j=0;j;j++)for(h=1;h;h++); lcd_clr(); draw_bmp(0,0,112 ,welcome_3); for(i = 0;i<5;i++)for(j = 1;j;j++)for(h = 1;h;h++); } void main (void) { //uint i; P0 =0xff; P1 =0xff; P2 =0xff; P3 =0xff; delay(255); lcd_init(); lcd_init(); lcd_init(); lcd_clr(); logo(); delay(120); lcd_clr(); //lcd_clr(); //sendChangeCmd(); //TMOD:GATE|C/! T|M1|MO|GATE|C/! T|M1|M0 // 0 0 1 0 0 0 0 1 TMOD = 0x21; TH0 = 0X4C; TL0 = 0x00; //SCON:SM0|SM1|SM2|REN|TB8|RB8|TI|RI // 0 1 0 0 0 0 0 0 ET0 = 1; ES = 1; EA = 1; while(1) { display_Pi(); //display_amp(1); //display_Temp(); //sendChangeCmd(); } }
mybao 发布于 2007-5-29 13:37:00 注意身体啊
computer00 发布于 2007-5-29 15:22:00 if(serial_buff[1]==0) { draw_bmp(48,1,8,num[12]);//显示" " if(serial_buff[2]==0) { draw_bmp(56,1,8,num[12]);//显示" " } } if(serial_buff[4]==10) { draw_bmp(72,1,8,num[10]);//设置小数点 }
?????????????????????????????????????????????????????????????
原本放在change里面不是好好的吗?在change里面处理好了,然后显示的时候, 一下全部显示不就行了?你要显示一个空格,就是num[12],那让serial_buff[1]=12就OK了. 小数点也是同样的道理.
for(i = 1; i <8; i++) { draw_bmp(40+i*8,1,8,num[serial_buff][i]]); }
xzhenggen 发布于 2007-5-30 8:46:00 没仔细看以为电脑圈圈又是提供两个思维方式的子程序。想当然地误改,真是越改越乱。真得感谢21IC平台,使我幸运地认识了computer00(电脑圈圈)这样的好心人,感谢电脑圈圈耐心细致的指点和帮助。自学单片机真的好难啊!!光有恒心和毅力还是不够的,还要有高手贵人的指点和帮助。就像是学武功一样,光有武功秘籍是不够的,还须有高手指点和帮助。幸运地是我第一次单独做项目,就得到了电脑圈圈这样的好心高手帮助,今天收获成功喜悦,心存感激溢于言表。假如没有遇到认识电脑圈圈这样有耐心,细致热心助人的高手,我的项目到目前还是处于摸索状态,停滞不前。不可能这么快走向成功的第一步。前面得到电脑圈圈地帮助很多很多。。。电脑圈圈真得是我的良师益友。。。以下两个子程序加入进去,直接调用就OK了!!。 void change(unsigned long temp) { unsigned char i;
serial_buff[4]=10; //小数点 for(i=1;i<8;i++) { if(i==4)continue; //跳过小数点的位置 if(temp!=0) { serial_buff[8-i]=temp%10; temp/=10; } else { serial_buff[8-i]=0; } }
if(serial_buff[1]==0) { serial_buff[1]=12; //空格 if(serial_buff[2]==0) { serial_buff[2]=12; //空格 } } } //////////////////////////////////////////////////////////////
void display_Pi() { unsigned int vt; float pow; unsigned char i; vt=read7896(); pow=vt*AD_Loop_PickVol_PER;//AD采集数值 if(pow>=1) { change(pow*1e3); draw_bmp(104,1,8,num[12]);//显示" "加入此句,是因为测试时显示mW转W时,有时m没消掉。 draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=1e-3) { change(pow*1e6); draw_bmp(104,1,8,ELAPHT[11]);//显示"m" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } else if(pow>=1e-6) { change(pow*1e9); //将前面的3位结果放到后面 serial_buff[7]=serial_buff[3]; serial_buff[6]=serial_buff[2]; serial_buff[5]=serial_buff[1]; //前面4位改为空格 for(i=1;i<5;i++)serial_buff[i]=12; draw_bmp(104,1,8,ELAPHT[10]);//显示"u" draw_bmp(112,1,8,ELAPHT[12]);//显示"W" } //显示读数 for(i = 1; i <8; i++) { draw_bmp(40+i*8,1,8,num[serial_buff][i]]); } //??? line=0; //此句在我前面的子程序里如果不加入时,小数点会出现三位,数值循环左移。 draw_bmp(0,1,8,ELAPHT[13]);//显示"Pi" }
computer00 发布于 2007-5-30 10:48:00 其实你没必要将数字和字符分开做字库,完全可以把它们做成一个表。就像你那些"-","+","."等,也可以把"u","W"等放到num(或者换个名字)里。然后再使用宏定义,就更方便了。当然,你现在的程序已经可以了,懒得改也无妨了。
#define A_u 20 /*20表示它在数组中的位置,根据你的情况定*/ #define A_m 21 #define A_W 22 //自己决定上面这些值,最好按次序来
//然后就可以把它们放到buff中去处理了
serial_buff[9]=A_W;//显示"W",反正每次都要显示,一次赋值就够了
if(pow>=1) { change(pow*1e3); serial_buff[8]=12;//显示" "加入此句,是因为测试时显示mW转W时,有时m没消掉。 } else if(pow>=1e-3) { change(pow*1e6); serial_buff[8]=A_m;//显示"m" } ................... ................... ...................
//一次将数字和单位都显示出来 for(i = 1; i <10; i++) { draw_bmp(40+i*8,1,8,num[serial_buff][i]]); }
|
| 【关闭】【打印】 |
|
|