CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

PIC18F26J50 UART RS232 PROBLEM

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
niccolo.calandri



Joined: 20 May 2016
Posts: 10

View user's profile Send private message

PIC18F26J50 UART RS232 PROBLEM
PostPosted: Fri May 20, 2016 1:51 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Fri May 20, 2016 2:08 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Fri May 20, 2016 2:31 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sat May 21, 2016 2:12 am     Reply with quote

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.....
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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