Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

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 ?!
 
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
    bajt.png
    33 KB · Views: 141
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 :D

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 ..
 
now THIS IS STRANGE :D :D :D

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 :D - it works ..
 
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..
To set up an Asynchronous Transmission:
1. Initialize the SPBRGH:SPBRG registers for the
appropriate baud rate. Set or clear the BRGH
and BRG16 bits, as required, to achieve the
desired baud rate.
2. Enable the asynchronous serial port by clearing
bit, SYNC, and setting bit, SPEN.
3. If interrupts are desired, set enable bit, TXIE.
4. If 9-bit transmission is desired, set transmit bit,
TX9. Can be used as address/data bit.
5. Enable the transmission by setting bit, TXEN,
which will also set bit, TXIF.
6. If 9-bit transmission is selected, the ninth bit
should be loaded in bit, TX9D.
7. Load data to the TXREG register (starts
transmission).
8. If using interrupts, ensure that the GIE and PEIE
bits in the INTCON register (INTCON<7:6>) are
set.

This make sense to set the baudrate then, enable the serial port.
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top