View previous topic :: View next topic |
Author |
Message |
jjacob
Joined: 08 Mar 2008 Posts: 54 Location: PORTUGAL (PORTO)
|
18F26K22 Two Hardware UARTS - RS485 |
Posted: Tue Apr 04, 2017 12:43 pm |
|
|
Hello,
I'm trying to implement a RS485 converter. I have a MASTER serial device that sends data to my converter, then converter sends to rs485 network. If convert receives something from rs485 network then sends to serial device.
Code: | #include <18F26K22.h>
#device adc=10
#FUSES INTRC_IO // INTRC_IO Internal RC Osc, no CLKOUT
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOPUT //No Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES NOMCLR //Master Clear pin NOT enabled
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES NODEBUG //No Debug mode for ICD
#use delay(clock = 16000000)
#define INIT_UART_BAUDRATE 9600
#use rs232(UART1, baud=INIT_UART_BAUDRATE, stream=rf, xmit=PIN_C6,rcv=PIN_C7, errors)
#use rs232(UART2, baud=INIT_UART_BAUDRATE, stream=rede, ENABLE = PIN_B5 , xmit=PIN_B6,rcv=PIN_B7, errors)
#define BUFFER_SIZE_A 32
BYTE buffer_A[BUFFER_SIZE_A];
BYTE next_in_A = 0;
BYTE next_out_A = 0;
#define BUFFER_SIZE_B 32
BYTE buffer_B[BUFFER_SIZE_B];
BYTE next_in_B = 0;
BYTE next_out_B = 0;
#INT_RDA
void serial_isr() {
int t;
buffer_A[next_in_A] = fgetc(rf);
t = next_in_A;
next_in_A = (next_in_A + 1) % BUFFER_SIZE_A;
if (next_in_A == next_out_A)
next_in_A = t; // Buffer full !!
}
#define bkbhit_A (next_in_A!=next_out_A)
BYTE bgetc_A() {
BYTE c;
while (!bkbhit_A);
c = buffer_A[next_out_A];
next_out_A = (next_out_A + 1) % BUFFER_SIZE_A;
return (c);
}
#INT_RDA2
void serial_isr2() {
int t;
buffer_B[next_in_B] = fgetc(rede);
t = next_in_B;
next_in_B = (next_in_B + 1) % BUFFER_SIZE_B;
if (next_in_B == next_out_B)
next_in_B = t; // Buffer full !!
}
#define bkbhit_B (next_in_B!=next_out_B)
BYTE bgetc_B() {
BYTE c;
while (!bkbhit_B);
c = buffer_B[next_out_B];
next_out_B = (next_out_B + 1) % BUFFER_SIZE_B;
return (c);
}
void main() {
enable_interrupts(INT_RDA2 | INT_RDA);
enable_interrupts(GLOBAL);
printf("\r\n\Running...\r\n");
// The program will delay for 10 seconds and then display
// any data that came in during the 10 second delay
do {
while (bkbhit_A)
fputc(bgetc_A(), rede);
while (bkbhit_B)
fputc(bgetc_B(), rf);
} while (TRUE);
} |
It works with only one of uart. With two simultaneous don't work. What I'm doing wrong?
Thanks for the help. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Tue Apr 04, 2017 12:53 pm |
|
|
this ?
enable_interrupts(INT_RDA2 | INT_RDA);
I don't think is 'legal'. At least I've always only used one device per enable_interrupt.
I'd have to check on the eng PC to confirm but I do know the 46K22 will run 2 HW UARTs at 921600 for days without a hiccup !
Jay |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1354
|
|
Posted: Tue Apr 04, 2017 1:07 pm |
|
|
It's not legal. The OP will have to call them like:
Code: |
enable_interrupts(INT_RDA);
enable_interrupts(INT_RDA2);
|
The only time I've seen a bitwise OR used for enable_interrupts() is for Change Notification interrupts, but there is still a specific way to do it. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Tue Apr 04, 2017 1:58 pm |
|
|
Also, general comments:
Far safer to use:
#use delay(INTERNAL=16MHz)
This ensures the clock is correctly programmed for 16Mhz.
You also don't need to specify the pins, if you use 'UART1' or 'UART2'. These are equivalent (for UART1) to
xmit=PIN_C6, rcv=PIN_C7, FORCE_HW
so it is rather silly to put the pin names as well... |
|
|
jjacob
Joined: 08 Mar 2008 Posts: 54 Location: PORTUGAL (PORTO)
|
|
Posted: Wed Apr 05, 2017 4:07 am |
|
|
Hello,
Thank you all for your help. It's solved.
It was the:
Code: |
enable_interrupts(INT_RDA);
enable_interrupts(INT_RDA2);
|
|
|
|
|