Connect with us

UART,hyperterminal and LCD

Discussion in 'Microcontrollers, Programming and IoT' started by lady_krizzie, Sep 4, 2012.

  1. lady_krizzie

    lady_krizzie

    30
    0
    Aug 2, 2012
    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
     
  2. Harald Kapp

    Harald Kapp Moderator Moderator

    9,137
    1,846
    Nov 17, 2011
    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
     
  3. lady_krizzie

    lady_krizzie

    30
    0
    Aug 2, 2012
    Oh, that will do a lot of work. Anyway, thank you. I will try to do it.
     
  4. Harald Kapp

    Harald Kapp Moderator Moderator

    9,137
    1,846
    Nov 17, 2011
    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 */
    
    }
     
  5. dahhal

    dahhal

    58
    0
    Jul 17, 2012
    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: Sep 4, 2012
  6. Harald Kapp

    Harald Kapp Moderator Moderator

    9,137
    1,846
    Nov 17, 2011
    unsigned char - right.
     
  7. lady_krizzie

    lady_krizzie

    30
    0
    Aug 2, 2012
    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.
     
  8. dahhal

    dahhal

    58
    0
    Jul 17, 2012
    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.
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-