PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : LCD HD44780 im 4-bit Mode mit Busy-Abfrage



crowdy
24.05.2011, 17:51
Moin moin,

der Anschluss eines HD44780-Kompatiblen LCD's ist mit den bekannten Tutorials (RN-Wissen, mikrocontroller.net und Peter Fleury) ja eigentlich sehr gut dokumentiert... Nun habe ich aber dennoch ein paar Probleme, an denen ich nun schon eine ganze Weile sitze. Und zwar möchte ich das LCD initialisieren, in den 4-bit Modus bringen und das unter Verwendung des Busy-Flags. Dazu habe ich einige Funktion geschrieben die eng an Peter Fleury's lib und den lib's von mikrocontroller.net angelehnt sind. Bei der Kompilierung gibt es keine Probleme oder kritische Warnungen, allerdings bleiben zwei der vier Zeile schwarz.

Angeschlossen ist das LCD an PORTC (atmega16), Jtag ist disabled. Wenn ich auf die R/W-Leitung verzichte und die lcd_routines.c von mikrocontroller.net verwende funktioniert's. Mit der lib von Peter Fleury aber leider nicht (Allerdings habe ich die lib komplett in eine main.c gepackt, weshalb auch da ein Fehler liegen könnte.)

Aber hier jetzt nur mal das eigengewächs:


#include <avr/io.h>
#include <util/delay.h>

#define DD 0x00
#define RS 0x04
#define EN 0x05
#define RW 0x06

#define dis_en_1() PORTC |= _BV(EN)
#define dis_en_0() PORTC &= ~_BV(EN)
#define dis_rw_1() PORTC |= _BV(RW)
#define dis_rw_0() PORTC &= ~_BV(RW)
#define dis_rs_1() PORTC |= _BV(RS)
#define dis_rs_0() PORTC &= ~_BV(RS)

////////////////////////////////////////////////////////////////Display//////////////////////////////////////////////////////////////////////
void dis_init( void );
void dis_dd_en( void );
void dis_busy_8(void);
void dis_busy_4(void);
void dis_cmd_4( uint8_t cmd);
void dis_dd_4( uint8_t dd );
/////////////////////////////////////////////////////////////////UART////////////////////////////////////////////////////////////////////////
void RS232_init( void );
void uart_putc( unsigned char c );
void uart_puts( char *s );
void uart_putc_bit( uint8_t c );
uint8_t uart_getc( void );
////////////////////////////////////////////////////////////////delay////////////////////////////////////////////////////////////////////////
void delay_ms( uint16_t ms );
/////////////////////////////////////////////////////////////////main////////////////////////////////////////////////////////////////////////
int main(void)
{ uint8_t sp;

RS232_init();

uart_puts( "\n\rLCD-Test" );
sp = uart_getc();

delay_ms(100);

dis_busy_8();
uart_puts( "\n\rLCD-Initialisierung gestartet..." );

dis_init();

//uart_puts( "\n\rLCD-Initialisierung abgeschlossen" );
//sp = uart_getc();

//dis_cmd_4(0x28);
//uart_puts( "\n\rLCD-Cursor Function setting!" );
//sp = uart_getc();

//dis_cmd_4(0x08);
//uart_puts( "\n\rLCD-Cursor Display OFF" );
//sp = uart_getc();

//dis_cmd_4(0x01);
//uart_puts( "\n\rLCD-Display geloescht" );
//sp = uart_getc();

//dis_cmd_4(0x06);
//uart_puts( "\n\rLCD-Cursor Entry Mode Set" );
//sp = uart_getc();

dis_dd_4(0x30);

dis_dd_4(0x31);

dis_dd_4(0x32);

return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////Display//////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void dis_init( void )
{ uint8_t i, sp;

DDRC = 0x7F; //PC0-6 as Output

dis_rs_0();
dis_rw_0();
dis_en_0();

//uart_puts( "\n\r" );
//uart_putc_bit(PORTC);

delay_ms(100);

PORTC = 0x03;

for( i=0; i<=2; i++) //3x Function setting
{
//uart_puts( "\n\r" );
//uart_putc_bit(PORTC);
//sp = uart_getc();

dis_dd_en();

delay_ms(6);
}

PORTC = 0x02; //in 4-Bit Modus wechseln
_delay_us(2);
dis_dd_en();

dis_cmd_4(0x28); //Function Set: 0010|1000
dis_cmd_4(0x0E); //Display Control: 0000|1110
dis_cmd_4(0x06); //Entry Mode Set: 0000|0110
dis_cmd_4(0x01); //Display Clear
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline void dis_dd_en( void )
{
dis_en_1();

//uart_puts( "\n\rdis_dd_en: " );
//uart_putc_bit(PORTC);

_delay_us(5);

dis_en_0();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void dis_busy_8(void)
{
uint8_t rep;

DDRC = 0x70;

dis_rw_1();

do
{ dis_en_1();
_delay_us(2);
rep = ((0x0F & PINC)<<4);
dis_en_0();
}while( rep & 0x80);

dis_rw_0();

}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void dis_busy_4(void)
{ uint8_t rep, sp;

//uart_puts( "\n\rdis_busy_4 gestartet" );

PORTC &= 0xF0;
DDRC = 0x70;

dis_rw_1();
//sp = uart_getc();
do
{ dis_en_1();
_delay_us(2);
rep = (PINC<<4);
_delay_us(2);
dis_en_0();

_delay_us(5);

dis_en_1();
_delay_us(2);
rep |= (0x0F & PINC);
_delay_us(2);
dis_en_0();
//uart_puts("\n\rrep = ");
//uart_putc( rep + '0' );
}while( rep & 0x80);

//uart_puts( "\n\rdis_busy_4 beendet" );

dis_rw_0();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void dis_cmd_4( uint8_t cmd )
{
//uart_puts( "\n\rdis_cmd_4 gestartet" );

dis_busy_4();

dis_rs_0();

PORTC &= 0xF0; //PC0-3 = 0
PORTC |= (cmd >> 4); //PC0-3 = higher nibble
_delay_us(2);

dis_dd_en();

PORTC &= 0xF0; //PC0-3 = 0
PORTC |= (0x0F & cmd); //PC0-3 = lower nibble
_delay_us(2);

dis_dd_en();

//uart_puts( "\n\rdis_cmd_4 beendet" );
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void dis_dd_4( uint8_t dd )
{
dis_busy_4();

dis_rs_1(); // RS auf 1 setzen

PORTC &= 0xF0; //PC0-3 = 0
PORTC |= (dd >> 4); //PC0-3 = higher nibble
_delay_us(2);

dis_dd_en();

PORTC &= 0xF0; //PC0-3 = 0
PORTC |= (0x0F & dd); //PC0-3 = lower nibble
_delay_us(2);

dis_dd_en();

dis_rs_0();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////UART////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void RS232_init( void )
{
UCSRB |= (1<<TXEN)|(1<<RXEN); //Enable Tx, Rx, IRQ off
UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //asynchron 8N1
UCSRC &= ~((1<<UPM0)|(1<<UPM1));

UBRRH = ( 51>>8 ); //9.600 BdR
UBRRL = 51;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void uart_putc( unsigned char c )
{
while ( !(UCSRA & (1<<UDRE)) );
UDR = c;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void uart_puts( char *s )
{
while ( *s )
{
uart_putc( *s );
s++;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void uart_putc_bit( uint8_t c )
{
uart_puts( "\t" );
for(uint8_t j=0x80; j>= 0x01; j>>=1 )
{
if( j == 0x08 ) uart_putc( '|' );
if( (c & j) == 0 ) uart_putc( '0' );
else uart_putc( '1' );
}

}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
uint8_t uart_getc( void )
{
while ( !(UCSRA & (1<<RXC)) );
return UDR;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////delay////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void delay_ms( uint16_t ms )
{
for( uint16_t t=0; t<=ms; t++ )
_delay_ms(1);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Ich hoffe, dass ein geübtes Auge dort vielleicht einen Schnitzer findet, auch wenn es villeicht etwas schwierg ist da der Code doch etwas gewuchert ist...

Über Anregungen würde ich mich sehr freuen...

crowdy
26.05.2011, 20:12
so... ich weiß der Thread ist vielleicht nicht ganz so sexy ;), aber inzwischen weiß ich auch das es wohl auschließlich an der Funktion zum Abfragen des Busy-Bits liegt (ein Hardwareproblem schließe ich inzwischen aus). Also anders formuliert: Was ist an dieser Funktion falsch?

void dis_busy_4(void)
{ uint8_t rep;

PORTC &= 0xF0;
DDRC = 0x70;

dis_rw_1();

do
{ dis_en_1();
_delay_us(1);
rep = (PINC<<4);
dis_en_0();

_delay_us(1);

dis_en_1();
_delay_us(1);
rep |= (0x0F & PINC);
dis_en_0();
}while( rep & 0x80);

dis_rw_0();
}Der entsprechende Teil von P.Fleury sieht ja ähnlich aus, funktioniert bei mir allerdings auch nicht (aber das könnte auch noch ein weiteres Problem sein):mad:

DDR(LCD_DATA0_PORT) &= 0xF0; /* configure data pins as input */

lcd_e_high();
lcd_e_delay();
data = PIN(LCD_DATA0_PORT) << 4; /* read high nibble first */
lcd_e_low();

lcd_e_delay(); /* Enable 500ns low */

lcd_e_high();
lcd_e_delay();
data |= PIN(LCD_DATA0_PORT)&0x0F; /* read low nibble */
lcd_e_low();
Kann es eigentlich aus zu Problemen kommen, wenn die Wartezeiten zu lang werden?