View previous topic :: View next topic |
Author |
Message |
vlady_2009
Joined: 22 Jun 2016 Posts: 5
|
INT_RDA, 2 x RS232 connections, circular buffer not working |
Posted: Tue Apr 18, 2017 5:33 am |
|
|
I have a PIC18F248 connected to PC via a MAX232 (pins RC4, RC5) and a ESP8266 (pins RC6, RC7). The ESP8266 is connected to the hardware EUSART pins to enable highest baud rate (eventually). At the moment just trying to ensure can receive data stream OK so can then write the appropriate parser.
The code below is based upon the CCS ex_sisr.c
Communication between the PIC and the PC is working fine. Data to and from the ESP8266 is also working (the AT+GMR commands the ESP8266 to output a long stream of firmware version and SDK info, which is good for testing comms in this case).
Problem is the INT_RDA and the circular buffer doesn't appear to be working correctly.
If I include a delay_ms after sending the AT+GMR command to the ESP8266 (see the commented out line in the code listing) the expected information is displayed on the PC/terminal program received from the ESP8266 via the PIC/MAX232. If the delay_ms is commented out, the PC/terminal program output is "garbled" for the starting characters.
Appears that the circular buffer is not working and getting over written or similar???
I've stared at this heaps to no avail, any help greatly appreciated. (Oh, compiler version 4.14).
Code: |
#include <18F248.h>
#device adc=10
#priority INT_RDA, INT_TIMER1
#zero_ram
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES PUT //Power Up Timer
#use delay(clock=24000000)
#use rs232(stream=PC_IO, baud=9600,parity=N,xmit=PIN_C4,rcv=PIN_C5,bits=8, ERRORS)
#use rs232(stream=PICinput, baud=38400,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, ERRORS)
#define LED_BUFFER_OVERRUN PIN_C0
#define BUFFER_SIZE 64
#define BUFFER_kbhit (next_in!=next_out)
int8 buffer[BUFFER_SIZE];
int8 next_in = 0;
int8 next_out = 0;
int8 bufferOverrunFlag = 0;
int8 tickCount = 0;
int8 timeOut = 0;
int8 timeOutFlag = false;
int8 cmdActiveFlag = false;
#INT_TIMER1
void timer1_interrupt() { //Freq 13.3hz, period=0.075sec
tickCount++;
if (tickCount > timeOut) {
disable_interrupts(INT_TIMER1);
timeOutFlag = true;
tickCount = 0;
} else {
set_timer1(9285); //prescaler=8, 24Mhz, preload=9285 -> Freq 13.3hz, period=0.075sec
}
}
#INT_RDA
void serial_isr() {
int t;
buffer[next_in]=fgetc(PICinput);
t=next_in;
next_in=(next_in+1) % BUFFER_SIZE;
if(next_in==next_out) { // Buffer full !!
next_in=t;
bufferOverrunFlag = 1;
}
}
char buffer_getc() {
char c;
while(!BUFFER_kbhit);
c=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(c);
}
void main() {
char recChar;
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
enable_interrupts(GLOBAL);
output_low(LED_BUFFER_OVERRUN);
enable_interrupts(INT_RDA);
delay_ms(1000);
next_in=next_out;
fprintf(PC_IO,"\n\rStart\n\r");
while(TRUE){
if (cmdActiveFlag==1) {
while (BUFFER_kbhit) {
recChar=buffer_getc();
fprintf(PC_IO,"%c",recChar);
}
if (timeOutFlag == 1) {
fprintf(PC_IO,"\n\r**** TIMED OUT ****\n\r");
cmdActiveFlag=false;
next_in=next_out; //empty buffer
}
if (bufferOverrunFlag==1) output_high(LED_BUFFER_OVERRUN);
}
if (kbhit(PC_IO) && cmdActiveFlag == false) { //command etc received from PC
recChar = fgetc(PC_IO);
switch (recChar) {
case 'G': fprintf(PC_IO,"\n\rSENT CMD\n\r");
fprintf(PICinput,"AT+GMR\r\n"); //start input stream to PIC
cmdActiveFlag = true;
timeOut = 128; //128*0.075sec = 9.6sec
timeOutFlag = false;
tickCount = 0;
set_timer1(9285); enable_interrupts(INT_TIMER1);
//delay_ms(250); //**** DUMMY DELAY *********************************************
break;
default: fprintf(PC_IO,"Unknown cmd\n\r");
break;
}
}
}
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Tue Apr 18, 2017 6:19 am |
|
|
Basic question... that's a 5 volt PIC and a 3 volt peripheral, so do you have proper logic level interface between the two devices? I know you say it works...but it might be 'marginal'....
Jay |
|
|
vlady_2009
Joined: 22 Jun 2016 Posts: 5
|
|
Posted: Tue Apr 18, 2017 6:41 am |
|
|
No that's taken into account, separate linear regulators supplying the appropriate voltages, with a resistor divider for the conversion on the PIC TX to ESP8266 RX.
When using a large enough buffer, no problems with getting the expected responses from the ESP8266, just a problem when trying to use a small buffer/interrupt etc. |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Tue Apr 18, 2017 7:21 am |
|
|
What compiler version are you using? There was a period, though I can't remember which versions were affected, where printf was incorrectly leaving serial interrupts turned off. That would give similar symptoms to those you are reporting. |
|
|
vlady_2009
Joined: 22 Jun 2016 Posts: 5
|
|
Posted: Tue Apr 18, 2017 7:36 am |
|
|
RF Developer
I'm using compiler version 4.14 if that helps.
Regards |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Tue Apr 18, 2017 7:50 am |
|
|
It's not data TO the ESP rather FROM the ESP that may be marginal... you have to see what the PIC wants as a '1' for that input pin and then see IF the ESp can produce it. The ESp might give say 3.0 as a '1' and the PIC needs 4.2 as a '1'.
Usually (from my memory...) the PIC UART RCV pin is type ST ( D041...spec), so needs 80% VDD as a logical '1'. 5 *.8=4 volts. If this is true for your PIC (you'll have to check) then the ESP can never give a true '1'.
You might be lucky and it gives a 3.3 for a '1' and the PIC seems happy with that but really you need to check the datasheet. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Tue Apr 18, 2017 2:04 pm |
|
|
CCS compiler numbers are always X.XXX.
Look at the end of your listing file to get the number. 4.140?.
If it was 4.014, then 'give up'. This was before V4 became a usable compiler...
However I'd say that your problem is undoubtedly that the module does not produce enough voltage to drive the PIC serial input.
It _needs_ an input buffer. |
|
|
vlady_2009
Joined: 22 Jun 2016 Posts: 5
|
|
Posted: Tue Apr 18, 2017 8:09 pm |
|
|
Guys
Used a buffer (from CD4050) to convert the ESP8266 TX to 5v for input to PIC - same problem observed.
Version 4.140 originally used, tried also compiling with version 5.008 - same problem observed.
Below is a annotated screen shot of the output on the serial monitor when running the code (includes using CD4050 buffer and version 5.008).
1. top portion shows output when delay_ms(250) is included to effectively allow sufficient time for ESP8266 to finish output into the PIC buffer without other portion of the main code running. This output is as per expected as confirmed from observing output from ESP8266 connected directly to PC via a USB-TTL converter (no PIC involved). This would indicate that the #INT_RDA routine and loading into the buffer etc is working correctly, and that subsequently, the buffer_getc() routine is working correctly outputting to the PC.
2. lower portion shows output when the delay_ms(250) is commented out. This shows the problem in that the circular buffer does not seem to be working correctly, outputting to PC when PIC cycles available and the interrupt storing chars when received.
Seems that I have something wrong in the code.
[img]
http://i.imgur.com/1fFrwdZ.jpg
[/img] |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 18, 2017 9:53 pm |
|
|
You're running a soft UART for the PC_IO stream. If any interrupts
occur while the soft UART is transmitting or receiving, it will disrupt
the bit timing and you'll get garbled data.
You could add DISABLE_INTS to the #use rs232() statement for the
PC_IO stream. Ideally, you would make the baud rate for the PC_IO
stream be as fast as possible, to reduce the amount of time that interrupts
are disabled.
The CCS manual says (in the #use rs232 section):
Quote: |
DISABLE_INTS -
Will cause interrupts to be disabled
when the routines get or put a
character. This prevents character
distortion for software implemented
I/O and prevents interaction between
I/O in interrupt handlers and the main
program when using the UART. |
|
|
|
vlady_2009
Joined: 22 Jun 2016 Posts: 5
|
|
Posted: Wed Apr 19, 2017 1:02 am |
|
|
PCM programmer
Thanks, DISABLE_INTS in the #use rs232() statement for the PC_IO stream was the solution,
coupled with that the baud rate needed to be at least 19200 for the PC_IO stream to avoid missing input via INT_RDA when interrupts off during soft UART call.
Thanks to all that replied. |
|
|
|