mheber
Joined: 13 Jan 2012 Posts: 3 Location: Germany
|
RS485 with PIC24 |
Posted: Mon Sep 16, 2013 2:10 pm |
|
|
I have a question about the handling of RS485 with the PIC24 Family.
For PIC18 the code works fine but with PIC24 only send works but receive hangs.
The essential part of the code is:
Code: |
#define RS485_ID 11 // The device's RS485 address or ID
#define RS485_RX_PIN PIN_F4 // Data receive pin
#define RS485_TX_PIN PIN_F5 // Data transmit pin
#define RS485_ENABLE_PIN PIN_F3 // Controls DE pin. RX low, TX high.
#define RS485_RX_ENABLE PIN_F2 // Controls RE pin. Should keep low.
#define RS485_BAUD 9600 // Transmission speed
#include "TMCL.c"
|
TMCL.C:
Code: |
#ifndef TMCL_RS485_DRIVER
#define TMCL_RS485_DRIVER
#ifndef RS485_ID
#define RS485_ID 0x10 // The device's RS485 address or ID
#endif
#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
#ifndef RS485_BAUD
#define RS485_BAUD 9600 // Baud rate
#endif
#PIN_SELECT INT2=RS485_RX_PIN
#use rs232(baud=RS485_BAUD, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=8, long_data, force_sw, errors, stream=RS485)
#use rs232(baud=RS485_BAUD, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=8, long_data, force_sw, multi_master, errors, stream=RS485_CD)
#define RCV_OFF() {disable_interrupts(INT_EXT2);}
#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_ni, rs485_no;
int rs485_buffer[RS485_RX_BUFFER_SIZE];
// Purpose: Enable data reception
// Inputs: None
// Outputs: None
void RCV_ON(void)
{
output_low(RS485_RX_ENABLE);
clear_interrupt(INT_EXT2);
enable_interrupts(INT_EXT2);
}
// Purpose: Initialize RS485 communication. Call this before
// using any other RS485 functions.
// Inputs: None
// Outputs: None
void tmcl_init()
{
output_high (PIN_G7); // only for interrupt test
RCV_ON();
rs485_ni=0;
rs485_no=0;
ext_int_edge(2, H_TO_L);
enable_interrupts(INT_EXT2);
enable_interrupts(GLOBAL);
output_low(RS485_RX_ENABLE);
}
// Purpose: Interrupt service routine for handling incoming RS485 data
#INT_EXT2
void serial_isr()
{
int8 t;
output_high (PIN_A3); // only for interrupt test
rs485_buffer[rs485_ni] = fgetc(RS485);
t = rs485_ni;
rs485_ni = (rs485_ni+1) % sizeof(rs485_buffer);
if(rs485_ni == rs485_no)
rs485_ni=t; // Buffer full !!
output_low (PIN_A3); // only for interrupt test
}
#define bkbhit (rs485_ni != rs485_no)
int8 bgetc()
{
int8 c;
while(!bkbhit);
c = rs485_buffer[rs485_no];
rs485_no = (rs485_no+1) % sizeof(rs485_buffer);
return c;
}
// 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();
}
}
|
One difference is in teh PIC18 code: instead of INT_EXT2 I use INT_EXT2_H2L, INT_EXT2 and ext_int_edge(2, H_TO_L);
does not work with the PIC18 so I guess there is some compiler Problem. |
|