¿Se muestran los caracteres de bloque en 16x 2 LCD en lugar de letras al interactuar con atmega328p?

0

Estoy tratando de mostrar algunos caracteres en 16x2 LCD (1602 A) usando Arduino Uno (atmega328p-pu). He escrito mi código usando C incrustado para el modo de 4 bits. El código está abajo.

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

#define LCD_DATA_DDR DDRD
#define LCD_CTRL_DDR DDRB
#define LCD_DataBus PORTD  //Using PD4 to PD7
#define LCD_CTRL_PORT PORTB

//function prototypes
void LCD_Write(unsigned char cmd, unsigned char reg_select);
void LCD_WriteData(char data);
void LCD_WriteCmd(char cmd);
void LCD_Init();

void LCD_Write(unsigned char cmd, unsigned char reg_select)
{
  char  tempCmd;
  if(reg_select == 1)
    LCD_CTRL_PORT |= (1<<PB0);   //Select Data Register
  else
    LCD_CTRL_PORT &= ~(1<<PB0);   //Select Command Register

  //Mask data/cmd
  tempCmd = cmd;
  tempCmd &= 0xf0;// mask Lower 4 bits

  //Set data/cmd
  LCD_DataBus &= 0xf0;           //Set PORTD LSB to HIGH since we use PD4 to PD7
  LCD_DataBus |= tempCmd;        //Set bits in PORTD

  //Send data/cmd
  LCD_CTRL_PORT |= (1<<PB1); // Send a High-to-Low pulse at Enable pin
  _delay_ms(400);
  LCD_CTRL_PORT &= ~(1<<PB1); // Send a High-to-Low pulse at Enable pin

  //******Send next 4bits

  //mask data/cmd
  tempCmd = cmd << 4; //shift left 4 times so the LSB bit can be sent.
  tempCmd &= 0xf0; //mask Lower 4 bits

  //Set data/cmd in bus
  LCD_DataBus &= 0xf0;
  LCD_DataBus |= tempCmd;

  //Send data/cmd
  LCD_CTRL_PORT |= (1<<PB1); // Send a High-to-Low pulse at Enable pin
  _delay_ms(400);
  LCD_CTRL_PORT &= ~(1<<PB1); // Send a High-to-Low pulse at Enable pin

  return ;
}

//Send data by setting RS=1.
void LCD_WriteData(char data)
{
  LCD_Write(data, 1);
}

//Send cmd by setting RS=0.
void LCD_WriteCmd(char cmd)
{
  LCD_Write(cmd, 0);
}

void LCD_Init()
{
    LCD_WriteCmd(0x02); // to initialize LCD in 4-bit mode.
    _delay_ms(1);
    LCD_WriteCmd(0x28); //to initialize LCD in 2 lines, 5X7 dots and 4bit mode.
    _delay_ms(1);
    LCD_WriteCmd(0x01); // clear LCD
    _delay_ms(1);
    LCD_WriteCmd(0x0E); // cursor ON
    _delay_ms(1);
    LCD_WriteCmd(0x80); // —8 go to first line and –0 is for 0th position
    _delay_ms(1);
    return;
}

int main(void)
{
    LCD_DATA_DDR |= 0xf0;  //set the LCD DDRD to output
    LCD_CTRL_DDR |= 0b00000011; //For RS, E

    LCD_Init();
    _delay_ms(30);
    LCD_WriteData('a');
    LCD_WriteData('2');
    while(1)
    {

    }//while
}

Cuando ejecuto este código C, obtengo algunos bloques blancos en la fila superior, en lugar de letras. Luego, ejecuté una versión Arduino del código LCD, pero funcionó bien. Por favor, diga qué me falta en mi código c incrustado.

Estoy usando los siguientes pines para la interfaz LCD,

  • D4 a D7 = PD4 a PD7
  • RW = conectado a tierra
  • RS = PB0
  • E = PB1

Gracias.

    
pregunta PraveenMax

3 respuestas

1

¿Realmente quieres escribir tu propio código? La Arduino LiquidCrystal library ya está funcionando. La inicialización de esas pantallas no es fácil, ya que podría estar en modo de 8 bits o de 4 bits. La biblioteca LiquidCrystal utiliza una secuencia especial con comandos y retrasos.

Mi experiencia es que incluso cuando se encuentra una secuencia de trabajo para inicializar la pantalla, puede fallar en algunas situaciones. La secuencia de Arduino LiquidCrystal se encuentra con muchas pruebas y errores y está funcionando ahora.

La fuente de la biblioteca LiquidCrystal con la secuencia especial está en Github: LiquidCrystal .cpp .

Debido a que la visualización es lenta, no es necesario utilizar la escritura directa en los registros de salida. Podría usar digitalWrite o escribir sus propias funciones para la escritura de registros de salida de bajo nivel.

Después del encendido, debería tener un retraso de aproximadamente 150 ms, porque la pantalla aún no está lista.

    
respondido por el Jot
1

Algunas de sus operaciones bitwise están confundidas, por ejemplo,

  LCD_DataBus &= 0xf0;           //Set PORTD LSB to HIGH since we use PD4 to PD7
  LCD_DataBus |= tempCmd;        //Set bits in PORTD

&= 0xf0 borra los cuatro bits más bajos del registro (PD0 - PD3). No hace nada a los cuatro bits superiores.

Lo que probablemente desee es &= 0x0f , para borrar los cuatro bits superiores antes de que algunos de ellos se configuren en la siguiente línea. (Alternativamente, si no está utilizando la otra mitad de PORTD, considere simplemente ejecutar LCD_DataBus = tempCmd ).

Además, para lo que vale, no necesita retrasar 400 ms (!!) mientras pulsa E. La señal solo necesita ser alta para 450 ns (0.00045 ms); Cualquier demora será suficiente. (Si la velocidad de su reloj es baja, es posible que no necesite ningún retraso).

    
respondido por el duskwuff
-1
  

Indique qué me falta en mi código c incrustado.

su código no está inicializando su lcd correctamente. compáralo con el código arduino que te ayudará a resolver problemas.

    
respondido por el dannyf

Lea otras preguntas en las etiquetas