el microcontrolador no funciona con Nokia 5110 LCD (PCD8544)

0

Estoy luchando con mi primer microcontrolador AVR: AtTiny85 para que funcione con la conocida pantalla Nokia 5110. Escribí mi propio código para manejar la pantalla LCD, no funcionó. Luego probé un código encontrado en algún lugar de Internet, se suponía que debía manejar la pantalla, pero no fue así. Pensé que mi pantalla está rota, pero la conecté a Raspberry Pi y ejecuté un script Adafruit, funcionó sin problemas.

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

#define PIN_SCE PB0
#define PIN_RESET PB1
#define PIN_DC PB2
#define PIN_SCLK PB3
#define PIN_MOSI PB4

enum
{
    FUNCTION_SET = 0x20,
    FS_CHIP_POWERDOWN = 0x4,
    FS_VERTICAL_ADDR = 0x2,
    FS_EXTENDED_INSTR = 0x1,

    DISPLAY_NORMAL = 0xc,
    DISPLAY_BLANK = 0x8,
    DISPLAY_ALL_ON = 0x9,
    DISPLAY_INVERSE = 0xd,

    DRAM_SET_X = 0x80,
    DRAM_SET_Y = 0x40,
};

void BitTransfer(uint8_t Bits)
{
    PORTB &= ~(1 << PIN_SCE);
    int8_t i;
    for(i = 7; i>=0; i--)
    {
        if((Bits >> i) & 1)
            PORTB |= (1 << PIN_MOSI);
        else
           PORTB &= ~(1 << PIN_MOSI);

        PORTB |= (1 << PIN_SCLK);
        _delay_us(10);
        PORTB &= ~(1 << PIN_SCLK);
        _delay_us(10);
    }
    PORTB &= ~(1 << PIN_MOSI);
    PORTB |= (1 << PIN_SCE);
}

void SendCommand(uint8_t Command)
{
    PORTB &= ~(1 << PIN_DC);
    BitTransfer(Command);
}

void SendData(uint8_t Data)
{
    PORTB |= (1 << PIN_DC);
    BitTransfer(Data);
}

int main(void)
{
    DDRB |= (1 << PIN_SCE);
    DDRB |= (1 << PIN_RESET);
    DDRB |= (1 << PIN_DC);
    DDRB |= (1 << PIN_SCLK);
    DDRB |= (1 << PIN_MOSI);
    PORTB = 0;
    _delay_us(10);
    PORTB |= (1 << PIN_RESET);
    PORTB |= (1 << PIN_SCE);
    _delay_us(10);

    SendCommand(FUNCTION_SET | FS_EXTENDED_INSTR);
    SendCommand(0xa5); // VOP
    SendCommand(0x06); // temp coefficient
    SendCommand(0x13); // BIAS
    SendCommand(FUNCTION_SET);
    SendCommand(DISPLAY_ALL_ON);
    while(1)
    {
    }

    return 0;
}

Alimente mi AVR con el pinout 3.3 v de Raspberry Pi, igual que con la pantalla LCD. El AVR está funcionando a una frecuencia de 1 MHz. Cuando desconecto el enchufe que conduce al suelo, aparece una línea negra en la pantalla por un momento. No sé, tal vez es un problema de hardware?

    
pregunta user3366592

1 respuesta

1

¿Son esos los mismos comandos que los otros ejemplos de trabajo utilizados? Mis ejemplos de trabajo (este es el raspberry pi que está impulsando la pantalla) tienen algunos comandos / configuraciones más.

    spi_command(0x21); //extended commands
//    spi_command(0xB0); //vop
    spi_command(0xBF); //vop
    spi_command(0x04); //temp coef
    spi_command(0x14); //bias mode 1:48
    spi_command(0x20); //extended off
    spi_command(0x0C); //display on

//experiment 1
if(1)
{
    spi_command(0x80); //column
    spi_command(0x40); //row
    for(ra=0;ra<504;ra++) spi_data(ra);
}

Probablemente esté ejecutando lo suficientemente lento como para no necesitar ningún retraso, pero podría esparcir un poco más, entre todo, básicamente, el cambio de D / C a la selección de spi para el primer cambio de datos, etc.

¿Tiene un alcance para examinar el bus? Puede alimentar las señales a la frambuesa pi y muestrear muy rápido y guardar los datos para usarlos como analizadores lógicos (el método básico es más fácil / mejor, pero también puede hacerlo en Linux). O utilice cualquier otro microcontrolador siempre que sea más rápido de lo que cree que está golpeando.

También puedes poner leds en las líneas y hacer que los retrasos sean masivos, lo suficientemente lento para que puedas ver visualmente lo que está sucediendo en qué orden.

Si la pantalla funciona cuando se usa el código de estante, pero no con el suyo, claramente no es la pantalla. Es algo que tu código está haciendo o no está haciendo. Es un objetivo spi bastante fácil con el que meterse, no se requiere la lectura de nuevo, solo se eliminan las cosas.

Probablemente no tenga el almacenamiento en el microcontrolador, pero si lo hace en el pi, también puede tomar otro enfoque, tomar su código de bit bang, simular el gpio y hacer un archivo de registro de cada cambio de estado. Entonces haz que el programa real simplemente destruya esos. Al menos se puede ver visualmente

#include <stdio.h>

unsigned char port;

static void spi_delay ( void )
{
}

static void spi_dc ( unsigned int x )
{
    if(x) port|=(1<<0);
    else  port&=~(1<<0);
    printf("0x%02X,\n",port);
}
static void spi_cs ( unsigned int x )
{
    if(x) port|=(1<<1);
    else  port&=~(1<<1);
    printf("0x%02X,\n",port);
}
static void spi_clk ( unsigned int x )
{
    if(x) port|=(1<<2);
    else  port&=~(1<<2);
    printf("0x%02X,\n",port);
}
static void spi_mosi ( unsigned int x )
{
    if(x) port|=(1<<3);
    else  port&=~(1<<3);
    printf("0x%02X,\n",port);
}

static void spi_command ( unsigned int cmd )
{
    unsigned int ra;
    unsigned int rb;

    spi_dc(0);
    spi_cs(0);
    spi_delay();
    for(rb=cmd,ra=0;ra<8;ra++,rb<<=1)
    {
        spi_mosi((rb>>7)&1);
        spi_delay();
        spi_clk(1);
        spi_delay();
        spi_clk(0);
        spi_delay();
    }
    spi_cs(1);
}

static void spi_data ( unsigned int data )
{
    unsigned int ra;
    unsigned int rb;

    spi_dc(1);
    spi_cs(0);
    spi_delay();
    for(rb=data,ra=0;ra<8;ra++,rb<<=1)
    {
        spi_mosi((rb>>7)&1);
        spi_delay();
        spi_clk(1);
        spi_delay();
        spi_clk(0);
        spi_delay();
    }
    spi_cs(1);
}

int main ( void )
{
    port=0;

    spi_clk(0);
    spi_data(0);
    spi_cs(0);
    spi_cs(1);

    spi_command(0x21); //extended commands
...

para ese init y comando dando esta salida:

0x00,
0x01,
0x01,
0x01,
0x05,
0x01,
0x01,
0x05,
0x01,
0x01,
0x05,
0x01,
0x01,
0x05,
0x01,
0x01,
0x05,
0x01,
0x01,
0x05,
0x01,
0x01,
0x05,
0x01,
0x01,
0x05,
0x01,
0x03,
0x01,
0x03,
0x02,
0x00,
0x00,
0x04,
0x00,
0x00,
0x04,
0x00,
0x08,
0x0C,
0x08,
0x00,
0x04,
0x00,
0x00,
0x04,
0x00,
0x00,
0x04,
0x00,
0x00,
0x04,
0x00,
0x08,
0x0C,
0x08,
0x0A,

Nota del código Tengo bit 0 como D / C, bit 1 es cs, 2 es clk y 3 mosi. No se reinició en este código, creo que solo se pueden ajustar fácilmente.

Puedes tomar esa salida y luego introducirla en algún código que ejecutes en el pi o el microcontrolador (si tienes el espacio).

for(x=0;x<datalen;x++)
{
  PORT = data[x];
  delay();
}

Puedes crear algunas herramientas para ver visualmente las formas de onda (recomiendo mirar el formato vcd muy simple y usar gtkwave). o incluso mejor, simplemente imprímelos como binarios y gira tu cabeza hacia un lado.

Al menos puede tener la sensación de que tiene las cosas bien conectadas y de que está funcionando correctamente, una vez que funciona, sustituya las funciones de ajuste / borrado de cada bit con acceso directo al gpio y mueva el código al microcontrolador Incluso puede escribirlo de manera que se compile en ambos sentidos con una capa de abstracción.

Si tiene un alcance multicanal, puede ahorrarse un montón de trabajo. Bit spi spi o i2c o mdio, etc. realmente necesita un alcance o necesita construir un analizador lógico a partir de un microcontrolador o algo así. Se prefiere el alcance, especialmente para cosas como i2c y mdio, donde puede ver cuándo los autobuses cambian de dirección y qué tan rápido / lento son las flexiones.

    
respondido por el old_timer

Lea otras preguntas en las etiquetas