|
|
View previous topic :: View next topic |
Author |
Message |
niccolo.calandri
Joined: 20 May 2016 Posts: 10
|
PIC18F26J50 UART RS232 PROBLEM |
Posted: Fri May 20, 2016 1:51 pm |
|
|
Dear all,
I have a problem to read something from the uart. I have a SIM900A working fine. It receive data from the TX pin of the PIC. It transmits back the AT code but the pic did not see anything!!!
I finished all the possible options. Do you have any idea?
Code: |
#include <18F26j50.h>
#device PASS_STRINGS=IN_RAM
#include <stdio.h>
#include <string.h>
#fuses NOWDT, NOPROTECT, NODEBUG
#use delay(internal=48000000, USB_FULL, ACT=USB)
#use rs232(uart1, baud=115200, PARITY=N, BITS=8, ERRORS)
|
Code: |
int8 buffer[40];
int8 next_in = 0;
int8 next_out = 0;
void pic_init(void)
{
usb_init_cs();
}
#INT_RDA
void serial_isr()
{
int8 t;
buffer[next_in] = getc();
t = next_in;
next_in = (next_in+1) % sizeof(buffer);
if(next_in == next_out)
next_in=t; // Buffer full !!
}
#define bkbhit (next_in != next_out)
int8 bgetc()
{
int8 c=0;
while(!bkbhit);
c = buffer[next_out];
next_out = (next_out+1) % sizeof(buffer);
return c;
}
// firmware entry point
void main(void)
{
pic_init();
enable_interrupts(INT_EXT);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
char r;
while(1)
{
usb_task();
while (usb_cdc_kbhit())
{
r=usb_cdc_getc();
putc(r);
}
}
}
|
I never enter in the #INT_RDA. I also debug the RX signal with a scope and it is perfect. 3.3V - 115200khz.
I'm wondering why the RX port doesn't work? I miss something? I have to set some fuse? Change ? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Fri May 20, 2016 2:08 pm |
|
|
First you don't show a complete, contiguous program so we can't 'copy/paste'test' making it harder to debug...
2nd this CAN be your problem..
enable_interrupts(INT_EXT);
Enabling an Interrupt without it's Interrupt Service Routine WILL cause the PIC to NOT work correctly !!
Also, it's good PIC Practice to have an 'I'm alive LED'. A simple toggle an LED within 'main()' say every second or so, just to confirm it IS running the program.
HTH
Jay |
|
|
niccolo.calandri
Joined: 20 May 2016 Posts: 10
|
|
Posted: Fri May 20, 2016 2:31 pm |
|
|
Code: |
#include <18F26j50.h>
#device PASS_STRINGS=IN_RAM
#include <stdio.h>
#include <string.h>
#fuses NOWDT, NOPROTECT, NODEBUG
#use delay(internal=48000000, USB_FULL, ACT=USB)
#use rs232(uart1, baud=115200, PARITY=N, BITS=8, ERRORS)
//-----------------USB interface-------------------------------//
#define USB_USE_FULL_SPEED TRUE // t
#define USB_INTERNAL_PULLUPS TRUE // togliere se non va
//-----------------SD interface-------------------------------//
#include <stdlib.h>
#include <usb_cdc.h>
#define RX_BUF_SIZE 64
// prototypes
void serial_rx(void);
void pic_init(void);
int8 buffer[40];
int8 next_in = 0;
int8 next_out = 0;
void serial_rx(void)
{
char c=usb_cdc_getc();
if(c==0x0A)
{
usb_cdc_puts(not_found);
usb_cdc_putc('\n');
}
else
{
rx_buffer[p_rx_buf]=c;
if(p_rx_buf<RX_BUF_SIZE)
{
p_rx_buf++;
}
}
}
void pic_init(void)
{
usb_init_cs();
}
#INT_RDA
void serial_isr()
{
int8 t;
buffer[next_in] = getc();
t = next_in;
next_in = (next_in+1) % sizeof(buffer);
if(next_in == next_out)
next_in=t; // Buffer full !!
}
#define bkbhit (next_in != next_out)
int8 bgetc()
{
int8 c=0;
while(!bkbhit);
c = buffer[next_out];
next_out = (next_out+1) % sizeof(buffer);
return c;
}
// firmware entry point
void main(void)
{
pic_init();
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
char r;
while(1)
{
usb_task();
usb_cdc_putc("LED BLINK")
usb_cdc_putc(buffer) //empty BUFFER! ALWAYS
usb_cdc_putc(bgetc); // still empty
delay_ms(200);
while (usb_cdc_kbhit())
{
r=usb_cdc_getc();
putc(r);
}
}
}
|
Sorry, this is the complete code...
I use the USB to check that the pic is working.
I also tried to avoid any interrupt and tried to use only getc(). Nothing.
I'm thinking that I have to set trisc? for input? Or the pic have some problem ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Sat May 21, 2016 2:12 am |
|
|
Several big ouches here.
The silly thing is that your 'serial_rx' routine, uses the code where it checks if the address has reached the buffer size, and if so, zeros it, while the similar code in your INT_RX routine uses %.
Now, %, _only works safely in an interrupt, if the buffer size is a binary value_. Otherwise it will result in interrupts being disabled in just about every division in the main code. There should be a warning about this in the example, but there isn't. Your USB buffer is 64 bytes, while your RS232 one is 40 bytes. So in the place where it doesn't matter you are using the 'fix', but in the one where it does, you are not.
So, start by using the same 'test' from your USB code, in your INT_RC code, or changing the serial buffer to a binary size (32/64 bytes).
Then why are you buffering the USB. You do realise that the cdc example, already buffers the USB?.
The buffer code you have for USB, you never seem to call.
Then the code goes screwy. You send the 16bit address of the RS232 buffer in memory, as a character, out on the usb....
usb_cdc_putc(buffer);
Wrong. Doesn't do anything worthwhile.
You comment 'empty buffer! ALWAYS'. It doesn't.
The next line using bgetc, will then hang forever, if no serial data is waiting.
This is probably why your code is not working....
If you want to send the serial data, the code is:
Code: |
while (bkbhit)
{
usb_cdc_putc(bgetc());
}
|
Which will send all the data in the RS232 buffer to the USB.
Then do you have the USB_Vdd connected with a suitable resistive divider to the PIC?. USB_init_cs, depends on the USB connection being sensed (the cs stands for 'connection sense'), and requires that there is such a connection, and you tell the code this exists. You don't specify such a pin.
Code: |
#include <18F26j50.h>
#device PASS_STRINGS=IN_RAM
#fuses NOWDT, NOPROTECT, NODEBUG
#use delay(internal=48000000, USB_FULL, ACT=USB)
#use rs232(uart1, baud=115200, PARITY=N, BITS=8, ERRORS)
//always do _all_ the chip setup's before loading libraries. Some do not
//work correctly if loaded first.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define USB_CON_SENSE_PIN PIN_B1
//choose a pin that suits you, have a resistive divider from USB_Vdd
//feeding this pin.
#include <usb_cdc.h>
// prototypes
void serial_rx(void);
void pic_init(void);
int8 buffer[64]; //change to avoid problem
int8 next_in = 0;
int8 next_out = 0;
void pic_init(void)
{
usb_init_cs();
}
#INT_RDA
void serial_isr()
{
int8 t;
buffer[next_in] = getc();
t = next_in;
if (++next_in>=sizeof(buffer)
next_in=0; //other way to avoid problem
if(next_in == next_out)
next_in=t; // Buffer full !!
}
#define bkbhit (next_in != next_out)
int8 bgetc()
{
int8 c;
while(!bkbhit)
;
c = buffer[next_out];
next_out = (next_out+1) % sizeof(buffer);
return c;
}
// firmware entry point
void main(void)
{
int1 first==TRUE; //keep to the C standard. Declare variables
//_before_ calling routines. CCS allows later declaration, but it
//can cause problems
pic_init();
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
while(TRUE)
{
usb_task();
if (first)
{
usb_cdc_putc("LED BLINK\n")
first=FALSE;
//Only show message the first time.
}
while (bkbhit) //clear RS232 RX buffer to USB
{
usb_cdc_putc(bgetc());
}
while (usb_cdc_kbhit())
{
putc(usb_cdc_getc());
}
}
}
|
I've got rid of the delay, the unused USB buffer code, and had it just display the message the first time round the loop. I've also just directly sent the byte, rather than using a temporary variable.
The delay potentially can cause problems. Remember your serial rate allows over 10000 characters per second. With a 200mSec delay in the loop, if the serial receives more than 40 characters (with your original buffer), it'll lose data. In 200mSec, it could receive 2304 characters..... |
|
|
|
|
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
|