热门关键词: usb人体输入设备 田岛工具 陶瓷元件生产设备 usb人体学输入设备 人造石设备 金彬标准件模具 材料检测设备
  IC库存(8958万) PDF资料(329万) IC价格 IC求购 资讯 技术资料
电子元器件搜索:
维库电子市场网是知名的电子元器件交易网站,为电子生产企业提供IC库存和技术资料查询服务。
相关专题
恳请电脑圈圈,程序匠人,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]]);
      }


关闭】【打印
友情链接:
© 2007 电子设备网 网站地图