rs 485 bus

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

rs 485 bus

6,321 次查看
DanielMorley
Contributor I
I am trying to recieve a message via the Uart for a MC9S08GT16A.  The following code is my attempt to read a line of text and send it out.  I cannot seem to find any indication that I am recieving data.  
 
 
 
 void RecMsg() {
 byte ix=0;    // String pointer
 byte dummy;    // dummy var for reading SCIS1
 byte nxt_char;
 char msg[8] ;
    SEREN == OFF ;
  SCI1C2_RE = 1;    // enable Rx
 
        
 dummy = SCI1S1;   // 1st half of TDRE clear procedure
 msg[ix++] = dummy;
 while( msg[ix++] != 0x00) {
   nxt_char =SCI1D ; // 2nd half of TDRE clear procedure
    msg[ix++]=nxt_char ;
   while(!SCI1S1_TDRE){
     feedCOP();
   };
 } //end while((SCI1D
 while(!SCI1S1_TC){
   feedCOP();
 };
 if(ix>>1)
 SendMsg(msg);
 
 SCI1C2_TE = 0;
  
} //end RecMsg
标签 (1)
0 项奖励
22 回复数

1,839 次查看
bigmac
Specialist III
Hello Daniel,
 
There seems to be a little confusion over which flags to test.  Firstly, you need to wait until the RDRF flag is set before attempting to read each received character.  You also attempt to test the TDRE and TC flags associated with the send process - this confuses the issue for receive function.
 
I assume that the SEREN signal is used for switching the RS485 transceiver device between receive and send modes.  I also assume that you are using two-wire, half-duplex RS485 operation (not 4-wire operation).  I would suggest that receive mode should remain operational, for both the transceiver and the SCI module, unless you are actually in the process of sending data.  However, I cannot see any need to clear the TE and RE bits within the RecMsg() or SendMsg() functions.
 
Broadly speaking, the SendMsg() function should -
Set SEREN signal active to enable send mode for the transceiver (and usually to disable receive).
Send the required sequence of characters, waiting for the TDRE flag to become set, between characters.
After the final character is sent, wait for the TC flag to become set.
Set SEREN inactive to revert to receive mode.
You can then revert to polling for further receive characters.  Ultimately, you may want to use interrupts for the receive process, so that you can do other things whilst waiting for each receive character.
 
Regards,
Mac
 

Message Edited by bigmac on 2007-02-0802:25 PM

0 项奖励

1,839 次查看
DanielMorley
Contributor I
 Thanks for your reply.  I am trying to follow your advice.  Yes all of your asssumptions are correct,  reguarding SEREN is on and off for the external 485 chip.  The sendmessage works find.  The recieve function is where I just cann't get a handle on.  I am using the send message to check the SCI1D for any sign of life.   It is giving me 000 as an output.  Reguardless of what data I send.  Do you see anything wrong for this vesion of the function. 
 
 
 
 
 SCI1_Receive(void){
 
 
 static unsigned char pointer = 0;
 uchar ReceiveBuffer[10];
 uchar myChar;
 
 
 
 SEREN == OFF ;
  SCI1C2_RE = 1;    // enable Rx
  SCI1C2_RIE=1;
  
  myChar=SCI1S1;
  myChar=SCI1C3;  // Reading SCI1C3 is needed as described in EB642
   SendMsg(num2asc(SCI1D));
 ReceiveBuffer[pointer++] = SCI1D;
 if(pointer >= 10) {
   SendMsg(num2asc(SCI1D));
   pointer = 0;
    
 }
 
      SCI1C2_RIE=0;
 // SendMsg(pointer);
}
0 项奖励

1,839 次查看
bigmac
Specialist III
Hello Daniel,
 


Daniel Morley wrote:
 The sendmessage works find.  The recieve function is where I just cann't get a handle on.  I am using the send message to check the SCI1D for any sign of life.   It is giving me 000 as an output.  Reguardless of what data I send. 
 

Am I correct in assuming you are attempting to do a "loopback", where each character sent from the send buffer is to be received by the receive buffer.  If this is the case, you will need to ensure the following -
  1. Two separate buffers, one for send and the other for receive, each with its associated pointer.  These should have global scope, per Rocco's post.
  2. Since you are polling the flags, you may only send a single character at a time, and must then wait for the RDRF flag to become set before reading SCI1D.  You do not appear to be doing this.  After this has occurred, you may then send the next character.
  3. For a loopback test to succeed, the receive buffer associated with the RS485 driver must be continuously enabled, even when sending.  Conventionally, this would not be the case for a RS485 interface.
Item 2 would no longer apply if you were to use receive interrupts, since the send and the receive processes would be entirely separate - the receive buffer would be filled from within the ISR independently of the data sent.
 
Regards,
Mac
 
0 项奖励

1,838 次查看
alexod
Contributor I
I am starting to implement an RS485 multi-drop bus using HCS08 based micro controller.

I was looking into using a delayed collision detect.  The TX ready interrupt (TDRE) ISR to suck data from my TX message buffer.  The RX data ready RDRF ISR was to pop the echo'd byte and compare against the appropriate TX message buffer byte.

So the message buffer was an array of bytes, a target byte count, a read  pointer, a verify pointer and a rewind pointer(start of message).

TX ISR:
     SCID = msgBuf[rdOffset++];

RX ISR:
    temp = SCID
    if msgBuf[vfOffset++] != temp {
       disable TX INT
       rdOffset = 0;
       vfOffset = 0;
       startRetryCnt();
    }

Since I am getting RX overrun (OR) interrupts I assume my TX and periodic interrupts are pre-empting the RX interrupt.  Is this why Bigmac proposed letting the TX byte travel through the TX Buf, tx shifter, rx shifter rxbuf and compare before second byte sent out?

I was trying to spend as little time as possble on the bus, since a collision requires a back off period anyway I figured 3 bytes of error were as bad as one.

For now I'm going to back off, and use a less aggressive mechanism more along the lines of Mac's, and prove I can detect collisions before I try to optimize bus utilization.
0 项奖励

1,839 次查看
bigmac
Specialist III
Hello,
 
My use of half-duplex RS485 communications has always been associated with a master/slave system.  Since the slave will only generate a transmission in response to a request made by the master, there is no chance of collision with normal operation.  Of course, it is always possible that the request byte(s) may be corrupted so that two slaves may attempt to respond, but this shoould be a very infrrequent event, and would be detected by using a checksum or CRC for the returned data.
 
I would think that RS485 communications may be inappropriate where collision is a frequent possibility.  My reason for saying this is that the output state is actively driven in both directions that can result in high currents during a collision.  RS485 drivers do have current limiting for short circuit protection, but the current level may be higher than you might wish to cater for during normal operation.
 
Accepting that it may not be possible to use master/slave operation, to detect a collision the primary issue would be to determine the send byte corresponding to the current received byte.  The comparison should be done within the receive ISR, because once the ISR is exited, the position within the receive buffer could be ambiguous, especially if there is a delay before the buffer is next read.
 
One possible method might be to allocate an additional global variable, and a global flag.  When sending each data byte within the send ISR, also place the current character value within the new global variable.  When no more data is to be sent, perhaps the variable should be zeroed to indicate that receive comparison is no longer required.
 
Within the receive ISR, if the variable value is non-zero, do the comparison with the incoming byte value, and set the global flag if there is an error.  You will need to determine if  the echo of each send byte should also be placed in the receive buffer (there doesn't appear to be any specific reason to do so).
 
If zero is a valid send value, an alternative method of determining when the comparison is required would be to examine the current state of the send enable output line from the MCU.
 
A final word about your baud rate.  The critical timing will commence when the send character is actually written to SCID.  There should be immediate exit from the ISR after this occurs.  You then require that the SCI receive interrupt should be the next event, and SCID read should be the first thing done within the ISR, to minimize any possibility of overrun.
 
You must also ensure that any other higher priority interrupts cannot occur.  Perhaps these could be disabled within the send ISR, and re-enabled within the receive ISR.  The maximum number of MCU cycles between the write and read operations for SCID will dictate the maximum allowable baud rate, and this may be significantly less than the RS485 specification allows.
 
Note that this limitation only applies when you require collision detection as a result of a send, and not to the normal receipt of SCI data
 
Regards,
Mac
0 项奖励

1,839 次查看
alexod
Contributor I
Mac,

Thanks for the info.

The slaves on my bus are easily discarding rubbish, and resynching with the next whole message seen.  I have variable length packets, and if the byte count gets scrambled, then I end up lookig for a long message before typically discarding for bad check sum.

I have a multi master potential, and was looking for a smart way to resend.  However, the data would either be
1 - infrequent user command, users will press again if they didn't see it, especially with a membrane keypad.
2 - host streamed data has a short life span, and lost data can be dropped without damage to the whole.
3 - critical data requires an ack, and so will be handled. - corrupted ack or no ack will cause re-send.

I think I can stand sending only one byte and waiting for the rx'd version before sending the next.

Will try disabling Ticker while waiting for the echos
0 项奖励

1,839 次查看
bigmac
Specialist III
Hello,
 
With a multi-master system, I guess the only likely send contention is between masters.  I would assume that each slave would be specifically addressed by one of the masters, so the return slave transmissions would be well regulated.
 
A possible approach is for each master unit to also possess a unique slave address, so that it may be polled by the currently active master, duriing "round robin" polling of the various slaves.  In this way, one of the other master units may be assigned as the active master.  This should avoid any transmission contention.
 
To cater for a reset condition, perhaps due to temporary power loss, and the startup of the system, perhaps each master should monitor the period since last polled, and if it should exceed a limit, to assume current master status, and commence polling operation.  The possibility of contention during this process could be minimized by making the time period a random value between minimum and maximum limits.
 
Should a data transmission be corrupted, the ease of detecting the start of the next data packet by each slave will depend, to some extent, on the type of data being transmitted.  If the data can be limited to ASCII characters, it opens up the possibility of using control character to define the start and end of the packet, in addition to handshaking the data transfer.  The most complex case would occur if the data may assume any 8-bit value.
 
If the size of the data packet is relatively small, the ASCII approach might be adopted, even though two characters would be required to represent a random 8-bit value. Of course, if the data to be sent can be naturally represented as an ASCII string, the choice is obvious.  It is also possible that the size of a variable length packet need not be sent if the beginning and end of the packet are uniquely defined.
 
Previously, I have chosen to use the special 9-bit mode so that I can directly differentiate the byte (or should that be nonnet for nine bits) that represents the slave address.  The ninth bit setting can also filter the incoming data to the slaves, so that each slave will monitor only address bytes, until its own address is received, although personally, I have not found this to be necessary.  One drawback with this method is that the SCI receive ISR processing will be a little more complex, to determine the ninth-bit status, and avoid the need to store other than 8-bit values within the receive circular buffer..  Otherwise, two bytes of RAM would be needed to store each 9-bit value.
 
Regards,
Mac
 
0 项奖励

1,839 次查看
alexod
Contributor I
For this system I am using an ASCII formatted header,

STX (or was it SOH I forget), then
3 bytes address, these being a byte for 
  device type
  device unique address
  sub function address.
byte count, I needed variable length packets so I added the byte count.  The payload is not ascii, hence not just using ETX

First byte of payload was a message type ID

after the payload I added a footer
XOR Checksum,
EOT

I found the SOH, ADDR combination sufficient that nodes (including idle masters) only synch'd with start of real messages. If I ever latched onto the wrong thing, data looking like header, worst case byte counter would get set to 255, Check sum typically failed, and I missed a few messages in between.

As for line idle, I was simply going to restart an idle timer in the RX ISR.  If this timer expires, then line is idle.  Of course, I could only detect after the shifter in the SCI captured the byte, so I could possibly have an outgoing byte in the pipe at the same time.  Hmm, isn't there a receiver active flag I could look at?

A comparator  between TX and RX lines (with delay buffers) would be excellent, especially if it was hardwired  to the TX enable of the RS485 driver, that would stop that commotion.


I agree with Mac, a round robin scheme, where the Master A reliquishes bus control, explicitly giving it to Master B, who gives to Master C etc.  Trouble is starting the system, everyone having to register.  A static configuration will allow this, but needs either NVRAM/FLASH/EEPROM set up or dip switch/jumper setting.

One thing that has helped in the past is giving a "random delay" to units when they start registering.  This needs to be appropriately scaled for your app.  Thankfully I'm in infotainment, not engine management, so I have time.

I was hoping to find a standard way of doing things, but neither Modbus, DMX nor NMEA 0183 seemed to help me.  Did I miss an existing mulit drop "multi master" standard while looking?
0 项奖励

1,839 次查看
celsoken
Contributor V
Dear Alexod,

Maybe you could use some CSMA-CD strategies to deal with collisions. I don't know the current status of CSMA-CD but in ancient times they were listening to the bus all the time and when a collision happens, both transmitters shut up, wait for a random time (ms) and transmit after this random time if the line was idle.

There was also a variation of CSMA-CD that instead a random time, there was a node attribute, priority, so the higher priority nodes had shorter times.

In hardware terms you'll need one xor gate checking TX against RX line.

Maybe you could look at CAN startegies, too. But since the CAN chips take care of this comm level, maybe you'll have to llok at the basics.

I hope it helps,

Celso
0 项奖励

1,839 次查看
alexod
Contributor I
Celso,

Thanks, will look into it.  The flow diagram on Wikipedia's entry for CSMA/CD looks very familiar.

The board design is pretty solid at the moment and I can't lobby for additional hardware for collision detect. 

As for just an XOR.  I got caught out a few years ago.  I had two 8:1 mux devices, they shared addresses, and differed only in bit 0 of the address went through an inverter to CS# of one device, and direct to the other.  We ended up with a gate delay which meant we had trouble reading those devices.  I am now concerned that if I XOR TXD and RXD, there is the propagation delay through the TX buffer(charge pump/driver) and RX buffer, so there will be glitches at the leading edge of each transition on the TX line.  I would want some assurance that that glitch would not be a problem.

As for CAN.  You'd think being an in-car infotainment system we would be going CAN.  However, the project architect elected to use RS485, primarily as a cost issue, but also so we never get connected to the vehicles own CAN bus.  The project will be heading to marine applications too, hence my interest in NMEA 0183 NMEA 2000.


Again thanks,

Alex
0 项奖励

1,839 次查看
irob
Contributor V

I appologize for piggy-backing onto this discussion.  But I too am about to start a RS-422/485 design, using a MC9S08QG8 as the master micro.

 

For development of the system, I am wondering what you all might recommend for hardware.  For instance, is there a good eval board that has a 485 transceiver which can be connected to a PC for debug?

 

Thanks for your recommendations.

0 项奖励

1,839 次查看
celsoken
Contributor V

Dear Irob,

 

So you're promoting the QG8 as a master. Yoda would be proud huh?

 

If I had to do it w/ available stuff, I'd use the DEMO9S08GQ8, wich already has a RS-232 interface, a gender changer (change DB9 female to male) and use a shelf PC RS-232 to 485 converter. Remember to use one QG8 pin for flow control (RTS or DTR).

 

The same type of converter could be used for sniffing the network.

 

I hope it helps,

 

Celso

0 项奖励

1,839 次查看
irob
Contributor V
Thanks, everyone!  Great suggestions.  I have the DEMOQG8 board.  For monitoring, I have been using the open source RealTerm for some time now, which even has the flow control bit option for RS485 apps.  Could be useful in your dev setup, celsoken.
0 项奖励

1,839 次查看
peg
Senior Contributor IV

Hi Rob,

 

Yes, Realterm is great for this. (I think I may have put you on to it previously).

If you use a demoboard you can simply use say a MAX232 to convert the 232 back to TTL then you can use say a MAX491 to make your 485 interface (along with another output for transmitter control). I have several products that talk on a 2-wire RS-485 bus. I also make a converter with automatic flow control to interface RS-232-only devices onto the bus. This is simply a MAX232 and a MAX491 with a 555 monostable monitoring the Tx and driving the Tx enable for 1 byte time and a bit. Many commercial converters use a similar circuit. If you use an automatic converter then there is nothing special to do for RS-485 over RS-232. Even without the only difference between RS-232 and RS-485 is driving the Tx enable (if 2-wire). This is simply turn it on before write the SCI, then wait for the last byte to actually leave and turn it off.

0 项奖励

1,839 次查看
irob
Contributor V

Yes, that's right, Peg!  I do have you to thank for with the discovery of RealTerm.

 

Not to muddy the waters, but in fairness, I recently purchased one of I2C chip's boards (which is the developer of RealTerm, I guess). Using RealTerm to debug I2C traffic was far from non-trivial.  We had a very hard time with RealTerm's interface.  Finally gave up and bought a competitor's product from The Board Shop.

 

But I digress.  :smileyhappy:

0 项奖励

1,839 次查看
alexod
Contributor I
I found Total Phase had acceptable tools for I2C & SPI.  But this is digressing too far. 
0 项奖励

1,839 次查看
celsoken
Contributor V

Realterm sounds nice to me! I'll evaluate that! Thanks Irob!

Cheers,

 

Celso

0 项奖励

1,839 次查看
alexod
Contributor I

For my development system, we had the actual boards in house pretty quick, so no eval board for the CPU.

 

The other end is quite important though, the data for your RS485 bus.

 

We started with a real low cost USB to RS485 device from an outfit called Light-O-Rama.  Basically it's an FTDI chip in a small housing with RJ45 plugs for the RS485 interface.

 

I later switched to a quad serial port box from Quatech.  These are switchable between RS232, 422 and 485.  They have a version with voltage protection too.

 

 

For monitoring I went with Free Serial Port Monitor by http://www.hhdsoftware.com/  I find this software gives all that I expected from our old HP serial protocol analyzer.

0 项奖励

1,839 次查看
peg
Senior Contributor IV
Hi alexod,

I will be, over the next few weeks, converting an existing product from single master - many slave to multi-master (1, 2 or 3) - many slaves on a two-wire 485 bus. I have many ideas in my head how to implement this but have not started in ernest yet. Collisions is of course the major new problem here. I am looking to implement idle line detect to save nodes listening to all of a message not intended for them and also to use this as a method of collision avoidance.
So stay tuned, we may have some ideas we can share.

0 项奖励

1,839 次查看
rocco
Senior Contributor II
Hi, Daniel:

I notice that your buffer pointer is static, but the buffer itself is local. Therefore, the buffer is going to be created and destroyed on the stack for each character.

That may or may not be the problem . . .
0 项奖励