Author Topic: Separating Mantissa from Decimal part of a float  (Read 1547 times)

0 Members and 1 Guest are viewing this topic.

Offline noname4me

  • Regular Contributor
  • *
  • Posts: 93
Separating Mantissa from Decimal part of a float
« on: December 25, 2017, 11:32:41 pm »
Hi,

I am writing a function which will work out the contents of the USART1->BRR register when using STM32 microcontrollers.

This register sets up the USART speed, and works in the following manner:

Tx/Rx baud = fCK/(16*USARTDIV)

USARTDIV is programmed into the USARTx->BRR register to set up the speed.

The integer part is programmed into bits 4 to 16, while the decimal part goes into bits 0 to 3.

I would like to write a function that can do the sum above, and work out what goes in each portion and, given the baud rate and fCK, return the value that can be programmed into the BRR register.

I can get the integer part fine, but I don't know how to deal with the decimal part - could anyone please help me understand what I need to do?

I've been experimenting on an online compiler with the following on http://en.cppreference.com/w/c/numeric/math/modf :

Code: [Select]
#include <stdio.h>
#include <math.h>
#include <float.h>
 
int main(void)
{
float fck = 48000000;
float baudrate = 9600;
float temp;
double topout;
float bottom;

temp = (fck/baudrate)/16;
bottom = modf(temp, &topout);

//topout stores the mantissa
//bottom stores the divider
//temp is the original number

printf("temp = %.4f\n bottom = %.4f\n topout = %.5f\n",temp,bottom,topout);
//to extract this and make the brr:

int mantissa;
int divisor;

mantissa = (int)topout;

divisor = ((int)(bottom*10));
divisor = divisor % 10000;

printf("mantissa = %.4d\n divisor = %.4d\n",mantissa,divisor);
}

http://coliru.stacked-crooked.com/view?id=d2fb35446965eb41

Thanks
 

Online rstofer

  • Super Contributor
  • ***
  • Posts: 7517
  • Country: us
Re: Separating Mantissa from Decimal part of a float
« Reply #1 on: December 25, 2017, 11:40:53 pm »
Multiply the fraction by 16, add 0.5 and convert to integer?
 

Offline noname4me

  • Regular Contributor
  • *
  • Posts: 93
Re: Separating Mantissa from Decimal part of a float
« Reply #2 on: December 25, 2017, 11:46:10 pm »
lol :palm: - thanks very much

I forgot about the *16 of the decimal part and was trying to make the decimal part output "5" for a value of 0.5

Your solution works  :-+
 

Offline amyk

  • Super Contributor
  • ***
  • Posts: 6867
Re: Separating Mantissa from Decimal part of a float
« Reply #3 on: December 26, 2017, 05:03:56 pm »
No, do not use floating-point for that... unless you want to eat up a huge chunk of your ROM :palm:
https://www.eevblog.com/forum/microcontrollers/samd11-i2c-driver-alone-consumes-12kb-out-of-16kb-and-facing-rom-overflow-error/

Unless you really need a "continuously variable" baud rate, just calculate the correct register setting for the rate you need and use that.
 

Online rstofer

  • Super Contributor
  • ***
  • Posts: 7517
  • Country: us
Re: Separating Mantissa from Decimal part of a float
« Reply #4 on: December 26, 2017, 05:27:44 pm »
Right!  Normally, you see baud rate constants inside #ifdef <some clock frequency> #endif blocks.  Then the integer and fractional components are defined for each required baud rate using #define.  The actual calculations can be done elsewhere.  Like Excel if a document is worthwhile.  Otherwise just using a calculator.

OTOH, if floating point is required by the project, the libraries will need to be included in any event.
 

Online mikerj

  • Super Contributor
  • ***
  • Posts: 2537
  • Country: gb
Re: Separating Mantissa from Decimal part of a float
« Reply #5 on: December 29, 2017, 09:03:36 pm »
You can simply treat the value in the BRR register as an integer, and scale the resulting frequency value by 2^12.

Baud = 4096*fCK/(16*BRR) = (256*fCK)/BRR

Do the multiplication first to avoid loss of precision, but also check the result of the multiply won't cause an overflow.
 

Offline Jope

  • Regular Contributor
  • *
  • Posts: 76
  • Country: de
Re: Separating Mantissa from Decimal part of a float
« Reply #6 on: December 30, 2017, 03:52:54 pm »
You don't have to worry about that at all - no floats, no separation of bits or anything.
You just need to divide your frequency by the baudrate and that's it:

Code: [Select]
uint32_t fck = 48000000;
uint32_t baudrate = 9600;
uint32_t BRR_value = fck/baudrate;

 

Offline noname4me

  • Regular Contributor
  • *
  • Posts: 93
Re: Separating Mantissa from Decimal part of a float
« Reply #7 on: January 01, 2018, 10:53:48 pm »
Hi

Thanks for the feedback guys - in my final applications I won't be using this function, this is just for me to play around with the USART and understand it better.

This is related to some problems that I am having with the USART, about which I will make another thread (it doesn't work with my initialisation function).

I will make note of the floating point issue for later: reduce them as much as possible.

Thanks
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 5495
  • Country: fr
Re: Separating Mantissa from Decimal part of a float
« Reply #8 on: January 02, 2018, 05:21:58 pm »
As jope has stated, you don't actually need any FP in this case.

And yes, on targets that don't have any FPU, you should learn how to make use of integer computation. Fixed point is one widely used way of manipulating fractional numbers with integers only.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 3286
  • Country: us
Re: Separating Mantissa from Decimal part of a float
« Reply #9 on: January 03, 2018, 02:36:31 am »
Quote
You just need to divide your frequency by the baudrate and that's it:
Code: [Select]
uint32_t BRR_value = fck/baudrate;

There was some flaming discussion about the fractional baud rate generator in the STM32F, and how awful ST's code is, back here:
https://www.eevblog.com/forum/microcontrollers/st's-(stm32cube)-software-ecosystem-is-terrible-how-can-we-fix-it/msg626014/#msg626014
 

Offline llkiwi2006

  • Regular Contributor
  • *
  • Posts: 102
  • Country: nz
Re: Separating Mantissa from Decimal part of a float
« Reply #10 on: January 03, 2018, 03:40:43 am »
libopencm3 has some nice comments regarding this: https://github.com/libopencm3/libopencm3/blob/580a2a4a63cad6ca32ac837cf6d1c64664ce80f3/lib/stm32/common/usart_common_all.c#L63

Quote
Yes it is as simple as that. The reference manual is talking about fractional calculation but it seems to be only marketing babble to sound awesome. It is nothing else but a simple divider to generate the correct baudrate.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 3286
  • Country: us
Re: Separating Mantissa from Decimal part of a float
« Reply #11 on: January 03, 2018, 04:09:23 am »
(alas, not true of all chips with fractional BRG hardware, so you need to watch carefully.  The Atmel SAM chips all seem to put the "Fractional" part of the BRG divisor in the high bits of the actual register.  You can still simplify the math as shown here, but then you have to shift bits or rotate before you can actually do the configuration...  (Sigh.  Why, Atmel, Why?))
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf