RS232 communications with a PIC chip

LK/ELK/VK/PK/OK/MX/GLK/EGLK/GVK/GLT Series

Moderators: Henry, Mods

arney
LCD!
Posts: 12
Joined: Fri Nov 11, 2005 8:54 pm

RS232 communications with a PIC chip

Post by arney »

I'm working on a project, where a PIC18F4620 is talking to a 2041 model LCD over RS232. I can transmit data to the LCD just fine as long as it's all sequential, but as soon as I stop/delay between characters, the LCD stops responding. I've tried varying lengths of characters/commands, and it all works fine till I try to start again after stopping. One example I've tried, is to set up the chip to transmit text upon a button push. The first time I push the button the text is transmitted, but it won't work again, till I reset the chip? Transmitting the same text to my PC's terminal works flawless. What could be going on here? Is this a synchronous/asynchronous transmission problem?

Raquel
Matrix Orbital
Matrix Orbital
Posts: 813
Joined: Thu Aug 19, 2004 3:37 pm
Location: MO Office

Post by Raquel »

Hi arney,
Thank you for your post. I wonder if I can have a look at the code you are running. I have a feeling that you are using a compiler built-in function that might be closing the USART port after the last use; and that you need to re-initialize before re-use. The module should just work as if it was talked to by a terminal program.
Raquel Malinis
Design and Development
Matrix Orbital

arney
LCD!
Posts: 12
Joined: Fri Nov 11, 2005 8:54 pm

Post by arney »

Sorry for the delay, I've been out of town looking for a house.
I don't use any functions or anything, I just load the data into the transmission register. That initiates the transmission. I then wait till the transmission is done before I transmit again. I've transmitted to a terminal program on a PC, and everything comes across just fine. This is how I transmit each byte:

TXREG = txdata;
while(!TXSTAbits.TRMT){}

Again, it works fine, when transmitting to a terminal program on my PC.

Raquel
Matrix Orbital
Matrix Orbital
Posts: 813
Joined: Thu Aug 19, 2004 3:37 pm
Location: MO Office

Post by Raquel »

Hi arney,

How about trying:

while(!TXSTAbits.TRMT);
TXREG = txdata;

Do the while check first before actually writing to the register. This makes sure that the TSR is empty the very first time you write to the register. Since you mentioned that only after stopping previous transmission is when you have the problem.
Have you also connected the module to a terminal program? The module should just display fine, if it does not, then the problem is with the module or its settings. Maybe it is worth trying to connect it with a terminal program first.
Please keep me posted.
Raquel Malinis
Design and Development
Matrix Orbital

arney
LCD!
Posts: 12
Joined: Fri Nov 11, 2005 8:54 pm

Post by arney »

Yeah, sorry the lines are out of order. I tried checking before the first, between each one, and after the last just for OCD sake. I also used a HEX terminal program to talk to the LCD and send it commands.

Tom
Matrix Orbital
Matrix Orbital
Posts: 1030
Joined: Mon Jul 19, 2004 4:43 pm
Location: Calgary
Contact:

Post by Tom »

Why do you need delays in your programs? Can you provide some more code, so we can check what is happening? Have you tested the lcd module on a terminal program or some kind of test software?

arney
LCD!
Posts: 12
Joined: Fri Nov 11, 2005 8:54 pm

Post by arney »

I don't need "delays", but I do need to write to the LCD, go do X, then update the LCD. I can only write to the LCD the first time. I tested to see how long I could go before things stopped working...
This is the function I wrote:

void writeLCD (char txdata)
{
TXREG = txdata;
while(!TXSTAbits.TRMT){} //waiting for RS232 transmission end
}

But I've been testing it by checking the TRMT bit, write to TXREG, check bit, write to register, etc... Delay10KTCYx(x), PORTAbits.RA0=0;, check bit, write to register, delay longer, PORTAbits.RA0=1;, etc...
I'm toggling a LED to see if I'm making to each point.

Raquel
Matrix Orbital
Matrix Orbital
Posts: 813
Joined: Thu Aug 19, 2004 3:37 pm
Location: MO Office

Post by Raquel »

Hi arney,

There is just no reason for the display to stop displaying the characters you send it. I am not quite sure when you said you used a HEX terminal program to talk to the LCD and send it commands. What was the result of this? Was the LCD behaving as it should? Say if you connect the LCD to a terminal program such as hyperterminal, if you keep typing, characters should be displayed on the LCD. If you stop typing, then start typing again, the LCD should display the characters no problem (simulating the delays you put in the code). Please find out if this is happening. We need to make sure that the LCD is working properly before we go on and look at the code again.

Also, when you go back to your microcontroller, I wonder about the data you are sending; how about sending exactly the same data everytime, say 'A' just to make sure we are sending data that can be displayed. If for some reason you are sending data which is 0x00 to 0x08; these might display blank on the LCD.

Please keep me posted.
Raquel Malinis
Design and Development
Matrix Orbital

arney
LCD!
Posts: 12
Joined: Fri Nov 11, 2005 8:54 pm

Post by arney »

The HEX terminal is just a terminal program that you can type in HEX values and send them. This allows me to play around with the different commands. I didn't know how to send these with hyperterminal. I'll double check things, and try out what you suggested. I probably won't get a chance to get back to you till sometime tomorrow, but I'll let you know as soon as I can. Thanks for all the help!

Raquel
Matrix Orbital
Matrix Orbital
Posts: 813
Joined: Thu Aug 19, 2004 3:37 pm
Location: MO Office

Post by Raquel »

Hi arney,
No problem with getting back later. Have fun with house hunting. Good luck!
Raquel Malinis
Design and Development
Matrix Orbital

arney
LCD!
Posts: 12
Joined: Fri Nov 11, 2005 8:54 pm

Post by arney »

Hey, could it be because the baud rate generator can't get exactly right? I'm running the LCD at 9600, but the microcontroller is running at 9615. I'm going to try running it as slow as the LCD can go, and see if that'll take care of the problem. Also, in the documentation, it lists the jumper settings for the different baud rates and I2C addresses, and the baud rates are listed twice. Is that because J3 doesn't matter in RS232 mode?

Paradigm
Matrix Orbital
Matrix Orbital
Posts: 255
Joined: Thu Sep 13, 2001 6:00 pm
Location: Calgary, Alberta, Canada

Post by Paradigm »

I'll start by clarifying a few points that I've seen so far:

1) Hyperterminal CAN NOT send commands. It has no way of sending 0xFE which is the command prefix. If someone can correct me, PLEASE DO!

2) The allowable error in RS232 is 3%, so at 9600, you could vary from 9312 to 9888, so the value of 9615 is perfectly good.

To be blunt, I haven't got a clue. Assuming that you are in fact setting up the baud rate generator (post that code), what you have posted should work no problem. When I'm faced with a problem like this I generally write a new program from scratch that only excercises what I'm having problems with. To that end I would do the following:

Write a program that JUST sets up the RS232, sends a bunch of characters, then delays, sends a bunch of characters, and so on. In pseudo-code it would be:

Code: Select all

Setup the RS232
while (1) {
    Transmit the letter 'A' 10 times
    Wait a bit
}
And see if you can get that running. Then post that program in it's entirety. Don't forget to use the code markup tags. To use them simply use

Code: Select all

<code>
Your text
</code>
But replace the <> with square brackets. Let us know how it turns out either way.
James McTavish, P.Eng
Director of Engineering
Matrix Orbital

arney
LCD!
Posts: 12
Joined: Fri Nov 11, 2005 8:54 pm

Post by arney »

Yeah, I didn't think hyperterminal could do raw hex codes, and thanks for the info on the RS232 error. Another thing is I made the RS232 cable twice, since a wire broke on the first one. But I'm sure I wired it correctly, especially since it's getting data across the first time I transmit. But about the code, I'm using a PIC18F4620, with a 4MHz running the chip at 16MHz (x4 PLL). But here's my complete code, please tell me if I'm doing anything wrong (oh yeah, sorry for the lack of comments... after writing it from scratch a few times and all the numerous changes, I get tire of rewriting all the comments):

Code: Select all

//LCD testing code
#include <p18f4620.h>
#include <usart.h>
#include <delays.h>
#include <string.h>

#pragma config OSC = HSPLL	//type of oscillator
#pragma config WDT = OFF	//turning off "Watch Dog Timer"
#pragma config MCLRE = ON	//enable reset pin
#pragma config PBADEN = OFF	//port B starts as digital
#pragma config LVP = OFF	//low voltage programming disabled

//prototypes
void setup(void);
void PORTBinterrupt(void);
void writeLCD (char);
void writecommand (char);

//interrupt vector
    void HighISR(void)
{
	if (INTCONbits.RBIF == 1)
	{
		if (SW2 == 0)
		{
			writeLCD('2');
			PORTAbits.RA1=1;	//debugging
		}		

		if (SW3 == 0)
		{
			writeLCD('3');
			PORTAbits.RA1=0;	//debugging
		}
    LATB = PORTB;	//clear any mismatch (read datasheet for explaination)
	INTCONbits.RBIF=0;	//clear port B interrupt flag
	}
	INTCON=0b11001000;
}

#pragma code
void main(void)
{
	PORTAbits.RA0=1;
	setup();
	PORTAbits.RA0=1;
	while(1)	//infinite loop
	{
	PORTAbits.RA0^=1;	//toggle LED
	writeLCD('H');
	writeLCD('I');
	Delay10KTCYx(100);	// 5/80 of a second
	}
}

void setup(void)
{

//	RCONbits.IPEN=0;	//disable priority interrupts
  /* Configure all PORTB pins for input */
	TRISB = 0xFF;
	ADCON0=0b00111100;
    ADCON1 = 0x0F;
	INTCON2bits.RBPU=0;	//port B pull ups
	TRISA = 0;
	PORTA=0;
	PORTB=0;

//opening USART "manually"
	TXSTA = 0;           // Reset USART registers to POR state
	RCSTA = 0;
	SPBRGH=0;
	SPBRG=0x67;
	TXSTAbits.SYNC = 0;
	TXSTAbits.TX9 = 0;
	RCSTAbits.RX9 = 0;
	TXSTAbits.BRGH = 1;
	RCSTAbits.CREN = 1;
	PIE1bits.TXIE = 0;
	PIE1bits.RCIE = 0;
	TXSTAbits.TXEN = 1;  // Enable transmitter
	RCSTAbits.SPEN = 1;  // Enable receiver

	INTCON=0b11001000;

}

void writeLCD (char txdata)
{

	while(!TXSTAbits.TRMT){} //waiting for RS232 transmission end
	TXREG = txdata;
}

void writecommand (char txdata)
{
	while(!TXSTAbits.TRMT){} //waiting for RS232 transmission end
	TXREG = 0xFE;	//initiate command
	while(!TXSTAbits.TRMT){} //waiting for RS232 transmission end
	TXREG = txdata;
}

Raquel
Matrix Orbital
Matrix Orbital
Posts: 813
Joined: Thu Aug 19, 2004 3:37 pm
Location: MO Office

Post by Raquel »

Hello arney,
Now that you have posted your code, we can look at what's happening. First of all, I would like you to confirm if the following link contains the same datasheet that you are using for the PIC:

http://ww1.microchip.com/downloads/en/D ... 39626b.pdf

I have based the following observations/questions thinking that the above link is correct (PIC18F4620):
1. I do not see the initialization of TRISC; based on the datasheet (again if I have it right) on page 201, Section 18, TRISC6 and TRISC7 must be set inorder to used them as USART pins;
2. Are you using the AD converter right now? If you are, maybe we can skip it for now until we've figured the problem out, so set ADCON0 to 0x00 and yes ADCON1 to 0x0F

Also, your original post gave me the impression that you were sending only characters to display and not commands; and that after delays on transmission, the diplay does not respond anymore (ie, does not display characters anymore). The code does not call the writecommand() this then says that you do NOT send commands.

I'll still be looking at the code rignt now; but please confirm the above questions.
Raquel Malinis
Design and Development
Matrix Orbital

arney
LCD!
Posts: 12
Joined: Fri Nov 11, 2005 8:54 pm

Post by arney »

I've used the writecommand function, but I cut those out to simplify things. I will need to be able to transmit commands also. I changed and put in the TRISC, but it was still working without it. Originally I just used the library function to set up the USART, but then when I rewrote it, without the libary, I followed the direction on page 211 and 213, which never mention TRISC. I was using the A/D, but cut that code out when I started running into problems. So the ADCON0 is an artifact of that, but I changed it. It still works exactly the same, even with the changes you suggested. I can't understand why this doesn't work. I'm probably going to be working on it till late this evening... sucks

Post Reply