View previous topic :: View next topic |
Author |
Message |
kmp84
Joined: 02 Feb 2010 Posts: 345
|
#int_rda and Buffering + rs485 |
Posted: Fri Jun 11, 2010 2:40 pm |
|
|
Hi Friends...I'm new programmer and I have a problem with serial asynchronous communication between PC and PIC with rs485 driver (SN75176).
When I send a packet with SIO monitor to my PIC16F628A I do not get a valid packet ...??? Here is my code:
Code: |
/*
1 1 1 1 2 1 1 Bytes
|*********|***|*******|***********|*******|****|
|STX |Addr|COP|ACK/NAK| data |CRC_?? |ETX |
**********************************************
*/
#include <16F628A.h>
#device *=16
#fuses HS,NOWDT,NOPROTECT,NOLVP,MCLR
#use delay(clock=11 059 200)
#use rs232(baud=9600,xmit=PIN_B2,rcv=PIN_B1,enable=PIN_B3,errors)
//#include <CRC_mod.C>
#define STX_PC 0xD2
#define ETX_PC 0xD3
#define STX_N8 0xC2
#define ETX_N8 0xC3
#define ACK 0x41
#define NAK 0xFF
#define cop_on_rly 0x61
#define cop_off_rly 0x62
#define cop_status 0x63
#define address 0x01
#define BUFFER_SIZE 64
// #define BUFFER_SIZE_2 9
int packet_buffer[BUFFER_SIZE];
int ext_buffer[BUFFER_SIZE];
int next_in;
int next_out;
#define data_in (next_in!=next_out)
#int_rda
void serial_isr() {
ext_buffer[next_in]=getc();
if(++next_in==BUFFER_SIZE) // Buffer full !!
next_in=0;
}
/*
#int_ext
void power_down_isr (){
*/
int get_buff_int()
{
int retval;
while(!data_in);
retval = ext_buffer[next_out];
if(++next_out == BUFFER_SIZE)
next_out = 0;
return retval;
}
// GET_PACKET
// function to get a packet from the buffer and read the data
short get_packet(int * packet_ptr)
{
short retval;
int CRC;
retval = TRUE;
packet_ptr[0] = get_buff_int(); //STX_PC 0xD2
if(packet_ptr[0] != STX_PC)
retval = FALSE;
putc (packet_ptr[0]);
packet_ptr[1] = get_buff_int();
if(packet_ptr[1] != address) //addres_slave 0x01
retval = FALSE;
putc (packet_ptr[1]);
packet_ptr[2] = get_buff_int(); // COP 0x60.61,62
putc (packet_ptr[2]);
packet_ptr[3] = get_buff_int(); // ACK/NAK 0x41/0xFF
if(packet_ptr[3]!= ACK)
retval = FALSE;
putc (packet_ptr[3]);
packet_ptr[4] = get_buff_int(); // data_byte 1byte
putc (packet_ptr[4]);
packet_ptr[5] = get_buff_int(); // data_byte 1byte
putc (packet_ptr[5]);
packet_ptr[6] = get_buff_int(); // CRC_check 1byte
// CRC=packet_ptr[6];
//if(CRC != generate_8bit_crc(packet_ptr, 7 , CRC_8))
// retval = FALSE;
putc (packet_ptr[6]);
packet_ptr[7] = get_buff_int();
if(packet_ptr[7] != ETX_PC) //ETX_PC 0xD3
retval = FALSE;
putc (packet_ptr[7]);
return retval;
}
void boot_led ()
{
output_low (PIN_A2);
output_low (PIN_A3);
}
void main() {
next_in=0;
next_out=0;
setup_timer_0(T0_EXT_H_TO_L|T0_DIV_2);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(global);
enable_interrupts(int_rda);
boot_led ();
printf("\r\n\Running...\r\n");
while (TRUE){
// delay_ms (50);
if(!data_in)
continue;
if(get_packet(packet_buffer))
{
output_high (PIN_A2);
output_low (PIN_A3);
// printf(" Valid Pecket \r\n\n");
}
else
{
output_high (PIN_A3);
output_low (PIN_A2);
// printf(" Wrong Packet \r\n\n");
}
}
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jun 11, 2010 5:04 pm |
|
|
You need a method to debug your program. You need to find out what
is wrong with the packet.
I suggest that you add a software UART port, with a MAX232-type chip
and send debug information to a terminal window on the PC.
Or, you could add an LCD, and use that to display debug information.
But the terminal window method is better.
Then, after the packet is received, you can transmit the bytes to the
terminal window as Hex numbers by using printf with "%x". |
|
![](templates/subSilver/images/spacer.gif) |
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Fri Jun 11, 2010 11:57 pm |
|
|
Hi PCM Programmer..! I'm using function "putc();" for debugging info, and I see a valid packet back, but
Code: |
if(get_packet(packet_buffer))
{
output_high (PIN_A2); // turn_on red_led
output_low (PIN_A3); // turn_off green_led
// printf(" Valid Pecket \r\n\n");
}
else
{
output_high (PIN_A3); // turn_on green_led[i]
output_low (PIN_A2); // turn_off red_led
// printf(" Wrong Packet \r\n\n");
}[/i]
}
} |
this function turn_on wrong green led (wrong packet) every time ?
I forget to post my compiler version. v.4.104 |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Sat Jun 12, 2010 9:21 am |
|
|
Change your packet reader, so you can see which of the branches causes the problem. Something like (first part only):
Code: |
short get_packet(int * packet_ptr)
{
short retval = TRUE;
int CRC;
packet_ptr[0] = get_buff_int(); //STX_PC 0xD2
if(packet_ptr[0] != STX_PC) {
retval = FALSE;
putc ("stx");
}
packet_ptr[1] = get_buff_int();
if(packet_ptr[1] != address) { //addres_slave 0x01
retval = FALSE;
putc ("addr");
}
|
This way you will only get the debug message 'back', when it goes to the condition causing the 'false', and you will see what is triggering this.
As a comment, are you sure the application sending the message, does not add a LF, or CR (or both) to the packet?. If so, these need to be dealt with, or the message will rarely align where you expect it in the buffer....
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
kmp84
Joined: 02 Feb 2010 Posts: 345
|
#int_rda and Buffering + rs485 |
Posted: Mon Jun 21, 2010 6:04 am |
|
|
Hi. PCM,Ttelmah I found my problem, but I don't know how to do this:
1. My general problem is packets that receive is variable length and with circular buffering method and Func. get_packet(). Maybe is not True Way to receive different packets with variable length. Can you tell me what is the best method for using "#int_rda " and variable length packet receive ?
Thanks:) |
|
![](templates/subSilver/images/spacer.gif) |
arunb
Joined: 08 Sep 2003 Posts: 492 Location: India
|
RE |
Posted: Wed Jun 23, 2010 2:14 am |
|
|
You must design a protocol ( a series of rules/format a packet must follow).
I thought this kind of a protocol should do
Code: | |STX |Addr|LEN|COP|ACK/NAK| data |CRC_?? |ETX | |
LEN indicates the length of data (payload only) that follows, you also need an array that could store the received data. LEN can be 1 byte long
So the packet would consist of a header, payload and a end of packet (EOP) part
Header size will be STX + Addr+ LEN+COP+ACK/NAK
Payload length is the total size of the data you wish to send.
EOP length is CRC bytes+ETX
The total size of the packet will be header size+payload size+EOP size
In the receive part of program all you need to do is to wait for ETX, then the address that will indicate if the packet is intended for the node, then the length of payload. |
|
![](templates/subSilver/images/spacer.gif) |
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Thu Jun 24, 2010 4:01 am |
|
|
hi.. My packet structure is defined,, Problem is that on the same rs485 bus have other slave devices with diferent packet , but my function "get_packet ()" requirement minimum 8 bytes for checking .. |
|
![](templates/subSilver/images/spacer.gif) |
|