PIC12F1572 UART communication problem.

Thread Starter

FPerez

Joined Jul 11, 2014
4
Hi everyone! First post here, great to join this community.*

I'm trying to build a program for a PIC12F1572 using Mplab X Ide v.2.15 and XC8 compiler. It would listen for serial data and when '0' is received it sets RA4 high. In case of receiving '1' it sets RA4 low, and if it receives an 's' it sends out the status of RA4 (sends '1' if RA4 is high and '0' if low).
Thought it would be quite straight forward but it's turned out pretty challenging!
Circuitry is quite simple, the pic12f1572 is connected to a max232 chip, which is connected to a computer running a terminal program. Checked both the pic and the max232 and both are working just right. There must be some problem in my code for it just doesn't work, RA4 state doesn't never change at all, and sending an 's' doesn't return anything on terminal screen.
Here's the code:

Rich (BB code):
#include <xc.h>


#pragma config WDTE       =    OFF // watch dog timer off
#pragma config MCLRE      =    ON
#pragma config CP         =    OFF
#pragma config LVP        =    OFF // Low voltage program off
#pragma config FOSC       =    INTOSC

unsigned char cUART_char;
unsigned char cUART_data_flg;
unsigned char valor_rele;

void init_uart(void);
void UART_putc(unsigned char c);
void interrupt InterruptHandlerLow ();

void main()
{
 
    OSCCONbits.SCS = 0;
    OSCCONbits.IRCF = 0x0F; // 16Mhz
    OSCCONbits.SPLLEN = 0;
    TRISAbits.TRISA4 = 0; // R4 es output
    LATAbits.LATA4 = 0; // R4 a GND

    init_uart(); // init UART module
    while (1) // infinite loop which handles ncoming data as they arrive
    {
        if (cUART_data_flg==1)// if new data available, send it back through USART tx line (echo it)
        {
            if (cUART_char == '1'){
                LATAbits.LATA4 = 0;
            }
            else if (cUART_char == '0'){
                LATAbits.LATA4 = 1;
            }
            else if (cUART_char == 's'){
                valor_rele = PORTAbits.RA4;
                 UART_putc(valor_rele); // Mandas el valor del relé
            }
            cUART_data_flg=0; // clear new data flag so one charactor will echoed once
        }
    }
}


void interrupt InterruptHandlerLow ()
{
  if (PIR1bits.RCIF==1)//is interrupt occured by EUSART receive?,
                        //then RCREG is full we have new data (cleared when RCREG is read)
  {
  // if(RCSTA&0x06) //more efficient way than following commented method to check for reception error
    if(RCSTAbits.FERR==1 || RCSTAbits.OERR==1 )
    {
      RCSTAbits.CREN=0;    //Overrun error (can be cleared by clearing bit CREN)
      cUART_char=RCREG;    //clear Framing error
      RCSTAbits.CREN=1;
    }
    else
    {
       cUART_char = RCREG; // read new data into variable
       cUART_data_flg = 1; // new data received. so enable flg
    }
  }
}

void init_uart(void) // init UART module for 9600bps boud, start bit 1, stopbit 1, parity NONE
{

    TXCKSEL = 0;
    RXDTSEL = 0;
    cUART_data_flg=0;   // init data receive flag to zero (no data)
    TRISAbits.TRISA1=1; //Make UART RX pin input
    TRISAbits.TRISA0=0; //Make UART TX pin output
    SPBRGH  = 0x01;     //9600bps 16MHz Osc
    SPBRGL  = 0xA0;

    RCSTAbits.CREN=1;   //1 = Enables receiver
    RCSTAbits.SPEN=1;   //1 = Serial port enabled (configures RX/DT and TX/CK pins as serial port pins)
    BAUDCONbits.BRG16=1;//1 = 16-bit Baud Rate Generator ? SPBRGH and SPBRG

    TXSTAbits.SYNC=0;  //0 = Asynchronous mode
    TXSTAbits.BRGH=1;  //1 = High speed
    TXSTAbits.TXEN=1;  //1 = Transmit enabled

    PIE1bits.RCIE=1;     // 1 = Enables the EUSART receive interrupt
    INTCONbits.GIE = 1;  //enable interrupts
    INTCONbits.PEIE = 1;
}

void UART_putc(unsigned char c)
{
  TXSTAbits.TXEN=0;// disable transmission
  TXREG=c;            // load txreg with data
  TXSTAbits.TXEN=1;    // enable transmission
  while(TXSTAbits.TRMT==0) // wait here till transmit complete
  {
    NOP();
  }
}



It'll be great if you could take a look at it, as I'm kinda stuck here...*
I use a pickit3 to load the program into the micro controller, and the code compiles and loads just right.*

Thank you very much indeed!!
Kind regards,
Fran
 

tshuck

Joined Oct 18, 2012
3,534
Avoid claiming everything works when you haven't validated it (or, at least you haven't shown that you have).

Try making the PIC output data to the terminal and verify your serial communication is fine for transmitting from PIC to PC.

Since you neglected to mention it, I'll ask: do you have a pullup on MCLR?

Have you tried wrap-around tests on your devices (connect RX and TX on your UART interfaces) to verify they are configured properly?
 

Thread Starter

FPerez

Joined Jul 11, 2014
4
Thanks for your time tshuck :)

I performed a loopback test and MAX232 outputs the data I send from my computer, I guess this part is working ok then. As per the PIC, data transmission from PIC to PC doesn't work. I modified the main function code to just test data transmission, and didn't work. ( I also added a led+resistor in RA2 to see it blink, so I could verify the PIC works).
About the pull-up resistor, yes, I placed 10k resistor from VDD to MCLR

Rich (BB code):
void main()
{
    OSCCONbits.SCS = 0;
    OSCCONbits.IRCF = 0x0F; // 16Mhz
    OSCCONbits.SPLLEN = 0;
    TRISAbits.TRISA2 = 0; // R4 es output
    LATAbits.LATA2 = 0; // R4 a GND

    init_uart(); // init UART module
    while (1) // infinite loop which handles ncoming data as they arrive
    {
             LATAbits.LATA2 = 0;
             _delay(1000000);
             LATAbits.LATA2 = 1;
             _delay(1000000);

                TXSTAbits.TXEN=0;// disable transmission
                TXREG=0xFF;            // load txreg with data
                TXSTAbits.TXEN=1;    // enable transmission
                while(TXSTAbits.TRMT==0) // wait here till transmit complete
                {
                  NOP();
                }
    }
}
Seems like something's wrong/missing in my uart_init() function. :(
 

tshuck

Joined Oct 18, 2012
3,534
One thing I don't see is any specification for the ANSELA register (page 105)- this is responsible for setting the pins to digital I/O functionality.

Also, you don't need to turn the transmitter module on and off - it will only transmit while something is in the transmit buffer.
 

Thread Starter

FPerez

Joined Jul 11, 2014
4
Thanks tshuck!
You're right, I forgot to set the ANSELA register bits to 0, they're set now.
Also commented the two lines to turn the transmitter module on/off.
Unfortunately, there must be something else, as it's still not working :(
 

Thread Starter

FPerez

Joined Jul 11, 2014
4
Hi again.
Fixed it !!
I had not set the ansela register properly. Now it's working!
You saved my day tshuck, thank you!!

Cheers,
Fran
 

tshuck

Joined Oct 18, 2012
3,534
Hi again.
Fixed it !!
I had not set the ansela register properly. Now it's working!
You saved my day tshuck, thank you!!

Cheers,
Fran
I've been bitten by the ANSEL register enough times that it's one of the first 5 things I check for...

Glad to hear you got it! :)
 
Top