Maker Pro
Maker Pro

UART,hyperterminal and LCD

lady_krizzie

Aug 2, 2012
30
Joined
Aug 2, 2012
Messages
30
Hi,
I'm making a project that will display characters in hyperterminal and in my LCD, whatever I pressed in my keyboard. Unluckily, I can only display right characters in the hyperterminal and strange characters in the LCD. Here is my basic code. I am using AT90USB64, Atmel Studio 6, ADM 3202, RS232 and LCD 16*2... I already search for answers and tutorials but none worked. I also include here UART library, because I learned that USB uC is not supported in free download of Atmel. Thank you in advance.

Code:
#include <avr/io.h>
#include "uart.h"
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "lcd.h" 

//static FILE mystdout = FDEV_SETUP_STREAM (uart_putc, NULL, uart_getc());

int main(void)
{
	hw_uart_init();
	hw_lcd_init();
	
	char foo;
	char *bar;
	
	while (1)
	{
		{
			foo = uart_getc();
			//fprintf_P(foo, ("%c"), bar);
			lcd_puts_wrap(foo);
		}
		
		{
			uart_putc(foo, bar);
		}
		
	}
	
	return 0;
}

Code:
#include "uart.h"

/*
 *	Send one character through UART
 */
int uart_putc(char c, FILE *unused)
//int uart_putc(char c)
{
	while (!(UCSR1A & (1<<UDRE1)))
	;
	UDR1 = c;
	
	return 0;
}

/*
 *	Receive one character from UART
 */
char uart_getc(void)
{
	while ((UCSR1A & (1<<RXC1)) == 0)
		;
	return UDR1;
}

/**
 *	Enable hardware uart module
 */
void hw_uart_init(void)
{
	UCSR1B |= (1<<RXEN1 | 1<<TXEN1);
	//UCSR1C |= (1<<UCSZ11 | 1<<UCSZ10);
	UBRR1H = (BAUD_PRESCALE>>8);
	UBRR1L = BAUD_PRESCALE;
}

Code:
#ifndef UART_H_
#define UART_H_

	#include <stdio.h>
	#include <avr/io.h>

	#ifndef F_CPU
	#define F_CPU	8000000UL
	#endif
	
	#define USART_BAUDRATE	9600
	//#define BAUD_PRESCALE	(((F_CPU*10 / (USART_BAUDRATE * 16UL+5))) - 1)
	#define BAUD_PRESCALE (((((F_CPU * 10) / (16L * USART_BAUDRATE)) + 5) / 10) - 1)

	void hw_uart_init(void);
	int uart_putc(char c, FILE *unused);
	//int uart_putc(char c);
	char uart_getc(void);

#endif /* UART_H_ */


*UART code library made by my superior
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,700
Joined
Nov 17, 2011
Messages
13,700
The character sets of the LCD is likely to be different from the ASCII that is used by teh hyperterminal. You need to look up the mapping of Bytes and characters in the LCDs datasheet. When "printing" to the LCD you need to re-map the characters.

Example:
Assume a mapping of the LCD that is like "A"=0x00, "B"=0x01, "C"=0x02 etc. (the actuual mapping you take from the datasheet)
To "print" ASCII "A" = 0x41 you need to output 0x00 to the LCD.

Actual numbers or codes may be different, but I hope you get the principle
 

lady_krizzie

Aug 2, 2012
30
Joined
Aug 2, 2012
Messages
30
Oh, that will do a lot of work. Anyway, thank you. I will try to do it.
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,700
Joined
Nov 17, 2011
Messages
13,700
Not so much work:
Set up a byte array with 256 elements. Use the ASCII code as the index into the array. Place the LCD code into the corresponding array elements. Here is some pseudo code:
Code:
/* these declarations are dummies only to satisfy the compiler */
/* you need to implement these yourself */
void terminalout(char foo) {};
void LCD_out(unsigned int foo){};

int main (void)
{
unsigned int LCD_code[256];

/* set up the array */
LCD_code[(int) 'A'] = 0x00;
LCD_code[(int) 'B'] = 0x01;
/*... just as an example, codes must be fitted to the LCD */
/* main work is setting up this array*/

terminalout('A'); /* output ASCIII 'A' to hyperterm */ 
LCD_out(LCD_code[(int) 'A']); /* output LCD code corresponding to 'A' to LCD */

}
 

dahhal

Jul 17, 2012
58
Joined
Jul 17, 2012
Messages
58
Set up a byte array with 256 elements. Use the ASCII code as the index into the array. Place the LCD code into the corresponding array elements.

Essentially a hash map. Great Solution.

The only addition I would add is to use a unsigned char instead of an unsigned int as you only need 1 byte for ASCII.

Code:
unsigned char LCD_code[256];
 
Last edited:

lady_krizzie

Aug 2, 2012
30
Joined
Aug 2, 2012
Messages
30
I tried changing lcd_puts_wrap to lcd_putc and it worked without re mapping. Only it displays 16 characters on the upper display of the LCD.
 

dahhal

Jul 17, 2012
58
Joined
Jul 17, 2012
Messages
58
I tried changing lcd_puts_wrap to lcd_putc and it worked without re mapping. Only it displays 16 characters on the upper display of the LCD.

Seems there is a bug in the lcd_puts_wrap function or that it is not set up properly, or incompatible with the hardware. Going by just the name here the wrapper would take the string where the putc is just the char. If you have the Source code for it I'll bet that the wrap would call the putc function though the wrapper would also add the line break when required. Likely to be '\n' though you should consult your LCD data sheet.
 
Top