# 2 PICs connected with RS232

Status
Not open for further replies.

#### janetsmith2000@yahoo.com

##### New Member
Hi,

I wish to connect two PiCs together using RS232.
There are 2 inputs, Vin1 and Vin2 (analog). The signals are converted into Digital form and passed it to the next PIC via RS232 connection.

However, on the receiver End, how the PIC distinguish if the signal is coming from Vin1 or Vin2?

#### Attachments

• 2pic_rs232.gif
3.7 KB · Views: 994

#### bmcculla

##### New Member
Just send two bytes. The first is the channel number and the second is the value. Or if your values are 10 or 12 bits just use the unused bits as a channel number.

Brent

#### janetsmith2000@yahoo.com

##### New Member
how to make sure the receiver end has the same timing as the Tx PIC?

let's say, four bytes are sent in sequence,
0x01 0x07 0x02 0x66
which shows channel 1 produces 0x07, channel 2 produces 0x66.

How to avoid the receiver misinterprete it as channel 7 produces 0x02?
Do I have to insert some escape number, like 0x00 as the start flag of each reading?
0x00 0x01 0x07 0x00 0x02 0x66

#### ivancho

##### New Member
What you need to do is create your own protocol. As I posted recently in another message, I normally use ASCII 27 (ESC) as my "syncronization key"

So say you send a ESC + 1 + VALUE

On the other end your pic waits for the ESC command, then it knows that what comes next is the channel and the one after that is the value. It is not completly fool proof... but it works well for me

Ivancho

#### bmcculla

##### New Member
You could also use a simple master slave protocol. The Master sends a byte that requests data from a specific A to D on the Slave. The slave then sends the correct data. The slave only sends data when its requested by the master.

Brent

#### janetsmith2000@yahoo.com

##### New Member
bmcculla:
i think in order to implement the master-slav method, i have 2 provide a fix number of pins for slave, i cannt add extra slave later on so the flexibility will be some how limited. Thanks

ivancho:
for the ESC + 1 + VALUE format, what if the value is also ESC?
that is, the data will be ESC + 1 + ESC. How do u solve this problem?

#### Exo

##### Active Member
You received a ESC (27), then you know the next two bytes are data and channel, even if one of them is a ESC also...

#### ivancho

##### New Member
Yep, ditto on what EXO said..... you are always pulling the port for 3 bytes.

#### janetsmith2000@yahoo.com

##### New Member
Hi,

I've developed the code using the ideas of u guys. both sensor and receiver are using XTAL 20 Mhz. The baud rate for the rs232 is 9600.
I have made a loop to check the incoming byte continuosly. However, if the loop is rather slow, some data will be missing.
How to ensure the loop is fast enough to catch all the incoming byte? or perhaps we could make sensor send data in slower rate?

/* sensor */
void main() {
SENSOR sensor[SENSOR_SIZE];
BYTE i;

while (TRUE) {
sensor[TEMPERATURE].value = 45;
sensor[DIP_SWITCH].value = input_d();
sensor[RANDOM].value = 34;
sensor[SINE_WAVE].value = 33;

for (i = 0; i < SENSOR_SIZE; i++) {
putc(SYNC_BYTE);
putc(sensor.id);
putc(sensor.value);
}
}
}

void main() {

BYTE i;
RECV recv;
DATA_BUFFER data_buffer;

recv.sm_recv = SM_RECV_LISTEN;
recv.byte_count = sizeof(SENSOR);

data_buffer.data_count = 0;

while (TRUE) {
while (kbhit()) {
switch(recv.sm_recv) {

case SM_RECV_LISTEN:
if (getc() == SYNC_BYTE) {
recv.sm_recv = SM_RECV_ID;
}
break;

case SM_RECV_ID:
data_buffer.sensor[data_buffer.data_count].id = getc();
recv.sm_recv = SM_RECV_ID;
break;

case SM_RECV_VALUE:
data_buffer.sensor[data_buffer.data_count].value = getc();
data_buffer.data_count++;
recv.sm_recv = SM_RECV_LISTEN;
break;
}
}
}
}

#### bmcculla

##### New Member
Interrupts are the best way to solve this problem. The UART hardware should generate an interrupt when it finishes receiving a byte. You just have an interrupt service routine save the values into a buffer for use in the main part of the program when it has time. You will have to write some low level code to work with the UART instead of the putc and receive command that you are using, but its not that hard.

The master slave protocol I suggested earlier would also solve this problem. To solve the problem of knowing how many channels the slave has you just implement a command from the master that asks the slave how many channels it has.

Brent

#### janetsmith2000@yahoo.com

##### New Member
The program i've written will loop continuosly to check if a new Internet packet has been intercepted. on the other end, it also checks for the signal coming from the sensor.

If i use interrupt mechanism, i afraid that my PIC doesnt have time to check for the internet packet, as there is a continuosly data flow from the sensor, and thus keeps the PIC in Interrupt mode always.

#### Nigel Goodwin

##### Super Moderator
janetsmith2000@yahoo.com said:
If i use interrupt mechanism, i afraid that my PIC doesnt have time to check for the internet packet, as there is a continuosly data flow from the sensor, and thus keeps the PIC in Interrupt mode always.

If you're using the hardware USART you've got all the time the serial data is arriving to do other things, only when a complete byte is assembled in the buffer does it generate an interrupt. You then process the byte and return to what you were doing while the next byte is arriving in the USART.

You've got a great deal more time for your program, using interrupts from the USART, than you have without them.

#### motion

##### New Member
How fast are you getting data from the sensors? You are sending 3 bytes per sensor reading. At 9600 baud 8-bits & no parity, you are sending a maximum of 960 bytes/sec or 320 sensor readings/sec.

The 20Mhz PIC can easily service 960 interrupts/sec. I have written programs for a 20Mhz PIC that serve interrupts at close to 20Khz rate with code longer than your sample. Even using polling will not tax the PIC. 9600 baud is so slow that in 20Mhz PICs, I use polling to receive and transmit thru the USART while refreshing an LCD. I use interrupts for faster events like generating pulses for a stepper motor driver.

The bottle neck is really the communications baud rate. You should consider increasing the baud rate to cope with the sensor sampling rate.

#### janetsmith2000@yahoo.com

##### New Member
if i am not going to use interrupt, would i solve the problem if i change the oscillator of sensor_pic to 4Mhz and set a lower baud rate for it?

#### motion

##### New Member
janetsmith2000@yahoo.com said:
if i am not going to use interrupt, would i solve the problem if i change the oscillator of sensor_pic to 4Mhz and set a lower baud rate for it?

I don't fully understand your problem. I don't think reducing the clock will eliminate it. Both the sample rate and the transmission rate will be reduced to 1/5 of the original speed.

Does the "putc" function wait for an empty transmit register before writing to it? If not, then that is the reason why you are losing some data.

Another issue is that your receiver program wait for a kbhit() before receiving a byte. Would it result in some bytes being overrun?

#### janetsmith2000@yahoo.com

##### New Member
After i catch the 1st byte (sync), i will assume the next byte would be id byte, but if the next byte arrives before the receiver able to detect it, the receiver will take the 3rd byte as the id byte.

#### Nigel Goodwin

##### Super Moderator
janetsmith2000@yahoo.com said:
After i catch the 1st byte (sync), i will assume the next byte would be id byte, but if the next byte arrives before the receiver able to detect it, the receiver will take the 3rd byte as the id byte.

There are many ways of dealing with your problem, as already suggested using an interrupt routine triggered by the USART would give you loads of time to do what you want (about 1mS for each byte received at 9600 baud - that's about 5000 instructions). There shouldn't be any chance of missing a byte.

Using the USART and polling for the completed flag would still give you loads of time as well, as long as you don't spend more than 1mS on processing between checking the flag.

But even using a software UART would probably give you plenty of time, the stop bit at the end is around 100uS, as long as your processing is faster than that it wouldn't lose anything either - that's about 500 instructions at 20MHz.

As you are generating the signal yourself, you could also add extra stop bits, adding a second one would double your available time to 200uS (assuming a software UART).

#### bmcculla

##### New Member
I'd bet that getc polls for an incomming char preventing you from doing anything else in that time. Interrupts are the way to go. You might consider making your Ethernet packets interrupt driven too.

You should write your own code for the low level send and receive functions to make them work with interrupts. Writing your own functions might take a bit of time but you won't be tripped up by the unknown behavior of the standard functions.

Code:
void UART0_ISR (void) interrupt 4
{

if (TI0)
{
TI0 = 0;
UART0Busy = 0;
}
if (RI0)
{
RI0 = 0;
}

}

{

SFRPAGE = UART0_PAGE;
if(CircBufNotEmpty(&TxBuf))
{
if (!UART0Busy)
{
EA = 0;
IE &= 0xEF;
SBUF0 = CircBufRemoveElement(&TxBuf);
UART0Busy = 1;
IE |= 0x10;
EA = 1;
}
}

}

Here are some interrupt driven uart functions that I wrote for the 8051. The new putc function puts a character onto the transmit buffer instead of printing it directly. The main function calls all the Task_ functions in sequence in a while (1) loop. The Task_ functions check a single time if there is something to do and exit immediately if there isn't. The result is polling with something happening in at the same time. You just have to keep the functions from being too long.

Hope this helps
Brent

Status
Not open for further replies.

Replies
13
Views
2K
Replies
1
Views
2K
Replies
15
Views
3K
Replies
6
Views
2K
Replies
6
Views
1K