La interfaz LCD de 20x4 caracteres con TI TM4C1294 genera algunos caracteres aleatorios

0

Tengo un LCD de 20x4 caracteres conectado a mi kit TI TM4C1294 de la siguiente manera:

  1. Bus de datos al puerto A.
  2. pines RS, RW y E al puerto L 0-2

Escribí este código para conducirlo:

#include <stdint.h>
#include <stdbool.h>
#include "inc/tm4c1294ncpdt.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"

void LCD_SendChar(short c)
{
    GPIO_PORTA_AHB_DATA_R = c;
    GPIO_PORTL_DATA_R |= 0x01;
    GPIO_PORTL_DATA_R |= 0x04;
    asm ("  NOP");
    GPIO_PORTL_DATA_R &= ~(0x04);
    LCD_IsBusy();
}

void LCD_SendCmd(short command)
{
    GPIO_PORTA_AHB_DATA_R = command;
    GPIO_PORTL_DATA_R |= 0x00;
    GPIO_PORTL_DATA_R |= 0x04;
    asm ("  NOP");
    GPIO_PORTL_DATA_R &= ~(0x04);
    LCD_IsBusy();
}

void LCD_SendString(char* value)
{
    while(*value != 0)
    {
        LCD_SendChar(*value++);
    }
}

void LCD_Init()
{
    LCD_SendCmd(0x01);
    LCD_SendCmd(0x38);
    LCD_SendCmd(0x0E);
    LCD_SendCmd(0x06);
    LCD_SendCmd(0x02);
}

int main(void)
{
    // Enable clock gating control for GPIO A and L
    SYSCTL_RCGCGPIO_R |= SYSCTL_RCGCGPIO_R10;
    SYSCTL_RCGCGPIO_R |= SYSCTL_RCGCGPIO_R0;

    // Wait until GPIO blocks are ready.
    while((SYSCTL_PRGPIO_R & SYSCTL_PRGPIO_R10) == 0);
    while((SYSCTL_PRGPIO_R & SYSCTL_PRGPIO_R0 ) == 0){};

    // Configure as Output, digital, no alternate or analog functions.
    GPIO_PORTA_AHB_DIR_R = 0xFF;
    GPIO_PORTA_AHB_DEN_R = 0xFF;
    GPIO_PORTA_AHB_AFSEL_R = 0x0;
    GPIO_PORTA_AHB_AMSEL_R = 0x0;
    GPIO_PORTA_AHB_PCTL_R  = 0x0;

    GPIO_PORTL_DIR_R = 0x7;
    GPIO_PORTL_DEN_R = 0x7;
    GPIO_PORTL_AFSEL_R = 0x0;
    GPIO_PORTL_AMSEL_R = 0x0;
    GPIO_PORTL_PCTL_R  = 0x0;

    LCD_Init();

    LCD_SendCmd(0x94);
    LCD_SendString("Hello World!");
    LCD_SendCmd(0xD4);
    LCD_SendString("Hello World!");

    while (1);

}

La placa se está ejecutando a una velocidad de 120MHz.

El problema es con el direccionamiento de línea. Descubrí que el direccionamiento de línea para un LCD de 20x4 es 0x80 , 0xC0 , 0x94 , 0xD4 para las líneas 1 a 3 respectivamente. Cuando se envía un "Hello World" en dos líneas como se muestra, las dos cadenas se muestran en la misma línea con un carácter aleatorio entre ellas. Si intento un "Hello World" para una línea mientras cambio la dirección de la línea cada vez que funciona bien. ¿Cuál podría ser la razón para no abordar las líneas correctamente? y cuál es el trato con esos caracteres aleatorios?

Sospecho con:

  1. Los valores proporcionados para cada función de retardo no son precisos.
  2. He leído que debo comprobar si la pantalla LCD está ocupada o no, pero no entendí el mecanismo detrás de ella.

Actualización: Además de Finbarr me las arreglé para verificar el indicador de ocupado. Aquí está mi función

void LCD_IsBusy()
{
    GPIO_PORTA_AHB_DIR_R = 0x00;
    GPIO_PORTL_DATA_R  = 0x00;
    GPIO_PORTL_DATA_R |= 0x02;
    while(GPIO_PORTA_AHB_DATA_R & 0x80)
    {
        GPIO_PORTL_DATA_R &= ~(0x04);
        GPIO_PORTL_DATA_R |= 0x04;
    }

    GPIO_PORTA_AHB_DIR_R = 0xFF;
}

Lo que me ayudó a eliminar todas las demoras en las llamadas. El código anterior se actualiza.

    
pregunta 3bdalla

1 respuesta

4

Su función LCD_SendCmd contiene la siguiente línea:

GPIO_PORTL_DATA_R |= 0x00;

Lo que no hace nada. Lo que debe hacer es poner el bit 0 a cero para acceder al registro de comandos, así que sustitúyalo por

GPIO_PORTL_DATA_R &= ~(0x01);

de lo contrario, nunca se borrará una vez que hayas comenzado a escribir datos.

También debe agregar código para verificar el estado de ocupado para asegurarse de que la pantalla esté lista para más datos o comandos; esto normalmente implica leer el registro de estado y probar el indicador Ocupado. La hoja de datos de la pantalla le dirá qué bit es.

La verificación del indicador de ocupado significa también que no tiene que poner retrasos arbitrariamente largos en el código para asegurarse de que los comandos se completen de otra manera que no sea para las operaciones de configuración iniciales definidas en la hoja de datos (porque el indicador de ocupado no se inicia trabajando hasta que el procesador de la pantalla comience a funcionar) y para asegurarse de que se mantengan la configuración, la retención y los tiempos de ciclo mínimos para las líneas de control. En caso de duda, es mejor verificarlos con un osciloscopio en lugar de confiar en las funciones de retardo.

    
respondido por el Finbarr

Lea otras preguntas en las etiquetas