char byte_to_ascii(char value_to_convert, volatile char *converted_value) {

 if (value_to_convert < 10) {
  return (value_to_convert + 48);
 } else {
  char a = value_to_convert / 10;
  double x = fmod((double)value_to_convert, 10.0);
  char b = (char)x;
  a = a + 48;
  b = b + 48;
  *converted_value = a;
  *(converted_value+1) = b;
  return 0;
 }
}

此功能的目的是通过99采取的0 unsigned char值,并返回它要么是ascii的等效的情况下,它是0-9或操纵可以从调用代码下面的函数被参考的小型全局字符数组完成。

我问这个问题,因为从相同的供应商两个编译器解释以不同的方式此代码。

此代码被写成一个方法来解析通过RS485发送转换成可以容易地被传递到一个发送-LCD-串的函数字符串地址字节。

此代码为PIC18架构(8位UC)写入。

问题是,一个特定的编译器的自由/评估版本生成完美的汇编代码而遭受性能损失的作品,但付出和所谓优越的编译器在能够参考所有的地址的费用更有效地生成代码用我的字节数组来驱动我的LCD显示器上的图形。

我知道我把大量的泥浆水中使用专有的编译器比典型建筑少,但我希望有人在那里有一些建议。

感谢。

有帮助吗?

解决方案

和取模的整数除法可以很非常昂贵。我不知道你的具体的架构,但我猜它是昂贵的那里。

如果你需要同时,除法和模数,做他们中的一个,并得到通过乘法/差值另外一个。

q =p/10;
r = p - q*10;

其他提示

我肯定会避免使用一个PIC浮点东西。而且我也没有 - 尝试易用的任何分歧。有多少次你看到发送非ASCII字符的LCD?你可以将其保存到LCD的存储器中,然后通过它的内存位置打电话了吗?

下面就是由10分的样子在我的代码,注意它需要完成17个周期。想想有多长,将采取,并确保有没有别的等待这一点。

61:                         q = d2 / 10;
 01520  90482E     mov.b [0x001c+10],0x0000
 01522  FB8000     ze 0x0000,0x0000
 01524  2000A2     mov.w #0xa,0x0004
 01526  090011     repeat #17
 01528  D88002     div.uw 0x0000,0x0004
 0152A  984F00     mov.b 0x0000,[0x001c+8]

如果你在你的代码中的浮点东西,看在程序存储器你编译后,象征选项卡上(这样你就可以真正阅读的话),并查找浮点代码,将需要包括在内。你会发现它接近顶部(取决于您的代码),在_reset标签后不久(ISH)。

矿开始于001BC与_ floatsisf行号223和存储器地址,经过几个额外的标签(_fpack,_divsf3等)继续,并在535和存储器地址0042C在_funpack结束,最后一行。如果你能处理(42C-1BC = 0x270 =)624个字节失去了程序空间,巨大的,但一些芯片刚才的空间2K这不是一个选项。

代替浮点的,如果可能的话,尽量使用定点算术,以2为底数

至于不能够参考所有的字节数组中的液晶显示器,让你检查,以确保你不会试图发送一个空(这是一个很好的地址),但它获得的由代码检查停止ASCII字符串的结束? (它的前发生在我身上)。

我可能写为:

char byte_to_ascii(char value_to_convert, volatile char *converted_value)
{
 if (value_to_convert < 10) {
  return value_to_convert + '0';
 } else {
  converted_value[0] = (value_to_convert / 10) + '0';
  converted_value[1] = (value_to_convert % 10) + '0';
  return 0;
 }
}

是不是穷人的形式转换为浮动,通话FMOD,并转换为整数,而不是仅仅使用%运算符?我会说是的。还有更易读的方式来减缓程序,以满足一些时序要求,例如在睡循环。无论是什么编译器或者什么扭捏的汇编代码或任何其他,这是一个非常模糊的方式来控制你的程序的执行速度,我把它称为一种欠佳。

如果完善的汇编代码意味着它可以正确的,但它比转换更慢于浮点和背部,然后用整数和睡在一个for循环。

对于不完善的汇编代码,有什么问题呢? “在能够参考我所有的字节数组的地址为代价”?它看起来像类型char *在你的代码工作,因此它似乎可以解决你所有的字节数组C标准说你能方式。有什么问题?

坦率地说,我会说是的..

如果你想 B'/ STRONG>是余数,或者使用MOD或滚你自己:

char a = value_to_convert / 10;
char b = value_to_convert - (10 * a);

转换到/从彩车是永远做事情的方式,除非你的价值观真的是浮动。

此外,我会强烈建议坚持中明确提到你的数据类型为“签字”或“签名”的约定,并留下了,而实际上的裸“符” 的角色(字符串的一部分)。你逝去的原始数据,这点我觉得应该是一个无符号的字符(假设当然,在源的的签名!)。人们很容易忘记,如果事情应该符号/无符号,并用裸露的字符,你会得到各种翻车错误。

大多数8位万分之一永远采取乘法(并且比为永远除法更多),所以尝试和最小化这些。

希望这有助于..

代码似乎是在做两个非常不同的事情,这取决于它给了在范围0-9或10-99的数。出于这个原因,我要说的是,这个功能是用拙劣的形式:我会分裂的功能分为两个功能

由于我们通过10这里讨论师..

这是我的服用。它只是简单的操作和甚至不需要宽寄存器。

unsigned char divide_by_10 (unsigned char value)
{
  unsigned char q;
  q = (value>>1) + (value>>2);
  q += (q>>4);
  q >>= 3;
  value -= (q<<3)+q+q;
  return q+((value+6)>>4);
}

干杯,   尼尔斯

这是典型的优化做不必要的一样的东西,不时如果在内部闲逛。

是您converted_value全球价值或者以这样的方式,否则分配编译器知道不要去动它?

PIC的不喜欢做指针运算。

作为视窗程序员所指出的,使用MOD运算符(见下文)。

char byte_to_ascii(char value_to_convert, volatile char *converted_value) {

 if (value_to_convert < 10) {
  return (value_to_convert + 48);
 } else {
  char a = value_to_convert / 10;  
  char b = value_TO_convert%10;
  a = a + 48;
  b = b + 48;
  *converted_value = a;
  *(converted_value+1) = b;
  return 0;
 }
}

是的,我相信你的功能:点击 char byte_to_ascii(char value_to_convert, volatile char *converted_value) {结果

if (value_to_convert < 10) {
    return (value_to_convert + 48);
} else {

char a = value_to_convert / 10;
double x = fmod((double)value_to_convert, 10.0);
char b = (char)x;
a = a + 48;
b = b + 48;
*converted_value = a;
*(converted_value+1) = b;
return 0;

}
}
is in poor form:

Don't use decimal numbers for ASCII chars, use the character, i.e. '@' instead of 0x40.
There is no need for using the fmode function.

Here is my example:
// Assuming 8-bit octet
char value;
char largeValue;
value = value_to_convert / 100;
value += '0';
converted_value[0] = value;
largeValue = value_to_convert - value * 100;
value = largeValue / 10; value += '0';
converted_value[1] = value;
largeValue = largeValue - value * 10; value += '0';
converted_value[2] = value;
converted_value[3] = '\0'; // Null terminator.

Since there are only 3 digits, I decided to unroll the loop. There are no branches to interrupt the prefetching of instructions. No floating point exceptions, just integer arithmetic.

If you leading spaces instead of zeros, you can try this:
value = (value == 0) ? ' ' : value + '0';
结果

只要是一个nitwitt,但是从同样的功能的多个return语句可以被认为是不好的形式(MISRA)。

此外,一些讨论以上是对permature优化的极限。有些任务必须由编译器。然而,在这样一个简约嵌入式环境,这些技巧可能是有效的还是

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top