Usable Baud Rates for Teensy-LC

Status
Not open for further replies.

eyehave

New member
I have make code to check error rate of baud rates in teensy-LC.

Code:
#include <stdio.h>
#include <stdlib.h>

#define __MKL26Z64__	/* teensy-LC */
//#define __MK20DX256__	/* teensy 3.1 & 3.2 */

#if defined(__MKL26Z64__)
#define KINETISL
#define F_CPU 48000000
#define F_PLL 96000000
#define F_BUS 24000000
#elif defined(__MK20DX256__)
#define KINETISK
#define F_CPU 96000000
#define F_PLL 96000000
#define F_BUS 48000000
#endif


#if defined(KINETISK)
#define BAUD2DIV(baud)  (((F_CPU * 2) + ((baud) >> 1)) / (baud))
#define ACTUIAL(count)   (F_CPU / 16 / (count/32))
#elif defined(KINETISL)
#define BAUD2DIV(baud)  (((F_PLL / 2 / 16) + ((baud) >> 1)) / (baud))
#define ACTUIAL(count)   (F_PLL / 2 / 16 / count)
#endif

int main()
{
	int baud[] = {115200, 230400, 250000, 460800, 500000, 921600, 1000000, 2000000, 4608000};
	printf("<F_CPU : %d>\n", F_CPU);
	for(int i=0;i<(sizeof(baud)/sizeof(int));i++){
		int count = BAUD2DIV(baud[i]);
#if defined(KINETISK)
		if (count < 32) count = 32;		
#elif defined(KINETISL)
		if (count == 0) count = 1;
#endif		
		int actual = ACTUIAL(count);

		float err = ((float)(actual - baud[i]) / (float)baud[i]) * (float)100.0;
		printf("baud: %d, count: %d, actual: %d, error: %.2f\n", baud[i], count, actual, err);	
		
	}
	return 0;
}

<output>
<F_CPU : 48000000>
baud: 115200, count: 26, actual: 115384, error: 0.16
baud: 230400, count: 13, actual: 230769, error: 0.16
baud: 250000, count: 12, actual: 250000, error: 0.00
baud: 460800, count: 7, actual: 428571, error: -6.99
baud: 500000, count: 6, actual: 500000, error: 0.00
baud: 921600, count: 3, actual: 1000000, error: 8.51
baud: 1000000, count: 3, actual: 1000000, error: 0.00
baud: 2000000, count: 2, actual: 1500000, error: -25.00
baud: 4608000, count: 1, actual: 3000000, error: -34.90

But, I got difficult result than PJRC site. (https://www.pjrc.com/teensy/td_uart.html)
ex) 230400bps error rate
my code : 0.16%
PJRC site : -6.99%

Is there a problem with my code?
 
Last edited:
Your LC numbers look correct for Serial1 (UART0). You can also verify error by setting Serial1 baud rate and then examining the count in UART0_BDH and UART0_BDL.
Code:
void setup() {
  Serial.begin(9600);
  while (!Serial);
  delay(1000);
  int baud = 230400;
  Serial1.begin(baud);
  Serial.println(UART0_BDH, HEX);
  Serial.println(UART0_BDL);
  int count = (UART0_BDH & 0x1F) << 8 | UART0_BDL;
  int actual = F_PLL / 16 / 2 / count;
  Serial.println(count);
  Serial.println(actual);
  float err = 100.*(actual - baud) / (float)baud;
  Serial.println(err);
}

void loop() {

}
output is
Code:
0
13
13
230769
0.16

or in perl
Code:
#! /usr/bin/perl
$clock = 96000000;
while (<>) {
        $baud = $_ + 0;
        $count = int((($clock / 32) + int($baud / 2)) / $baud);
        $count = 1 if $count < 1;
        $count = 8191 if $count > 8191;
        $actual = int($clock / 32 / ($count)); # Teensy LC
        $error = ($actual - $baud) / $baud;
        $percent = sprintf("%+.2f", $error * 100);
        print "$baud\t$percent%\n";
}
 
Last edited:
I wonder if the table is maybe wrong, or if it is worst case....
That is Serial2 and Serial3 use a different Clock and different formulas depending on clock speed:
Code:
#elif defined(KINETISL)

#if F_CPU <= 2000000
#define BAUD2DIV(baud)  (((F_PLL / 16 ) + ((baud) >> 1)) / (baud))
#elif F_CPU <= 16000000
#define BAUD2DIV(baud)  (((F_PLL / (F_PLL / 1000000)) + ((baud) >> 1)) / (baud))
#else
#define BAUD2DIV(baud)  (((F_PLL / 2 / 16) + ((baud) >> 1)) / (baud))
#endif

#define BAUD2DIV2(baud) (((F_BUS / 16) + ((baud) >> 1)) / (baud))
#define BAUD2DIV3(baud) (((F_BUS / 16) + ((baud) >> 1)) / (baud))
#endif
I have not tried them to see what it does on Serial2 and 3 which use F_BUS instead of F_PLL or also how running at 48mhz versus 24mhz effects this.
 
I wonder if the table is maybe wrong, or if it is worst case....
That is Serial2 and Serial3 use a different Clock and different formulas depending on clock speed:
Yes, the column heading for LC says Serial1-3, so table probably reports worst case. LC Serial2 and Serial3 use F_BUS. Here's perl script for UART1 and UART2 (Serial2 and Serial3)
Code:
#! /usr/bin/perl
$clock = 24000000;
while (<>) {
        $baud = $_ + 0;
        $count = int((($clock / 16) + int($baud / 2)) / $baud);
        $count = 1 if $count < 1;
        $count = 8191 if $count > 8191;
        $actual = int($clock / 16 / ($count)); # Teensy LC
        $error = ($actual - $baud) / $baud;
        $percent = sprintf("%+.2f", $error * 100);
        print "$baud\t$actual\t$percent%\n";
}
230400 214285 -6.99%

Serial2 (UART1) sketch
Code:
void setup() {
  Serial.begin(9600);
  while (!Serial);
  delay(1000);
  int baud = 230400;
  Serial2.begin(baud);
  Serial.println(UART1_BDH, HEX);
  Serial.println(UART1_BDL);
  int count = (UART1_BDH & 0x1F) << 8 | UART1_BDL;
  int actual = F_BUS / 16  / count;
  Serial.println(count);
  Serial.println(actual);
  float err = 100.*(actual - baud) / (float)baud;
  Serial.println(err);
}

void loop() { }
 
Last edited:
Status
Not open for further replies.
Back
Top