|
|
View previous topic :: View next topic |
Author |
Message |
sysysy
Joined: 17 Nov 2010 Posts: 38 Location: 121
|
DUPLEX COMMUNICATION for PIC16F877A |
Posted: Sat Mar 26, 2011 10:56 am |
|
|
I'm using 2 set of RF module 315Mhz and 433Mhz for communication between the control board (MCU1) and the small car board (MCU2).
For 1 way communication, it work very well, I can just simply wireless control the car movement direction.
But when now wanna proceed to full duplex communication, it cant work at all. I try separately in tx and rx pin both MCU, all work well, but when come to 2 way communication...dunno why everything like down.
Last edited by sysysy on Sat Mar 26, 2011 9:41 pm; edited 1 time in total |
|
|
sysysy
Joined: 17 Nov 2010 Posts: 38 Location: 121
|
|
Posted: Sat Mar 26, 2011 12:29 pm |
|
|
Eventually, it is work...
but i wonder why the full duplex communication will make all the things become lag... juz like many packet lost ....
in default mode(when i press ntg), i send 'U', but in another side, not necessary stable'U' displayed, but sometimes the data will be changed....
i know it is not stable, but i dunno what is the main cause.... |
|
|
sysysy
Joined: 17 Nov 2010 Posts: 38 Location: 121
|
|
Posted: Sun Mar 27, 2011 12:54 am |
|
|
Hi,
can anyone tell me what is hardware uart and software uart?
i am using pin rc6 and rc 7 of 16f877a uart port...then that mean im controlling them with software, right? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sun Mar 27, 2011 1:55 am |
|
|
C6, and C7, are the hardware UART pins. So unless you are doing something 'silly', you have the full advantages of a hardware UART. You _never_ want to use a software UART, if you can help it, and with a software UART only 'half duplex' is supported.
I'd suspect your problem is the nature of your code. Key thing to understand is that the hardware UART, _only_ has just under two characters of buffering in each direction. If (for instance), you have code like:
Code: |
printf("FRED");
if (kbhit()) in=getc();
|
Then after the first two characters of 'FRED' are transferred to the output, the code _sits and waits_ till these are sent, before it can send the last two characters. Meanwhile, there are only 1.9999 characters of input buffering, so if the communication is properly 'full duplex', input data _will_ be lost while waiting.
For 'full duplex' comms, you _must_ use interrupt driven receive with a larger input buffer _as the minimum_ (ex_sisr.c).
So:
Software UART _only_ supports half duplex at best.
Hardware UART gives half duplex plus a couple of characters 'overlapped' comms, without interrupt buffering.
Hardware UART with interrupt driven receive, gives full duplex, but you have to 'wait' for transmission.
Full duplex, without transmission waits, requires interrupt driven TX and RX.
Best Wishes |
|
|
sysysy
Joined: 17 Nov 2010 Posts: 38 Location: 121
|
|
Posted: Mon Mar 28, 2011 12:14 pm |
|
|
Hi, the code below is work well in half duplex, but when come to full duplex it is super super lag and slow response...I'm guessing because the while_loop at the read_packet function there.
But logically i think it should be like this...because all the time, i'm transmit data out, so in another side, the read packet always receive data and should not stuck in while loop keep waiting...
And if i simply comment out the read_packet in MCU2 side, so everything work smooth. the problem juz raise up when full duplex communication.
Can anyone suggest me a solution to solve this...
in MCU1
Code: |
#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=2400,RCV=PIN_C7, ERRORS,stream=x_command)
#use rs232(baud=2400,XMIT=PIN_C6, ERRORS,stream=x_data)
#define TEST_B PIN_C3
#define SYNC_DATA 0x00
#define RECEIVE_HEADER 0xAA
#define SEND_HEADER 0xBB
#include "LCD.C"
char uart_rec(void)
{
char rec_data;
rec_data = fgetc(x_command);
return rec_data;
}
char read_packet(void)
{
char data;
char checksum;
do
{
while (uart_rec() != RECEIVE_HEADER);
data = uart_rec();
checksum = uart_rec();
} while (checksum != (char)(RECEIVE_HEADER + data));
return data;
}
void uart_send(char data)
{
fputc(data,x_data);
}
void send_packet(char data)
{
char i;
char buffer[3];
buffer[0] = SEND_HEADER;
buffer[1] = data;
buffer[2] = (char)(SEND_HEADER + data);
for (i = 0; i < 3; i++) uart_send(SYNC_DATA);
for (i = 0; i < 3; i++) uart_send(buffer[i]);
}
void main()
{
char command=0;
lcd_init();
lcd_putc("\fDTesting");
set_tris_B(0b111100);
set_tris_A(0);
while(1)
{
command = read_packet();
printf(lcd_putc,"\f %c",command);
send_packet('O');
while(input(TEST_B)==0)
send_packet('J');
}
}
|
in MCU2
Code: |
#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=2400,XMIT=PIN_C6,errors,stream=tx_mit)
#use rs232(baud=2400,RCV=PIN_C7,errors,stream=rx_rcv)
#define TX_Forward PIN_A3
#define TX_Reverse PIN_A0
#define TX_INC PIN_B5
#define TX_DEC PIN_B4
#define TX_Right PIN_A4
#define TX_Left PIN_A2
#define SYNC_DATA 0x00
#define SEND_HEADER 0xAA
#define RECEIVE_HEADER 0xBB
#include "LCD.C"
char uart_rec2(void)
{
char rec_data1;
rec_data1 = fgetc(rx_rcv);
return rec_data1;
}
char read_packet2(void)
{
char data0,data1;
char checksum1;
while (uart_rec() != RECEIVE_HEADER);
data1 = uart_rec();
return data1;
}
void uart_send(char data)
{
fputc(data,x_command);
}
void send_packet(char data)
{
char i;
char buffer[3];
buffer[0] = SEND_HEADER;
buffer[1] = data;
buffer[2] = (char)(SEND_HEADER + data);
for (i = 0; i < 3; i++) uart_send(SYNC_DATA);
for (i = 0; i < 3; i++) uart_send(buffer[i]);
}
void main()
{
char display=0;
lcd_init();
set_tris_A(0b111111);
set_tris_B(0b11111111);
printf(lcd_putc,"\fRF control");
while(1)
{
display=read_packet2();
printf(lcd_putc,"\n %c",display);
send_packet(0x55);
while(input(TX_Forward)==0)
send_packet('A');
while(input(TX_Reverse)==0)
send_packet('B');
while(input(TX_INC)==0)
send_packet('C');
while(input(TX_DEC)==0)
send_packet('D');
while(input(TX_Right)==0)
send_packet('G');
while(input(TX_Left)==0)
send_packet('F');
send_packet(0x55);
}
}
|
|
|
|
sysysy
Joined: 17 Nov 2010 Posts: 38 Location: 121
|
|
Posted: Tue Mar 29, 2011 11:17 am |
|
|
Hi Ttelmah,
in PIC 16f877A, the int_rda is it mean i already set the RCIE. then when RCIF also be set, then the int_rda will be trigger, am i right?
1 more things,
i wanna ask that when i replace my code
if ( fgetc(data)=='0xBB') {....}
from
while( fgetc(data)!='0xBB');{...}
then my things become not working?
i taught that they are same meaning. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9228 Location: Greensville,Ontario
|
|
Posted: Tue Mar 29, 2011 11:29 am |
|
|
== means is equal to...
!= means is NOT equal to....
With a project open, pressing F11 will bring up the CCS help screens, full of information.
hth |
|
|
sysysy
Joined: 17 Nov 2010 Posts: 38 Location: 121
|
|
Posted: Tue Mar 29, 2011 11:38 am |
|
|
temtronic wrote: | == means is equal to...
!= means is NOT equal to....
|
I know this but just...
In if (fgetc(data)=='0xBB')...i juz proceed to implement things that i want when the data is '0xBB'...
but in while( fgetc(data)!='0xBB');
if data not a '0XBB' , it is keep looping until data is '0XBB' then juz escape the loop. Then doing a following things...
so, this is equal... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9228 Location: Greensville,Ontario
|
|
Posted: Tue Mar 29, 2011 12:04 pm |
|
|
Would have to see all of the program to see what is happening..you may have missed a semicolon or a bracket and even though it compiles fine, may not do what you think it should. |
|
|
sysysy
Joined: 17 Nov 2010 Posts: 38 Location: 121
|
|
Posted: Wed Mar 30, 2011 8:42 am |
|
|
Hi,
i try in many ways, but my full duplex really cant work.
sometimes maybe my question is silly, but i'm really not so understand to this... I'm sorry...
as Ttelmah reply before,
for full duplex , muz be use interrupt...
in my case,
i wonder why once i put both of my controller fgetc() together, whole things not work. But it really work well when i use half duplex communication only.
i also try the way use int_rda interrupt,
but also not work at all, i even suspect my program never enter in #int_rda();
And i did below code in my main function.
enable_interrupts(int_rda);
enable_interrupts(global);
i read my PIC16f877a datasheet many many times. interrupt only happen when RCIE and RCIF be set. and RCIF is set when transfer complete from rsr to rcreg register.
Besides,
Back to origin, i ignore my own coding method,
i try to follow the simplest way from the ccs manual,
i only use fputc(); in my transmit side main function and only use fgetc() in my receiver side main function.
the result i get is, if i send 'A' out, the receiver side will have a sequence 5 data displayed on my lcd (80 84 21 5 65).... of course, once of them 65 is mean character 'A'. it is not remain in static 'A' in my receiver side.
another way, i use
Code: | if(kbhit()) display= fgetc(); |
it is worst, never get any data...i do try use getc() and both fgetc(), also same result. the reason i use fgetc() because i use stream.
I spend many time in trial and error, and some own my logic way...but no result.
Anyway, i really hope someone can really willing to patiently guide me. Although i am slow, but i really try my best to learn and solve this.
Thanks. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Mar 30, 2011 9:11 am |
|
|
You need to get your head round understanding that if you use 'putc' (or fputc, exactly the same except using streams), once more than 1.99999 characters is sent, the code will _wait_ for subsequent characters to be sent. If you send five characters, for three character times the code will just sit and wait. If more than two characters arrive _while this code is waiting_, they _will_ be lost. Unless your serial is in the form of 'send something', and data in the other direction _won't_ start till this is sent (half duplex - comms _only_ occur in one direction at a time), there _must_ be at the _minimum_ interrupt driven serial reception. If you want to be processing things while transmission occurs, then you also need interrupt driven transmission as well.
Using putc, and getc, directly in the 'main' code, _only_ works if you can wait for transmission to occur, and comms are half duplex. For full duplex comms, where you also need to be performing tasks asynchronously to the data, you need to be using interrupt driven transmit and receive.
Code for both of these, comes as examples with the compiler. use them.
Best Wishes |
|
|
sysysy
Joined: 17 Nov 2010 Posts: 38 Location: 121
|
|
Posted: Wed Mar 30, 2011 9:50 am |
|
|
may i know can my rda_isr routine write as this?
Code: | #int_rda
void rcv_isr()
{
if(fgetc(x_data)==0xAA) // when first byte = to the header byte
c_data = fgetc(x_data); // second bye is data character desired receive
printf(lcd_putc,"\f %c",command);
}
|
In 2 reply post from you, you keep telling me
Quote: | once more than 1.99999 characters is sent, the code will _wait_ for subsequent characters to be sent. |
maybe, you trying to explain me something based to my previous question, but i really don't know main point of this. From what i understanding,
In my sending pattern...everytime i transmit my data out,
I write that in the, send_packet function
Code: |
void send_packet(char send_data)
{
fputc(0xAA,x_command); // send the data header byte
fputc(send_data,x_command); // send the actual data
}
|
So, everytime, at most I just transmit out 2 byte data only.
Finally if let say in my main program
Code: |
while(1)
{
send_packet('A');
if(fgetc(x_data)==0xAA)
c_data = fgetc(x_data);
printf(lcd_putc,"\f %c",command);
}
|
from my own logic, send data and receive data do not have obvious conflict at all since i keep looping send data and check condition to receive data. In addition, tx and rx never share any registers. so, if make this in half duplex, it work well. But once i make this in both of my PIC main program, they r not working. Just like there is a conflict happen, i cant figure out what happen.
Yes, i am trying to understand the interrupt example also, because it use a lot of buffer that i am not so understand. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Mar 30, 2011 10:10 am |
|
|
The interrupt being called, implies there is just _one_ character waiting. Your code here, then waits for a second character, and then sends a character back. Three transactions, for the one arriving character...
The whole point is your entire code needs to be 'full duplex'. The INT_RDA, must receive just _one_ character, and nothing else.
Use INT_TBE, to send data.
Your code needs to be looping, doing it's work, and the interrupts need to do _just_ their jobs. INT_RDA, should receive one character _only_ anything much else destroys your duplex comms...
Best Wishes |
|
|
sysysy
Joined: 17 Nov 2010 Posts: 38 Location: 121
|
|
Posted: Fri Apr 01, 2011 11:29 am |
|
|
Hi Ttelmah,
Now I already use both tbe and rda interrupt in the both MCU program already.
So I trying to display the data on the LCD in each of the MCU while each of them is keep transmitting data.
The problem is the data is super not stable, means variety of weird character is displayed/blinking on my both LCD. And maybe 1 of them just the actual data that I sent from other MCU. I did use the buffer method which refer from the ccs example.
Anyway, the interrupt method that I tried in half duplex also work well, but facing problem in full duplex comm.
May I know most probably what cause this happen? |
|
|
|
|
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
|