|
|
View previous topic :: View next topic |
Author |
Message |
Jim Guest
|
Problem when modify the rs485 driver rs485.c |
Posted: Sat May 27, 2006 11:19 pm |
|
|
hi,
I am modifying the CCS driver rs485.c so that instead of having the Format: source | destination | data-length | data | checksum, it will have the following modified format:
Start-of-TX-char| source | destination | data-length | data | checksum
I defined the Start-of-TX-char as '^'.
The problem that I don't see the Start-of-TX-char as the first received character for a giving TXed, but I see the "source". Do you guys have any pointer? Here is the modified code from rs485.c. I am using PCH 3.228 and PIC16F876 and PIC16F628A ( the CCS RFID development kit)
Code: |
#ifndef RS485_DRIVER
#define RS485_DRIVER
#ifndef RS485_ID
#define RS485_ID 0x10 // The device's RS485 address or ID
#endif
#ifndef RS485_USE_EXT_INT
#define RS485_USE_EXT_INT FALSE // Select between external interrupt
#endif // or asynchronous serial interrupt
#if(RS485_USE_EXT_INT == FALSE)
#ifndef RS485_RX_PIN
#define RS485_RX_PIN PIN_C7 // Data receive pin
#endif
#ifndef RS485_TX_PIN
#define RS485_TX_PIN PIN_C6 // Data transmit pin
#endif
#ifndef RS485_ENABLE_PIN
#define RS485_ENABLE_PIN PIN_B4 // Controls DE pin. RX low, TX high.
#endif
#ifndef RS485_RX_ENABLE
#define RS485_RX_ENABLE PIN_B5 // Controls RE pin. Should keep low.
#endif
#use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=9, long_data, errors, stream=RS485)
#use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=9, long_data, force_sw, multi_master, errors, stream=RS485_CD)
#if getenv("AUART")
#define RCV_OFF() {setup_uart(FALSE);}
#else
#define RCV_OFF() {setup_uart(FALSE);}
#endif
#else
#ifndef RS485_RX_PIN
#define RS485_RX_PIN PIN_B0 // Data receive pin
#endif
#ifndef RS485_TX_PIN
#define RS485_TX_PIN PIN_B3 // Data transmit pin
#endif
#ifndef RS485_ENABLE_PIN
#define RS485_ENABLE_PIN PIN_B4 // Controls DE pin. RX low, TX high.
#endif
#ifndef RS485_RX_ENABLE
#define RS485_RX_ENABLE PIN_B5 // Controls RE pin. Should keep low.
#endif
#use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=9, long_data, errors, stream=RS485)
#use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=9, long_data, multi_master, errors, stream=RS485_CD)
#define RCV_OFF() {disable_interrupts(INT_EXT);}
#endif
#define RS485_wait_time 20 // Wait time in milliseconds
#bit rs485_collision = rs232_errors.6
#ifndef RS485_RX_BUFFER_SIZE
#define RS485_RX_BUFFER_SIZE 40
#endif
int rs485_state, rs485_ni, rs485_no;
int rs485_buffer[RS485_RX_BUFFER_SIZE];
[b]static int8 msg_hearder = '^'; /* start of the message char */[/b]
// Purpose: Enable data reception
// Inputs: None
// Outputs: None
void RCV_ON(void) {
#if (RS485_USE_EXT_INT==FALSE)
while(kbhit(RS485)) {getc();} // Clear RX buffer. Clear RDA interrupt flag. Clear overrun error flag.
#if getenv("AUART")
setup_uart(UART_ADDRESS);
setup_uart(TRUE);
#else
setup_uart(TRUE);
#endif
#else
clear_interrupt(INT_EXT);
enable_interrupts(INT_EXT);
#endif
}
// Purpose: Initialize RS485 communication. Call this before
// using any other RS485 functions.
// Inputs: None
// Outputs: None
void rs485_init() {
RCV_ON();
rs485_state=0;
rs485_ni=0;
rs485_no=0;
#if RS485_USE_EXT_INT==FALSE
enable_interrupts(INT_RDA);
#else
ext_int_edge(H_TO_L);
enable_interrupts(INT_EXT);
#endif
enable_interrupts(GLOBAL);
output_low(RS485_RX_ENABLE);
}
// The index for the temporary receive buffer
int8 temp_ni;
// Purpose: Add a byte of data to the temporary receive buffer
// Inputs: The byte of data
// Outputs: None
void rs485_add_to_temp(int8 b) {
// Store the byte
rs485_buffer[temp_ni] = b;
// Make the index cyclic
if(++temp_ni >= RS485_RX_BUFFER_SIZE)
{
temp_ni = 0;
}
}
// Purpose: Interrupt service routine for handling incoming RS485 data
#if (RS485_USE_EXT_INT==FALSE)
#int_rda
#else
#int_ext
#endif
void incomming_rs485() {
int16 b;
static int8 cs,state=0,len;
static int16 to,source;
[b]static int1 header_find = FALSE;[/b]
b=fgetc(RS485);
[b] if (!header_find)
{
if (msg_hearder == b)
{
header_find = TRUE;
}
return;
}[/b]
cs^=(int8)b;
switch(state) {
case 0: // Get from address
temp_ni=rs485_ni;
source=b;
cs=b;
rs485_add_to_temp(source);
break;
case 1: // Get to address
to=b;
#if (getenv("AUART")&&(RS485_USE_EXT_INT==FALSE))
setup_uart(UART_DATA);
#endif
break;
case 2: // Get len
len=b;
rs485_add_to_temp(len);
break;
case 255: // Get checksum
if ((!cs)&&(bit_test(to,8))&&(bit_test(source,8))&&((int8)to==RS485_ID))
{ // If cs==0, then checksum is good
rs485_ni=temp_ni;
}
#if (getenv("AUART")&&(RS485_USE_EXT_INT==FALSE))
setup_uart(UART_ADDRESS);
#endif
header_find = FALSE;
state=0;
return;
default: // Get data
rs485_add_to_temp(b);
--len;
break;
}
if ((state>=3) && (!len)) {
state=255;
}
else {
++state;
}
}
// Purpose: Send a message over the RS485 bus
// Inputs: 1) The destination address
// 2) The number of bytes of data to send
// 3) A pointer to the data to send
// Outputs: TRUE if successful
// FALSE if failed
// Note: Format: source | destination | data-length | data | checksum
int1 rs485_send_message(int8 to, int8 len, int8* data) {
int8 try, i, cs;
int1 ret = FALSE;
RCV_OFF();
#if RS485_USE_EXT_INT
disable_interrupts(GLOBAL);
#endif
for(try=0; try<5; ++try)
{
rs485_collision = 0;
[b] fputc(msg_hearder, RS485_CD);[/b]
fputc((int16)0x100|rs485_id, RS485_CD);
fputc((int16)0x100|to, RS485_CD);
fputc(len, RS485_CD);
for(i=0, cs=rs485_id^to^len; i<len; ++i) {
cs ^= *data;
fputc(*data, RS485_CD);
++data;
}
fputc(cs, RS485_CD);
if(!rs485_collision) {
ret = TRUE;
break;
}
delay_ms(RS485_ID);
}
RCV_ON();
#if RS485_USE_EXT_INT
enable_interrupts(GLOBAL);
#endif
return(ret);
}
// Purpose: Wait for wait time for the RS485 bus to become idle
// Inputs: TRUE - restart the watch dog timer to prevent reset
// FALSE - watch dog timer not restarted
// Outputs: None
void rs485_wait_for_bus(int1 clrwdt)
{
int16 i;
RCV_OFF();
for(i=0; i <= (rs485_wait_time*20); ++i)
{
if(!input(RS485_RX_PIN))
i = 0;
else
delay_us(50);
if(clrwdt)
restart_wdt();
}
}
// Purpose: Get a message from the RS485 bus and store it in a buffer
// Inputs: 1) A pointer to a buffer to store a message
// 2) TRUE - wait for a message
// FALSE - only check if a message is available
// Outputs: TRUE if a message was received
// FALSE if wait is FALSE and no message is available
// Note: Data will be filled in at the pointer as follows:
// FROM_ID DATALENGTH DATA...
int1 rs485_get_message(int* data_ptr, int1 wait)
{
while(wait && (rs485_ni == rs485_no)) {}
if(rs485_ni == rs485_no)
return FALSE;
else {
int n;
n = rs485_buffer[(rs485_no+1)%sizeof(rs485_buffer)] + 2;
for(; n>0; --n)
{
*data_ptr = rs485_buffer[rs485_no];
if(++rs485_no >= sizeof(rs485_buffer))
{
rs485_no = 0;
}
++data_ptr;
}
return TRUE;
}
}
#endif
|
|
|
|
Jim Guest
|
|
Posted: Sat May 27, 2006 11:21 pm |
|
|
Hi,
I tried to highed the code that I added in, but somehow it did not work.
Please look for the variable: "msg_hearder".
Thank |
|
|
|
|
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
|