Disabling UART on Due?

Ouch, my missunderstanding too i guess :stuck_out_tongue:

Anyway code is not mine, im just modding it to do some other stuff, but that's the part i need to get working.

If you want to see the full project for the code i have posted, you can find it here:

BR

Section 29.2.2 of the SAM3X datasheet and block diagram in section 29.2.3 suggest peripheral clocks can be independently disconnected. So I guess one way to "turn off" an USART would be to disable its clock.

Disclaimer: just thinking out loud, I've just skimmed the datasheet :slight_smile:

Bi0H4z4rD:
Ouch, my missunderstanding too i guess :stuck_out_tongue:

Anyway code is not mine, im just modding it to do some other stuff, but that's the part i need to get working.

If you want to see the full project for the code i have posted, you can find it here:

GitHub - Magister54/opengauge: Automatically exported from code.google.com/p/opengauge

BR

Hey, that's a nice project! Think I've googled you up a couple years ago :stuck_out_tongue:

Getting some data off that OBD connector hidden somewhere under my steering wheel is one of the things I'd like to do sooner or later... Just bookmarked your project :slight_smile:

Thanx for the reply! That code/project is not mine, i am using parts of its code to do some other stuff, like reading ecu sw info and other service operations.

Anyway, i found some bugs in that code which are now corrected (and tested) and enable fast init, aswell as the bitbang for a more standard 9600bps communication speed instead of 10400bps.

Just for the record:

Uploaded with ImageShack.us

BR

The SAM3X has registers PIO_PER and PIO_PDR which control whether a pin is used as a digital output or by a peripheral:

g_APinDescription[pin].pPort -> PIO_PER = g_APinDescription[pin].ulPin; (pin is digital io)
g_APinDescription[pin].pPort -> PIO_PDR = g_APinDescription[pin].ulPin; (pin is peripheral)

Posting this in the hope that it just works - if it does, great, if not then you're probably going to need to study the datasheet.

Thanks stimmer, will definitely try this out and post results as soon as i do it.

BR

hi Bi0H4z4rD,

sorry for late reply on this but yes, you should use what stimmer suggested you. This is the only way to assign a pin either to GPIO multiplexing or to a peripheral.

by the way, if you want to send 5bit frames, maybe are you able use the USART with the proper configuration. That way you won't have to do it manually:

36.2 Embedded Characteristics
• Programmable Baud Rate Generator
• 5- to 9-bit Full-duplex Synchronous or Asynchronous Serial Communications

I didn't check deeply the DS, so maybe am I wrong.

thanks for your reply aethaniel

what i want to send is 8N1 bits at 5bps (baudrate), not 5 bits :slight_smile:

I'm still up to testing it, which should happen sometime before sunday.

BR

oooops i read a bit fast your posts, sorry.

I have found what i was looking for:

USART2->US_CR = US_CR_TXEN;//Enables USART2 TX
USART2->US_CR = US_CR_RXEN;//Enables USART2 RX
USART2->US_CR = US_CR_TXDIS;//Disables USART2 TX
USART2->US_CR = US_CR_RXDIS;//Disables USART2 RX

But now i find that if i have set the pins as digital previously like this:

pinMode(16, OUTPUT);
pinMode(17, INPUT);

the USART2 wont start, and will stay in LOW status, and therefor, not read anything.

Any clues on how to solve that?

I already tried the

g_APinDescription[pin].pPort -> PIO_PER = g_APinDescription[pin].ulPin;  (pin is digital io)
g_APinDescription[pin].pPort -> PIO_PDR = g_APinDescription[pin].ulPin;  (pin is peripheral)

and it didnt do the job.

BR

Now, this is weird...

This code:

#define IN    17 //RX2
#define OUT   16 //TX2

void setup(){
Serial2.begin(115200);
Serial.begin(115200);
Serial2.print("123456");
delay(1000);
USART2->US_CR = US_CR_RXDIS;
USART2->US_CR = US_CR_TXDIS;
pinMode(OUT, OUTPUT);
pinMode(IN, INPUT);
delay(1000);
  digitalWrite(OUT, HIGH);
  delay(200);
  digitalWrite(OUT, LOW);
  delay(200);
  digitalWrite(OUT, HIGH);
  delay(200);
  digitalWrite(OUT, LOW);
  delay(1400);
USART2->US_CR = US_CR_TXEN;
USART2->US_CR = US_CR_RXEN;
  Serial2.print("123456");
  delay(20);
  Serial2.print("123456");
  Serial.print("Done");
}
void loop(){}

Gives the following response:

Uploaded with ImageShack.us

The red square represents the first (one time) "Serial2.print("123456");".

Any clues of what might be happening here?

BR

Serial2 is USART1, not USART2.

Thanks for the tip stimmer!

I changed it from USART2 to USART1, but still getting exactly the very same thing on the LA.

The weird thing is that it does the "LOW/HIGH" thing before serial printing "123456" for the first time, while that is supposed to go after printing it.

BR

Bi0H4z4rD:
Trying to do some ISO-9141 (car ECU) communications, and i need to send a 5-baud start sequence which is done with:

pinMode(TX0, OUTPUT);

pinMode(RX0, INPUT);

digitalWrite(TX0, HIGH);
....
Serial.begin(10400);




BR

You mean K-Line I think so you have the same Problem I have with L-Line and the USART may you can use an K-Line Transciever and the Lin support from the SAM.

Thanks for your reply Markus.

You mean one like this one?: http://www.nxp.com/documents/application_note/AN00093.pdf

BR

I can't understand exactly what didn't work with the PIO_PER/PDR approach - I modified your example like this:

#define IN    17 //RX2
#define OUT   16 //TX2

void setup(){
  pinMode(0,INPUT);
  pinMode(1,INPUT);
Serial2.begin(115200);
Serial2.print("123456");
delay(1000);

g_APinDescription[IN].pPort -> PIO_PER = g_APinDescription[IN].ulPin; 
g_APinDescription[OUT].pPort -> PIO_PER = g_APinDescription[OUT].ulPin; 

pinMode(OUT, OUTPUT);
pinMode(IN, INPUT);
delay(1000);
  digitalWrite(OUT, HIGH);
  delay(200);
  digitalWrite(OUT, LOW);
  delay(200);
  digitalWrite(OUT, HIGH);
  delay(200);
  digitalWrite(OUT, LOW);
  delay(1400);

g_APinDescription[IN].pPort -> PIO_PDR = g_APinDescription[IN].ulPin;
g_APinDescription[OUT].pPort -> PIO_PDR = g_APinDescription[OUT].ulPin;


  Serial2.print("123456");
  delay(20);
  Serial2.print("123456");
}

void loop(){}

and connected pin 16 directly to pin 1 (to get output from Serial2 on the serial monitor), and also connected it to an LED. It appears to flash and transmit serial exactly as you'd want.

You are totally right stimmer, just checked it with the LA and it works perfectly. I must have done something wrong while trying it.

Big thanks for the help!

BR

I am working with K-line that is similar to yours. My code starts the bit-bang before activating the UART1.
I am using UART0 for debug. This is on a 1284 chip.

  digitalWrite (TX, HIGH); // makes K-line high 3
  digitalWrite(ledPin,HIGH);
  delay(2000);       // wait for K-line to be clear 3
  digitalWrite (TX, LOW); // makes K-line low  3
  delay(25);
  digitalWrite (TX, HIGH); // makes K-line high  3
  delay(25);        //last delay before first message
  Serial1.begin(10400);

Also, I think there is a function called Serial.end() to stop serial comms.. I am not positive about it though.

cyclegadget:
I am working with K-line that is similar to yours. My code starts the bit-bang before activating the UART1.
I am using UART0 for debug. This is on a 1284 chip.

  digitalWrite (TX, HIGH); // makes K-line high 3

digitalWrite(ledPin,HIGH);
 delay(2000);       // wait for K-line to be clear 3
 digitalWrite (TX, LOW); // makes K-line low  3
 delay(25);
 digitalWrite (TX, HIGH); // makes K-line high  3
 delay(25);        //last delay before first message
 Serial1.begin(10400);





Also, I think there is a function called Serial.end() to stop serial comms.. I am not positive about it though.

Hi I used this code on the Leonardo for Lin,

int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated

long interval = 250;

//Lin Initailisation
#define linspeed                19200
unsigned long Tbit = 1000000/linspeed;

#define uartlenght                 10

//Tbits Header
#define breakfield                 13
#define breakdelimiter              1
#define breakfieldinterbytespace    2

int frameerrordelay = ((breakfield + breakdelimiter) - uartlenght)*Tbit;
//int frameerrordelay = (breakfield + breakdelimiter + breakfieldinterbytespace) - uartlenght;

#define syncfield                  uartlenght
#define PIDfield                   uartlenght
#define syncfieldPIDinterbytedelay  0
int syncfieldPIDinterbytespace = syncfieldPIDinterbytedelay*Tbit;

//Tbit Response
#define responsedelay               8
int responsespace = responsedelay*Tbit;
#define interbytedelay              0
int interbytespace = interbytedelay*Tbit;

#define numbers  4
byte message[numbers],sending[numbers];
byte linb,sync,PID,checksum;
int n = 0;

void setup() {
  // initialize serial port and LIN:
  Serial.begin(19200);
  Lininit();
  pinMode(13, OUTPUT);
}

void loop() {
  blinking();
  LinReading();
//  LinWriting();
}

void LinReading() {
  LinRead();
  PrintlnLin();
  ClearFrame();
}

void LinWriting() {
  LinWrite(sending);
  Answer();
  delay(1000);
}

void Lininit() {
  Serial1.begin(linspeed);
  pinMode(0,INPUT_PULLUP);
}

void Answer() {
  for (int i=0;i<numbers;i++) {
     sending[i] = n;
  }
  n++;
  n = n % 256;
  Serial.println(n,HEX);
}

void LinRead() {
  if (1<<FE1) {
    delayMicroseconds(frameerrordelay);               //after Frame Error Tbit to Sync Field
    if (Serial1.available() > 0) {
      sync = Serial1.read();
      if (sync != 0x55) {
        sync = 0x00;
      }
      delayMicroseconds(syncfieldPIDinterbytespace);  //Interbyte Space
      if (Serial1.available() > 0) {
        PID = Serial1.read();
      }
      delayMicroseconds(responsespace);               //after PID Tbit space
      for (int i=0;i<numbers;i++) {
        message[i] = Serial1.read();
        if (interbytespace == 0) {                    //Interbyte Space
          delayMicroseconds(1);
        } else {
          delayMicroseconds(interbytespace);
        }
      }
      checksum = Serial1.read();
    }
  } else {
    Serial.println("NO Break");
  }
}

void LinResponse(byte* sending) {
  if (1<<FE1) {
    delayMicroseconds(frameerrordelay);                 //after Frame Error Tbit to Sync Field
    if (Serial1.available() > 0) {
      sync = Serial1.read();
      if (sync == 0x55) {
        delayMicroseconds(syncfieldPIDinterbytespace);  //Interbyte Space
        if (Serial1.available() > 0) {
          PID = Serial1.read();
          if (PID == 0x11) {
            delayMicroseconds(responsespace);           //after PID Tbit space
            for (int i=0;i<numbers;i++) {
              Serial1.write(sending[i]);
              if (interbytespace == 0) {
                delayMicroseconds(1);
              } else {
                delayMicroseconds(interbytespace);
              }
              Serial1.write(MessageCRC(message,0));
            }
          }
        }
      }
    }
  }
}

void LinWrite(byte* sending) {
  Serial1.end();
  pinMode(0,OUTPUT);
  digitalWrite(1, LOW);
  delayMicroseconds(breakfield*Tbit);                 //after Frame Error Tbit to Sync Field
  digitalWrite(1, HIGH);
  delayMicroseconds(breakdelimiter*Tbit);
  Serial1.begin(linspeed);
  Serial1.write(0x55);
  Serial1.write(0x03);
  delayMicroseconds(responsespace);
  for (int i=0;i<numbers;i++) {
    Serial1.write(sending[i]);
    if (interbytespace == 0) {
      delayMicroseconds(1);
    } else {
      delayMicroseconds(interbytespace);
    }
  }
  Serial1.write(MessageCRC(sending,0));
}
  
void PrintlnLin() {
  if(sync != 0) {
//    Serial.print("Break Field   Sync:  ");
//    Serial.print(sync,HEX);
    Serial.print("PID:  ");
    Serial.print(PID & 0x3F,HEX);            //PID without CRC
    Serial.print("   CRC:  ");
    Serial.print(PIDCRC(PID));
    Serial.print("  Message:  ");
    for (int i=0;i<numbers;i++) {
      Serial.print(message[i],HEX);
      Serial.print(";");
    }
    Serial.print("  Checksum:  ");
    Serial.print(checksum,HEX);
    Serial.print("  ChecksumCRC:  ");
    Serial.println(MessageCRC(message,0),HEX);
  }
}

void ClearFrame() {
  sync = 0;
  PID = 0;
  for (int i=0;i<numbers;i++) {
    message[i] = 0;
  }
  checksum = 0;
}

void blinking() {
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;
    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;
    // set the LED with the ledState of the variable:
    digitalWrite(13, ledState);
  }
}

int PIDCRC(int PID) {
  int P0 = ((PID>>0) + (PID>>1) + (PID>>2) + (PID>>4)) & 1;
  int P1 = ~((PID>>1) + (PID>>3) + (PID>>4) + (PID>>5)) & 1;
  return (P0 | (P1<<1));
}

byte MessageCRC(byte* message, uint16_t sum) {
  for (int i=0;i<numbers;i++) {
    sum += message[i];
  }
  while(sum>>8)  // In case adding the carry causes another carry
    sum = (sum&255)+(sum>>8); 
  return (~sum);
}

And for the Due I have Isolated and changed the Atmel Framework Examplecode. I will attach it but I have at the moment not the time for tests also I had also to comment out the USART1_Handler in the variant.cpp to let it complie proper.

B.R.
Markus

Lin_am_Due_final.zip (36.6 KB)