PIC16F877A UART Troubles

Discussion in 'Embedded Systems and Microcontrollers' started by ActivePower, Oct 16, 2012.

  1. ActivePower

    Thread Starter Member

    Mar 15, 2012
    155
    23
    Hi all,

    I recently tried connecting the UART of my PIC16F877A to a PC to send some ASCII characters after successfully testing my MAX232.

    I simulated the program in MPLAB SIM where it seems to work fine. When it comes to actual hardware though I ran into some trouble with the terminal screen filling up with seemingly random characters.

    I felt it must be a Baud rate error and changed the Baud rate a couple of times but to no avail.

    Here is my code:

    Code ( (Unknown Language)):
    1.  
    2.  
    3. //main.c
    4. //To set up a UART transmit connection between a PC and PIC16F877A
    5.  
    6. #include<htc.h>
    7. #define _XTAL_FREQ 20000000
    8. #define BAUD 9600
    9. #define BRGR (_XTAL_FREQ)/(16*(129+1))
    10.  
    11. __CONFIG(FOSC_HS & CPD_OFF & CP_OFF & WDTE_OFF & BOREN_OFF & PWRTE_OFF & DEBUG_ON & LVP_OFF);
    12.  
    13.  
    14. void UART_Init()
    15. {
    16.     //SET UP TX
    17.     SPBRG=BRGR;             //Baud rate set at 9600 B/s and 20 MHz crystal
    18.     BRGH=1;                 //High speed Baud rate generator selected
    19.     SPEN=1;                 //Serial Port Enabled
    20.     SYNC=0;             //No Sync Transmission
    21.     TX9=0;          //8 Bit transmission
    22.     TXEN=1;             //TXIF set; no data in TXREG
    23.     //SET UP RX
    24.     RX9=0;          //8 Bit reception
    25.  
    26.  
    27.  
    28. }
    29.  
    30. void UART_Write(unsigned char byte)
    31. {
    32.     while(!TXIF);                       //if Transmit buffer is empty
    33.     TXREG=byte;                 //write to 8 bit tx buffer
    34.     __delay_us(10);                 //wait for some time
    35.    
    36. }  
    37.  
    38.  
    39.  
    40.  
    41. void main()
    42. {
    43.     UART_Init();
    44.     while(1)
    45.     {
    46.         UART_Write('0');
    47.     }
    48. }      
    49.    
    50.    
    51.  
    52.  
    53.  
    NOTE: I just configured the reception. I am not actually receiving anything

    Here's the random characters I captured off the terminal.

    I admit I might have messed it all up in the code somewhere. Please help me find it.

    Thanks!
     
  2. JohnInTX

    Moderator

    Jun 26, 2012
    2,341
    1,024
    For 9600 baud at 20MHz SPBRG should be 31 (BRGH=0) or 129 (BRGH=1). Your calculation does not do that. See tables 10-3 and 10-4 in the databook.

    If you have a scope send 'U' (55h) to the UART. The bit times are easy to see and should be 104us.
     
  3. ActivePower

    Thread Starter Member

    Mar 15, 2012
    155
    23
    Thanks for pointing that out. I made the change in my code and tried sending the data again but it made little change. Now, though the characters are not repeating as they should be, they are still not the right data I hope to see.

    New code:

    Code ( (Unknown Language)):
    1. //main.c
    2. //To set up a UART transmit connection between a PC and PIC16F877A
    3.  
    4. #include<htc.h>
    5. #define _XTAL_FREQ 20000000
    6. #define BAUD 9600
    7. #define BRGR (_XTAL_FREQ)/(16*(129+1))
    8.  
    9. __CONFIG(FOSC_HS & CPD_OFF & CP_OFF & WDTE_OFF & BOREN_OFF & PWRTE_OFF & DEBUG_ON & LVP_OFF);
    10.  
    11.  
    12. void UART_Init()
    13. {
    14.     //SET UP TX
    15.     SPBRG=129;              //Baud rate set at 9600 B/s and 20 MHz crystal
    16.     BRGH=1;                 //High speed Baud rate generator selected
    17.     SPEN=1;                 //Serial Port Enabled
    18.     SYNC=0;             //No Sync Transmission
    19.     TX9=0;          //8 Bit transmission
    20.     TXEN=1;             //TXIF set; no data in TXREG
    21.     //SET UP RX
    22.     RX9=0;          //8 Bit reception
    23.  
    24.  
    25.  
    26. }
    27.  
    28. void UART_Write(unsigned char byte)
    29. {
    30.    
    31.     while(!TXIF);                       //if Transmit buffer is empty
    32.     TXREG=byte;                 //write to 8 bit tx buffer
    33.    
    34.    
    35. }  
    36.  
    37.  
    38.  
    39.  
    40. void main()
    41. {
    42.     UART_Init();
    43.     while(1)
    44.     {
    45.         UART_Write("A");
    46.     }
    47. }      
    48.    
    49.    
    50.  
    51.  
    52.  
    Also, the UART connection I made isn't very reliable and I need to redo the connections every once in a while to avoid running into a break condition on the terminal. Any workaround for this?

    Thanks
     
  4. JohnInTX

    Moderator

    Jun 26, 2012
    2,341
    1,024
    Make sure RC7 and RC6 are set up as inputs in TRISC (SPEN will take over from there.)
    Are you sure your oscillator freq is 20MHz?
    Does the compiler know that you are compiling for an 'F877? I'm not familiar with HTC on midrange. I don't have htc.h for midrange but make sure that things like BRGH=1 actually evaluate to bsf TXSTA,2. It probably does but I always check the obvious when things that should work don't.

    Yes, fix your hardware. Is it pinned correctly? Ground connected? With a logic '1' on TXD (UART idle) you should have some (-)volts on the RX input of the PC. (-) volts on the PC TX line should result in a logic '1' at the PIC RXD pin. Ground should be ground i.e. 0V between the PC box and Vss of the PIC.

    Try writing only one char 'U' instead of many in a while(1) loop or use a long delay between writes so that you can scope / logic probe the PIC TXD pin. A scope should show the character. A logic probe should show logic high and blink on each character (won't find baudrate errors though). Use the MCLR to reset the PIC instead of cycling power. The MAX232 takes a bit of time to come up to volts.

    Other than that, it should get at least a char out.

    BTW: I like to set up config registers as a single binary byte write instead of individual bits. That way, I know all bits are configured and I haven't forgotten any. Sometimes there are hardware-specific reasons as well. Your way should work OK, though. (By config registers I mean things like peripheral control registers, not the PIC hardware config regs)
     
    Last edited: Oct 17, 2012
Loading...