![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
AndresRam
Joined: 27 May 2017 Posts: 16 Location: Colombia
|
problem with usart |
Posted: Sun Feb 25, 2018 1:36 pm |
|
|
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);
} |
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Feb 25, 2018 2:44 pm |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19372
|
|
Posted: Sun Feb 25, 2018 3:15 pm |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
AndresRam
Joined: 27 May 2017 Posts: 16 Location: Colombia
|
|
Posted: Sun Feb 25, 2018 3:30 pm |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Feb 25, 2018 5:52 pm |
|
|
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
.................... } |
|
|
![](templates/subSilver/images/spacer.gif) |
AndresRam
Joined: 27 May 2017 Posts: 16 Location: Colombia
|
|
Posted: Sun Feb 25, 2018 8:42 pm |
|
|
THANKS VERY MUCH!!
the solution was add ERRORS!!!! |
|
![](templates/subSilver/images/spacer.gif) |
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Wed Feb 28, 2018 6:18 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
AndresRam
Joined: 27 May 2017 Posts: 16 Location: Colombia
|
|
Posted: Wed Feb 28, 2018 5:02 pm |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Feb 28, 2018 6:42 pm |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19372
|
|
Posted: Thu Mar 01, 2018 1:06 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9174 Location: Greensville,Ontario
|
|
Posted: Thu Mar 01, 2018 5:51 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|