serial strangeness

Status
Not open for further replies.

arhi

Member
where to begin ... well .. let start with code .. C18, 18F4520

Code:
#include <p18cxxx.h>
#include <pwm.h>
#include <usart.h>
#include <delays.h>

#pragma config OSC = HSPLL
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config WDT = OFF
#pragma config MCLRE = ON
#pragma config PBADEN = OFF
#pragma config CCP2MX = PORTC
#pragma config LVP = OFF
#pragma config XINST = OFF


volatile unsigned char distance;

void rx_handler (void);

#pragma code rx_interrupt = 0x08
void rx_int(void){
  _asm goto rx_handler _endasm
}

#pragma code

#pragma interrupt rx_handler
void rx_handler(void){
  distance = ReadUSART();
  LATDbits.LATD3 ^= 1; // CHANGE LED
 PIR1bits.RCIF = 0;
}

void main(){
  ADCON0 = 0;
  ADCON1 = 0x0F;
  TRISA = 0;
  TRISB = 0;
  TRISC = 0;
  TRISD = 0;
  TRISE = 0;

  LATA = 0;
  LATB = 0;
  LATC = 0;
  LATD = 0;
  LATE = 0;

  //PWM ON
  T2CON = 0;
  OpenPWM1(249);
  OpenPWM2(249);
  SetDCPWM1(1023);
  SetDCPWM2(1023);

  TRISCbits.TRISC7 = 1;
  RCSTAbits.SPEN = 1;

  // baud rate  = FOSC/(64*(x+1)) // for brgh_low
  // 9600 bps, 40MHz, x=64
  OpenUSART(USART_TX_INT_OFF & 
            USART_RX_INT_ON & 
            USART_ASYNCH_MODE & 
            USART_EIGHT_BIT & 
            USART_CONT_RX & 
            USART_BRGH_LOW, 
  64);

  LATDbits.LATD3 = 1; // TURN LED ON
  RCONbits.IPEN = 1;
  IPR1bits.RCIP = 1;
  INTCONbits.GIEH = 1;
  while(1); // do nothing
}

let us continue with schematic ... all as it suppose to be ..
MCLR is via 10K resistor to Vcc
LED is on D3 over resistor to gnd
crystal (10MHz) and 2 capacitors where they should be
decoupling 10n on both sides
100uF on power rails

the serial out (from another PIC - works perfectly, gnd's connected together) connected to RX pin on 18F4520 (no pull up's, no pull downs ... tx from 16F coming to RX of this 18F)

on RX (clearly seen by scope, one byte comes every 300ms) the line is at Vcc (5v) level and goes low when needed (bits in package).... so .. every 300ms the led should change right .... yeeeah .. if it did I'd not be posting the message ...

here's the thing ...

N - I attach the batteries (4.9V) - scope shows signals coming trough - led do not change
Y - I attach pickit2 (4.7-4.8V) - scope show identical signal - led DOES change - pic receives data ?!?!?!?!! WHY
N - I attach batteries via regulator (4.8)- no fun, led do not change
N - I attach batteries via diode (4.7V) - no fun, led do not change
N - I attach external PSU (3V - 5.5V) - no fun, led do not change

I used the same power for both PIC's, I used different power for the PIC's .. same @#%@#$_)% if 18F is powered from PK2 it works?!?!?!?

Now, please tell me wt* I'm doing wrong before I break something.
 
Last edited:
did more testing ...
when I power both devices from pk2, release pic18 from reset it usually works, (not always)
when I just power from pk2, it does not work just like powering from other sources ...

now, wth it works only in some cases .. 9600 is not too high speed to be affected by anything, the signal is clear and nice on the scope, streight lines, go rail to rail .. adding capacitors did not help...
 
I would use a PICKit2 on the RX uC as a debugger and check to see what is going on in the code. Check the various UART RX registers for error conditons. Does it ever generate an interrupt. Compare working to non working .
etc.

Maybe you have done that.

3v0
 
thanks for the ideas.. here are some new informations
- added 100nF from mclr to gnd
- tried configuring usart as USART_BRGH_HIGH, 255 (again 9600)
- when powered from PK2 sometimes everything works, sometimes not, when powered from any other source - it does not work
- using PK2 usart to read the data from 16F show that 16F is sending a byte every 300ms and PK2 is reading the byte correctly
- scope show that sent data is ok, timing perfect (from 16F)
- interrupt get triggered only when powered from pk2 (and not every time) .... argh, hard to explain ... I connect PK2, release from reset and it do not work, i disconnect, connect again, release from reset and then it works, every byte triggers the interrupt (the RD3 led show that), then I attach external power (while device is still working), deatach the pk2 and it still continues to work (every byte trigers the interrupt) ... then I reset the 18F (gnd + mclr) it start from scratch and - no, no interrupts ... not a single one


now ...
Check the various UART RX registers for error conditons

this sounds like a good idea ... I cannot "debug" it as the darn thing work like a charm trough debugger but maybe in the "while(1);" loop I can add some "check for RX error and clear it" ... will try to do it now .. thanks for the hint, but I still don't get why, even if the rx error happened, the interrupt is not triggered on next byte ?!
 
I guess it does not make any sense to look at the registers if it never generates the interrupt. Sorry about that.
 
Maybe another thing you have already done.

Have you verified that the RXing PIC is executing code when it is not working. Maybe a 2nd LED that blinks all the time.
 
yup, done that ...

first before I initialise anything I blink both leds, then blink one all the time and other one inside interrupt

funny hah ..

btw here's the scope of the byte ...

I have one idea .. maybe the imbecile cannot get "only one byte" I'll change the "sender" to send 2 bytes in a row instead of only one .. maybe that will help ...
 

Attachments

  • bajt.png
    33 KB · Views: 142
My mind keeps comming back to it why it works some of the time and what possible connection it could have to the presence of the PICkit2.

I was thinking about uninitialized variable related to the UART, but on the PICs they retain their value between resets.

Maybe think about switching to a software UART and see if the problem is still there. It is a bit of a long shot but if the problem remains you can step through the bit bang code to see where it goes wrong.

Good Luck.
 
My mind keeps comming back to it why it works some of the time and what possible connection it could have to the presence of the PICkit2
welcome to my nightmare

Maybe think about switching to a software UART and see if the problem is still there. It is a bit of a long shot but if the problem remains you can step through the bit bang code to see where it goes wrong.

will try ... but slowly starting to walk away from all this ..
 
welcome to my nightmare
will try ... but slowly starting to walk away from all this ..

Perhaps you have offended the petty god of micro controllers by not wearing the correct shirt.

At times I get to the point where anything I do is wrong or does not work. A good nite of sleep and the problem is obvious.
 
At times I get to the point where anything I do is wrong or does not work. A good nite of sleep and the problem is obvious.

A night already passed nothing changed

I'll try few more things today and walk away ... come back to it in few days ...
 
now THIS IS STRANGE

it works ... done manually .. was not working either and then started to work ?!?!? .. I'm giving up .. it works now .. why .. that's for someone else to decide ?!?!?!?!

Code:
#include <p18cxxx.h>
#include <delays.h>

#pragma config OSC = HSPLL
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config WDT = OFF
#pragma config MCLRE = ON
#pragma config PBADEN = OFF
#pragma config CCP2MX = PORTC
#pragma config LVP = OFF
#pragma config XINST = OFF

volatile unsigned char distance;

void low_isr(void);
void high_isr(void);

#pragma code low_vector=0x18
void interrupt_at_low_vector(void){
  _asm GOTO low_isr _endasm
}
#pragma code
#pragma interruptlow low_isr
void low_isr(void){
  // LOW INTERRUPT CODE
}
#pragma code high_vector=0x08
void interrupt_at_high_vector(void){
  _asm GOTO high_isr _endasm
}
#pragma code
#pragma interrupt high_isr
void high_isr(void){
 //HIGH INTERRUPT CODE
  distance = RCREG;
  LATDbits.LATD3 ^= 1;
  PIR1bits.RCIF = 0;
}
#pragma code

void main(){
  ADCON0 = 0;
  ADCON1 = 0x0F;
  TRISA = 0;
  TRISB = 0;
  TRISC = 0x80;
  TRISD = 0;
  TRISE = 0;

  LATA = 0;
  LATB = 0;
  LATC = 0;
  LATD = 0;
  LATE = 0;

  //USART
  TRISCbits.TRISC7 = 1;

  TXSTA = 0x00; //transmit disabled
  RCSTA = 0x90; //SPEN + CREN
  BAUDCON = 0x02; //0x22 RXDTP, WUE
  SPBRGH = 0;
  SPBRG = 64;

  ///////////////////////////////////////////////////////
  //BAUDCONbits.RXDTP = 0;
  ///////////////////////////////////////////////////////

  PIE1bits.TXIE = 0; // no interrupt for sending
  PIE1bits.RCIE = 1; // interrupt on receive
  RCONbits.IPEN = 1;
  IPR1bits.RCIP = 1;
  INTCONbits.GIEH = 1;
  
  LATDbits.LATD2 = 1;
  LATDbits.LATD3 = 1;
  while(1){
    LATDbits.LATD2 ^= 1;
    Delay1KTCYx(200);
  }
}

Without BAUDCONbits.RXDTP = 1; it was not working (but darn bit is set few lines above) .. then I added BAUDCONbits.RXDTP = 1; and it started to work .. changed it to BAUDCONbits.RXDTP = 0; .. it worked .. commented it .. it works ?!?!?!?!?!?

now .. it works .. I'm restarting the laptop to compile again to see if it will work ...

anyhow .. whatever was reason for problem .. it is solved now (no idea how)

laptop booted .. lemme check if I recompile and flash what will happen - it works ..
 
me too ... I spend another hour to find out why and gave up ... it works, that's enough
 
I don't know if this could be the case where you need to set one register before the other. Let's see the datasheet sequence..

This make sense to set the baudrate then, enable the serial port.
 
Last edited:
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…