AVR LCD está en blanco después de cambiar el código

0

El siguiente es mi código

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

#define Delay_ms(x) _delay_ms(x)
#define RS   1       //PC0
#define RW   1       //PC1
#define EN   2       //PC2


void lcd_cmnd(unsigned char);
void lcd_data(unsigned char dta);


int main()
{
    DDRC=0xff;
    DDRD=0xff;
    lcd_cmnd(0x38);          //sets 8-bit interacing
    Delay_ms(1);


    lcd_cmnd(0x0e);           //display on
    Delay_ms(1);
    lcd_cmnd(0x08);           //display off
    Delay_ms(1);
    lcd_cmnd(0x01);        //clears screen
    Delay_ms(1);



    lcd_cmnd(0b00000000);
    lcd_cmnd(0x06); //Entry Mode, Increment cursor position, No display shift

    lcd_data('N');
    Delay_ms(250);

    lcd_data('a');
    Delay_ms(25);
    lcd_data('s');
    Delay_ms(25);
    lcd_data('i');
    Delay_ms(25);
    lcd_data('r');
    Delay_ms(25);
return 0;
}
void lcd_cmnd(unsigned char cmd)
{
    PORTD=cmd;
    PORTC=(0<<RS);                //command mode   PC0=RS(low)
    PORTC|=(0<<RW);                // read mode  PC1=RW
    PORTC=(1<<EN);                 // enable high   PC2=EN
    Delay_ms(1);
    PORTC=(0<<EN);                 //enable low
    Delay_ms(50);
}

void lcd_data(unsigned char dta)
{

    PORTC|=(0<<RW);              //PC1=RW (low)
    PORTC|=(1<<0);               //DATA mode   PC0=RS
    PORTD=dta;
    PORTC=(1<<EN);                //enable high   PC2=EN


    Delay_ms(1);
    PORTC=(0<<EN);                //enable low
    Delay_ms(50);
}

Se ejecuta bien, la simulación en proteus se ejecuta pero el cursor parpadea y no se muestra nada. No se por que

A continuación hay otro código que se ejecuta y se muestra en la pantalla LCD "Hello World!"

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

//Define functions
//==========================================================
void io_init(void);                         //Initializes IO
void send_nibble(unsigned char __rs, unsigned char __data);

//==========================================================

int main (void)
{
    io_init();

   _delay_ms(15);
   send_nibble(0,0b0010);   //Set to 4 bit operation (note: 1 nibble operation)
   _delay_ms(5);

   send_nibble(0,0b0010);   //Function set, 4 bit
   send_nibble(0,0x08);     //display off, cursor off

   send_nibble(0,0b0000);
   send_nibble(0,0b1111);   //Display ON, Cursor On, Cursor Blinking

   send_nibble(0,0b0000);
   send_nibble(0,0b0001);   //Clear Display

   send_nibble(0,0b0000);
   send_nibble(0,0x06); //Entry Mode, Increment cursor position, No display shift

   send_nibble(1,0b0100);  //H
   send_nibble(1,0b1000);

   send_nibble(1,0b0110);  //e
   send_nibble(1,0b0101);

   send_nibble(1,0b0110);  //l
   send_nibble(1,0b1100);

   send_nibble(1,0b0110);  //l
   send_nibble(1,0b1100);

   send_nibble(1,0b0110);  //o
   send_nibble(1,0b1111);

   send_nibble(1,0b0010);  //Space
   send_nibble(1,0b0000);

   send_nibble(1,0b0101);  //w
   send_nibble(1,0b0111);

   send_nibble(1,0b0110);  //o
   send_nibble(1,0b1111);

   send_nibble(1,0b0111);  //r
   send_nibble(1,0b0010);

   send_nibble(1,0b0110);  //l
   send_nibble(1,0b1100);

   send_nibble(1,0b0110);  //d
   send_nibble(1,0b0100);

    return(0);
}

void io_init (void)
{
    /*
    PC 7: N/A
    PC 6: Reset
    PC 5: Enable
    PC 4: Register Select
    PC 3: Data 7
    PC 2: Data 6
    PC 1: Data 5
    PC 0: Data 4
    */

    DDRC = 0b00111111;  //63
}

void send_nibble(unsigned char __rs, unsigned char __data)
{
   PORTC = (__rs<<4) | __data | 0b00100000;      // Set RS &amp; Data. Set EN=High
   _delay_ms(1);
   PORTC = (__rs<<4) | __data;                   // Set RS &amp; Data. Set EN=Low
   _delay_ms(1);
}

Intenté proceder en el mismo orden pero en vano. Estoy atascado en aprender la programación de LCD durante los últimos 10 días. Cualquier ayuda saludable y efectiva es apreciada de antemano!

    
pregunta nasir

4 respuestas

1

Es hora de elaborar mi comentario original ...

Parece que está malinterpretando la parte que el operador de desplazamiento a la izquierda (< <) juega el operador OR a nivel de bits (|) en los bits de configuración. Puede usar el operador OR para establecer un bit en 1, pero no puede usarlo para restablecer un bit en 0. Por ejemplo, en su código:

PORTC|=(0<<RW);                // read mode  PC1=RW

... parece que intentas restablecer el bit RW en PORTC a 0, pero eso no es lo que ocurrirá con el código anterior. Dado que RW se define como 1, 0 < < 1 se compilará como "0 desplazado a la izquierda por 1 bit" (es decir, multiplicado por 2), que sigue siendo solo 0. Entonces, O BIEN, el valor 0 de PORTC no se modifica a PORTC. Es decir, si el bit 1 de PORTC estaba activado, seguirá encendido después de que se ejecute lo anterior.

Suponiendo que lo que realmente desea hacer es restablecer el bit 1 (RW) de PORTC a 0, dejando todos los demás iguales, entonces eso puede hacerse usando el operador AND:

PORTC &= (255 - (1<<RW));

Personalmente, dada la confusión que esto le está causando, recomendaría simplemente definir y utilizar RW (y otros bits) de la siguiente manera:

//     Bit:  76543210
#define RS 0b00000001
#define RW 0b00000010
#define EN 0b00000100

PORTC |= RW;            // Turn on the RW bit
PORTC &= 255 - RW;      // Turn off the RW bit

Para mí eso es más claro de todos modos. Alternativamente, si realmente desea trabajar con números de posición de bit, puede ocultar las acrobacias a nivel de bit en una macro de la siguiente manera:

#define biton(port,bitnum) port |= (1 << bitnum)
#define bitoff(port,bitnum) port &= 255 - (1 << bitnum)

biton(PORTC,RW);
bitoff(PORTC,RW);
    
respondido por el aja
0

Usted define RS y RW como 1 , a pesar de que están en diferentes pines. Corrija su definición de RS .

    
respondido por el Ignacio Vazquez-Abrams
0

Su código de "no funciona" es una desviación significativa de su código de "trabajo". No ha vinculado a una hoja de datos para la pantalla que está programando, ni ha explicado qué era deficiente con el código de "trabajo" que está tratando de arreglar. Todo lo que puedo hacer es volver a los primeros principios. Sin una hoja de datos, no puedo decir qué está mal con su código "no funciona", pero puedo modificar su código "funcional" para que coincida con la intención inferida de su código "no funcional".

Parece que estás intentando mostrar la cadena "Nasir" en tu LCD. Una tabla ASCII proporciona números binarios que puede sustituir en el código "de trabajo" en lugar de "Hola mundo". Como alternativa, parece que desea hacer una sola llamada para mostrar un solo carácter, por lo que podría agregar una rutina al código "de trabajo" para completar dos llamadas a send_nibble como:

void print_character(char letter)
{
  send_nibble(1, letter >> 4);  // send high nibble (discard low bits)
  send_nibble(1, letter & 0xF);  // send low nibble
}

cambiando así

send_nibble(1,0b0111);  //r
send_nibble(1,0b0010);

en

print_character('r');

haciendo que el código "de trabajo" sea más fácil de leer y mantener. Podrían obtenerse mejoras en la legibilidad y la capacidad de mantenimiento si se crea una función print_string () y se hace un ciclo a través de cada personaje.

void print_string(const char* string)
{
  for (const char* letter = string; *letter; ++letter)
  {
    send_nibble(1, *letter >> 4);  // send high nibble (discard low bits)
    send_nibble(1, *letter & 0xF);  // send low nibble
  }
}

permitiendo

print_string("Hello world");

Mucho menos líneas de código, y potencialmente un binario más pequeño también. Pero todo se reduce a qué problema intentaba solucionar su código de "no funciona".

    
respondido por el Josh
0

Permítame agregar algunas líneas a comentarios anteriores según mi experiencia. Le recomiendo depurar su conexión muy a menudo mientras se conecta la pantalla LCD, tenemos que lidiar con varios pines y, si están cortos en algún lugar (conectándose a través de cables en el circuito de compilación flexible especialmente en la placa de pruebas), encontrará una pantalla LCD en blanco con el código que se ejecuta en la MCU. De lo contrario todo es simple. Aquí está el código y el diagrama del circuito con un ejemplo funcional completo: Interfaz LCD 16x2 o 20x4 con AVR (totalmente compatible)

    
respondido por el Umesh L

Lea otras preguntas en las etiquetas