Baud rate on QE128

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Baud rate on QE128

5,224 Views
akak
Contributor I
Hello,

I'm using a QE128 device and I would like to set the baud rate, using a bean, to 57600 or 115200. However, I noticed it will only let me set these baud rates when I have a certain clock rate set. Could I bypass this by changing the SBR12:smileyfrustrated:BR0 registers?

Assuming I used a fixed clock rate, if I want to change the baud rate during operation, do I change the SBR12:smileyfrustrated:BR0 registers, or is there some other way this is commonly done?

Thanks!


Labels (1)
0 Kudos
Reply
20 Replies

2,143 Views
akak
Contributor I
Whoops, nevermind, found it in the PE help. You have to use the getReg and setReg functions, I think.
0 Kudos
Reply

2,143 Views
akak
Contributor I
That clears up a lot - thank you, Jim!
0 Kudos
Reply

2,143 Views
akak
Contributor I
Thanks for the replies!

How exactly does changing the SBR12:smileyfrustrated:BR0 registers work?

I'm looking at this manual: http://www.freescale.com/files/microcontrollers/doc/ref_manual/MC9S08QE128RM.pdf?fpsp=1

On page 261 they mention baud rate generation: BusClk/ (SBR12:smileyfrustrated:BR0) * 16. So if my bus is currently at 7372800, and I want baud rate of 57600, then I just need SBR12:smileyfrustrated:BR0 to equal 8, because 7372800/(8 * 16) = 57600. Right?

What I get confused about is on page 253. It says that SCIxBDH and SCIxBDL control the prescale divisor for baud rate generation, and to first write to SCIxBDH to buffer the high half and then write to SCIxBDL. What do they mean by buffering the high half? Sorry, I'm kind of new to all of this.

Thanks for your help!

0 Kudos
Reply

2,143 Views
allawtterb
Contributor IV


akak wrote:
What I get confused about is on page 253. It says that SCIxBDH and SCIxBDL control the prescale divisor for baud rate generation, and to first write to SCIxBDH to buffer the high half and then write to SCIxBDL. What do they mean by buffering the high half? Sorry, I'm kind of new to all of this.


The reason for this is described right below the portion you read on page 253.  The values in SCIxBDH:smileyfrustrated:CIxBDL are not used until you write to SCIxBDL.  If you write to SCIxBDL then to SCIxBDH, the value put into SCIxBDH won't be used to update the modulo divide rate for the SCI baud rate generator.
 
Also, in Jim's example he used an unsigned long but it should be an unsigned int.  You might also want to mask the upper nibble of baudrate and bitwise OR it with a masked SCIxBDH  to preserve the status of LBKDIE and RXEDGIE.  
Code:
unsigned int baudrate;baudrate = 8;  SCIxBDH = (SCIxBDH & 0xE0) | ((baudrate >> 8) & 0x1F); // Preserve the bits not associate with the baud rateSCIxBDL = baudrate & 0xff;

If you ever think you might want to enable either of these interrupts you would want to use the above code.   


Message Edited by allawtterb on 2008-01-30 08:04 PM
0 Kudos
Reply

2,143 Views
JimDon
Senior Contributor III
He is right about the hi bits - on HCS12 and 08QG the are unused.
Its long because I calculate bauds rate on the fly.


0 Kudos
Reply

2,143 Views
allawtterb
Contributor IV
I'm curious, do you ever have a case where the baud rate modulo uses more than 16-bits? 
The variable name baudrate in this case is actually misleading as it is the baudrate modulo and not the actual baud rate(which could certainly need more than 16-bits) the value is holding.
0 Kudos
Reply

2,143 Views
JimDon
Senior Contributor III

Ok, wise guy :smileyhappy:.

#define CLK  (12000000L)
void SetBaud( unsigned long baudrate)  // up to 115200, so 16 bit not enough.
{  // For chips with nothing in the upper byte!
    baudrate =  ((CLK)/baudrate)/32L;
    h = baudrate >> 8;
    l = baudrate & 0xff;
}

It might seem weird how I did that, but the term (CLK)/baudrate is the one likely to be truncated due to integer math, so by adding extra places it keeps it more correct, and /32 is just shifting. Perhaps you could live with out it, but I didn't feel like checking all the values.

I suppose I could have created an intermediate value, but why?

BTW: If you go into the PE dialog on the SCI set up bean, and click the "..." button next to the baud rate box, and get on the timing - Baud Rate Dialog you can set the Error Allowed, and he will the generate the baud rate. If you enter in all the baud rates you want in the dialog, he will make a table of them. Also, the % error will be displayed. Also, if you go change the clock he will regenerate the table to match.

In my case I can't change the clock, and it seems that 115200 with an 8.5% error talks to the pc fine.
I'm starting to like PE.





Message Edited by JimDon on 2008-01-30 05:24 PM
0 Kudos
Reply

2,143 Views
allawtterb
Contributor IV
Not trying to nitpick or be a wise-guy at all, the only reason I asked was to point out why I suggested an unsinged int instead of an unsigned long.  The function that you posted above is exactly what I would suggest for the original poster because he mentioned wanting to change baud rates during code operation.  The only benefit I could see for having an intermediate value of an unsigned int would be you wouldn't have to perform a shift on a 32-bit value, which might save some time.
 
If you use standard baud rates then a few extra #defines and let the pre-processor do the work would save quite a bit of time on an 8-bitter.  


Message Edited by allawtterb on 2008-01-30 11:05 PM
0 Kudos
Reply

2,143 Views
JimDon
Senior Contributor III
 allawtterb,
I was just kidding you. Sorry.
Anyway, on a routine like this who cared (with in reason)? You only call it once.
People spend way too much time fretting about how long it takes.
You have to consider the way in which a piece of code is being used before you spend time fretting about how long it takes.

To be sure there is a time to care, and in fact how often a routine is called is a strong indicator of how much time you need to spend on speed.






0 Kudos
Reply

2,143 Views
bigmac
Specialist III
Hello,
 
I seem to recall a previous thread on one of these forums (although I could not find it), that addressed the issue of 16-bit registers, where high byte must be written first.  It was confirmed that these registers may be properly handled by writing a 16-bit value directly to the register, rather than two separate 8-bit values.
 
For example, in assembler the following behaves as required -
   LDHX  #8
   STHX  SCI1BD
 
The CW compiler should also give the correct result for the following code -
SCI1BD = 8;
 
I don't consider a run-time calculation for the baud rate divider value to be a good method.  I would not be concerned about the number of cycle, but the number of bytes of flash wasted by the calculations.  Even if multiple rates are required, for the majority of instances they will conform with standard rates, and are best handled as a look-up table of divisor values IMHO.  Perhaps something like the following code would work -
 
#define  BUSCLK  12000000L
 
#define  SCICLK  BUSCLK/16
#define  DIV1152 SCICLK/115200
#define  DIV576  SCICLK/57600
#define  DIV384  SCICLK/38400
#define  DIV192  SCICLK/19200
 
#define  B1152   0  /* baudndx values */
#define  B576    1
#define  B384    2
#define  B192    3
 
const word baudtab[4] = {DIV1152, DIV576, DIV384, DIV192};
 
void setbaud1( byte baudndx)
{
   word temp;
 
   temp = SCI1BD & 0xC000;
   SCI1BD = baudtab[baudndx] | temp;
}

JimDon wrote:
 
In my case I can't change the clock, and it seems that 115200 with an 8.5% error talks to the pc fine

 
This amount of error is about twice the maximum allowable baud rate error for the SCI module (assuming the PCs baud rate setting has zero error).  It is possible that this amount of error may seem to give correct operation, due to the re-synchronisation process within the receive part of the SCI module.  Any timing errors are corrected at each data transition, and will prevent errors occurring provided the number of sequential 0's or 1's is limited.  You may find that errors start to occur for received characters containing four or more successive 0's or 1's.
 
Regards,
Mac
 
0 Kudos
Reply

2,143 Views
bigmac
Specialist III
Hello again, I have exceeded the edit period for my previous post ...
 
It occurred to me, that with the baud rate calculations previously presented, any remainder associated with the integer division process will be truncated, resulting in an actual baud rate that will always equal, or exceed the nominal baud rate.  The error will often be a lower value if a rounding process is used within the calculation, so that the baud rate error may range both sides of the nominal baud rate.
 
My previous macros might be modified, thus -
 
#define  SCICLK  BUSCLK/16
#define  DIV1152 (SCICLK+57600)/115200
#define  DIV576  (SCICLK+28800)/57600
#define  DIV384  (SCICLK+19200)/38400
#define  DIV192  (SCICLK+9600)/19200
 
It should also be possible to test (at compile time) whether the the highest baud rate will be sufficiently accurate, for the chosen bus frequency.  If the highes baud rate is within tolerance, any lower rates that are an even sub-multiple of the highest rate, should have lower error.  Perhaps something similar to the following untested code for inclusion within the same header file as the above macros -
 
#if    ((DIV1152*115200L-SCICLK)*100>SCICLK*4)  // +4 percent error test
#error "Invalid bus frequency for 115200 baud"
#endif
#if    ((SCICLK-DIV1152*115200L)*100>SCICLK*4)  // -4 percent error test
#error "Invalid bus frequency for 115200 baud"
#endif
 
Regards,
Mac
 
0 Kudos
Reply

2,143 Views
JimDon
Senior Contributor III
It occurred to me, that with the baud rate calculations previously presented, any remainder associated with the integer division process will be truncated, resulting in an actual baud rate that will always equal, or exceed the nominal baud rate.

This is simply not correct in the case of the calculation I presented. The /32 after the divsion prevents just that. I have tested it and it generates the exactly correct values.  I simply ask that before you delcare this to be a fact, you inspect the equation and submit it to a fair test. In the context presented, it is correct.

As for the 8.5% error I agree that it certainly does not sound right. It is a demo for a USB serial and I will have to invesigate to see if this is correct (which is why I said seems). I had thought that the 12 Mhz xtal was for USB timing - also if you have a 12 Mhz xtal you can not us the FLL, so either it is running at 12 Mhz or they are running of the internal clock.

Note I do not ask the compiler to do any math.

#define CLK  (12000000L)
unsigned long baudrate = 600;

baudrate =  ((CLK)/baudrate)/32L;





Message Edited by JimDon on 2008-01-31 08:52 AM
0 Kudos
Reply

2,143 Views
bigmac
Specialist III
Hello Jim,
 
Firstly, if your CLK parameter is meant to represent the bus frequency, I would question whether the final divisor should be 16, rather than 32.  For the purpose of the following discussion, I will assume a value of 16.
 
Of course your calculation method will provide the correct division ratio when there is an integral relationship between the bus frequency and the baud rate.  The rounding process is intended to compensate, when this relationship is non-integral, so the calculated division ratio provides the closest baud rate to the nominal value.  The rounding process is most important for very high baud rates, and of lesser importance for lower baud rates where the baud rate divisor is a much larger value.
 
Consider the following example, where the required baud rate is 115200 bits per second, and a division ratio of 8 is used.  To provide the exact baud rate, this would require a bus frequency of 14.7456 MHz.  Assuming the actual baud rate should remain within a tolerance of +/- 4 percent, this would give an allowable range for the bus frequency of 14.156 to 15.335 MHz, for the particular division ratio.
 
Plugging any frequency, within this range, into the formula for calculating the required baud rate divisor, should produce a value of 8.  This is not the case with your calculation using integer division.  For any bus frequency less than the nominal frequency, for example 14.745 MHz, the result of the calculation would be the inappropriate value of 7.  The rounding process previously considered takes into account the truncation of the remainder of the division process, and should produce the correct result.
 
Regards,
Mac
 


Message Edited by bigmac on 2008-02-01 02:28 PM
0 Kudos
Reply

2,143 Views
JimDon
Senior Contributor III
I dont' know where you got 8 from.
Since you started with the clock frequency, not the bus clock you SHOULD be dividing by 32.

14.7456 MHz is a "magic" oscillator frequency that makes all standard baud rate come out exact. I actually have 4 of them in my parts drawer from the good old days, when systems were very intolerant of such errors. (sparkfun has them for 1.50).


Well, in any case you meant  4, but the point is well taken. If your clock frequency goes out to more that 3 significant digits the biased integer divsion will not work. Of course don't go out of your mind worrying about this, as most clock frequencies are fine, but his magic value does give 0% error. However, if you are designing a USB to serial converter, you should go with this magic value.


Code:
For 14.7456 ONLY
#define 115200baud         0    #define 57600baud          1    #define 38400baud          2    #define 19200baud          3    #define 14400baud          4    #define 9600baud           5    #define 4800baud           6    #define 2400baud           7    #define 1200baud           8    #define 600baud            9   

static const  byte BaudH[10] = {0,0,0,0,0,0,0,0,1,3};
static const  byte BaudL[10] = {4,8,12,24,32,48,96,192,128,0};

void SetBaud(byte b)
{
 SCIxBDH = BaudH[b]; 
 SCIxBDL = BaudL[b];
}







0 Kudos
Reply

2,143 Views
bigmac
Specialist III
Hello,
 
I will attempt to summarise the the requirements to achieve a standard baud rate of 115200 with the QE128.
 
Using FBE clock mode will require a crystal close to a "magic" frequency.  Possible frequencies are 14.7456MHz and 11.0992MHz.  There are also two other lower frequencies, but these are impractical because the resulting bus frequency will be generally too low (fbus = fxtal/2).
 
Using FEE clock mode, would typically use a 32.768kHz crystal.  There appears to be four configurations of FLL setup that would provide a sufficiently accurate baud rate, for this frequency.  These configurations are included within Table 11.7 of the Reference Manual.
 
FLL factor:  DCO freq:  Bus clock:  Baud div.  Baud error:
  1024       33.5544    16.7772        9       +1.1 %
  1216       39.8459    19.9230       11       -1.7 %
  1536       50.3316    25.1668       14       -2.5 %
  1824       59.7688    14.9422        8       +1.3 %
 
The relationship between DCO frequency and the bus clock is controlled by the BDIV setting.  The third alternative above produces the maximum allowable bus frequency.
 
Regards,
Mac
 
0 Kudos
Reply

2,143 Views
JimDon
Senior Contributor III
Of course, as accurate as possible given the clock and desired baud rate.

As has been pointed out, with a given clock the closest value for the register may not give a closed enough baud rate.

0 Kudos
Reply

2,143 Views
akak
Contributor I
Thanks for your help. I'm kind of unsure how to actually write to the register, though. From what I understand usually you have an include file like mcxxxqe128.h that defines all the registers for you, but I'm using Processor Expert and it seems it already defined things (so I can't use that .h file). Is there supposed to be some special way to write to registers using PE? Thanks for bearing with me.
0 Kudos
Reply

2,143 Views
JimDon
Senior Contributor III
Code:
unsigned long baudrate;SCIxBDH = baudrate >> 8;SCIxBDL = baudrate & 0xff;
OR to load 8
SCIxBDH = 0;
SCIxBDL = 8;

 

0 Kudos
Reply

2,143 Views
Ake
Contributor II
Hello,
If you want to change the baudrate to the SCI, you can either change the SBR12:smileyfrustrated:BR0 bits in the SCIxBD register, or you can change the fBUS or you can change both the register and the bus frequency.
 
Well the two later suggestions were not something I would do, which makes the first suggestion what I would recommend.
 
But I have not tried to set the baud rate under PE.
Perhaps someone else has tried it?
 
Regards,
Ake
0 Kudos
Reply

2,143 Views
JimDon
Senior Contributor III
Sure you can. Just load the registers yourself.
However, the baud rate will still be inaccurate to some amount, and may or may not work reliably.
Thats because certain clock rates just don't divide down to the correct  frequency for a given baud rate.
Time was we would use a certain oscillator with an odd value just for that reason.


0 Kudos
Reply