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 support@ccsinfo.com

problem with usart

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



Joined: 27 May 2017
Posts: 16
Location: Colombia

View user's profile Send private message

problem with usart
PostPosted: Sun Feb 25, 2018 1:36 pm     Reply with quote

I have the following problem:

I can not get reception but I can transmit between my PIC and a NEXTION display.

When I communicate my PIC with the simulator of the NEXTION in my PC through a FTDI232 everything works OK.

On another board (picclicker) with my PIC and the NEXTION everything works OK.

With an oscilloscope I can determine the voltage values in the lines:

PIC and PC (tx: 3.3 volt, rx: 5 volt, seen from the pic)
PIC and NEXTION (tx: 3.3 volt, rx: 3.3 volt, seen from the pic) on the board that does not work.
PIC and NEXTION (tx: 3.3 volt, rx: 3.3 volt, seen from the pic) on the board that does work.

picclicker is a board of evaluation (the other board, where serial reception does not work is the electronic board that I developed).

This really has no explanation, someone to give me a hand please.
Code:

#if defined(__PCH__)

#include <18f47j53.h>
#device ADC=12
#include <lib\tft.h>
#include <ds1302_2.c>
#define BUZZ   PIN_E0
byte beep_positivo;
//-----------------------------------------------------------------------
void BEEP3()
{
      int8 i;
      for (i = 0 ; i < 200 ; i++ )
      {
         output_high(BUZZ);
         delay_us(400);
         output_low(BUZZ);
         delay_us(75);
      }
}
void set_clock(){
   byte day,mth,year,dow,hour,min;

   year=13;     
   mth=5;   
   day=1;   
   dow=1;   
   hour=8;   
   min=14;
   
   rtc_set_datetime(day,mth,year,dow,hour,min);
}

#DEFINE BCD2BIN(val) (((val)&15) + ((val)>>4)*10) //conversion Bcd a Binario
#ignore_warnings 208  // no retorna valor de interrupcion

//////////////////////////////////////////////////////////////////////////////

#ZERO_RAM

///=================================================================================
#int_rda2// Guarda datos
void serial_isr() {                 
    rcvchar2=0x00;       
    rcvchar2=fgetc(DISPLAY);
   addcbuff2(rcvchar2);
   MTR2_TOGGLE
          }
       
 ///=================================================================================
#int_RTCC // contar tiempo
void TIEMPOS(void){               
    SET_RTCC(set_time);
      cent1++;
     
   if (cent1>=30){
         deci1++;
      deci_MTR++;
      cent1=0;}
     
   if (deci1>=10){
        seg1++;
       segRead++;
        deci1=0;}
             
}       
       
///---------------------------------------------------------------------------------
///------------------------- MAIN --------------------------------------------------
///---------------------------------------------------------------------------------
///=================================================================================
void main()
{
   fConfigurar_puertos();

   delay_ms(1000);
   MTR1_TOGGLE
   delay_ms(100);
   
   rtc_init();
   delay_ms(100);
 //--- inicializa variables ------------
   deci_MTR=0,segRead=58;
   flagcommand2=0;
   day_o=0xff,mth_o=0xff,year_o=0xff,hour_o=0xff;
   enable_interrupts(int_rda2);
   enable_interrupts(global); //****
   
//=====================================================================           
//================= PROGRAMA PRINCIPAL ================================
//=====================================================================
while(1) // ---A
    {
//---------LED MONITOR--------------------------   
   if(deci_MTR>=tMTR){
      deci_MTR=0;
      MTR2_TOGGLE
   }
   
//----------RECEPCION SERIAL ---------------------   
   if(flagcommand2){
      flagcommand2=0;
      MTR1_TOGGLE
      hour=cbuff2[0],min=cbuff2[1],day=cbuff2[2],mth=cbuff2[3],year=cbuff2[4];
     beep_positivo=cbuff2[0];
     //fprintf(DISPLAY,"%s",cbuff2);
      fprintf(DISPLAY,"n3.val=%02u",hour);
      tx_end();
      fprintf(DISPLAY,"n4.val=%02u",min);
      tx_end();
      fprintf(DISPLAY,"n0.val=%02u",day);
      tx_end();
      fprintf(DISPLAY,"n1.val=%02u",mth);
      tx_end();
      fprintf(DISPLAY,"n2.val=%02u",year);
      tx_end();
       
            if(beep_positivo==1)
      {
      BEEP3();
      }
      day_o=day,hour_o=hour,year_o=year,mth_o=mth;
     
      disable_interrupts(global); //****
      rtc_set_datetime(day,mth,year,dow,hour,min);
       enable_interrupts(global); //****
     
      }

//------------ LER RELOJ ----------------------------
   if(segRead>=60){
       MTR1_ON
       
      disable_interrupts(global); //****
      rtc_get_date( day, mth, year, dow);
      rtc_get_time( hour, min, sec );
      enable_interrupts(global); //****
     
      if(sec<=30){segRead=sec;}
      else{segRead=0;}
     
     fprintf(DISPLAY,"n4.val=%02u",min);
     tx_end();
     if(hour_o!=hour){
        hour_o=hour,fprintf(DISPLAY,"n3.val=%02u",hour);
        tx_end();
         }
     if(day_o!=day){
        day_o=day,fprintf(DISPLAY,"n0.val=%02u",day);
        tx_end();
        }
     if(mth_o!=mth){
        mth_o=mth,fprintf(DISPLAY,"n1.val=%02u",mth);
        tx_end();
        }     
     if(year_o!=year){
        year_o=year,fprintf(DISPLAY,"n2.val=%02u",year);
        tx_end();
         }   
         
      MTR1_OFF

   }
   
///==============================================================
   }// de while ppal
     
} // De main

#endif


tft.h :
Code:

#FUSES NOWDT
#FUSES PLLEN                 
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES INTRC_PLL_IO         
#FUSES NOCLOCKOUT           
#FUSES NOFCMEN                  //Fail-safe clock monitor disabled
#FUSES NOIESO                   //Internal External Switch Over mode disabled

#use delay(clock=48000000,crystal=16000000)
#pin_select U2TX=PIN_D6
#pin_select U2RX=PIN_D5
#use rs232(baud=9600,UART2,stream=DISPLAY)
//#use rs232(baud=9600,parity=N,xmit=PIN_D6,rcv=PIN_D5,bits=8,stream=DISPLAY)

//++++++++++++++++++++++++++++++++++++++++++++/*
/*
#use fast_io(A) // Estas directivas economizan memoria
#use fast_io(B) //   con esta instruccion evitamos que
#use fast_io(C) //   se este configurando cada vez que usamos
#use fast_io(D) //   alguna instruccion de entrada o salida
#use fast_io(E)
/*
#use standard_io(A) // Estas directivas economizan memoria
#use standard_io(B) //   con esta instruccion evitamos que
#use standard_io(C) //   se este configurando cada vez que usamos
#use standard_io(D) //   alguna instruccion de entrada o salida
#use standard_io(E)
*/
//-------------Defines------------------------------------------
#BYTE PORTA = 0xF80  // para 18F4523 / 18f47j53
#BYTE PORTB = 0xF81
#BYTE PORTC = 0xF82
#BYTE PORTD = 0xF83
#BYTE PORTE = 0xF84
/*
#BYTE ADCON0 = 0xFC2
#BYTE ADCON1 = 0xFC1

#BYTE ANCON0 = 0xF48
#BYTE ANCON1 = 0xF49
*/

//-----------  OUT ------------------------------------
#DEFINE   MTR1_ON      output_high(PIN_D1);//
#DEFINE   MTR1_OFF    output_low(PIN_D1);
#DEFINE   MTR1_TOGGLE   output_toggle(PIN_D1);

//-----------  OUT ------------------------------------
#DEFINE   MTR2_ON      output_high(PIN_D2);//
#DEFINE   MTR2_OFF    output_low(PIN_AD2);
#DEFINE   MTR2_TOGGLE   output_toggle(PIN_D2);


///============================================================================

int   const      lenbuff2=100;// BUFFER RECEP
int1             flagcommand2=0; // Flag para indicar datos disponible
int1            f_ini=0; // verificar que la trama si inicie por 71
//int1         f_end=0;// verificar que la trama si inicie por 0xff
char          contFF=0;


char   rcvchar2=0x00;      // Buffer
int     xbuff2=0x00;
char    cbuff2[lenbuff2];


////---------------------------------------------------------
// Variables Globales

// RELOJ DS1302
byte day,mth,year,dow,hour,min,sec;
byte day_o,mth_o,year_o,hour_o;

// RTCC interno
byte seg1,deci1,cent1;// base
int const   set_time=100; // base de tiempo para reloj RTCC 16 Mhz RTCC_DIV_256
byte deci_MTR,segRead;
char const tMTR=3;//parpadeo de monitor

//*   funciones

#include "tft.c"


tft.c :
Code:

void fConfigurar_puertos(void){

   setup_counters(RTCC_INTERNAL,RTCC_DIV_256|RTCC_8_BIT);
 
   enable_interrupts(INT_RTCC); // Habilito InterrupciĆ³n RTCC

   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
  setup_comparator(NC_NC_NC_NC);
  setup_vref(FALSE);
/*
   set_tris_a(0b00000001);
   set_tris_b(0b00000000);  //0x00
   set_tris_c(0b10000000); //0x80
   set_tris_d(0b00110000);
   set_tris_e(0b00000000); //0x00
*/
   PORTB=0b00000000;
   PORTA=0b00000000;
   PORTC=0b00000000;   
   //PORTD=0b00000000;
   PORTE=0b00000000;
 

   
    disable_interrupts(global); //****
  //  enable_interrupts(int_rda2);
  // enable_interrupts(global); //****

}

/********************************************************************************
 * Borra buffer de cualquier tamaƱo
*********************************************************************************/
void CLR_BUFF(char *s, char tamano) {
   
    char i=0;

    for (i = 0; i < tamano; i++) {
        *s = '\0';
        *s++;
    }
}


///--------------------------------------------------------------------------
void addcbuff2(char c){     

      switch(c){
         
        case '1':         
         f_ini=1;
         xbuff2=0;           
         contFF=0;
             break; 
        case 'f':               
          f_ini=0;
         flagcommand2=1; 
         cbuff2[xbuff2]='\0';
         xbuff2++;
       
            break;     
        case 0x00:               
            break;         
         default:
            if(f_ini){
            cbuff2[xbuff2]=c;     
         xbuff2++;
         if(xbuff2>lenbuff2){xbuff2=0;}   
         }

      }
     

}   

//----------------------------------------------------------------

void tx_end(){
   
   fputc(0xff,DISPLAY), fputc(0xff,DISPLAY), fputc(0xff,DISPLAY);
   delay_us(10);
}
PCM programmer



Joined: 06 Sep 2003
Posts: 20366

View user's profile Send private message

PostPosted: Sun Feb 25, 2018 2:44 pm     Reply with quote

You have two boards, the MikroElektronica PIC clicker board and
the board you made. One works. The other one doesn't work.

Compare the two boards until you find the problem. Compare the
traces. Compare the regulated voltages. Compare the amount and
placement of bypass capacitors. Compare everything.
Ttelmah



Joined: 11 Mar 2010
Posts: 13375

View user's profile Send private message

PostPosted: Sun Feb 25, 2018 3:15 pm     Reply with quote

Have you done a basic 'flash an LED' test on the board and verified it is running at the right clock rate?. reason I query this is these two entries:

Code:

#FUSES INTRC_PLL_IO 

#use delay(clock=48000000,crystal=16000000)


These disagree with each other as to what clock source you are running.
AndresRam



Joined: 27 May 2017
Posts: 16
Location: Colombia

View user's profile Send private message

PostPosted: Sun Feb 25, 2018 3:30 pm     Reply with quote

OK, the new board work ok with another routine, another peripherals.

The transmission from pic to Display is OK, I see in nextion display the info send for the pic,

any question:

#int_rda2 work well with my configuration of RS232?
my RS232 configuration is soft or hardware?

Although the strange thing is that the same code works well in MICROE board in the same pins of tx and rx !!!

what's more, my board works well (both reception and sending) when I simulate the nextion display with a virtual terminal on my PC through an FTDI rs232 to USB module adapter
PCM programmer



Joined: 06 Sep 2003
Posts: 20366

View user's profile Send private message

PostPosted: Sun Feb 25, 2018 5:52 pm     Reply with quote

AndresRam wrote:

#int_rda2 work well with my configuration of RS232?

You need one improvement. Add the ERRORS parameter to the
#use rs232() statement. Example:
Code:
#use rs232(baud=9600,UART2,stream=DISPLAY, ERRORS)



AndresRam wrote:

my RS232 configuration is soft or hardware?

Look at the .LST file for your program. If the ASM code in the #int_rda2
function is talking to hardware registers, then the hardware UART is used.
Example: In the code below, you can see that the code is talking to PIR3
and RCREG2. This code is using the hardware UART.
Code:
.................... #int_rda2
.................... void serial_isr()
.................... {                   
.................... rcvchar2=fgetc(DISPLAY); 
*
000BE:  BTFSS  PIR3.RC2IF
000C0:  BRA    00BE
000C2:  MOVFF  RCREG2,rcvchar2
000C6:  BCF    PIR3.RC2IF
000C8:  GOTO   0068
.................... } 
AndresRam



Joined: 27 May 2017
Posts: 16
Location: Colombia

View user's profile Send private message

PostPosted: Sun Feb 25, 2018 8:42 pm     Reply with quote

THANKS VERY MUCH!!

the solution was add ERRORS!!!!
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Wed Feb 28, 2018 6:18 am     Reply with quote

AndresRam wrote:
the solution was add ERRORS!!!!


No, that is NOT the solution. That's a symptom; an indication you are on to something. A system should never, under normal working conditions, have any serial communications errors. Now you have to find out why the UART was giving errors: why is that? Timing problems? Noise? Incorrect voltage levels? Incorrect framing (number of bits, stop bits etc.)? Receiver overrunning (new characters coming in before cdoe has dealt with old one or ones)? Then you correct that problem. Then you've got a solution.
AndresRam



Joined: 27 May 2017
Posts: 16
Location: Colombia

View user's profile Send private message

PostPosted: Wed Feb 28, 2018 5:02 pm     Reply with quote

Thank very much,
Of course, you are right in fact. The following happens: when feeding the Nextion Display for the first time, I do not know what "garbage" sends to the microcontroller. but only when it is turned on, for the rest there is no "garbage" to worry about. I thought about solving this by doing a small restart with a WatchDog in the microcontroller to give time for the Nextion to send the "garbage", but only with the ERRORS was enough.
PCM programmer



Joined: 06 Sep 2003
Posts: 20366

View user's profile Send private message

PostPosted: Wed Feb 28, 2018 6:42 pm     Reply with quote

One possibility is to add a 10K pullup resistor to the Rx pin of the PIC.
Connect the pullup to the same Vdd voltage as the PIC.
If the Rx pin is floating for a while during power-up, the PIC could receive
garbage. The pullup may stop this problem.
Ttelmah



Joined: 11 Mar 2010
Posts: 13375

View user's profile Send private message

PostPosted: Thu Mar 01, 2018 1:06 am     Reply with quote

Lets expand a fraction on what PCM_Programmer has said.

It is quite common for serial devices to take longer to wake up than the PIC.
Even the 'standard' MAX232 does this. Result is that during the first few mSec after boot, the PIC can/will receive garbage.

First thing that can help is the pull-up resistor. Tries to ensure that if the device hasn't actually switched it's output 'on', the line will go high, rather than floating. This is also necessary for any device who's output can go 'tri-state'. Things like RS485 buffers for example. Not having this can cause just the odd erratic problem that is hard to find...

Then, if the device is something that shouldn't send data before you 'ask' it, then at the start of the code, flush the input buffer, before enabling the RS232 interrupt.

On 'ERRORS', the general rule is that either your code needs to test and handle errors, or you should always have this in any RS232 setup that uses the hardware UART.
temtronic



Joined: 01 Jul 2010
Posts: 6218
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Mar 01, 2018 5:51 am     Reply with quote

As both PCM P and Mr. T point out, you need to clear the UART and your rcv buffer.

using your code...
Code:
 day_o=0xff,mth_o=0xff,year_o=0xff,hour_o=0xff;
   enable_interrupts(int_rda2);

I'd add code inbetween those lines so...
Code:

 day_o=0xff,mth_o=0xff,year_o=0xff,hour_o=0xff;

//
//insert rcv buffer clear code here
// it fills all bytes of the buffer with 0x00 or 0xff
// cbuff2[] ,I think is your buffers name
//
   enable_interrupts(int_rda2);

Jay
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