Working on an Interrupt Based LIN-Client

Status
Not open for further replies.

Markus_L811

Well-known member
Hello there,

some weeks ago I finished an LIN-Master that used the LIN-Break provided by the Teensy Chips (T3.0 - 3.6). After this I was working on an LIN-Slave with Interrupt based Breakdetection, detection and reading works also handling from different IDs, what I can't get to work is the LIN-Response, I hope someone can help me solv it.

Technically I struggle on this part:
Code:
void LIN_Slave::response(frame d) {  
  UART0_TWFIFO = 1;
  
  byte b;
  
  notes(&tmp);
  
  //Serial.print(d.length);
  
  //UART0_C2 &= ~UART0_C2_RX_ENABLE;
  
  UART0_C1 |= UART_C1_LOOPS;
  UART0_C1 |= UART_C1_RSRC;

  if (d.version == 1 || d.version == 0)
    d.crc = dataChecksum(d.data, d.length, 0);
  else
    d.crc = dataChecksum(d.data, d.length, message[1]&0x3F);

  __disable_irq();
  delayMicroseconds(100);
  __enable_irq();
  
/*   
  //junkpart for direct wiring
  byte junk[] = {0x00, 0x55, message[1]};
  for (int i = 0; i < 3; i++) {
    while(!(UART0_S1 & UART_S1_TDRE));
      UART0_D = junk[i];
  }
   */
  
  for (int i = 0; i < d.length; i++) {
    while(!(UART0_S1 & UART_S1_TDRE));
      UART0_D = d.data[i];
  }
  
  while(!(UART0_S1 & UART_S1_TDRE));
    UART0_D = d.crc;
	

  Serial.println(d.crc, HEX);
  
//  Serial.print("UART0_C2 ");
//  PRINTBIN(UART0_C2);

  //UART0_C2 |= UART0_C2_RX_ENABLE;
  
  UART0_C1 |= UART_C1_LOOPS;
  //UART0_C1 |= UART_C1_RSRC;
  
//  Serial.print("UART0_C2_");
//  PRINTBIN(UART0_C2);
}

If I connect 2 Teensys without the LIN-Stuff between it (T1 Tx to T2 Rx, T1 Rx to T2 Tx) it works well (needed to include the junkpart for the Master to transmit enough bytes)

I used the Parts from SKPang http://skpang.co.uk/catalog/teensy-canbus-and-linbus-breakout-board-include-teensy-32-p-1566.html for the LIN-Parts.

Based on the MCP2004A(LIN Bus-Driver) the Rx Pin to the Uart has the following behavior
MCP2004A_RX.JPG
 

Attachments

  • Lin_Slave_lib.ino
    1.5 KB · Views: 78
  • LIN_Master_Example.ino
    1.5 KB · Views: 64
  • lin_bus.cpp
    11.3 KB · Views: 99
  • lin_bus.h
    1.6 KB · Views: 65
  • lin_slave.cpp
    7.9 KB · Views: 94
  • lin_slave.h
    1.2 KB · Views: 59
  • Teensy_3.x_LIN_Master.zip
    12.5 KB · Views: 74
  • Teensy_3.x_LIN_Slave.zip
    6.2 KB · Views: 78
Sorry I have not done anything with CanBus or LIN type stuff, so hard to know exactly what you are trying to do... So hopefully someone who does play/work with this stuff can give more answers.
So for example I have never used an MCP2004A nor have any.

But I do have a reasonable understanding of the basics of the Uarts.

Also personally I prefer to not muck as much directly in the registers like this. Since the code is mucking with Loops, I get the impression you are trying to do some half duplex stuff, but the MCP2004A has TX and RX pins, but in addition it has a CS/Wake pin... Again I have not looked through all of the details of these pins.

So the real questions are, how are you hooking it up with a direct connect between the two? Full or Half duplex? From your wiring mention it sounds like Tx->RX RX->TX... so full duplex setup.
So again why is it trying to talk directly to UART registers? Instead of HardwareSerial member functions like write, flush, read, available ?

If you are needing to do Half duplex and you are not using a transmit enable pin, to do so. Then typically only the TX pin is used of the UART on both ends...

When I have done that in the past (example drive Dynamixel Servos),

In that case when I initialize the Serial port for half duplex, I do something like:

Code:
   //<Get pointer to underlying register structure for the serial port>
  if (pserial == &Serial1) s_pkuart = &KINETISK_UART0;
  ... 

  pserial->begin(baud);  // start up the serial port
  s_pkuart->C1 |= UART_C1_LOOPS | UART_C1_RSRC;  // enable half duplex mode
   volatile uint32_t *reg = portConfigRegister(tx_pin);
    *reg = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS; // pullup on output pin;
  setRX();  // default to be in RX ready mode

I then have some helper functions, which in these cases, looks sort of like:
Code:
void setTX() {
    if (s_pkuart) s_pkuart->C3 |= UART_C3_TXDIR;
}

void setRX() {
  pSerial->flush();  // Make sure we complete the output before we switch
  if (s_pkuart) s_pkuart->C3 &= ~UART_C3_TXDIR;
}


And then when I am sending data I end up doing something like:
Code:
void txPacket(uint8_t* buf, uint16_t cnt) {
   setTX();
   pserial->write(buf, cnt);
   setRX();
Note the write may actually be several writes... Example I may generate a header that first gets sent, then a write for the data, and another write for checksum, or...

But again this is assuming Half duplex...

Again not sure how you use the LIN driver. Do you have to do something like drive the CS pin? ...
Hopefully others who do this will give you more information.

Kurt
 
Hello KurtE thanks for the input,

_stream and Serial are not working inside the IRS, if I connect it like this:
(Without any external wires PIN CS activate the Chip nothing more)
Teensy_Lin_direkt_ohne_Lin_Steckplatine.jpg
It works if I connect with the LIN Linedriver between it
Teensy_Lin_direkt_mit_Lin_Steckplatine.jpg
Only recieving is working, and it stops working if I try to send from the Slave.

Basicly the Tx from the LIN Linedriver transmits the same as the Rx gets (snipping beginning Post) with direct wiring it does not happen.

LIN is a sort of halfduplex on one Line with an higher Voltage eg. 12V in Car enviroment
 
Do you have a pullup resistor on pin1 of the lin transceiver?
According to the MCP2004 datasheet, pin1 RXD is a open drain output and therefore needs a pullup resistor.
 
Do you have a pullup resistor on pin1 of the lin transceiver?
According to the MCP2004 datasheet, pin1 RXD is a open drain output and therefore needs a pullup resistor.

Yes Pin1 (should) have a PullUp with the init from Serial1 with Serial1.begin() RXD has PullUp activate
 
Interesting part is my LIN-Master is working with _stream and does also hears by the LIN-Driver what is transmit, but in this case the Uart does not care.
 
There is no reference to a CS pin in your linSlave code.
In order for the slave to be able to transmit, you need to make the CS pin high to put the transceiver in Operation Mode(enable the transmitter) before transmission.
After transmission you make the CS pin low, this will put the transceiver in POWER DOWN(disable transmitter & receiver).
The next rising edge on the LIN bus will then put the transceiver in Ready Mode(enable the receiver).
see FIGURE 1-5 from the datasheet.
 
There is no reference to a CS pin in your linSlave code.
In order for the slave to be able to transmit, you need to make the CS pin high to put the transceiver in Operation Mode(enable the transmitter) before transmission.
After transmission you make the CS pin low, this will put the transceiver in POWER DOWN(disable transmitter & receiver).
The next rising edge on the LIN bus will then put the transceiver in Ready Mode(enable the receiver).
see FIGURE 1-5 from the datasheet.

Yes thats right neurofun, there is no CS code inside the lib, atm CS is allways HIGH.
 
Status
Not open for further replies.
Back
Top