Necesita ayuda para inicializar la pantalla en ATmega162

0

Tengo un DEM 16217 SYH-PY LCD de 2x16 caracteres y tengo problemas para inicializarlo.

Estoy usando AVR Studio 4. Las 8 líneas de datos están conectadas al puerto A del microcontrolador mientras que las 3 líneas de control están conectadas al puerto E. Habilitar es PE2, R / W es PE1 y S es PE0. Las conexiones del puerto A son DBn a PORTAn. Por lo que puedo ver en la hoja de datos, no parece que las instrucciones tomen más de 2 ms. Por alguna razón, la verificación de bandera ocupada no funciona correctamente, por lo que usé un retardo de 2 ms en su lugar.

Al principio, quería que parpadeara un LED después de cada paso, pero resultó ser mucho mejor tener una salida en un puerto serie.

Aquí está mi código:

#include <avr/io.h>
#include<util/delay.h>
#include "LED.h"
#include "Terminal.h"

void Screen_Execute(void)
{
    _delay_us(2);
    PORTE=PORTE | 4;
    _delay_us(2);
    PORTE=PORTE ^4;
    _delay_us(2);
    //_delay_us(2);

}

void Screen_busy(void)
{
    _delay_ms(2);
    //is the screen busy?   
    //PORTE=PORTE | 2;
    //DDRA=0x7F;
    //Screen_Execute();
    //while ((PINA & 128))
    //{
        //Screen_Execute();
        //BLINK_LED(500);
    //}// wait until zero
    //DDRA=0xFF;
    //PORTE=PORTE ^ 2;
    //Screen_Execute();
    //no longer busy
}




void Screen_init(void)
{

    //BLINK_LED(1000);
    SEND_STRING("Starting initialization\r\n",0);
    DDRE=0xFF;
    PORTE=0x00;
    DDRA=0xFF;
    PORTA=0x30;
    _delay_ms(250);
    _delay_ms(1000);
    SEND_STRING("Step 1 executing.\r\n",0);

    Screen_Execute();//voltage stabilized
    _delay_ms(5);//first output complete
    SEND_STRING("Step 1 complete.\r\n",0);


    //PORTA=0x30;
    //Screen_Execute();//second time
    //_delay_us(110);//end 

    //PORTA=0x30;//third time
    //Screen_Execute();

    SEND_STRING("Step 2 start.\r\n",0);
    //BLINK_LED(1000);
    Screen_busy();
    PORTA=0x38;//two lines, 8 bits, 5*7 characters
    SEND_STRING("Step 2 execute.\r\n",0);
    Screen_Execute();
    SEND_STRING("Step 2 complete.\r\n",0);

    SEND_STRING("Step 3 start.\r\n",0);
    //BLINK_LED(1000);
    Screen_busy();
    PORTA=0x08;//screen off
    SEND_STRING("Step 3 execute.\r\n",0);
    Screen_Execute();
    SEND_STRING("Step 3 complete.\r\n",0);


    SEND_STRING("Step 4 start.\r\n",0);
    //BLINK_LED(1000);
    Screen_busy();
    PORTA=0x14;//cursor goes to home and screen is cleared
    SEND_STRING("Step 4 execute.\r\n",0);
    Screen_Execute();
    SEND_STRING("Step 4 complete.\r\n",0);

    //Screen_busy();
    //PORTA=0x04;//
    //Screen_Execute();//end of init
    //Screen_busy();
    SEND_STRING("Step 5 start.\r\n",0);
    //BLINK_LED(1000);
    PORTA=0x0F;
    Screen_Execute();//cursor blinks, screen works
    SEND_STRING("Step 5 execute.\r\n",0);
    Screen_busy();
    SEND_STRING("Step 5 complete.\r\n",0);
}

Mi problema es que después de la inicialización, el cursor aparece en una posición aleatoria en la pantalla.

Cuando trato de hacer la inicialización como se describe en la documentación, al enviar la línea PORTA=0x30; 3 veces, no funciona. Además, si trato de usar un tiempo más apretado, de nuevo no funciona.

    
pregunta AndrejaKo

1 respuesta

2

Me gusta la forma en que haces la depuración del puerto serie y los comentarios en cada etapa.

Parece que su pantalla, como cualquier otro carácter pequeño pantalla LCD que he tenido en mis manos , utiliza el interfaz Hitachi 44780 . ¿Puedo preguntarle por qué no está utilizando un código de biblioteca LCD disponible en el mercado ?

¿Le gustaría algo como el siguiente trabajo para usted?

// WARNING: untested code. And therefore riddled with bugs.
#define SCREEN_ENABLE 4
#define SCREEN_READ 2
#define SCREEN_RS 1
// LCD #defines copied from http://techref.massmind.org/techref/io/lcd/44780.htm
#define LCDClearDisplay 1
#define LCDCursorHome   2
#define LCDOff      8   ;0x08 turn the display (and the cursor) off.
#define LCDOn       12  ;0x0C Turn on the display, but without a cursor
#define LCDCursorOn 14  ;0x0E Turn on the cursor (as an underline) as well as the display
#define LCDCursorBlink  15  ;0x0F Turn on a blinking block cursor as well as the display
#define LCDCursorLeft   16  ;0x10 Move the cursor left by one character
#define LCDCursorRight  20  ;0x14 Move the cursor right one letter
#define LCDShiftLeft    24  ;0x18 Shift the entire display left one character
#define LCDShiftRight   30  ;0x1C Shift the entire display right one character
#define LCDGoto     128 ;0x80 Add the location of the character position 
                ;   to which you wish to move the cursor

void screen_enable(void){
    _delay_us(2);
    PORTE |= SCREEN_ENABLE;
    _delay_us(2); // must be at least 140 ns
}
void screen_disable(void){
    PORTE &= ~SCREEN_ENABLE;
    _delay_us(2);
}
void Screen_Execute(void)
{
    screen_enable();
    screen_disable();
}

/** wait until screen is no longer busy */
void screen_busywait(void)
{
    char busy = 0x80;
    DDRA=0x00; // all inputs, to avoid fighting the screen outputs
    while(busy){
        // read busy flag
        PORTE |= SCREEN_READ; // read
        PORTE &= ~SCREEN_RS; // instruction: read busy flag and address
        screen_enable();
        // read busy bit while the Enable bit is high
        busy = PINA & 0x80;
        screen_disable;
        //BLINK_LED(500);
    }// wait until no longer busy

    // switch to "normal" "MCU writes to display" mode.
    PORTE &= ~SCREEN_READ; // write
    DDRA=0xFF;
}

void screen_send_instruction( char instruction ){
    PORTA=instruction;
    PORTE=0x00 + SCREEN_RS; // RS high: instruction
    DDRE=0xFF;
    DDRA=0xFF;
    Screen_Execute();
};

void Screen_init(void)
{    
    //BLINK_LED(1000);
    SEND_STRING("Starting initialization\r\n",0);
    // see http://techref.massmind.org/techref/io/lcd/44780.htm

    _delay_ms(15);
    SEND_STRING("Step 1 executing.\r\n",0);
    screen_send_instruction( 0x30 );
    _delay_ms(250);
    SEND_STRING("Step 1 complete.\r\n",0);

    screen_send_instruction( 0x30 );//second time
    _delay_ms(5);
    screen_send_instruction( 0x30 );//third time
    _delay_ms(1);

    SEND_STRING("Step 2 start.\r\n",0);
    screen_send_instruction( 0x38 ); // 8 bit interface, 2 line display, normal font
    SEND_STRING("Step 2 complete.\r\n",0);

    SEND_STRING("Step 3 start.\r\n",0);
    //BLINK_LED(1000);
    screen_busywait();
    screen_send_instruction( LCDOff );//screen off
    SEND_STRING("Step 3 complete.\r\n",0);

    screen_busywait();
    screen_send_instruction( 0x06 );// Entry mode: increment

    screen_busywait();
    screen_send_instruction( LCDClearDisplay );//cursor goes to home and screen is cleared

    screen_busywait();
    screen_send_instruction( LCDCursorOn );//screen on and underline cursor on.

    SEND_STRING("Step 4 start.\r\n",0);
    //BLINK_LED(1000);
    screen_busywait();
    screen_send_instruction( 0x14 );//Move the cursor right one letter (why????)
    SEND_STRING("Step 4 complete.\r\n",0);

    SEND_STRING("Step 5 start.\r\n",0);
    //BLINK_LED(1000);
    screen_busywait();
    screen_send_instruction( LCDCursorBlink );//Turn on a blinking block cursor as well as the display
    SEND_STRING("Step 5 complete.\r\n",0);
}

ps: en lugar de usar 11 pines de su MCU para controlar la pantalla, algunas personas sacrifican una pequeña velocidad para recuperar algunos de esos pines: algunos controlan la pantalla LCD con 7 pines de la MCU en modo de 4 bits, otros controla su pantalla LCD con 1 pin de la MCU .

    
respondido por el davidcary

Lea otras preguntas en las etiquetas