0
\$\begingroup\$

I am trying to create a program that contains UART using the PIC18f25j50 device. I have attached my creation so far which is a simple program that outputs a single character repeatedly to the console of a PC. The problem is the console displays a different character (þ~) to the selected one. This character stays the same despite the character that is selected changing (e.g "M" -> "þ~", "g" -> "þ~").

My thinking is that it something to do with the clock or the baud rate but I can't see any error. I have a 8MHz crystal connected and the fuses are set so that there is no PLL. The baud rate equation is correct given that I desire the peripheral to be asynchronous, 8-bit and low speed (P.327 of the linked datasheet).

Would anyone have any idea where the mistake is or have ideas to try to fix this?

#include <xc.h>

#pragma config WDTEN = OFF  // Watchdog Timer (Disabled - Controlled by SWDTEN bit)
#pragma config PLLDIV = 2       // PLL Prescaler Selection bits (Divide by 2 (8 MHz oscillator input))
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset  (Enabled)
#pragma config XINST = OFF      // Extended Instruction Set (Disabled)
#pragma config CPUDIV = OSC1    // CPU System Clock Postscaler (No CPU system clock divide)
#pragma config CP0 = OFF        // Code Protect (Program memory is not code-protected)
#pragma config OSC = HS      // HS
#pragma config T1DIG = ON       // T1OSCEN Enforcement (Secondary Oscillator clock source may be selected)
#pragma config LPT1OSC = OFF    // Low-Power Timer1 Oscillator (High-power operation)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF       // Internal External Oscillator Switch Over Mode (Disabled)
#pragma config WDTPS = 1        // Watchdog Postscaler (1:1)
#pragma config DSWDTOSC = INTOSCREF// DSWDT Clock Select (DSWDT uses INTRC)
#pragma config RTCOSC = T1OSCREF// RTCC Clock Select (RTCC uses T1OSC/T1CKI)
#pragma config DSBOREN = OFF    // Deep Sleep BOR (Disabled)
#pragma config DSWDTEN = OFF    // Deep Sleep Watchdog Timer (Disabled)
#pragma config DSWDTPS = G2     // Deep Sleep Watchdog Postscaler (1:2,147,483,648 (25.7 days))

void tx_data(unsigned char);

#define FREQ 8000000    // Frequency = 8MHz
#define baud 9600
#define spbrg_value (((FREQ/64)/baud)-1)  

void main()
{
    TRISCbits.TRISC6 = 0; // TX pin set as output
    TRISCbits.TRISC7 = 1;   // RX pin set as input

    TXSTAbits.TX9=0;
    RCSTAbits.RX9=0;
    TXSTAbits.SYNC=0;
    TXSTAbits.BRGH=0;
    BAUDCONbits.BRG16=0;
    SPBRG=spbrg_value;     // Fill the SPBRG register to set the Baud Rate
    RCSTAbits.SPEN=1;      // To activate Serial port (TX and RX pins)
    TXSTAbits.TXEN=1;      // To enable transmission
    RCSTAbits.CREN=1;      // To enable continuous reception
while(1)
{
    tx_data('m');        // Transmit the same data back to PC
}


}

void tx_data(unsigned char data1)
{
    TXREG=data1;                      
    while(TXSTAbits.TRMT==0);            
}
\$\endgroup\$
  • \$\begingroup\$ There is a table somewhere in the ds giving spbrg values for different baud rates and clocks. Assign those directly rather than calculating. \$\endgroup\$ – Oleg Mazurov Mar 19 '16 at 1:26
  • \$\begingroup\$ @OlegMazurov Yes, P.329 for SYNC=0, BRGH=0, BRG16=0 and a baud rate of 9600 I have tried each pre-calculated value for SPBRG for all the FOSC specified. Each value changed the character that is outputted but all are still wrong. \$\endgroup\$ – Marmstrong Mar 19 '16 at 1:35
  • \$\begingroup\$ UART setup looks correct. Receiving characters and echoing them back makes debugging harder. What character(s) do you now get when sending the same character? Check that your CPU clock frequency is correct by eg. flashing a LED once per second. \$\endgroup\$ – Bruce Abbott Mar 19 '16 at 19:17
  • \$\begingroup\$ @BruceAbbott I get (þøø). I have created a blinking demonstration which confirms that the clock is 8MHz. I can also quite easily put it to 48MHz but when I do this nothing (Or not a letter character) is outputted by the UART. \$\endgroup\$ – Marmstrong Mar 19 '16 at 23:33
  • \$\begingroup\$ @BruceAbbott I am so confused. I have now found a combination that outputs the correct value. SPBRG is kept at 12 but the terminal is now set to expect data at 4800 baud. The SPBRG is calculated for 8MHz at 9600 baud?!? I tried to recalculate for 9600 baud with the assumed frequency of 4MHz (I can't see how it would be this) but the calculate SPBRG spews garbage again. Any Ideas \$\endgroup\$ – Marmstrong Mar 20 '16 at 1:45
4
\$\begingroup\$

Your tx_data function is defined as taking a single character (unsigned char) as an argument but you are passing a string (const char *). A good compiler should give you a warning about this. Try :

tx_data ('m');
\$\endgroup\$
  • \$\begingroup\$ Thanks for that. You are correct about the warning but this did not solve the problem. \$\endgroup\$ – Marmstrong Mar 19 '16 at 2:00
  • \$\begingroup\$ What Mathieu L. tries to say is that you're printing a pointer to the string "m", not the string. That's why it looks funny. \$\endgroup\$ – Oleg Mazurov Mar 19 '16 at 3:10
  • \$\begingroup\$ @OlegMazurov Yes, I have seen that is a problem and added his proposed fix but this doesn't solve the problem. \$\endgroup\$ – Marmstrong Mar 19 '16 at 12:01
  • \$\begingroup\$ @OlegMazurov I have added an edit to my question above which is another attempt but also doesn't work. \$\endgroup\$ – Marmstrong Mar 19 '16 at 12:31

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.