RS232 receiver problem PIC16

Discussion in 'Embedded Systems and Microcontrollers' started by Egberts, Jun 7, 2014.

  1. Egberts

    Thread Starter New Member

    Jun 7, 2014
    13
    0
    Hey guys!
    I am stuck with a little project of mine and I hope you can help me.
    I'm quite new to PIC programming and i am trying to build a PIC to PIC serial communication. I already programmed the sender, but now i have problems with the receiver part. I want to make a LED flash on RC0 every time a receiving interrupt occurs to check if it works. I use the PICkit 2 UART tool to send to my PIC, but when I do, nothing happens. Is there somthing wrong in the code or am i missing something?

    Thanks in advance!

    Code ( (Unknown Language)):
    1. #include <htc.h>
    2. #include <pic16f690.h>
    3.  
    4.  
    5.     unsigned char counter=0;//Overflow counter
    6.     unsigned char counter2=0;//Overflow counter
    7.  
    8.     void initTMR0 (void);
    9.     void initUART (void);
    10.  
    11.     void main()
    12.     {
    13.        initTMR0();  //TMR0 init
    14.        initUART();  // UART init
    15.        ANSEL = 0;
    16.        TRISB5 = 1; //RX input
    17.        TRISB7 = 0;// TX output
    18.        TRISC=0;     // PORTC = output
    19.        PORTC=0;     // PORTC reset
    20.  
    21.       while(1)
    22.       {
    23.  
    24.       };
    25.     }
    26.  
    27.  
    28.     void initTMR0(void)
    29.     {
    30.        OPTION_REGbits.PS0=1; //Prescaler is divide by 256
    31.        OPTION_REGbits.PS1=1;
    32.        OPTION_REGbits.PS2=1;
    33.        OPTION_REGbits.PSA=0; //Timer Clock Source is from Prescaler
    34.        OPTION_REGbits.T0CS=0;//Prescaler gets clock from FCPU (1MHz)
    35.  
    36.        INTCONbits.T0IE=1;   //Enable TIMER0 Interrupt
    37.        INTCONbits.T0IF=0;
    38.        INTCONbits.PEIE=1;     //Enable Peripheral Interrupt
    39.        INTCONbits.GIE=1;      //Enable interrupts globally
    40.  
    41.        PIR1bits.RCIF = 0;  // make interrupt flag = 0
    42.  
    43.     }
    44.  
    45.     void initUART(void)
    46.     {
    47.         SPBRG = 25; //Fosch 4Mhz -> baudrate 2400
    48.         TXSTAbits.BRGH = 0;  //Sets Low Baud Rate
    49.         TXSTAbits.SYNC = 0;  //Sets Asynchronous mode
    50.         RCSTAbits.SPEN = 1;  //Enables EUSART
    51.        // TXSTAbits.TXEN = 1;  //Enables the EUSART transmiter
    52.         RCSTAbits.CREN = 1; //enable receive
    53.         PIE1bits.RCIE = 1;  //enables receive interrupt flag
    54.        
    55.     }
    56.  
    57.  
    58.     //Main Interrupt Service Routine (ISR)
    59.     void interrupt ISR ()
    60.     {
    61.         //unsigned char c;
    62.  
    63.    if (PIR1bits.RCIF == 1)                  //check for recieve interrupt
    64.      {
    65.                   counter ++;
    66.            if (counter == 15)
    67.            {
    68.                 counter = 0;
    69.                 PORTC=0b00000001;
    70.            }
    71.            else PORTC=0;
    72.          PIR1bits.RCIF=0;                     //  interrupt flag off
    73.       }
    74.  
    75. }
    76.  
     
  2. micropad

    Member

    Dec 24, 2011
    38
    0
    I think Timer0 interrupt passter than uart
    off timer0 interrupt and try
     
  3. Egberts

    Thread Starter New Member

    Jun 7, 2014
    13
    0
    Thanks for your reply!
    I tried to disable the TMR0 interrupt, but still nothing happens.
    Is there something wrong with my code or am i missing something?
     
  4. micropad

    Member

    Dec 24, 2011
    38
    0
    Post your modified codes
     
  5. paulfjujo

    New Member

    Mar 6, 2014
    20
    3
    hello,


    try to declare counter volatile
    You must read RCREG to clear RCIF bit..

     
  6. Egberts

    Thread Starter New Member

    Jun 7, 2014
    13
    0
    Allright thanks for the answers guys!
    So i implemented an unsigned to read the RCREG and commented the TMR0 interrupt and this gave me some promising results. But still the LED isn't blinking so I dont know for sure if the communication works. What would be the next step?
    Tanks!

    The modified code:
    Code ( (Unknown Language)):
    1. #include <htc.h>
    2. #include <pic16f690.h>
    3.  
    4.  
    5.     unsigned char counter=0;//Overflow counter
    6.     unsigned char counter2=0;//Overflow counter
    7.  
    8.     void initTMR0 (void);
    9.     void initUART (void);
    10.  
    11.     void main()
    12.     {
    13.        initTMR0();  //TMR0 init
    14.        initUART();  // UART init
    15.        ANSEL = 0;
    16.        TRISB5 = 1; //RX input
    17.        TRISB7 = 0;// TX output
    18.        TRISC=0;     // PORTC = output
    19.        PORTC=0;     // PORTC reset
    20.  
    21.       while(1)
    22.       {
    23.  
    24.       };
    25.     }
    26.  
    27.  
    28.     void initTMR0(void)
    29.     {
    30.        OPTION_REGbits.PS0=1; //Prescaler is divide by 256
    31.        OPTION_REGbits.PS1=1;
    32.        OPTION_REGbits.PS2=1;
    33.        OPTION_REGbits.PSA=0; //Timer Clock Source is from Prescaler
    34.        OPTION_REGbits.T0CS=0;//Prescaler gets clock from FCPU (1MHz)
    35.  
    36.        //INTCONbits.T0IE=1;   //Enable TIMER0 Interrupt
    37.        //INTCONbits.T0IF=0;
    38.        INTCONbits.PEIE=1;     //Enable Peripheral Interrupt
    39.        INTCONbits.GIE=1;      //Enable interrupts globally
    40.  
    41.        PIR1bits.RCIF = 0;  // make interrupt flag = 0
    42.  
    43.     }
    44.  
    45.     void initUART(void)
    46.     {
    47.         SPBRG = 25; //Fosch 4Mhz -> baudrate 2400
    48.         TXSTAbits.BRGH = 0;  //Sets Low Baud Rate
    49.         TXSTAbits.SYNC = 0;  //Sets Asynchronous mode
    50.         RCSTAbits.SPEN = 1;  //Enables EUSART
    51.        // TXSTAbits.TXEN = 1;  //Enables the EUSART transmiter
    52.         RCSTAbits.CREN = 1; //enable receive
    53.         PIE1bits.RCIE = 1;  //enables receive interrupt flag
    54.  
    55.     }
    56.  
    57.  
    58.     //Main Interrupt Service Routine (ISR)
    59.     void interrupt ISR ()
    60.     {
    61.         unsigned c;
    62.  
    63.    if (PIR1bits.RCIF == 1)                  //check for receive interrupt
    64.      {
    65.                   counter ++;
    66.            if (counter == 15)
    67.            {
    68.         c = RCREG;
    69.                 counter = 0;
    70.                 PORTC=0b00000001;
    71.            }
    72.            else PORTC=0;
    73.          //PIR1bits.RCIF=0;                     //  interrupt flag off
    74.       }
    75.  
    76. }
     
  7. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    This may be a dumb response, but please assure us that you've wired between pins 18 and 12, and pins 19 and 10, assuming the PICkit is still connected to the programming pins (i.e. pins 19 and 18). The UART in the PICkit communicates over the two data lines, but obviously those lines have to be connected to the PIC's UART! Also, you aren't explicitly setting the TRIS bits for A0 and A1 to high-Z; even if the default state on reset does that, I always set them.

    And please, humor our nerdiness and don't say "RS232" when you mean UART or serial port. It's not RS232 unless you use the specified voltages, which everyone tries to avoid.

    A handy way to test a UART is
    Code ( (Unknown Language)):
    1.  
    2.    if (PIR1bits.RCIF == 1)                  //check for recieve interrupt SP-1
    3.      txreg = rcreg;
    4.  
    No interrupts needed. Just put it in a loop and see if what goes in comes out.
     
  8. Egberts

    Thread Starter New Member

    Jun 7, 2014
    13
    0
    I am sorry John, but i don't really understand what you mean. I placed the PIC on my breadboard and made two 'headers':
    - The program header: attached all the necessary lines to program device.
    - The UART header: Pin 2 VDD, pin 3 VSS, pin 4 (PIC)TX and pin 5 (PIC)RX, like in the PICkit 2 user guide.

    Haha i am sorry I confused those, I get the difference now!

    I followed your advice and i placed your line of code in my while(1) loop, but i still don't get any response from my UART. Same result all over again..
     
  9. paulfjujo

    New Member

    Mar 6, 2014
    20
    3
    hello,

    try to reverse the order in the hardware init part

    Code ( (Unknown Language)):
    1.  
    2.  
    3. void main()
    4.     {
    5.        initTMR0();  //TMR0 init
    6.        ANSEL = 0;
    7.       [B] ANSELH=0;[/B]
    8.         TRISB5 = 1; //RX input
    9.        TRISB7 = 0;// TX output
    10.        TRISC=0;     // PORTC = output
    11.        PORTC=0;     // PORTC reset
    12.        [B] initUART();[/B]  // UART init
    13.  
    don't forget to reenable
    Code ( (Unknown Language)):
    1. TXSTAbits.TXEN = 1;  //Enables the EUSART transmiter
    and

    Code ( (Unknown Language)):
    1. volatile  unsigned char counter=0;//Overflow counter
     
  10. Egberts

    Thread Starter New Member

    Jun 7, 2014
    13
    0
    Wow thanks guys I finally got it working! Made my day!
    But Paul, could you tell me what the difference is between a normal unsigned char and a volatile unsigned char?
     
  11. paulfjujo

    New Member

    Mar 6, 2014
    20
    3
    hello,

    volatile must be specified if you want to use a variable wich is used in your main
    application or other function AND inside an interrupt.
    Some compiler can adjust this type themself (like MikroC PRO)
    but other, as C18 MPLAB need to specify the type volatile xxxxx !
    other compiler , i don't know.
    so a volatile variable can be modfied everywhere in the program.
    at every time.
     
  12. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,394
    1,606
    The "volatile" qualifier is used to instruct the compiler not to make any assumption about a variable in that it's value may be used in non-obvious ways. This includes variables that change inside an ISR and also many system register values.

    Wikipedia has a decent article on it's use.

    There is some confusion about it's usage. Marking all variables as volatile is going overboard, but there are some key areas where this should be done, especially when using a compiler with optimization capabilities.

    With a basic (non optimizing) compiler you probably do not need it, but if you ever improve or change your compiler then formerly good code can break and fail.

    Aside: there is nothing special about the Mikro C compiler's ability to predict when to automatically apply volatile. In fact, if you can find where it places it's device specific headers (which are actually dot C types in Mikro C 'silently" included into your project) you can see where the register variables are commonly marked as volatile right in the manufacturer's own code.
     
Loading...