Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

Thread: Usable Baud Rates for Teensy-LC

  1. #1
    Junior Member
    Join Date
    Sep 2020
    Posts
    1

    Usable Baud Rates for Teensy-LC

    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 by eyehave; 09-09-2020 at 05:54 AM.

  2. #2
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,593
    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 by manitou; 09-10-2020 at 12:35 PM.

  3. #3
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,868
    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.

  4. #4
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,593
    Quote Originally Posted by KurtE View Post
    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 by manitou; 09-10-2020 at 09:43 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •