![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
stoyanoff
Joined: 20 Jul 2011 Posts: 375
|
universal RS232 communication protocol between controllers |
Posted: Fri May 31, 2013 1:36 am |
|
|
Hi! I want to use RS232 to transfer data between controllers. Till now I was using a simple protocol where the master demands data by sending special byte or prepares the slave for recieving data by sending another special byte. Here are code examples:
MASTER:
Code: |
#FUSES HS,NOWDT
#use delay(clock=20M)
#use RS232(STREAM=first,BAUD=9600,XMIT=PIN_D0,RCV=PIN_D1,PARITY=N,BITS=8,ERRORS,STOP=1,INVERT)
#define demandData 11
#define readyToRecieve 51
#define demandTransfer 78
void TransmitData(int dataCount)
{
int status=0;
int counter=0;
int command;
while(status!=1)
{
putc(demandTransfer);
while(counter<250)
{
if(kbhit(first))
{
command=getc(first);
if(command==readyToRecieve)
status=1;
}
counter++;
}
counter=0;
}
putc(dataCount,first);
for(int i=0;i<dataCount;i++)
{
putc(outcomeDataBuffer[i],first);
}
delay_ms(50);
}
int recieveData()
{
int counter=0;
int incomeDataCounter=0;
putc(demandData);
while(counter<250)
{
if(kbhit(first))
{
incomeDataCounter=getc();
for(int i=0;i<incomeDataCounter;i++)
{
incomeDataBuffer[i]=getc();
}
for(i=0;i<incomeDataCounter;i++)
{
writeint(incomeDataBuffer[i],0xc0);
delay_ms(1000);
}
return 1;
}
counter++;
}
return 0;
}
|
SLAVE:
Code: |
#FUSES HS,NOWDT
#use delay(clock=10M)
#use RS232(STREAM=first,BAUD=9600,XMIT=PIN_F1,RCV=PIN_F0,PARITY=N,BITS=8,ERRORS,STOP=1,INVERT)
#define demandData 11
#define readyToRecieve 51
#define demandTransfer 78
int RecieveData(int bytesToTransfer)
{
int command;
int dataCount=0;
if(kbhit())
{
command=getc();
if(command==demandTransfer)
{
putc(readyToRecieve);
while(!kbhit());
dataCount=getc();
for(int i=0;i<dataCount;i++)
{
incomeDataBuffer[i]=getc();
}
return dataCount;
}
if(command==demandData)
{
putc(bytesToTransfer);
if(bytesToTransfer!=0)
{
for(int i=0;i<bytesToTransfer;i++)
{
putc(outcomeDataBuffer[i]);
}
}
}
}
return 0;
}
|
The problem is this method is not quite sure because sometimes the transfered data is not correct. Can you offer me 100% sure method for bidirection USART transmition between controllers??
May be something with returning ACK will be more accurate?
Thanks! |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Fri May 31, 2013 2:21 am |
|
|
What kind of errors are you getting?
Missing data?
Too much data?
Corrupted data?
Anything else?
Mike |
|
![](templates/subSilver/images/spacer.gif) |
stoyanoff
Joined: 20 Jul 2011 Posts: 375
|
|
Posted: Fri May 31, 2013 2:49 am |
|
|
Corrupted data! |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Fri May 31, 2013 3:16 am |
|
|
stoyanoff wrote: | Corrupted data! |
What are the possible causes?
What I'm saying is:-
Don't make stabs in the dark, in the hope of stumbling on a solution.
Tackle the problem head on.
Mike |
|
![](templates/subSilver/images/spacer.gif) |
stoyanoff
Joined: 20 Jul 2011 Posts: 375
|
|
Posted: Fri May 31, 2013 3:51 am |
|
|
I suppose there is somekind of problem with the getting the start byte from the reciever. After the master recieves the correct byte (the slave is ready) by unknown reasons next databytes are uncorrect.. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19365
|
|
Posted: Fri May 31, 2013 3:55 am |
|
|
100% reliable. No.
You are never going to get to this. It is like standing on a solid rock. It is still not a '100% reliable way of stopping yourself sinking to the centre of the Earth'. 99.9, and then add as many nines as you want, but at the worst case, there are always little 'sneakers', like quantum theory, which potentially makes it possible for you to sink through the stone.....
There are lots of bits/questions to this.
First is what you want to do if a communication is corrupted?. This is critical.
The 'relatively full' solution, is to think in terms of a data 'packet'.
Start with this having a 'device ID', followed by a 'packet ID'. Then the data, followed by a checksum.
Now the receiving device, looks for packets with it's ID.
It then receives the whole packet, and decodes the checksum.
If the checksum is 'good', it acknowledges with it's own packet, saying "OK, I have received packet xxxx and a checksum".
Now the master holds a 'stack' of packets it wants to send. It works through the stack, and if a packet is waiting to send, send it. Then advances to the next packet. If there are gaps in the stack, it pauses for the same duration as the packet would take. It removes packets from the stack, _only_ when it receives a "received packet" message for this packet number.
Now, you'd need to work out how much data the packet should hold, and the checksum algorithm.
Simpler, if loss of a single packet does not matter, just have the slave ignore packets with an invalid checksum. Then 'replies' are not needed.
Key thing with the reply approach, is that the transmission is based upon some form of timer 'tick', sending packets at intervals, and keeping re-sending them if an acknowledgement is not received. This is the basis of most systems sending data over most data networks. However the 'throw away a packet with a bad checksum' approach, is the basis used where speed is vital (things like Skype, and video conferencing). These instead use the approach of interpolating for a moment when this happens. You can also add some form of partial error recovery. So a few small errors still leave acceptable data (look at Shannon encoding). A lot of systems use a combination of both. So data stored on hard drives, is commonly encoded so individual bit errors can be recovered from, and also with a checksum to each packet, and a retry if this is bad.
Now a lot depends on the nature of your corruption, and the nature of your data. If (for instance), it is actually single bit errors caused by things like lights being turned on, then something like Shannon encoding can recover this. However if it is (say) 'burst' errors, where when a particular motor switches on, data is lost for a fraction of a second, another approach is to alter the time sequence of the data. So instead of sending packets as 1,2,3,4,5....., you instead send, 1,8,16,2,9,17.... Now an interference 'burst', that destroys three packets, only leaves three 'one packet' holes in the data stream, instead of a three packet hole. If you design the data so you can interpolate a single lost packet, then the latter allows recovery....
If you look at data from things like remote spacecraft, the data from these is designed with a huge amount of error recovery built in. Reason is that a 'resend' request could take hours to reach them, and they don't have enough data storage to hold data for this sort of time interval.
Important to also understand something about 'data'. If I send you a packet of data, and 'to be sure', send it a second time, how does the receiver know which one is 'good'?. I can't without extra stuff like a checksum. So you end up sending 2 copies, and checksums. Depending on the packet size, 2+ times as much data. Just two one bit errors in each copy still leaves the data as unrecoverable. However basic Shannon encoding allows any one bit error to be recovered with only 1.5* the data being sent. You can use much longer encoding forms to increase the number of bits that can be lost, with recovery or detection.
You need to do some testing, and identify the nature of your losses. If it is just an occasional bit, and loss of a single packet is acceptable, then a simple checksum will be the 'easiest' solution. Beyond this, the nature of the data loss, will affect what the best solution is.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19365
|
|
Posted: Fri May 31, 2013 4:23 am |
|
|
Big problem with the code. Get rid of 'invert'.....
If you need to have the signal inverted, then add external buffering to do this.
Problem is that by specifying 'invert', you are forcing a software UART to be used. This means that the slave device _must_ be waiting to receive data when it arrives, or bits will be missed. If your slave code does anything at all, data will be lost.
Seriously, use the hardware UART, get rid of invert, and use interrupt driven buffering on the receive. Data reliability will go up by several orders of magnitude straight away....
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9173 Location: Greensville,Ontario
|
|
Posted: Fri May 31, 2013 5:19 am |
|
|
along with what has been said...
hardware issues..
You don't say which PICs you're using but
seems like you need two UARTS(1 to other PIC, 1 to PC).
so...you should use a PIC with 2 hardware UARTs(like the 46k22) or add one as a peripheral.
The use of 'invert' says you're not using a MAX232 type interface for PIC2PIC communications. Bad move if so.Depending on speed,distance,local EMI,etc. 'simple' TTL level data transfers are not reliable.I can easliy get 15 miles on solid copper with my tranceivers.
software issues...
You should use ISRs and buffers for data transfers. Easy,reliable,CCS has examples(ex_sisr.c) in the examples folder.
hth
jay |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri May 31, 2013 7:01 am |
|
|
my candidate for major trouble is this line,
in the 'receive' function.
delay_ms(1000);
with a software UART that is a HUGE potential for trouble.
though the looping getc() that precedes it has a risk all
its own.
there is simply too much interlocking complexity
and protocol dependency - for a software uart |
|
![](templates/subSilver/images/spacer.gif) |
stoyanoff
Joined: 20 Jul 2011 Posts: 375
|
|
Posted: Fri May 31, 2013 7:23 am |
|
|
Hardware RS232 is OK, but I want to have 2 channels(to communicate with 2 micros). So I don`t have 2 hardware RS232 and 1 of them must be software.
Is it possible to sepparate the hardware RS232 - to use the RX on 1 channel and TX on other channel???
Thanks! |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19365
|
|
Posted: Fri May 31, 2013 8:03 am |
|
|
Just use one UART, and RS485....
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Sat Jun 01, 2013 8:45 am |
|
|
Yes, you could mix up the hardware and software UARTs, if they run at the same baud rate. The real killer with software UARTs though, is that it's almost impossible to make them run in full-duplex mode (receiving and transmitting at the same time). You can do it if you use a recurring timer interrupt at 4x the baud rate, and poll the incoming line for data, but that implies very frequent interrupts and a slow baud rate. And if you insist on using the delay() instruction anywhere, forget it.
One easy solution to the need for multiple UARTs is simply to use multiple processors, and communicate between them some other way. They're cheap little things, so it could be an option.
The RS485 approach implies not just getting packets back and forth between processors, but arbitrating which one should transmit at any given time. It's certainly workable, but you have to know what you're doing. |
|
![](templates/subSilver/images/spacer.gif) |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sat Jun 01, 2013 12:34 pm |
|
|
stoyanoff wrote: | Is it possible to sepparate the hardware RS232 - to use the RX on 1 channel and TX on other channel??? | Yes, when the baudrate of both devices is the same it is very well possible to use the Rx for one device and the Tx for another device.
The reason you get so many different answers here is because we have no idea what you want to do. Gives us more details about your system and the answers you get will be better. |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9173 Location: Greensville,Ontario
|
|
Posted: Sat Jun 01, 2013 12:58 pm |
|
|
Also required is the distance between the two PICs.There is a tradeoff of baudrate vs. distance.Depending on which 'MAX232' type devices you're using will affect performance.
CCS does have a simple method of connecting several PICS ,shown in the FAQ section of the help files,software should be in the examples folder.
I've used a variation of it for years getting several miles between nodes.
hth
jay |
|
![](templates/subSilver/images/spacer.gif) |
stoyanoff
Joined: 20 Jul 2011 Posts: 375
|
|
Posted: Sun Jun 02, 2013 2:24 am |
|
|
This is a good idea. I suppose when several micros are connected to 1 dataline a device address byte is used as in I2C transfer
Usually I`m using parallel data transfer which is 99% reliable but it demands a lot of wires and pins. So I want to use something more complex but with same reliability... |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|