Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

MplabX & XC8 - PIC18F4550- USART Problem with 9600 baud rate & extrenal 20MHZ crystal

Status
Not open for further replies.

rushi53

Member level 2
Joined
Aug 19, 2009
Messages
46
Helped
2
Reputation
4
Reaction score
1
Trophy points
1,288
Location
India
Activity points
1,632
MplabX & XC8 - PIC18F4550- USART Problem with 9600 baud rate & extrenal 20MHZ crystal

I am interfacing PIC18F4550 with a touchscreen. My touchscreen gives serial output with 9600 baud rate.

Below is the format of touchscreen *output data at 9600baud rate.
0x0A X:0065 Y:0089 Z:0029 0x0D

I am using 20MHZ external crystal for PIC18F4550. I am using MPLAB-X and xc8 compiler.

With my code I am reading touchscreen and sending the received X, Y, Z co-ordinates back to PC via serial transmit.
My code run only once and then it gets hanged.

It seems like PIC is not receiving data continuously or there might be problem with my config bits.

Please help me in this.

Below is my code:

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <pic18f4550.h>
#include <xc.h>
 
#pragma config FOSC = HS
#pragma config WDT = OFF
#pragma config LVP = OFF
#pragma config PBADEN = OFF
 
void tx_data(unsigned char);
unsigned char rx_data(void);
unsigned char serial_data = ' ';
unsigned int i=0;
 
unsigned char serial_data1, serial_data2, serial_data3, serial_data4, serial_data5, serial_data6, serial_data7, serial_data8, serial_data9, serial_data10, serial_data11, serial_data12, serial_data13, serial_data14, serial_data15, serial_data16, serial_data17, serial_data18, serial_data19;
 
 
#define FREQ 20000000    // Frequency = 12MHz
#define baud 9600
#define spbrg_value (((FREQ/64)/baud)-1)    // Refer to the formula for Baud rate calculation in Description tab
void DelayMs(int count);
 
void main()
{
    int j;
     
   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)
    {
        while(serial_data != 'X')     // wait till X character is received
        {
            serial_data=rx_data();    // Receive data from PC
        }
            
            serial_data1=rx_data();    // Receive data from PC
            serial_data2=rx_data();    // Receive data from PC
            serial_data3=rx_data();    // Receive data from PC
            serial_data4=rx_data();    // Receive data from PC
            serial_data5=rx_data();    // Receive data from PC
            serial_data6=rx_data();    // Receive data from PC
            serial_data7=rx_data();    // Receive data from PC
            serial_data8=rx_data();    // Receive data from PC
            serial_data9=rx_data();    // Receive data from PC
            serial_data10=rx_data();    // Receive data from PC
            serial_data11=rx_data();    // Receive data from PC
            serial_data12=rx_data();    // Receive data from PC
            serial_data13=rx_data();    // Receive data from PC
            serial_data14=rx_data();    // Receive data from PC
            serial_data15=rx_data();    // Receive data from PC
            serial_data16=rx_data();    // Receive data from PC
            serial_data17=rx_data();    // Receive data from PC
            serial_data18=rx_data();    // Receive data from PC
            serial_data19=rx_data();    // Receive data from PC
 
            tx_data('X');        // Transmit the same data back to PC
            tx_data('=');        // Transmit the same data back to PC
            tx_data(serial_data2);        // Transmit the same data back to PC
            tx_data(serial_data3);        // Transmit the same data back to PC
            tx_data(serial_data4);        // Transmit the same data back to PC
            tx_data(serial_data5);        // Transmit the same data back to PC
            tx_data(0x0D);        // Transmit the same data back to PC
            tx_data(0x0A);        // Transmit the same data back to PC
            
            tx_data('Y');        // Transmit the same data back to PC
            tx_data('=');        // Transmit the same data back to PC
            tx_data(serial_data9);        // Transmit the same data back to PC
            tx_data(serial_data10);        // Transmit the same data back to PC
            tx_data(serial_data11);        // Transmit the same data back to PC
            tx_data(serial_data12);        // Transmit the same data back to PC
            tx_data(0x0D);        // Transmit the same data back to PC
            tx_data(0x0A);        // Transmit the same data back to PC
            
            tx_data('Z');        // Transmit the same data back to PC
            tx_data('=');        // Transmit the same data back to PC
            tx_data(serial_data16);        // Transmit the same data back to PC
            tx_data(serial_data17);        // Transmit the same data back to PC
            tx_data(serial_data18);        // Transmit the same data back to PC
            tx_data(serial_data19);        // Transmit the same data back to PC
            tx_data(0x0D);        // Transmit the same data back to PC
            tx_data(0x0A);        // Transmit the same data back to PC
            
        DelayMs(1000);
    }
}
 
 
void tx_data(unsigned char data1)
{
    TXREG=data1;                                     // Store data in Transmit register
    while(PIR1bits.TXIF==0);                             // Wait until TXIF gets low
}
 
 
unsigned char rx_data(void)
{
    while(PIR1bits.RCIF==0);                            // Wait until RCIF gets low
    return RCREG;                                   // Retrieve data from reception register
}
 
void DelayMs(int count)
{
    int Di,Dj;
    for(Di = 0 ; Di < count ; Di++)
    {
        for(Dj = 0 ; Dj < 100 ; Dj++);       
    }
}

 

Re: MplabX & XC8 - PIC18F4550- USART Problem with 9600 baud rate & extrenal 20MHZ cry

Hi,

I personally don´t like the solution.
Because the system hangs if you communication partner does not send.
There is a busy wait from byte to byte. This takes 100% of processing power. No chance to do anythin inbetween.

There are several ways to improve this. (The same job could be done with about 1% of processing power)

***
To your problem.
Code:
    while(1)
    {
        while(serial_data != 'X')     // wait till X character is received
        {
            serial_data=rx_data();    // Receive data from PC
        }

at first the varaible "serial_data" is initialized with ' '.
it is not 'X' and therefore the loop is getting processed
then 'X' is recived and it is stored in "serial_data"

then the complete main loop is processed.
but "serial_data" is not changed. It still contains "X"

And with this "X" it starts the loop anew.
therefore it won´t wait for an 'X'..

--> initialize serial_data = ' ' at the beginning of the loop.
just before "while(serial_data != 'X')"

Klaus
 

Re: MplabX & XC8 - PIC18F4550- USART Problem with 9600 baud rate & extrenal 20MHZ cry

Hi,
I personally don´t like the solution.
Because the system hangs if you communication partner does not send.
There is a busy wait from byte to byte. This takes 100% of processing power. No chance to do anythin inbetween.

There are several ways to improve this. (The same job could be done with about 1% of processing power)

Hi KlausST, Could you please suggest any other ways?


And thanks for pointing out my mistake in code, I have corrected it
at first the varaible "serial_data" is initialized with ' '.
it is not 'X' and therefore the loop is getting processed
then 'X' is recived and it is stored in "serial_data"

then the complete main loop is processed.
but "serial_data" is not changed. It still contains "X"

And with this "X" it starts the loop anew.
therefore it won´t wait for an 'X'..

--> initialize serial_data = ' ' at the beginning of the loop.
just before "while(serial_data != 'X')"

Klaus


after implementing your changes and few other changes to look code more readable,
my code is here:
Code:
#include <pic18f4550.h>
#include <xc.h>

#pragma config FOSC = HS
#pragma config WDT = OFF
#pragma config LVP = OFF
#pragma config PBADEN = OFF

// Program to depict the configuration of EUSART in PIC18F4550
// This code receives and then transmits the same data back to the PC .. // ..through PC's Serial Port

void tx_data(unsigned char);
unsigned char rx_data(void);
unsigned char serial_data;
unsigned int i=0;

unsigned char serial_dataX1, serial_dataX2, serial_dataX3, serial_dataX4;
unsigned char serial_dataY1, serial_dataY2, serial_dataY3, serial_dataY4;
unsigned char serial_dataZ1, serial_dataZ2, serial_dataZ3, serial_dataZ4;

#define FREQ 20000000    // Frequency = 12MHz
#define baud 9600
#define spbrg_value (((FREQ/64)/baud)-1)    // Refer to the formula for Baud rate calculation in Description tab
void DelayMs(int count);

void main()
{
    int j;
    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)
    {
        
        serial_data = ' ';
        serial_data = rx_data();
        if(serial_data=='X')
        {
            
            serial_data = rx_data();    // Receive data from PC
            serial_dataX1 = rx_data();    // Receive data from PC
            serial_dataX2 = rx_data();    // Receive data from PC
            serial_dataX3 = rx_data();    // Receive data from PC
            serial_dataX4 = rx_data();    // Receive data from PC
            
            serial_data = rx_data();    // Receive data from PC
            serial_data = rx_data();    // Receive data from PC
            serial_data = rx_data();    // Receive data from PC

            serial_dataY1 = rx_data();    // Receive data from PC
            serial_dataY2 = rx_data();    // Receive data from PC
            serial_dataY3 = rx_data();    // Receive data from PC
            serial_dataY4 = rx_data();    // Receive data from PC
            
            serial_data = rx_data();    // Receive data from PC
            serial_data = rx_data();    // Receive data from PC
            serial_data = rx_data();    // Receive data from PC

            serial_dataZ1 = rx_data();    // Receive data from PC
            serial_dataZ2 = rx_data();    // Receive data from PC
            serial_dataZ3 = rx_data();    // Receive data from PC
            serial_dataZ4 = rx_data();    // Receive data from PC
            

            tx_data('X');        // Transmit the same data back to PC
            tx_data('=');        // Transmit the same data back to PC
            tx_data(serial_dataX1);        // Transmit the same data back to PC
            tx_data(serial_dataX2);        // Transmit the same data back to PC
            tx_data(serial_dataX3);        // Transmit the same data back to PC
            tx_data(serial_dataX4);        // Transmit the same data back to PC
            tx_data(' ');        // Transmit the same data back to PC
            
            tx_data('Y');        // Transmit the same data back to PC
            tx_data('=');        // Transmit the same data back to PC
            tx_data(serial_dataY1);        // Transmit the same data back to PC
            tx_data(serial_dataY2);        // Transmit the same data back to PC
            tx_data(serial_dataY3);        // Transmit the same data back to PC
            tx_data(serial_dataY4);        // Transmit the same data back to PC
            tx_data(' ');        // Transmit the same data back to PC
            
            tx_data('Z');        // Transmit the same data back to PC
            tx_data('=');        // Transmit the same data back to PC
            tx_data(serial_dataZ1);        // Transmit the same data back to PC
            tx_data(serial_dataZ2);        // Transmit the same data back to PC
            tx_data(serial_dataZ3);        // Transmit the same data back to PC
            tx_data(serial_dataZ4);        // Transmit the same data back to PC
            tx_data(0x0D);        // Transmit the same data back to PC
            tx_data(0x0A);        // Transmit the same data back to PC
            
            DelayMs(10);
        }            
    }
}

void tx_data(unsigned char data1)
{
    TXREG=data1;                                     // Store data in Transmit register
    while(PIR1bits.TXIF==0);                             // Wait until TXIF gets low
}


unsigned char rx_data(void)
{
    while(PIR1bits.RCIF==0);                            // Wait until RCIF gets low
    return RCREG;                                   // Retrieve data from reception register
}

void DelayMs(int count)
{
    int Di,Dj;
    for(Di = 0 ; Di < count ; Di++)
    {
        for(Dj = 0 ; Dj < 100 ; Dj++);       
    }
}

However I don't find any luck. Still the results are same, I get following output on Terminal software on PC:
Code:
X05 =06Z04
And this output is strange too, because I should receive something like, X=0155 Y=0120 Z=0100
Also, I am receiving this output only once and then no response.

Please guide me.
 
Last edited:

Re: MplabX & XC8 - PIC18F4550- USART Problem with 9600 baud rate & extrenal 20MHZ cry

Hi,

It seems you write data to the UART output register before it is ready to accept new data.
* check if your fuction us correct
* maybe you need to clear/set a bit

Klaus
 

Re: MplabX & XC8 - PIC18F4550- USART Problem with 9600 baud rate & extrenal 20MHZ cry

You are adding a 1-second delay after each complete transmit, however what assures you that during this interval (an eternity for a microcontroller) the PC will not be sending a new packet ? It seems that it is blinding the communication, adding a break in the natural data flow.
 

Re: MplabX & XC8 - PIC18F4550- USART Problem with 9600 baud rate & extrenal 20MHZ cry

Don't include the processor-specific file - the xc.h file will do that for you (and that is the correct way of specifying the processor-specific registers).
As shown in the data sheet section 20.0 (top of the right text column on the page) you need to set the TRISC register. (Personally I prefer to set the Tx pin to output.)
What it the actual Fosc? You set a pre-processor variable to 20,000,000 and the associated comment is that you are using a 12MHz clock! In the first post you say you use an external 20MHz crystal. Which do you mean and how are you actually setting that (we are not shown the config settings and you don't have any code to configure the oscillator)?
Setting the oscillator is key to making the UART function correctly as there is generally only a few percent tolerance and getting strange characters is a common symptom of this.
While the TXIF bit can be used the way you are, I prefer to first wait until the TRMT bit is set and then write the value to the buffer. This does not take advantage of the effective double-buffer between the TXREG and the TSR but does force the transmission to be sequential.
Your delay function is almost certainly not accurate - use the compiler's delay macro.
If you could be missing characters ion the receive side then you should be checking for OERR and FERR errors. (Error checking is always recommended.)
Susan
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top