- 12V Akku mit 280 Ah bauen         
Ergebnis 1 bis 2 von 2

Thema: LCD HD44780 im 4-bit Mode mit Busy-Abfrage

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    04.02.2005
    Beiträge
    76

    LCD HD44780 im 4-bit Mode mit Busy-Abfrage

    Anzeige

    LiFePo4 Akku selber bauen - Video
    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:

    Code:
    #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...
    mfg crowdy

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    04.02.2005
    Beiträge
    76
    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?
    Code:
    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)
    Code:
    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?
    mfg crowdy

Ähnliche Themen

  1. LCD-Display 8bit mit busy-flag-Abfrage
    Von BoGe-Ro im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 25.08.2010, 14:49
  2. 20x4Display: Abfrage "Busy-Flag" reagiert nicht
    Von Dolfo im Forum Assembler-Programmierung
    Antworten: 0
    Letzter Beitrag: 17.10.2007, 22:56
  3. busy abfrage beinem lcd
    Von slaud im Forum C - Programmierung (GCC u.a.)
    Antworten: 1
    Letzter Beitrag: 14.09.2005, 21:45
  4. LCD-Display 16*2: Auf welchem Pin ist das Busy-Flag??
    Von Minifriese im Forum Elektronik
    Antworten: 6
    Letzter Beitrag: 07.05.2005, 23:48

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress