UART Transmitting Problem

Thread Starter

winson

Joined Dec 3, 2008
23
Hello everybody,

I was trying to write a UART program to send out few bytes of data by using PIC16F877A, CCS C compiler, MPLAB IDE, MPLAB SIM. The problem of my program is the code fail to transmit out the data to pin RC6 of Port C. So far i am just use MPLAB SIM to simulate my program and using Watch window to monitor all the register and symbol. To simulate the program i was pressing the "step into" button, and the first 2 bytes of data was load to TXREG and TSR but after that not able to load the third bytes of data beacuse TXIF flag is not set, this showing that TXREG was still full and the data look like "jam" already. from the Watch window the Port C does not show any value(0x00), i also try to press "animate" and let the program run for few minutes but still no data was show on Port C. Anybody can help to solve the problem or give some suggestion?

Below is my program,

#include <16F877A.h>

//***** Function prototype ******//
void init(void);
void transmit (void);
void transmit_empty (void);

//*****variable declaration******//
unsigned char TXSTA,RCSTA,SPBRG,INTCON,PIR1,PIE1,TXREG,PORTC,TRISC;
int count;

//****** define sfr address *****//
#byte TXSTA = 0x98
#byte RCSTA = 0x18
#byte SPBRG = 0x99
#byte PIE1 = 0x8c
#byte INTCON = 0x8b
#byte TXREG = 0x19
#byte RCREG = 0x1A
#byte PIR1 = 0x0c
#byte PORTC = 0x07
#byte TRISC = 0x87



char ucIPOD_packet_origin[2][7]={
{0xff,0x55,0x03,0x02,0x00,0x01,0xfa}, /* " play/pause " */
{0xff,0x55,0x03,0x02,0x00,0x08,0xf3} /* " fwd " */
};


/********************************************************************
FUNCTION : main()
DESCRIPTION : main loop
INPUT : Null
OUTPUT : Null
CREATE :
DATE : 07/10/08
********************************************************************/
void main()
{
init ();
transmit ();
while (1)
{
}
}


/********************************************************************
FUNCTION : init()
DESCRIPTION : sfr initialization
INPUT : Null
OUTPUT : Null
CREATE :
DATE : 07/10/08
********************************************************************/
void init ()
{
PORTC = 0x00; //0b 0000 0000 //Clear Port C

TRISC = 0xFF; //0b 1111 1111 //Enable USART Transmitter

TXSTA = 0x24; //0b 0010 0100 //Transmit Enable //SYNC = 0, Asynchronous Mode

RCSTA = 0x90; //0b 1001 0000 //Receive Enable //Serial Port Enable

SPBRG = 0x40; //0b 0100 0000 //SPBRG = 64, Baudrate = 19.231KBAUD, High Baud Rate

INTCON = 0x00; //0b 0000 0000 //Disable Global and Peripheral Interrupt

PIR1 = 0x10; //0b 0001 0000 //USART transmit/Receive Interrupt Flag bit

PIE1 = 0x00; //0b 0000 0000; //Individual enable bits for the peripheral interrupts.

count = 0;
}


/********************************************************************
FUNCTION : transmit()
DESCRIPTION : uart transmission
INPUT : Null
OUTPUT : Null
CREATE :
DATE : 07/10/08
********************************************************************/
void transmit ()
{
while (1) //Keep on looping
{
if (PIR1 == 0x10) //Check TXIF flag
{ //If TXREG is empty

TXREG = ucIPOD_packet_origin[0][count]; //Load data

count++; //Counter increment
}
}
}

[/code]

I am really no idea why such condition happen, everything look like set properly but it is not run.
Is it my simualtion methods is wrong or my code was having problem?

Any suggestion is appreciate.

Thanks
 

Thread Starter

winson

Joined Dec 3, 2008
23
I already successfully simulate my UART program by using Uart1 IO tab in MPLAB SIM. It is under Debugger > Settings > Uart1 IO. In Uart1 IO tab just click "Enable Uart IO" and select "Window" as output then press ok. After back to MPLAB main screen a "SIM Uart1" tab will exist in the output window. Press "run" to simulate the UART program and the transmitted data will show in output window as ASCII character, just have to refer ASCII table and verify the transmitted data.

Thanks everybody!
 

Thread Starter

winson

Joined Dec 3, 2008
23
Hi everybody.

I already try my UART transmiting program on the real hardware with a breadboard but the result is not successful. I was using an oscilloscope to trace the signal that send out from the USART Tx pin of 16F877A but the scope does not show any pulses and just maintain at 0V. This program is run well in MPLAB Simulation.

The peripheral circuitry of the 877A is simple, i was put the 20MHz crystal's leg to OSC1 and OSC2 with a 22pF capacitor from each crystal leg to ground. I connect 5V(3A) supply to the two VDD pin of 877A and 0V to the two VSS pin finally i also connect 5V supply to the MCLR pin for the reset purpose and i also try to put a 20k resistor to the VDD to limit the current but the result is still the same. This is all the thing that i do, but the scope does not show any digital pulses. Anybody can give me some suggestion or alert me some of the error that i done?
My latest version of code is show below, Thanks...

Rich (BB code):
#include <16F877A.h>

//***** Function prototype ******//
void init(void);
void transmit (void);
void transmit_empty (void);

//*****variable declaration******//
unsigned char TXSTA,RCSTA,SPBRG,INTCON,PIR1,PIE1,TXREG,PORTC,TRISC;
int count, next;

//****** define sfr address *****//
#byte TXSTA        =      0x98
#byte RCSTA        =    0x18
#byte SPBRG        =    0x99
#byte PIE1        =    0x8c
#byte INTCON        =    0x8b
#byte TXREG        =    0x19
#byte RCREG        =    0x1A
#byte PIR1        =    0x0c
#byte PORTC        =    0x07
#byte TRISC        =     0x87
#bit  TXIF        =    PIR1.4
#bit  TRMT        =    TXSTA.1




char remote_command_basic[3][10]=
{
    {0xff,0x55,0x06,0x02,0x00,0x01,0x00,0x00,0x00,0xf7},    //0 Play/Pause
    {0xff,0x55,0x06,0x02,0x00,0x01,0x00,0x00,0x00,0xf7},    //1 Play/Pause
    {0xff,0x55,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0xf8}        //2 Release
};

    
/********************************************************************
FUNCTION       : main()
DESCRIPTION : main loop
********************************************************************/
void main()
{
    init ();
    transmit ();
    while (1)
    {
    }
}


/********************************************************************
FUNCTION       : init()
DESCRIPTION : sfr initialization
********************************************************************/
void init ()
{
   
    PORTC = 0x00;    //0b 0000 0000        //Clear Port C
    
    TRISC = 0xFF;    //0b 1111 1111        //Enable USART Transmitter and Receiver
    
    TXSTA = 0x24;    //0b 0010 0100        //Transmit Enable    //SYNC = 0, Asynchronous Mode
    RCSTA = 0x90;    //0b 1001 0000        //Receive Enable    //Serial Port Enable
    
    SPBRG = 0x40;    //0b 0100 0000        //SPBRG = 64, Baudrate = 19.231KBAUD, High Baud Rate
                                                                                    
    INTCON = 0x00;    //0b 0000 0000        //Global and Peripheral Interrupt Disable

    PIR1 = 0x10;    //0b 0001 0000        //USART transmit/Receive Interrupt Flag bit

    PIE1 = 0x00;    //0b 0000 0000;        //Individual enable bits for the peripheral interrupts.
                    
    count = 0;
    next = 0;
}


/********************************************************************
FUNCTION       : transmit()
DESCRIPTION : uart transmission
********************************************************************/
void transmit ()
{
    while (1)                                //Keep on looping
    {
        if (TXIF == 1)                    //Check TXIF flag            
        {                                    //If TXREG is empty 
            
            TXREG = remote_command_basic[next][count];    //Load data
            delay_cycles( 1 );                //NOP
            delay_cycles( 1 );        
            delay_cycles( 1 );
            
            if (count > 8)                    //After 10th byte
            {
                next++;                        //Next packet
                if (next > 2)                //After 3rd packet
                {
                    return;                    //Return to main()
                }
            }
            count++;                        //Counter increment
            if (count > 9)                    //After 10th byte
            {
                count = 0;                    //Reset counter
            }
        }        //End first if loop
    }        //End while loop
}
 

Alberto

Joined Nov 7, 2008
169
You must initialise the uart registers before using it.
Rich (BB code):
RCSTA = $90 ' Enable serial port & continuous receive
TXSTA = $24 ' Enable transmit, BRGH = 1
SPBRG = 129 ' 9600 Baud @ 20MHz, 0,16%
($ sign=Hex)

Sorry but I don't know how to use them in C.

Alberto
 

Thread Starter

winson

Joined Dec 3, 2008
23
Thanks for your reply!:)

Yup, i did do the thing that you mention like below:

Rich (BB code):
//****** define sfr address *****//
#byte TXSTA        =      0x98
#byte RCSTA        =    0x18
#byte SPBRG        =    0x99
#byte PIE1        =    0x8c
#byte INTCON        =    0x8b
#byte TXREG        =    0x19
#byte RCREG        =    0x1A
#byte PIR1        =    0x0c
#byte PORTC        =    0x07
#byte TRISC        =     0x87
#bit  TXIF        =    PIR1.4
#bit  TRMT        =    TXSTA.1
Rich (BB code):
SPBRG = 0x40;    //0b 0100 0000        //SPBRG = 64, Baudrate = 19.231KBAUD, High Baud Rate
Anyway thanks for your attention!
Anybody can give me some suggestion? I'm really no idea about this project.

Any comments will be appreciate.
Thank you
 

Thread Starter

winson

Joined Dec 3, 2008
23
The program is able to work!

After i added "#fuses hs, nowdt, nolvp, noprotect" to my code, and by a digital oscilloscope i can see the data send out nicely.
 

vk4tec

Joined Feb 19, 2009
4
Yes you need to tell the system that

You have a HS oscillator
<this stops the MCU from being clocked>

Dont' use the watch dog timer
<this can just keep reseting and the program wont run>

Dont' use the low voltage programming
<can stop the program from even being loaded>

and no code protect
<thats your choice>

It is also as i found, needed that you watch you don't fill up the receive buffer.

Turn off the receiver when you are done.

Get your baud rate correct for your OSC, and be sure the pin is configured.

Otherwise the buffer will fill after 3 characters and the USART will stall if you don't manage it.

Andrew
 
Last edited:

Thread Starter

winson

Joined Dec 3, 2008
23
It is also as i found, needed that you watch you don't fill up the receive buffer.

Turn off the receiver when you are done.

Get your baud rate correct for your OSC, and be sure the pin is configured.

Otherwise the buffer will fill after 3 characters and the USART will stall if you don't manage it.

Andrew
Hi Andrew,:)

Thanks for your opinions, so is it mean that the receive buffer will automatic fill up with data when i did not use it?
 
Top