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

Thread: Generating serial line break for LIN-bus

  1. #1

    Generating serial line break for LIN-bus

    I'm trying to write a LIN-bus driver for Teensy 3.2

    A LIN-bus frame consist of break, synch(0x55), Ident, data. I'm trying to do this in software and found when I configure the uart there seems to be a delay of 1mS before the synch(0x55) is sent out.

    Code:
    int led = 13;
    int lin_cs = 23;
    int tx_pin = 1;
    int test_pin = 5;
    
    void setup() {
     
      pinMode(lin_cs, OUTPUT); 
      pinMode(test_pin, OUTPUT); 
      digitalWrite(lin_cs, HIGH);   
      pinMode(led, OUTPUT);   
    
      digitalWrite(test_pin, HIGH);
      pinMode(tx_pin, OUTPUT);    
      digitalWrite(tx_pin, HIGH); 
      delay(100);
       
      
      digitalWrite(tx_pin, LOW);  // Break
      delayMicroseconds(1024);    // Break dealy
      digitalWrite(tx_pin, HIGH); 
      
      digitalWrite(test_pin, LOW); 
      Serial1.begin(9600);
      digitalWrite(test_pin, HIGH); 
      
      Serial1.write(0x55); // Synch
      
      Serial1.write(0x23); // Ident
      Serial1.write(0x41);  // Data
    }
    
    void loop() {
    
      digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
      delay(500); 
      digitalWrite(led, HIGH);
      delay(100); 
    }
    Click image for larger version. 

Name:	scope_11.png 
Views:	11 
Size:	27.3 KB 
ID:	15407

    Any idea why there is a delay of 1mS before the synch byte is sent out and how to remove that ?

    The green trace is the test_pin to show where is the code is.

    I also tried this on an Uno board there is no delay before the synch byte is sent out.

  2. #2
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    2,882
    did you try a putting few ms delay after serial1.begin() before sending the byte? or perhaps try a pullup/pulldown on the TX pin when reconfiguring the peripheral for serial mode?

    you could also try setting serial mode first, then changing the core pin manually via registers, write it, then switch it back?

  3. #3
    Quote Originally Posted by tonton81 View Post
    did you try a putting few ms delay after serial1.begin() before sending the byte? or perhaps try a pullup/pulldown on the TX pin when reconfiguring the peripheral for serial mode?

    you could also try setting serial mode first, then changing the core pin manually via registers, write it, then switch it back?
    I don't want any delay before the synch byte (0x55).
    I might try and set it serial mode first. Change the pin, output the break then switch it back like you said but this might not make it portable across T3.2 and T3.6 but I will give it a go.

    I think it might be something to do with the buffer/FIFO/interrupt. When I use Serial1.write(0x55) then Serial1.write(0x23), I can't see the output straight away. Maybe it is queued. I did tried and changed the serial1.c interrupt priority from 64 to 32 but it didn't make any difference.

    Code:
    int led = 13;
    int lin_cs = 23;
    int tx_pin = 1;
    int test_pin = 5;
    
    void setup() {
     
      pinMode(lin_cs, OUTPUT); 
      pinMode(test_pin, OUTPUT); 
      digitalWrite(lin_cs, HIGH);   
      pinMode(led, OUTPUT);   
    
      digitalWrite(test_pin, HIGH);
      pinMode(tx_pin, OUTPUT);    
      digitalWrite(tx_pin, HIGH); 
      delay(10);
       
      
      digitalWrite(tx_pin, LOW);  // Break low
      delayMicroseconds(1024);    // Break delay
      digitalWrite(tx_pin, HIGH); // Break high
    
      Serial1.begin(9600);        // Configure serial
     
      digitalWrite(test_pin, LOW);  // Green trace on scope
      digitalWrite(test_pin, HIGH); 
      
      Serial1.write(0x55); // Synch
      
      delayMicroseconds(40);        // Delay to let it show up on scope
      digitalWrite(test_pin, LOW);   // Green trace on scope
      digitalWrite(test_pin, HIGH);
      
      Serial1.write(0x23); // Ident
      Serial1.write(0x41);  // Data
    }
    
    void loop() {
    
      digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
      delay(500); 
      digitalWrite(led, HIGH);
      delay(100); 
    }
    Click image for larger version. 

Name:	scope_14.png 
Views:	3 
Size:	20.2 KB 
ID:	15422

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,369
    There was a recent post IIRC and on serial .begin() there is a bit of overhead before the work is done? Doing that in advance will get it out of the way.

    As far as delay on .write see Serial.send_now() and Transmit Buffering

    Does that change the picture?

  5. #5
    I can't set the Serial1.begin(9600) in advance because I need to set the tx pin low to sent out the break. Unless I manually set the tx pin low via registers but I don't really want to mess about with registers.

    Just tried the Serial.send_now() but it didn't make any difference.

    Code:
    Serial1.begin(9600);        // Configure serial
      Serial.send_now();
      
      digitalWrite(test_pin, LOW);
      digitalWrite(test_pin, HIGH); 
      
      Serial1.write(0x55); // Synch
      Serial.send_now();
     
      delayMicroseconds(40);        // Delay to let it show up on scope
      digitalWrite(test_pin, LOW); 
      digitalWrite(test_pin, HIGH);
     
      Serial1.write(0x23); // Ident
      Serial.send_now();
      Serial1.write(0x41);  // Data
    I think Serial.send_now() might be just for the USB serial but I'm using Serial1.

    Tried Serial1.send_now() but it won't compile with an error of "'class HardwareSerial' has no member named 'send_now'".

  6. #6
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,369
    Opps - that was an easy test/fail.

    What happens if you call this after .begin()? :: void serial_set_transmit_pin(uint8_t pin) [from: ...\cores\teensy3\serial1.c]

    It does a set output, writes low, then sets for Serial usage - may be too fast of a low assuming it then goes high.

    Maybe in combination with what is posted it will restore the pin without a full .begin() call?

  7. #7
    I think it is working now.

    After the Serial1.begin(9600) I sent out the break then reconfigure using serial_set_transmit_pin(tx_pin) but I have to add serial_set_tx(tx_pin,1).

    Code:
    int led = 13;
    int lin_cs = 23;
    int tx_pin = 1;
    int test_pin = 5;
    
    void setup() {
     
      pinMode(lin_cs, OUTPUT); 
      pinMode(test_pin, OUTPUT); 
      digitalWrite(lin_cs, HIGH);   
      pinMode(led, OUTPUT);   
    
      digitalWrite(test_pin, HIGH);
      pinMode(tx_pin, OUTPUT);    
      digitalWrite(tx_pin, HIGH); 
      delay(10);
       
      
     // digitalWrite(tx_pin, LOW);  // Break low
     // delayMicroseconds(1024);    // Break delay
     // digitalWrite(tx_pin, HIGH); // Break high
    
      Serial1.begin(9600);        // Configure serial
    
      pinMode(tx_pin, OUTPUT);  
      digitalWrite(tx_pin, LOW);  // Break low
      delayMicroseconds(1024);    // Break delay
      digitalWrite(tx_pin, HIGH); // Break high
    
      serial_set_transmit_pin(tx_pin);
      serial_set_tx(tx_pin,1);
     
      digitalWrite(test_pin, LOW);
      digitalWrite(test_pin, HIGH); 
      
      Serial1.write(0x55); // Synch
    
      delayMicroseconds(40);        // Delay to let it show up on scope
      digitalWrite(test_pin, LOW); 
      digitalWrite(test_pin, HIGH);
     
      Serial1.write(0x23); // Ident
      Serial1.write(0x41);  // Data
      
    }
    
    void loop() {
    
      digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
      delay(500); 
      digitalWrite(led, HIGH);
      delay(100); 
    }
    Click image for larger version. 

Name:	scope_15.png 
Views:	3 
Size:	20.8 KB 
ID:	15423

    Thanks for everyone's help.

  8. #8
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    2,882
    for the most part 3.2/3.5/3.6 most if not all of the commands/registers are the same, so portability for most part should be okay if you are writing a library for LIN bus using uart maybe you can add LC support as well as some people do use them

Posting Permissions

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