在C中使用/不使用浮动分割

Psi*_*Psi 7 c floating-point microchip truncation integer-division

下面是我在C中编写的主要功能(对于PIC18F8722微处理器),试图以unsigned int函数设置的特定频率驱动2个多路复用7段显示get_ADC_value().显示屏还显示当前的多路复用频率.该频率范围设置#define在LAB_Fmin和LAB_Fmax范围内,并且必须get_ADC_value()随着从0增加或减少到255 而缩放.

但是这段代码不起作用,因为我认为有隐式转换intfloatat freq =.

挑战是使用浮点数修复此错误,并仅使用整数类型(int,char...)查找替代方法.

 while (1) {

   unsigned int x, y, z;
   float freq, delay;

    x = get_ADC_value(); 
    y = x & 0b00001111;
    z = (x & 0b11110000) >> 4 ;

    freq = LAB_Fmin + (((LAB_Fmax) - (LAB_Fmin))/ 255)*x ;
    delay = 1/(freq*1000); // convert hZ to ms delay accurately

    LATF = int_to_SSD(y); 
    LATH = 0b11111110; //enable 7seg U1
    for (unsigned int i = 0; i<(delay) ; i++){ 
        Delay10TCYx(250); //1ms delay
    }

    LATF = int_to_SSD(z); 
    LATH = 0b11111101; //enable 7seg U2
    for (unsigned int j = 0; j<(delay) ; j++){
        Delay10TCYx(250); //1ms delay
    }
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*ger 16

C被定义为int使用整数除法来划分s,并且只有当存在浮点时才首先将其他ints "提升" 为floats.请注意,如果将其分配给float- 如果右侧全部为ints,则除法将全部为整数,并且仅在最终赋值时将C转换为int结果float.

所以,用你的线:

freq = LAB_Fmin + (((LAB_Fmax) - (LAB_Fmin))/ 255)*x ;
Run Code Online (Sandbox Code Playgroud)

这一切都取决于什么LAB_FmaxLAB_Fmin是什么.什么freq或者什么都没关系x,因为由于括号迫使分裂成为第一个,所以已经完成了"损害".

如果这些LAB_F变量是ints,那么使用浮点除法的最简单方法是通过使用小数点简单地告诉C你想要通过使常量255成为浮点数而不是整数:( 255.或者255.0不那么微妙).

如果你只想使用整数运算,那么通常的建议是在任何除法之前进行所有乘法运算.当然,这种运行四溢的中间结果的风险-帮助,你可以使用的类型long.将您的LAB_Fx变量定义为long,并最后进行除法:

freq = LAB_Fmin + (((LAB_Fmax) - (LAB_Fmin)) * x / 255);
Run Code Online (Sandbox Code Playgroud)

  • 请注意,在许多系统(大多数32位系统,基于Win64的系统)上,`long`与`int`具有相同的大小. (3认同)

Lun*_*din 10

代码审查:

  • unsigned int x, y, z;避免在嵌入式系统上使用原始整数类型.应始终使用stdint.h中的精确宽度类型,以便准确了解所使用的大小.如果您无权访问stdint.h,请自行键入dede这些类型.

  • float freq, delay;通常应避免在大多数嵌入式系统上使用浮点数.特别是在没有FPU的8位MCU上!这将导致软件定义的浮点数非常慢且占用大量内存.你似乎没有理由在这个程序中使用浮点数,看起来你应该能够用uint16_t或更小的方式编写这个算法,除非你有极高的精度要求.

  • x = get_ADC_value(); 由于您似乎只对8位ADC读取感兴趣,为什么不使用8位类型?

  • 请注意,二进制数字文字不是标准C.

  • ((LAB_Fmax) - (LAB_Fmin))/ 255这看起来很可疑.首先,这些是整数还是浮点数?它们的大小是多少?你的问题的答案取决于那个.通过将文字交换到255.0f您可以强制转换为浮动.但你确定分裂应该是255吗?而不是256?

  • i<(delay).您应该始终避免在循环条件中使用浮点表达式,因为它会使循环不必要地变慢并且可能导致浮点不准确错误.而且,括号没有任何意义.

总的来说,你的程序遭受"草率打字",这意味着程序员没有考虑每个表达式中使用的类型.请注意,文字也有类型.隐式转换可能会导致很多这些表达式在太大的类型上计算,这对PIC来说是个坏消息.我建议阅读"平衡",即通常的算术转换.

这种"邋typing的打字"会让你的程序变得非常臃肿和缓慢,因为没有任何好处.您必须记住,PIC可能是仍然制造的代码效率最低的MCU.为任何8位MCU编写C代码时,应避免使用大于8位的类型.特别是,你应该避免像瘟疫一样的32位整数和浮点数.

您的程序会将所有数据重新调整为可以简化程序员思考的类型.这是一个常见的设计错误 - 相反,您的程序应该使用易于处理器使用的类型.例如,您可以使用计时器滴答作为单位,而不是毫秒.


Mit*_*eat 6

你对整数除法是正确的.改成

freq = LAB_Fmin + (((LAB_Fmax) - (LAB_Fmin)) / 255.0)*x;
                                                  ^^ 
Run Code Online (Sandbox Code Playgroud)

  • 他们最初不在那里! (3认同)
  • 是的,现在他们是,我想提醒你这个事实,所以我评论说:p (3认同)