0
\$\begingroup\$

I am using this 8-bit, 8-pin mcu for asynchronous EUSART.

Sometimes when I power it up, it gives me correct characters (e.g. I send 'w', it returns 'w'), but sometimes when I power it up, it returns strange chars (e.g. I send 'w', it returns 'w' or 'u' or 'W', etc.). This problem arises solely with powering up the mcu at different times (hence, it is not a time-invariant system, but it should be!).

Note that I do not program the mcu differently between these two instances.

  • External crystal oscillator: 4 MHz
  • Voltage: 3.2 V
  • Current consumption: When UART works accurately: 300 uA
  • Current consumption: When UART doesn't works accurately: 1200 uA

I am using receive interrupt to receive the chars and transmit the same char right back.

I am using MPLAB X IDE v3.20 and XC8 compiler. Complete code used is attached below. Please help.

/* * File: LF18313_uart_1.c * */

#include <stdio.h>
#include <stdlib.h>
#include <pic16lf18313.h>

#define _XTAL_FREQ (4000000UL)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG1
#pragma config FEXTOSC = XT     // FEXTOSC External Oscillator mode Selection bits (XT (crystal oscillator) from 100 kHz to 4 MHz)
#pragma config RSTOSC = EXT1X   // Power-up default value for COSC bits (EXTOSC operating per FEXTOSC bits)
#pragma config CLKOUTEN = OFF   // Clock Out Enable bit (CLKOUT function is disabled; I/O or oscillator function on OSC2)
#pragma config CSWEN = ON       // Clock Switch Enable bit (Writing to NOSC and NDIV is allowed)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2
#pragma config MCLRE = ON       // Master Clear Enable bit (MCLR/VPP pin function is MCLR; Weak pull-up enabled )
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config WDTE = OFF       // Watchdog Timer Enable bits (WDT disabled; SWDTEN is ignored)
#pragma config LPBOREN = OFF    // Low-power BOR enable bit (ULPBOR disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bits (Brown-out Reset disabled)
#pragma config BORV = LOW       // Brown-out Reset Voltage selection bit (Brown-out voltage (Vbor) set to 2.45V)
#pragma config PPS1WAY = OFF    // PPSLOCK bit One-Way Set Enable bit (The PPSLOCK bit can be set and cleared repeatedly (subject to the unlock sequence))
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will cause a Reset)
#pragma config DEBUG = OFF      // Debugger enable bit (Background debugger disabled)

// CONFIG3
#pragma config WRT = OFF        // User NVM self-write protection bits (Write protection off)
#pragma config LVP = ON         // Low Voltage Programming Enable bit (Low voltage programming enabled. MCLR/VPP pin function is MCLR. MCLRE configuration bit is ignored.)

// CONFIG4
#pragma config CP = ON          // User NVM Program Memory Code Protection bit (User NVM code protection enabled)
#pragma config CPD = ON         // Data NVM Memory Code Protection bit (Data NVM code protection enabled)

unsigned char rxc = 'a';

void UART_Init(unsigned long int desiredBaud) {
    TRISA1 = 1;         // PORT A1 is 'RX' and set as input
    ANSELA = 0x00;      // Disable analog functioning on analog pins
    RA0PPS = 0b10100;   // RA0 output source is UART TX
    RXPPS = 0b00001;    // RA1 input source is UART RX

    unsigned int baudReg;
    baudReg = (_XTAL_FREQ - desiredBaud*16UL)/(desiredBaud*16UL);
    BRGH = 1;           // BRG counter clock rates
    BRG16 = 0;
    SYNC = 0;           // Setting Asynchronous Mode

    SPBRG = baudReg;    // Writing SPBRG Register

    SPEN = 1;           // Enables Serial Port
    RCIE = 1;           // Enables Receiver Interrupt

    PEIE = 1;           // Enables Peripheral Interrupt
    GIE = 1;            // Enables Global Interrupt

    CREN = 1;           // Enables Continuous Reception
    TXEN = 1;           // Enables Transmission
}

void UART_Write(unsigned char data) {
    while(!TXIF) {}
    TXREG = data;
}

int main() {

    TRISA = 0x00;       //PORTA as Output

    UART_Init(9600);

    while(1) {

    }

    return 0;
}

void __interrupt ISR() {
    if (RCIF) {
        rxc = RCREG;
        UART_Write(rxc);
    }
}

Edit: There is no capacitor between VCC and GND

Edit: I have set MCLRE = OFF and PWRTE = ON, as requested. I have also added a 1uF capacitor between VCC & GND. But these did not affect the problem at hand. I tried to operate the mcu without 4MHz crystal oscillator while the code remained same with some minor changes as put in this Edit. The current consumption remained same, and the chars transmitted and received were having almost the same randomness as that when I used the 4MHz oscillator. So, it meant that the 4MHz crystal was not working properly. But it did not work even when I replaced this crystal with a different 4MHz crystal.

For a change, I tried 16MHz crystal and set the BRGH = 0 in the above code. Now, it works accurately! And it is time-invariant. But the current consumption is 1100uA. So, I would still like to know the possible causes of error with 4MHz crystal, because it uses 300uA (since I want the least power consumption).

\$\endgroup\$
  • \$\begingroup\$ Does #pragma config PWRTE = ON make a difference? \$\endgroup\$ – Roger Rowland Feb 24 '16 at 5:10
  • \$\begingroup\$ No, PWRTE = ON doesn't make a difference. \$\endgroup\$ – Ashish Ranjan Feb 24 '16 at 5:17
  • \$\begingroup\$ Can you show a schematic? Do you have bypass cap on the PIC power pins? Any floating inputs? The difference in power consumption maybe implies some physical cause. \$\endgroup\$ – Roger Rowland Feb 24 '16 at 5:25
  • \$\begingroup\$ The circuit diagram has been added. All the 6 pins (RA0 - RA5) except RA1 are declared as output. RA1 is declared input. There are no floating pins. Pins RA2 and RA3 are left bare (i.e. unconnected). \$\endgroup\$ – Ashish Ranjan Feb 24 '16 at 5:49
  • 1
    \$\begingroup\$ Do you have a datasheet for your 4MHz crystal? Are you using the correct loading capacitors? How have you constructed your circuit (breadboard, soldered)? \$\endgroup\$ – brhans Feb 24 '16 at 12:31
1
\$\begingroup\$

So, after a lot of debugging, it came to this:

Good news: I got UART working perfectly! (Current = 1100uA)

Bad news: I don't really know how it is working.

I cleared the SYNC, BRG16 & BRGH bits to 0. I set baud = 9600 by setting SPBRG = 25. Note that #pragma config FEXTOSC = XT (i.e. external oscillator).

Here is where it gets interesting. I removed the freaking external crystal oscillator and those 22pF capacitors and left the RA4 & RA5 pins unconnected.

So, the mcu is set to use the external oscillator but it does not actually have any physical external crystal oscillator connected to it. Even then it has the audacity to return correct characters!

Now, if someone could explain this solution, it would be really appreciated!

The circuit is on breadboard. Declaration of TX is output, RX is input.

The circuit diagram and code used are posted here: Pins RA2 - RA5 are kept unconnected.

enter image description here

/* 
 * File:   LF18313_uart_1.c
 * Author: Ashish Ranjan
 *
 * Created on 22 February, 2016, 10:05 PM
 */

#include <stdio.h>
#include <stdlib.h>
#include <pic16lf18313.h>


// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG1
#pragma config FEXTOSC = XT     // FEXTOSC External Oscillator mode Selection bits (XT (crystal oscillator) from 100 kHz to 4 MHz)
#pragma config RSTOSC = EXT1X   // Power-up default value for COSC bits (EXTOSC operating per FEXTOSC bits)
#pragma config CLKOUTEN = OFF   // Clock Out Enable bit (CLKOUT function is disabled; I/O or oscillator function on OSC2)
#pragma config CSWEN = ON       // Clock Switch Enable bit (Writing to NOSC and NDIV is allowed)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2
#pragma config MCLRE = OFF      // Master Clear Enable bit (MCLR/VPP pin function is digital input; MCLR internally disabled; Weak pull-up under control of port pin's WPU control bit.)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config WDTE = OFF       // Watchdog Timer Enable bits (WDT disabled; SWDTEN is ignored)
#pragma config LPBOREN = OFF    // Low-power BOR enable bit (ULPBOR disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bits (Brown-out Reset disabled)
#pragma config BORV = LOW       // Brown-out Reset Voltage selection bit (Brown-out voltage (Vbor) set to 2.45V)
#pragma config PPS1WAY = OFF    // PPSLOCK bit One-Way Set Enable bit (The PPSLOCK bit can be set and cleared repeatedly (subject to the unlock sequence))
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will cause a Reset)
#pragma config DEBUG = OFF      // Debugger enable bit (Background debugger disabled)

// CONFIG3
#pragma config WRT = OFF        // User NVM self-write protection bits (Write protection off)
#pragma config LVP = ON         // Low Voltage Programming Enable bit (Low voltage programming enabled. MCLR/VPP pin function is MCLR. MCLRE configuration bit is ignored.)

// CONFIG4
#pragma config CP = ON          // User NVM Program Memory Code Protection bit (User NVM code protection enabled)
#pragma config CPD = ON         // Data NVM Memory Code Protection bit (Data NVM code protection enabled)

unsigned char rxc = 'a';

void UART_Init(unsigned long int desiredBaud) {
    TRISA1 = 1;         // PORT A1 is 'RX' and set as input
    ANSELA = 0x00;      // Disable analog functioning on analog pins
    RA0PPS = 0b10100;   // RA0 output source is UART TX
    RXPPS = 0b00001;    // RA1 input source is UART RX

    unsigned int baudReg;
    baudReg = 25;
    BRGH = 0;           // BRG counter clock rates
    BRG16 = 0;
    SYNC = 0;           // Setting Asynchronous Mode

    SPBRG = baudReg;    // Writing SPBRG Register

    SPEN = 1;           // Enables Serial Port
    RCIE = 1;           // Enables Receiver Interrupt

    PEIE = 1;           // Enables Peripheral Interrupt
    GIE = 1;            // Enables Global Interrupt

    CREN = 1;           // Enables Continuous Reception
    TXEN = 1;           // Enables Transmission
}

void UART_Write(unsigned char data) {
    while(!TXIF) {}
    TXREG = data;
}

int main() {

    TRISA = 0x00;       //PORTA as Output

    UART_Init(9600);

    while(1) {

    }

    return 0;
}

void __interrupt ISR() {
    if (RCIF) {
        rxc = RCREG;
        UART_Write(rxc);
    }
}
\$\endgroup\$
  • \$\begingroup\$ #pragma config FCMEN = ON This is, most likely, the reason your circuit still works after removing the external crystal. The Fail-Safe Clock Monitor is enabled and when the PIC "senses" that the external crystal is missing it switched/ falls back to its internal oscillator (which probably is also running at 4 MHz) \$\endgroup\$ – m.Alin Feb 24 '16 at 14:36
  • \$\begingroup\$ You are right. It doesn't work with FCMEN = OFF \$\endgroup\$ – Ashish Ranjan Feb 24 '16 at 14:46
  • \$\begingroup\$ Whether your UART works or not with the internal oscillator will have a lot to do with the accuracy of the oscillator. \$\endgroup\$ – Scott Seidman Feb 24 '16 at 15:05
  • \$\begingroup\$ Yes, I wondered that one too. The error is generally 1% or so with factory calibration. So, it's pretty high compared to external crystal oscillators which have errors of 15-20 ppm. But that doesn't matter till the UART is working accurately, and in my case, it does work perfectly without external crystal oscillators. But, I guess current consumption is higher. \$\endgroup\$ – Ashish Ranjan Feb 24 '16 at 17:37
0
\$\begingroup\$

Both pins RX & TX too must be set as inputs. Also keep power up timer enabled, put decoupling capacitor between vdd and vss.

\$\endgroup\$
  • 1
    \$\begingroup\$ Not working. Tried all 3 steps. I think the TX should remain as output. \$\endgroup\$ – Ashish Ranjan Feb 24 '16 at 6:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.