UART not working in PIC

Status
Not open for further replies.

scorrpeio

Full Member level 5
Joined
Dec 26, 2006
Messages
286
Helped
10
Reputation
20
Reaction score
9
Trophy points
1,298
Activity points
3,496
hi...

I am working on UART for PIC18F4520.
All I need is to send the message from pic to hyperterminal of computer.
But it is not working :sad:

Please let me know what is going wrong in it

This is the code I wrote...

void EnableUART ( void )
{
RCSTAbits.SPEN = 1;
TRISCbits.TRISC6 = 0;
PORTCbits.RC6 = 0;

BAUDCON = 0x58;
SPBRG = 0x19; //BR = 9600 for 4MHz crystal osc
INTCONbits.GIE = 0; //Disable interrupts

TXSTAbits.TXEN = 0;
TXSTAbits.SYNC = 0;
TXSTAbits.BRGH = 0;
TXSTAbits.TX9 = 0;

}

void DisableUART ( void )
{
TXSTAbits.TX9 = 0;
}

void SendMessage ( char *Msg )
{
EnableUART();

TXSTAbits.TX9 = 1;
PutCh(*Msg);
DisableUART();

}

void PutCh ( char *Msg )
{

TXREG = 'A';

while( !PIR1bits.TXIF );

do {
// TXREG = *Msg;
// *(Msg++);
}while( *Msg != 0 );

}
 

From the data sheet:
The pins of the Enhanced USART are multiplexed
with PORTC. In order to configure RC6/TX/CK and
RC7/RX/DT as a USART:
• bit SPEN (RCSTA<7>) must be set (= 1)
• bit TRISC<7> must be set (= 1)
• bit TRISC<6> must be set (= 1)

Do you really want to keep switching between 8 and 9 bit transmission (the PC uses 8 bits mode):
bit 6 TX9: 9-bit Transmit Enable bit
1 = Selects 9-bit transmission
0 = Selects 8-bit transmission

You are turning the UART transmit off before sending data!
bit 5 TXEN: Transmit Enable bit
1 = Transmit enabled
0 = Transmit disabled

Also make sure you are using a suitable RS232 converter, the PIC logic levels and the PC serial port are not voltage compatible.

Brian.
 

Hi...

The problem is resolved though not fully.

I refined the code, which sends some garbage data on the hyperterminal.

Code:
#define StatusMSG1 "Booting Begins"
	void main()
	{
		// Indicator LED ON
		TRISB = 0x00; // Configure PORTB-pins as outputs
		PORTB = 0b00000111;
		
		//Initialise UART port for communication with Computer
		EnableUART();
		
		//Start Sending Status message on Port 80 (UART)
		SendMessage(StatusMSG1);
		
		//Initialise the Display like LCD 
		InitialiseDisplay();		

		while(1)
		{
		
		}
		
	}

The EnableUART and SendMessage are defined in another file as...

Code:
	void EnableUART  ( void )
	{
		TRISCbits.TRISC6   = 1;
		SPBRG 			   = 25; //BR = 9600
		TXSTAbits.TXEN 	   = 0;
		TXSTAbits.BRGH 	   = 1;
		RCSTAbits.SPEN 	   = 1;
		
		BAUDCTLbits.BRG16  = 0;		
	
		TXSTAbits.SYNC 	   = 0;		
		TXSTAbits.TX9  	   = 0;
		INTCONbits.GIE 	   = 0; 	//Disable interrupts
		TXSTAbits.TXEN 	   = 0;
		TXSTAbits.TXEN 	   = 1;
	}

	void SendMessage ( ram char* Msg )
	{
		while(*Msg)
		{
			TXREG = *Msg;
			while( !PIR1bits.TXIF );
			Msg++;
		}
		
		TXREG = NEWLINE; 
	}


If I directly use command as TXREG = 'A' instead of TXREG = *Msg, it works absolutely fine and successfully prints A on hyperterminal.
So, I think there is problem with char pointer. It might not be sending data properly. But, I am not sure of it.
Plz tell me why it prints garbage data on hyperterminal. Wht should be the remedy??
 

hi scorrpeio
try to do it using const key word

lcd_strram((const ram char*) buffer);

void lcd_strram (const ram char *str)
{
while(*str){
lcd_data(*str++);
}
}
 

hi

thnk u for reply...

I tried ur way...but it didnt work.

If I pass #define message to SendMessage() function, it prints garbage
and if I declare a char array, it prints data but not accurately.
I have made 1 change as...

Code:
#define StatusMSG1 "Booting Started"

	const char msg[]= StatusMSG1;
		// Indicator LED ON
		TRISB = 0x00; // Configure PORTB-pins as outputs
		PORTB = 0b00000111;
		
		//Initialise UART port for communication with Computer
		EnableUART();
		
		//Start Sending Status message on Port 80 (UART)
		//SendMessage(StatusMSG1);
		SendMessage(msg);
		//Initialise the Display like LCD 
		InitialiseDisplay();

the output of this code is....

BoigSatd instead of Booting Started

Any idea??? Can anyone resolve this issue?
 

problem is looking like that baud rate is not generating properly
but as u said that when u send a simple character it display
ru check it in Proteus and u using picc18 compiler
 
You are missing every second character. The UART seems to be working correctly though.
I suspect (but I cannot confirm) the problem is not in the UART code but in the memory organization. When the Baud rate is incorrect you usually see completely wrong characters rather than the correct ones in the wrong places.
Can you check the data in the 'Msg' array is actually stored as characters and not as words. Possibly you are only using half of the data by advancing the Msg pointer one word at a time while the text you are sending is stored in byte sized locations.

Incidentally, you should also set the USART RX pin to be an input so the USART can control it but I don't think it's essential in this case.

Brian.
 
I am also thinking the same way...
the pointer jump might be of 2 bytes while data is in single byte sequence.
So, what should be the remedy?

Moreover, if the #define message is passed to array and then array pointer is given to SendMessage()...it gives something as output
but if I directly pass #define message in the argument of SendMessage, it displays garbage data. I really dont understand what is the reason
 

MPLAB 8 version and C18 compiler
 

Try this then:
Code:
void UARTputs(char *data) {
  int len, count;
  
  len = strlen(data);
  for (count = 0; count < len; count++) 
    while( !PIR1bits.TXIF );
    TXREG = (*(data+count));
}
 
@Kaleborg
Even this code is not working... it prints nothing on the hyperterminal window.

I am attaching the recent modified code which gave the garbage output.
Plz suggest me remedy on it...it is sucking me now :sad:

main function
Code:
	//Initialise UART port for communication with Computer
	EnableUART();
		
	//Start Sending Status message on Port 80 (UART)
	SendMessage(StatusMSG1);

Function Definitions...
Code:
	void EnableUART  ( void )
	{
		TRISCbits.TRISC6   = 1;
		SPBRG 			   = 25; //BR = 9600
		TXSTAbits.TXEN 	   = 0;
		TXSTAbits.BRGH 	   = 1;
		RCSTAbits.SPEN 	   = 1;
		
		BAUDCTLbits.BRG16  = 0;		
	
		TXSTAbits.SYNC 	   = 0;		
		TXSTAbits.TX9  	   = 0;
		INTCONbits.GIE 	   = 0; 	//Disable interrupts
		TXSTAbits.TXEN 	   = 0;
		TXSTAbits.TXEN 	   = 1;
	}

	void SendMessage ( char* Msg )
	{
//		int len, count;
//  
//  		len = strlen(Msg);
//  		for (count = 0; count < len; count++) 
//    		while( !PIR1bits.TXIF );
//    		TXREG = (*(Msg+count));


		while( *Msg )
		{
			
			TXREG = *Msg;
			while( !PIR1bits.TXIF );
			Msg++;
		
		}
		
	//	TXREG = NEWLINE; 
	}
 

You are missing the { and } around the for loop.
If that doesn't fix it, try:


void SendMessage ( char* Msg )
{
int len, count;

len = strlen(Msg);
for (count = 0; count < len; count++)
{
while( !PIR1bits.TXIF );
TXREG = (Msg[count]);
}
}
 
write these lines before your header file

#pragma config OSC=HS, OSCS=OFF
#pragma config PWRT=OFF, BOR=ON, BORV=45
#pragma config WDT =OFF
#pragma config DEBUG=OFF,LVP=OFF,STVR=OFF
 
Yes, betwixt is right. I forgot to put {} in the for loop.
This routine works for me...
 
hello,

because of your guidance...its finally completed.

Yes...Its working.

But, it works only if I pass a char array to SendMessage Function.

Code:
        #define StatusMSG1  "Booting Started"
	const char msg[]= StatusMSG1;
        SendMessage(msg);

This works absolutely fine.

But...

Code:
        #define StatusMSG1  "Booting Started"
	  SendMessage(StatusMSG1);

This prints garbage data.
I am rookie in programming, so not understanding the why does it go wrong.

I think, there is problem in passing #define msg in PIC because it follows harvard architecture.

---------- Post added at 08:08 ---------- Previous post was at 08:06 ----------

I was thinking, if in future, a have to handle 10 messages....what should be design? Because my above char array is const, so it wont accept other messages than the one which is defined at time of declaration.
 

Well done getting it working so far.
Your SendMessage() is being passed a known value anyway so why not declare the messages in an array instead of as '#defines'. For example:
char *Messages = {"Message1", "Message2", "Message3", .....};
Then you can refer to them as SendMessage(Messages[n]) where 'n' is the place in the declaration. If ROM based you can add 'const' before the declaration so it becomes hard coded in fixed memory rather than being allocated as an array of variables.

Brian.
 
hi...

Being a rookie, I couldnt figure out this trick.
I tried it but it again started printing garbage... so I slightly modified it as..

Code:
const char ccBoot  [] 		= "Booting Started";
const char ccError [] 		= "Booting Error";
const char ccFinish[] 		= "Booting Finished. The next level Bootloader called!";

	SendMessage(ccBoot);
	SendMessage(ccError);

This works nicely.

Thank you all for helping me out.
Now, I have started up with Interfacing 16x2 LCD and stuck in that as well. Hope you will be helping me there also
 

I think the key point is not hardware problem.

I ran into this problem myself and was pulling my hair out trying to solve it. I was sending the string "123456789" using UART to my PC (putty). I was receiving every second character consistently. So the results in putty look like "13579". Where the hell are the even numbers?!

It turns out I needed to add a check into the write function that waits for both the TXIF and the TRMT bits to be set! It is not sufficient to wait for the TXIF alone.

void SendMessage ( ram char* Msg )
{
while(*Msg)
{
TXREG = *Msg;
while( !PIR1bits.TXIF );
while(!TXSTAbits.TRMT)continue;
Msg++;
}

TXREG = NEWLINE;
}

Hopefully this will help somebody else..
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…