开发者

What is the fastest way to do division in C for 8bit MCUs?

开发者 https://www.devze.com 2022-12-28 13:40 出处:网络
I am working on the firmware for a device that uses an 8bit mcu (8051 architecture). I am using SDCC (Small Device C Compiler). I have a function that I use to set the speed of a stepper motor that my

I am working on the firmware for a device that uses an 8bit mcu (8051 architecture). I am using SDCC (Small Device C Compiler). I have a function that I use to set the speed of a stepper motor that my circuit is driving. The sp开发者_开发知识库eed is set by loading a desired value into the reload register for a timer. I have a variable, MotorSpeed that is in the range of 0 to 1200 which represents pulses per second to the motor. My function to convert MotorSpeed to the correct 16bit reload value is shown below. I know that float point operations are pretty slow and I am wondering if there is a faster way of doing this...

void SetSpeed()
{
    float t = MotorSpeed;
    unsigned int j = 0;
    t = 1/t ;
    t = t / 0.000001;
    j = MaxInt - t;
    TMR3RL = j;      // Set reload register for desired freq
    return;
}


If I understand correctly what's going on You want to calculate the expression

MaxInt - 1000000/MotorSpeed

where MotorSpeed is a number form 0 to 1200 and represents number of pulses per second.

If Your compiler supports floating point arithmetic it must support integer division. Why don't You try that. If the speed is > 15 There is no problem, but for speeds in the range 0 to 15 the result is negative. It means that it's simply impossible to generate pulses with lower frequency than 16 Hz, if the counter is 16 bit wide and it's incremented at the rate of 1MHz. Do you have an additional prescaler that allows to reduce the frequency of increments? (I don't know 8051).


The classic way is to use fixed-point, by scaling up before dividing, and doing it all as integer.

j = (MotorSpeed * 65536) / 1200;

This still requires actual division (by 1200), but at least it's all-integer. The scaling should be very quick, since it's possible to implement using a shift.


unwind is right about fixed point.

I wrote a fixed library for SDCC on the 8051 that uses 32 bit numbers. Simply determine what precision you want in your fractions and apply the appropriate shift to the values.

For example, my fixed point library uses 2 bytes for fractional space.

So each number x is represented as x * 65535. You can use normal signed long addition and subraction.

For multiplication and division you need to adjust for the offset. Simple multiplication would give (x * 65535) * (y * 65535). Just break up and factor out the offset for each part of the numbers and add them all up.

Just break up your fixed point number into bytes or 16 bit ints and work on them in pieces.

Take a look at this article on embedded.com.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号