Connect with us

RS-232 PIC Communication

Discussion in 'Microcontrollers, Programming and IoT' started by LordSputnik, Jun 26, 2012.

Scroll to continue with content
  1. LordSputnik

    LordSputnik

    45
    0
    Aug 11, 2011
    I'm using a PIC18F25K22 and a MAX3232CPE to attempt to communicate with a PC using RS232.

    I send data from the PC using a terminal program called "Termite". An LED connected to the PIC's RX1 pin flickers a little when the data is sent, so I know that some data is being transferred through the MAX3232CPE to the PIC. However, the PIC doesn't recognise the data - the C18 function DataRdy1USART() returns 0.

    I suspect this is because I have the baud rate set incorrectly, or I've configured the USART on the PIC wrongly, but I don't know for certain. I'm using the following code:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <p18f25k22.h>
    #include <usart.h>
    #include <delays.h>
    
    #pragma config FOSC = INTIO67
    #pragma config WDTEN = OFF
    #pragma config MCLRE = INTMCLR
    
    void Run(void);
    
    void main()
    {
        OSCTUNE = 0b11000000;
        OSCCON |= 0b00110000;
        TRISB = 0x00;
        TRISC = 0b10000000;
        LATB = 0x00;
        LATC = 0x00;
        
        Open1USART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_SINGLE_RX & USART_BRGH_HIGH,51);
    
        //baud1USART(BAUD_IDLE_CLK_HIGH & BAUD_16_BIT_RATE & BAUD_WAKEUP_ON & BAUD_AUTO_ON);
        Run();
    }
    
    void Run()
    {
        char recv;
    
        while(1)
        {
            while(!DataRdy1USART())
            {
                LATBbits.LATB0 = 0;
                Delay10KTCYx(100);
                LATBbits.LATB0 = 1;
                Delay10KTCYx(100);
            }
            recv = getc1USART();
            while(Busy1USART());
            Write1USART(recv);
            while(!DataRdy1USART())
            {
                LATBbits.LATB1 = 0;
                Delay10KTCYx(100);
                LATBbits.LATB1 = 1;
                Delay10KTCYx(100);
            }
            recv = getc1USART();
            while(Busy1USART());
            Write1USART(recv);
        }
    }
    I know that the microcontroller clock speed is 1MHz, because an LED on PORTB0 flashes at a rate of 0.5Hz. This gives an on-time of 1s, which is 100x10k instructions (I used Delay10KTCYx), which is 1M instructions per seconds = 1MHz.

    So, to get a baud rate of 1200 baud, I used 1M/(16*1200) = spbrg+1 = 52.08, so spbrg = 51.

    I also had the line:
    Code:
    baud1USART(BAUD_IDLE_CLK_HIGH & BAUD_16_BIT_RATE & BAUD_WAKEUP_ON & BAUD_AUTO_ON);
    But I commented it out, because I don't know what each bitmask is supposed to do, and the C18 Libraries manual gives a useless description:

    http://ww1.microchip.com/downloads/en/DeviceDoc/MPLAB_C18_Libraries_51297f.pdf

    Can anyone tell me what I doing wrong?

    Many Thanks,
    Ben
     
    Last edited: Jun 26, 2012
  2. BobK

    BobK

    7,682
    1,686
    Jan 5, 2010
    1. The baud clock is based on the clock frequency of your PIC, not the instruction cycle. If the instruction cycle is 1MHz the clock frequency is 4MHz because it takes 4 clocks to execute and instruction.

    2. You DO need to understand the configuration bits and set them correctly to use the UART. Read your datasheet for descriptions of the bits and how to set them up.

    Bob
     
  3. LordSputnik

    LordSputnik

    45
    0
    Aug 11, 2011
    1. Could you explain that a little? In the datasheet, it says to set IRCF<2:0> to 011 in order for the HFINTOSC output frequency to be 1MHz. Without PLL enabled, that means the CPU is receiving a 1MHz clock, surely?

    2. The C18 OpenXUSART() function doesn't set all of the necessary configuration bits then? I thought that might be possible, but I had hoped the C function would take care of it.

    Many Thanks for your help!
    Ben

    EDIT: I have a schematic if it's helpful:

    [​IMG]
     
    Last edited: Jun 26, 2012
  4. BobK

    BobK

    7,682
    1,686
    Jan 5, 2010
    Well, if your delays added up to 1M instructions and it is blinking at 1Hz, the clock frequency is 4MHz, because it takes 4 clocks to execute 1 instruction.

    Looking at your code, you have enabled the 4X PLL in OSCTUNE, which is why your cloock is running at 4MHz.

    Bob
     
  5. LordSputnik

    LordSputnik

    45
    0
    Aug 11, 2011
    Ahh, of course, I forgot about that!

    But do I still need to set additional config bits if I'm using Open1USART()?
     
  6. BobK

    BobK

    7,682
    1,686
    Jan 5, 2010
    I am not sure whether your call to OpenUart will do everything you need. I have always set up the registers myself, I find it less frustrating that trying to get a library function to do what I want.

    Bob
     
  7. LordSputnik

    LordSputnik

    45
    0
    Aug 11, 2011
    Ok, thanks for your help, I'll adjust the baud rate and read up on the register setting tomorrow, and post back here if I manage to get it working or not!
     
  8. LordSputnik

    LordSputnik

    45
    0
    Aug 11, 2011
    Got it working.

    I think the main problem was that I hadn't turned off ADC inputs on the serial pins in the ANSELC register.

    I played around with the registers, and found that these settings worked, for 1200baud:

    Code:
        SPBRG1 = 51;
        
        TXSTA1 = 0b00100100;
        RCSTA1 = 0b10010000;
        BAUDCON1 = 0b00000000;
    However, I still needed to use Open1USART - I think it was setting some other register that the other C function needed.

    Working back from the registers, I realized that USART_SINGLE_RX was the original problem. Looking at the RCSTAX register, setting SREN: Single Receive Enable Bit, does nothing when working in ASYNC mode. Howevver, CREN: Continuous Receive Enable Bit, must be set to enable the receiver in ASYNC mode.

    So, to fix the original problem, I removed all the USART register settings, and just changed the line with Open1USART() to:

    Code:
    Open1USART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_HIGH,51);
    This worked with no problems.

    The full set up code is here:

    Code:
    void main()
    {
        OSCTUNE = 0b10000000;
        OSCCON |= 0b00110000;
        TRISB = 0x00;
        TRISC = 0b11000000;
    
        LATB = 0x00;
        LATC = 0x00;
    
        ANSELC = 0x00;
        ANSELB = 0x00;
    
        Open1USART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_HIGH,51);
    
        Run();
    }
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-