Max3100 for SPI to RS485 communication - Character Delay Problem

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Max3100 for SPI to RS485 communication - Character Delay Problem

7,063 Views
KH_SRNL
Contributor I

I am trying to communicate between a M68HC9S12C128 & RS485 based mass flow controller.

I am using a combination Max3100 & Max3160 to go from my SPI bus to RS485.  I am using the Max3100 SPI to TTL serial converter then the Max3160 TTL to RS485 converter.  The SPI is set up for interrupt driven transmit.  The Max3100 is set up to interrupt driven receive (RS485 back to embedded - 3100 toggles the IRQ interrupt on the 9S12). 

 

When characters are transmitted, there is a significant time delay between transmission of characters (enough that the mass flow controller doesn't see it as a continuous stream).  The Max3100 requires a 16 bit SPI transfer, so I toggle the CS line in my SPI transmit service interrupt (the automatic chip select on the 9S12 won't hold the CS line low through a 16 bit transfer).  I also put a small delay between 16 bit packet transmissions so the Max3100 recognizes the end of a packet transfer (Max doesn't recognize data packet otherwise). 

 

Any ideas on how to get around the character delay issue?  I am open to alternate parts if the Max3100 / 3160 is not the best chip set.  My SCI bus is used for communication with another device and I really don't want to run both devices off of it if possible. 

Thanks in advance.

Labels (1)
0 Kudos
11 Replies

1,721 Views
KH_SRNL
Contributor I

Thanks for the info Mac.  I eventually headed a completely different direction with the design.  This change was necessitated by other factors.

 

After working with the design for an extended period, it became obvious that one of the major problems was correctly pacing the data from the HCS12 to the Max3100 (through the SPI bus).  If the data was sent too fast, it overwrote the Max3100 transmit buffer, thus dropping characters.  If it was written too slow, then the receiving device detected a break in the transmission stream.  I think your suggestion of polling is probably the best.  It is very unfortunate that Maxim elected to not put a transmit FIFO on the 3100.  It would have made life a whole lot easier.

 

I am successfully using the Max3100 to talk to an FTDI serial to USB converter.  I think, in part, the key to the success with this application is I have control over both the transmitted data and the PC based application that receives the data from the USB. 

 

Thanks again to all for your help.

0 Kudos

1,721 Views
KH_SRNL
Contributor I

Thanks for the info.  You are probably correct on the SPI interrupt, I originally wrote the routine about a year ago and at the time had zero experience with SPI.  I'll check your suggestions on both the interrupt & clock rate when I return to work on Monday.

 

After thinking about it a bit I am convinced that my code is the problem.  The excessive delays I'm experiencing really don't make sense (from a hardware perspective).  I'll let you know how things turn out once I implement your recommendations.

0 Kudos

1,721 Views
Lundin
Senior Contributor IV
I'd either consider upgrading to a larger S12 MCU with 2 SCI ports, assuming you are using the 112 or 80 pin versions of S12C so that they will be pin-compatible. Or if that's not an option because of board space, a software SCI. I think there is an app note on a software SCI. Either option removes the need of expensive Maxim ICs and the only external circuit you'll need is a RS-485 tranceiver.

The upgrade to another S12 is certainly the smoothest way of doing it. S12XEG128 seems to be the best choise as it has everything the S12C got plus some more. S12D and S12XD are also possible, but worse choises as they are older chips that require external low voltage detection, something you have internally on S12C.

0 Kudos

1,721 Views
KH_SRNL
Contributor I

Thanks.  If at all possible I'm trying to stick with the existing controller.  This is a very low production run and design cost is the predominate $$$, not components.  The 9S12 chip is prepackaged on a carrier board with all of the support circuitry (El Micro CHIPS12).  Designing a new board with the 9S12 support circuitry would be a pretty good learning curve for me.

 

I'm still working with the code trying to minimize delays.  I boosted the SPI bus to 6 MHz and the communication is now marginal (successful transmissions about 1/2 the time).  I may revisit my interrupt service routines and see if I can use the Max3100 transmit buffer empty interrupt in combination with the SPI transmit buffer interrupt (SPI TX interrupt for character transmission & Max310 TX buffer interrupt for packet transmission).

 

Thanks again for your suggestion

 

0 Kudos

1,721 Views
kef
Specialist I

I'm not sure I understand the problem. Do you want to achieve back to back characters trasfer on RS485 bus? If yes, then what's target RS485 baudrate?

Also, could you explain what the following means: "Max doesn't recognize data packet otherwise"?

 

You say you rised SPI clock to 6MHz. But MAX31xx datasheet specifies max SCLK Period 238ns. Thats only little above 4.2MHz. At this freq, SPI byte transfer takes less than 2us, <50 bus cycles @ 25MHz bus clock. Polled SPI may make more sense at this speed.

 

 

0 Kudos

1,721 Views
KH_SRNL
Contributor I

Thanks.  Hopefully I can make better sense out of the problem.

RS485 - The target baud rate is 9600 baud.  I am transmitting an 8 character stream.  When RS485 data is transmitted out of the Max3160, there is a significant delay between transmitted characters.  This delay is sufficient such that the received RS485 mass flow meter doesn't interpret the data as a continuous 8 byte stream.  The flow meter manufacturer states the between character delay must be less than three characters long (mine is about 5).

In regards to the max3100 SPI interface.  For this device, the embedded must toggle the CS line  low for the duration of a 16 bit packet. Afterwards the CS line must toggle high before the next packet is transmitted to the Max3100.  I tried, but was unsuccessful, at getting the 9S12 SPI CS line to stay low for the 16 bit transfer, but there was always a short "blip" where the line went high at the end of the first 8 bits.  To resolve this issue, I used a general purpose I/O line on the 9S12 as my CS line.  Within the SPI transmit service routine I put a small delay to ensure the CS line was held low until all data was transmitted out.  It appeared the 9S12 SPI transmit buffer empty flag would signal an interrupt before all data was sent out (buffer empty but not transmitter) and the CS line would go high before the data was completely out (without the delay).  This is the delay that I refer to on the SPI interface.  I decided to implement the SPI transmit as interrupt driven to have better control over the CS timing.

 

I may be wrong on the SPI bus speed.  I didn't measure it, but the documentation on the CHIPS12 controller (9S12 packaged with supporting electronics) stated an internal bus speed of 25 MHz.  The Motorola S12SPIV3 doc indicated a SPI baud register value of 0x01 (SPIBR) corresponds  to a 6.25 Mhz baud rate at 25 MHz bus clock.  I assumed (based on the documentation) that's what it was running at.

 

Finally, yes the issue is the character delay on the RS485 transmit side.  I'm trying to get a hardware solution (with my existing controller) or software solution to resolve the excessive transmission delay (the baud rate on the flow meter is fixed at 9600).

Thanks very much for your assistance.

0 Kudos

1,721 Views
kef
Specialist I

I'm sure MAX3100 is able to transfer bytes at UART side back to back at much faster baudrates than 9600. (I used MAX3110 in the past without any problems.)

 

Right, SPTIE interrupt fires before SPI transfer is complete. But there's also a SPIE interrupt. SPIE fires after SPI transfer is complete. Isn't SPIE what you need?

 

Speaking about SPI clock, I meant that MAX3100 datasheet specifies minimum SCLK Period (tcp) = 238ns. You shouldn't use SPI clock higher than 1/238ns=4.2MHz

0 Kudos

1,721 Views
KH_SRNL
Contributor I

kef, I hate to keep imposing, but now I am really lost.  According to my documentation the SPIE is a receive data interrupt.  I almost can see how this may work as for every byte transmitted by the 9S12, the Max3100 sends a byte back (therefore using the receive interrupt as a slave select ensures all data has been sent & received).  The problem is I can't get it to work. 

The Motorola S12SPIV3.pdf describes the data transfer sequence as:  "a read of the SPISR with SPTEF=1 followed by a write to SPIDR puts data into the transmit data register."  SPTEF is the transmit empty interrupt enable.

I tried to force data out by enabling the receive (and system interrupts); toggling the SS line low and writing a byte to the SPIDR.  I expected it to write the byte out, the Max3100 to respond with a byte, and the receive data interrupt to call my ISR for the next byte.  With a scope I don't see anything, so I'm assuming even the first byte is not getting out.  Should I use the SPITE to send data and the receive data interrupt to toggle the SS line?

Your suggestions & insight would be very helpful & appreciated.

0 Kudos

1,721 Views
kef
Specialist I

In master mode, everytime you clock out a byte, you also clock in a byte, and SPIF is set when clock in and clock out are done. I see S12C datasheet talks about SPIF flag like about receive flag. But in fact S12C SPIE and SPIF bits behave very similar like on old HC11 family. And HC11 manual calls them SPI Transfer Complete Flag (SPIF) and SPI Interrupt Enable Bit (SPIE).

 

I'm not sure why your code doesn't work. Do you put all data to be send to Tx queue and enable SPTIE interrupt? If so, then substituting SPTIE with SPIE and SPTIF with SPIF won't be enough. Difference is that after you service(clear) SPIF, SPIF will stay 0 until another transfer is done. And SPTIF is always 1, unless you fill transmit buffer. To switch from SPTIE to SPIE, first byte should be put to SPDR not from SPI ISR. 

Should I use the SPITE to send data and the receive data interrupt to toggle the SS line?

 

This approach may work, but you should keep in mind that S12C transmit data register is double buffered and sending two SPI bytes you should service both SPIF==1 events. I mean SPTEF==1 and SPIF==1 events and MAX3100 CS should come like this:

 

SPTEF:
~\1/~\2/~~~~~~~~~~~~~~~~~~~~~~~~~
SPIF :
________________/3\_____________/4\______
CS   :
\_____________________________________/~~

 

It is on every second SPTEF interrupt you should disable SPTIE and enable SPIE. Then on second SPIE interrupt you may toggle CS.

 

One warning though. S12C SPI receiver isn't really double buffered. Data will be lost if SPDR isn't read before second clock in/clock out is done. SPIE ISRs have to not be delayed too much, else you may loose received data. (This issue is fixed on S12XD family. On S12XD you may complete clocking out 2 bytes, then read 2 clocked in bytes from SPDR.) So it is better to

 

SPTEF:
~\1/~~~~~~~~~~~~~~\2/~~~~~~~~~~~~~~
SPIF :
________________/3\_____________/4\______
CS   :
\_____________________________________/~~

 

on first SPTIF interrupt write data to SPIDR, disable SPTIE, enable SPIE. On first SPIE write second byte to SPIDR, on second SPIE toggle CS.

 

Hope it helps

Message Edited by kef on 2009-10-26 09:15 PM
0 Kudos

1,721 Views
KH_SRNL
Contributor I

Thanks.  I was finally able to get the system running with a combo of the two interrupts as you described.  I track the number of characters transmitted then pull the CS line high in the receive interrupt routine (after two characters are received).  I still have to use the transmit buffer empty interrupt to initiate the transfer and I'm not quite sure why.  At this point, I'm just glad I can move forward.

 

Thanks again for your help

 

0 Kudos

1,720 Views
bigmac
Specialist III

Hello,

 

With your use of a very fast SPI clock rate, IMHO you are making life more difficult than it needs to be with the use of interrupts for the SPI master.  The number of cycles required to enter and exit the ISR may well approach the transmission time for each byte, when using a polling process.  Personally, I would use polling under these circumstances, and importantly would not make use of the double buffering capability.

 

This will eliminate the possibility of an overrun error occuring, especially if the execution period of any other interrupt may exceed the SPI transmission time for a single byte.  An overrun condition is prevented by waiting for the SPIF flag to be set, and then clearing the flag by reading the SPIDR register.  This needs to be done whether or not you are making use of the return data.  I would see the process as follows:

  1. Set CS signal low
  2. Wait for SPTEF flag set (should already be set)
  3. Write MS byte to SPIDR
  4. Wait for SPIF flag set
  5. Read SPIDR
  6. Write LS byte to SPIDR
  7. Wait for SPIF flag set
  8. Read SPIDR 
  9. Set CS signal high

Regards,

Mac

0 Kudos