Problemas con la pantalla LCD cuando se usa con ATmega328P

0

Estoy tratando de usar una pantalla LCD de 16x2 para ser programada por el microcontrolador ATmega328P usando Atmel Studio v7. Estoy usando una biblioteca para este propósito que encontré en internet. Escribí este programa para medir las RPM de un motor utilizando sus sensores de efecto Hall:

#ifndef F_CPU
#define F_CPU 16000000UL // 16 MHz clock speed
#endif
#define D4 eS_PORTC1
#define D5 eS_PORTC2
#define D6 eS_PORTC3
#define D7 eS_PORTC4
#define RS eS_PORTD0
#define EN eS_PORTD1

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include "lcd.h" 

volatile uint16_t count = 0;

volatile float rpm = 0;

volatile float rps = 0;
int speed = 0;

volatile int flag = 0, prevflag = 0;
int num = 0;
char sec[4];

void Timer_init()
{
    TCCR1A |= (1<<COM1A1);
    TCCR1B  |= (1<<WGM12)|(1<<CS12)|(1<<CS10);

    OCR1A = 15624;

    TIMSK1 |= (1<<OCIE1A);
}

void ADC_init()
{
    ADMUX |= (1<<REFS0);
    ADMUX &= ~((1<<MUX3)|(1<<MUX2)|(1<<MUX1)|(1<<MUX0));
    ADCSRA |= (1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}

int main(void)
{
    DDRD |= (1<<DDD0)|(1<<DDD1);
    DDRD &= ~(1<<DDD2);
    DDRC |= (1<<DDC1)|(1<<DDC2)|(1<<DDC3)|(1<<DDC4);

    ADC_init();
    Timer_init();
    sei();
    Lcd4_Init();
    Lcd4_Clear();

    ADCSRA |= (1<<ADSC);
    while(1)
    {

    }
}

ISR (ADC_vect)
{
    int num = ADC;
    if (num >= 950)
        flag = 1;
    else
        flag  = 0;

    if (flag != prevflag)
        count++;
    prevflag = flag;

    ADCSRA |= (1<<ADSC);
}

ISR (TIMER1_COMPA_vect)
{
    rps = (float)count/(21.0 * 1.81);
    rpm = rps * 60.0;
    count = 0;
    Lcd4_Clear();
    Lcd4_Set_Cursor(1,1);
    Lcd4_Write_String("RPM = ");
    Lcd4_Set_Cursor(1,8);
    itoa(rpm, sec, 10);
    Lcd4_Write_String(sec);
}

Este programa funciona como se esperaba. Sin embargo, muestra casillas negras en la primera línea cuando intento escribir este código:

#ifndef F_CPU
#define F_CPU 16000000UL // 16 MHz clock speed
#endif
#define D4 eS_PORTC1
#define D5 eS_PORTC2
#define D6 eS_PORTC3
#define D7 eS_PORTC4
#define RS eS_PORTD0
#define EN eS_PORTD1

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include "lcd.h"


int sp,input;
char string[10];

void adc_init_current();
uint16_t adc_read();
int pid();
void pwm_init();
void tim1_init();
void adc_init_setpoint();

int main(void)
{
    DDRD |= (1<<DDD0)|(1<<DDD1);
    DDRC |= (1<<DDC1)|(1<<DDC2)|(1<<DDC3)|(1<<DDC4);

    sei();
    pwm_init();
    adc_init_setpoint();

    Lcd4_Init();
    Lcd4_Clear();
    Lcd4_Set_Cursor(1,1);
    Lcd4_Write_String("Hello");
    _delay_ms(2000);

    sp = adc_read()*255/1023;
    itoa(sp,string,10);
    Lcd4_Set_Cursor(1,1);
    Lcd4_Write_String("SP=");
    Lcd4_Set_Cursor(1,4);
    Lcd4_Write_String(string);
    while (1) 
    {
        //sp = adc_read();
        //OCR0A = (float)sp*255/1023;
    }
}
int pid()
{
    double error, k_p=1,k_i=0,k_d=0,integral=0,derivative=0,lastError=0,sampleTime=0.01,output;
    error = sp-input;
    integral += error*sampleTime;
    derivative = (error - lastError)/sampleTime;
    output = k_p*error + k_i*integral + k_d*derivative;
    lastError = error;
    return output;
}
void adc_init_current()
{
    ADMUX |= (1<<REFS0);
    ADCSRA |= (7<<ADPS0)|(1<<ADEN);
    ADMUX &= ~(15<<MUX0);   
}
void adc_init_setpoint()
{
    ADMUX |= (1<<REFS0)|(1<<MUX0)|(1<<MUX2);
    ADMUX &= ~(1<<MUX3)|(1<<MUX1);
    ADCSRA |= (7<<ADPS0)|(1<<ADEN);
}
uint16_t adc_read()
{
    ADCSRA |= (1<<ADSC);
    while (ADCSRA & (1<<ADSC));
    return ADC;
}
void pwm_init()
{
    TCCR0A |= (1<<WGM00)|(1<<WGM01)|(1<<COM0A1);
    TCCR0B |= (1<<CS01);
    DDRD|= (1<<DDD6);
}
void tim1_init()
{
    TCCR1A |= (1<<COM1A1);
    TCCR1B |= (1<<WGM12)|(1<<CS12);
    TIMSK1 |= (1<<OCIE1A);
    OCR1A = 625;
}
ISR (TIMER1_COMPA_vect)
{
    input = (adc_read()-512)*255/1023;
    Lcd4_Set_Cursor(1,8);
    Lcd4_Write_String("Cur=");
    itoa(input,string,10);
    Lcd4_Set_Cursor(1,12);
    Lcd4_Write_String(string);
    double output = pid();
    if (output >= 255)
    {
        output = 255;
    }
    OCR0A = output;
    Lcd4_Set_Cursor(2,1);
    itoa(output,string,10);
    Lcd4_Write_String("Output = ");
    Lcd4_Set_Cursor(2,10);
    Lcd4_Write_String(string);
}

Como puede ver, la inicialización del LCD en ambos programas es la misma, pero el segundo programa no escribe nada en el LCD, mientras que el primero sí lo hace.

Estoy usando el modo de 4 bits para escribir en la pantalla LCD. Las conexiones de los pines son las siguientes:
Vss - > GND
Vdd - > 5V
V0 - > Entrada de bote de 10k
RS - > Puerto D0
EN - > Puerto d1
D0-D3 - > no conectado
D4 - > Puerto C1
D5 - > Puerto c2
D6 - > Puerto C3
D7 - > Puerto C4
El archivo lcd.h que estoy usando se muestra a continuación:

//LCD Functions Developed by electroSome
#define eS_PORTA0 0
#define eS_PORTA1 1
#define eS_PORTA2 2
#define eS_PORTA3 3
#define eS_PORTA4 4
#define eS_PORTA5 5
#define eS_PORTA6 6
#define eS_PORTA7 7
#define eS_PORTB0 10
#define eS_PORTB1 11
#define eS_PORTB2 12
#define eS_PORTB3 13
#define eS_PORTB4 14
#define eS_PORTB5 15
#define eS_PORTB6 16
#define eS_PORTB7 17
#define eS_PORTC0 20
#define eS_PORTC1 21
#define eS_PORTC2 22
#define eS_PORTC3 23
#define eS_PORTC4 24
#define eS_PORTC5 25
#define eS_PORTC6 26
#define eS_PORTC7 27
#define eS_PORTD0 30
#define eS_PORTD1 31
#define eS_PORTD2 32
#define eS_PORTD3 33
#define eS_PORTD4 34
#define eS_PORTD5 35
#define eS_PORTD6 36
#define eS_PORTD7 37

#ifndef D0
#define D0 eS_PORTA0
#define D1 eS_PORTA1
#define D2 eS_PORTA2
#define D3 eS_PORTA3
#endif

#include<util/delay.h>

void pinChange(int a, int b)
{
    if(b == 0)
    {
        if(a == eS_PORTB0)
        PORTB &= ~(1<<PORTB0);
        else if(a == eS_PORTB1)
        PORTB &= ~(1<<PORTB1);
        else if(a == eS_PORTB2)
        PORTB &= ~(1<<PORTB2);
        else if(a == eS_PORTB3)
        PORTB &= ~(1<<PORTB3);
        else if(a == eS_PORTB4)
        PORTB &= ~(1<<PORTB4);
        else if(a == eS_PORTB5)
        PORTB &= ~(1<<PORTB5);
        else if(a == eS_PORTB6)
        PORTB &= ~(1<<PORTB6);
        else if(a == eS_PORTB7)
        PORTB &= ~(1<<PORTB7);
        else if(a == eS_PORTC0)
        PORTC &= ~(1<<PORTC0);
        else if(a == eS_PORTC1)
        PORTC &= ~(1<<PORTC1);
        else if(a == eS_PORTC2)
        PORTC &= ~(1<<PORTC2);
        else if(a == eS_PORTC3)
        PORTC &= ~(1<<PORTC3);
        else if(a == eS_PORTC4)
        PORTC &= ~(1<<PORTC4);
        else if(a == eS_PORTC5)
        PORTC &= ~(1<<PORTC5);
        else if(a == eS_PORTC6)
        PORTC &= ~(1<<PORTC6);
        else if(a == eS_PORTD0)
        PORTD &= ~(1<<PORTD0);
        else if(a == eS_PORTD1)
        PORTD &= ~(1<<PORTD1);
        else if(a == eS_PORTD2)
        PORTD &= ~(1<<PORTD2);
        else if(a == eS_PORTD3)
        PORTD &= ~(1<<PORTD3);
        else if(a == eS_PORTD4)
        PORTD &= ~(1<<PORTD4);
        else if(a == eS_PORTD5)
        PORTD &= ~(1<<PORTD5);
        else if(a == eS_PORTD6)
        PORTD &= ~(1<<PORTD6);
        else if(a == eS_PORTD7)
        PORTD &= ~(1<<PORTD7);
    }
    else
    {
        if(a == eS_PORTB0)
        PORTB |= (1<<PORTB0);
        else if(a == eS_PORTB1)
        PORTB |= (1<<PORTB1);
        else if(a == eS_PORTB2)
        PORTB |= (1<<PORTB2);
        else if(a == eS_PORTB3)
        PORTB |= (1<<PORTB3);
        else if(a == eS_PORTB4)
        PORTB |= (1<<PORTB4);
        else if(a == eS_PORTB5)
        PORTB |= (1<<PORTB5);
        else if(a == eS_PORTB6)
        PORTB |= (1<<PORTB6);
        else if(a == eS_PORTB7)
        PORTB |= (1<<PORTB7);
        else if(a == eS_PORTC0)
        PORTC |= (1<<PORTC0);
        else if(a == eS_PORTC1)
        PORTC |= (1<<PORTC1);
        else if(a == eS_PORTC2)
        PORTC |= (1<<PORTC2);
        else if(a == eS_PORTC3)
        PORTC |= (1<<PORTC3);
        else if(a == eS_PORTC4)
        PORTC |= (1<<PORTC4);
        else if(a == eS_PORTC5)
        PORTC |= (1<<PORTC5);
        else if(a == eS_PORTC6)
        PORTC |= (1<<PORTC6);
        else if(a == eS_PORTD0)
        PORTD |= (1<<PORTD0);
        else if(a == eS_PORTD1)
        PORTD |= (1<<PORTD1);
        else if(a == eS_PORTD2)
        PORTD |= (1<<PORTD2);
        else if(a == eS_PORTD3)
        PORTD |= (1<<PORTD3);
        else if(a == eS_PORTD4)
        PORTD |= (1<<PORTD4);
        else if(a == eS_PORTD5)
        PORTD |= (1<<PORTD5);
        else if(a == eS_PORTD6)
        PORTD |= (1<<PORTD6);
        else if(a == eS_PORTD7)
        PORTD |= (1<<PORTD7);
    }
}



//LCD 8 Bit Interfacing Functions
void Lcd8_Port(char a)
{
    if(a & 1)
    pinChange(D0,1);
    else
    pinChange(D0,0);

    if(a & 2)
    pinChange(D1,1);
    else
    pinChange(D1,0);

    if(a & 4)
    pinChange(D2,1);
    else
    pinChange(D2,0);

    if(a & 8)
    pinChange(D3,1);
    else
    pinChange(D3,0);

    if(a & 16)
    pinChange(D4,1);
    else
    pinChange(D4,0);

    if(a & 32)
    pinChange(D5,1);
    else
    pinChange(D5,0);

    if(a & 64)
    pinChange(D6,1);
    else
    pinChange(D6,0);

    if(a & 128)
    pinChange(D7,1);
    else
    pinChange(D7,0);
}
void Lcd8_Cmd(char a)
{
    pinChange(RS,0);             // => RS = 0
    Lcd8_Port(a);             //Data transfer
    pinChange(EN,1);             // => E = 1
    _delay_ms(1);
    pinChange(EN,0);             // => E = 0
    _delay_ms(1);
}

void Lcd8_Clear()
{
    Lcd8_Cmd(1);
}

void Lcd8_Set_Cursor(char a, char b)
{
    if(a == 1)
    Lcd8_Cmd(0x80 + b);
    else if(a == 2)
    Lcd8_Cmd(0xC0 + b);
}

void Lcd8_Init()
{
    pinChange(RS,0);
    pinChange(EN,0);
    _delay_ms(20);
    ///////////// Reset process from datasheet /////////
    Lcd8_Cmd(0x30);
    _delay_ms(5);
    Lcd8_Cmd(0x30);
    _delay_ms(1);
    Lcd8_Cmd(0x30);
    _delay_ms(10);
    /////////////////////////////////////////////////////
    Lcd8_Cmd(0x38);    //function set
    Lcd8_Cmd(0x0C);    //display on,cursor off,blink off
    Lcd8_Cmd(0x01);    //clear display
    Lcd8_Cmd(0x06);    //entry mode, set increment
}

void Lcd8_Write_Char(char a)
{
    pinChange(RS,1);             // => RS = 1
    Lcd8_Port(a);             //Data transfer
    pinChange(EN,1);             // => E = 1
    _delay_ms(1);
    pinChange(EN,0);             // => E = 04
    _delay_ms(1);
}

void Lcd8_Write_String(char *a)
{
    int i;
    for(i=0;a[i]!='
#ifndef F_CPU
#define F_CPU 16000000UL // 16 MHz clock speed
#endif
#define D4 eS_PORTC1
#define D5 eS_PORTC2
#define D6 eS_PORTC3
#define D7 eS_PORTC4
#define RS eS_PORTD0
#define EN eS_PORTD1

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include "lcd.h" 

volatile uint16_t count = 0;

volatile float rpm = 0;

volatile float rps = 0;
int speed = 0;

volatile int flag = 0, prevflag = 0;
int num = 0;
char sec[4];

void Timer_init()
{
    TCCR1A |= (1<<COM1A1);
    TCCR1B  |= (1<<WGM12)|(1<<CS12)|(1<<CS10);

    OCR1A = 15624;

    TIMSK1 |= (1<<OCIE1A);
}

void ADC_init()
{
    ADMUX |= (1<<REFS0);
    ADMUX &= ~((1<<MUX3)|(1<<MUX2)|(1<<MUX1)|(1<<MUX0));
    ADCSRA |= (1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}

int main(void)
{
    DDRD |= (1<<DDD0)|(1<<DDD1);
    DDRD &= ~(1<<DDD2);
    DDRC |= (1<<DDC1)|(1<<DDC2)|(1<<DDC3)|(1<<DDC4);

    ADC_init();
    Timer_init();
    sei();
    Lcd4_Init();
    Lcd4_Clear();

    ADCSRA |= (1<<ADSC);
    while(1)
    {

    }
}

ISR (ADC_vect)
{
    int num = ADC;
    if (num >= 950)
        flag = 1;
    else
        flag  = 0;

    if (flag != prevflag)
        count++;
    prevflag = flag;

    ADCSRA |= (1<<ADSC);
}

ISR (TIMER1_COMPA_vect)
{
    rps = (float)count/(21.0 * 1.81);
    rpm = rps * 60.0;
    count = 0;
    Lcd4_Clear();
    Lcd4_Set_Cursor(1,1);
    Lcd4_Write_String("RPM = ");
    Lcd4_Set_Cursor(1,8);
    itoa(rpm, sec, 10);
    Lcd4_Write_String(sec);
}
';i++) Lcd8_Write_Char(a[i]); } void Lcd8_Shift_Right() { Lcd8_Cmd(0x1C); } void Lcd8_Shift_Left() { Lcd8_Cmd(0x18); } //End LCD 8 Bit Interfacing Functions //LCD 4 Bit Interfacing Functions void Lcd4_Port(char a) { if(a & 1) pinChange(D4,1); else pinChange(D4,0); if(a & 2) pinChange(D5,1); else pinChange(D5,0); if(a & 4) pinChange(D6,1); else pinChange(D6,0); if(a & 8) pinChange(D7,1); else pinChange(D7,0); } void Lcd4_Cmd(char a) { pinChange(RS,0); // => RS = 0 Lcd4_Port(a); pinChange(EN,1); // => E = 1 _delay_ms(1); pinChange(EN,0); // => E = 0 _delay_ms(1); } void Lcd4_Clear() { Lcd4_Cmd(0); Lcd4_Cmd(1); } void Lcd4_Set_Cursor(char a, char b) { char temp,z,y; if(a == 1) { temp = 0x80 + b; z = temp>>4; y = (0x80+b) & 0x0F; Lcd4_Cmd(z); Lcd4_Cmd(y); } else if(a == 2) { temp = 0xC0 + b; z = temp>>4; y = (0xC0+b) & 0x0F; Lcd4_Cmd(z); Lcd4_Cmd(y); } } void Lcd4_Init() { Lcd4_Port(0x00); _delay_ms(20); ///////////// Reset process from datasheet ///////// Lcd4_Cmd(0x03); _delay_ms(5); Lcd4_Cmd(0x03); _delay_ms(11); Lcd4_Cmd(0x03); ///////////////////////////////////////////////////// Lcd4_Cmd(0x02); Lcd4_Cmd(0x02); Lcd4_Cmd(0x08); Lcd4_Cmd(0x00); Lcd4_Cmd(0x0C); Lcd4_Cmd(0x00); Lcd4_Cmd(0x06); } void Lcd4_Write_Char(char a) { char temp,y; temp = a&0x0F; y = a&0xF0; pinChange(RS,1); // => RS = 1 Lcd4_Port(y>>4); //Data transfer pinChange(EN,1); _delay_ms(1); pinChange(EN,0); _delay_ms(1); Lcd4_Port(temp); pinChange(EN,1); _delay_ms(1); pinChange(EN,0); _delay_ms(1); } void Lcd4_Write_String(char *a) { int i; for(i=0;a[i]!='
#ifndef F_CPU
#define F_CPU 16000000UL // 16 MHz clock speed
#endif
#define D4 eS_PORTC1
#define D5 eS_PORTC2
#define D6 eS_PORTC3
#define D7 eS_PORTC4
#define RS eS_PORTD0
#define EN eS_PORTD1

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include "lcd.h"


int sp,input;
char string[10];

void adc_init_current();
uint16_t adc_read();
int pid();
void pwm_init();
void tim1_init();
void adc_init_setpoint();

int main(void)
{
    DDRD |= (1<<DDD0)|(1<<DDD1);
    DDRC |= (1<<DDC1)|(1<<DDC2)|(1<<DDC3)|(1<<DDC4);

    sei();
    pwm_init();
    adc_init_setpoint();

    Lcd4_Init();
    Lcd4_Clear();
    Lcd4_Set_Cursor(1,1);
    Lcd4_Write_String("Hello");
    _delay_ms(2000);

    sp = adc_read()*255/1023;
    itoa(sp,string,10);
    Lcd4_Set_Cursor(1,1);
    Lcd4_Write_String("SP=");
    Lcd4_Set_Cursor(1,4);
    Lcd4_Write_String(string);
    while (1) 
    {
        //sp = adc_read();
        //OCR0A = (float)sp*255/1023;
    }
}
int pid()
{
    double error, k_p=1,k_i=0,k_d=0,integral=0,derivative=0,lastError=0,sampleTime=0.01,output;
    error = sp-input;
    integral += error*sampleTime;
    derivative = (error - lastError)/sampleTime;
    output = k_p*error + k_i*integral + k_d*derivative;
    lastError = error;
    return output;
}
void adc_init_current()
{
    ADMUX |= (1<<REFS0);
    ADCSRA |= (7<<ADPS0)|(1<<ADEN);
    ADMUX &= ~(15<<MUX0);   
}
void adc_init_setpoint()
{
    ADMUX |= (1<<REFS0)|(1<<MUX0)|(1<<MUX2);
    ADMUX &= ~(1<<MUX3)|(1<<MUX1);
    ADCSRA |= (7<<ADPS0)|(1<<ADEN);
}
uint16_t adc_read()
{
    ADCSRA |= (1<<ADSC);
    while (ADCSRA & (1<<ADSC));
    return ADC;
}
void pwm_init()
{
    TCCR0A |= (1<<WGM00)|(1<<WGM01)|(1<<COM0A1);
    TCCR0B |= (1<<CS01);
    DDRD|= (1<<DDD6);
}
void tim1_init()
{
    TCCR1A |= (1<<COM1A1);
    TCCR1B |= (1<<WGM12)|(1<<CS12);
    TIMSK1 |= (1<<OCIE1A);
    OCR1A = 625;
}
ISR (TIMER1_COMPA_vect)
{
    input = (adc_read()-512)*255/1023;
    Lcd4_Set_Cursor(1,8);
    Lcd4_Write_String("Cur=");
    itoa(input,string,10);
    Lcd4_Set_Cursor(1,12);
    Lcd4_Write_String(string);
    double output = pid();
    if (output >= 255)
    {
        output = 255;
    }
    OCR0A = output;
    Lcd4_Set_Cursor(2,1);
    itoa(output,string,10);
    Lcd4_Write_String("Output = ");
    Lcd4_Set_Cursor(2,10);
    Lcd4_Write_String(string);
}
';i++) Lcd4_Write_Char(a[i]); } void Lcd4_Shift_Right() { Lcd4_Cmd(0x01); Lcd4_Cmd(0x0C); } void Lcd4_Shift_Left() { Lcd4_Cmd(0x01); Lcd4_Cmd(0x08); } //End LCD 4 Bit Interfacing Functions

No puedo entender por qué la pantalla LCD funciona con el primer programa y no con el segundo. Por favor ayuda.

    
pregunta user170667

1 respuesta

1

Tienes un código que "funciona" y un código que "no funciona". Esa es una buena situación para la depuración.

Incluso sin las facilidades de un depurador completo, como es común en muchos dispositivos ARM-Cortex, puede aplicar varios enfoques de depuración diferentes. Uno de ellos se describe en la página MCVE de Stack Overflow: cree un ejemplo de código de error mínimo . A menudo, mientras se hace eso, las personas descubren el error subyacente.

En este momento, hay muchos códigos que no están relacionados con la pantalla LCD en ambos ejemplos. Así que trabaje para eliminar el código innecesario, usando una de las dos técnicas mencionadas en esa página de MCVE: o "reiniciar desde cero" (comenzando desde cero para agregar solo el código necesario) o "dividir y conquistar" (eliminar el código innecesario hasta que el problema desaparezca , luego agregue solo la última parte) para terminar con solo el código mínimo necesario para reproducir su problema.

Entonces es más fácil para usted comparar el código de trabajo mínimo con el código de no trabajo mínimo, y enfocarse en las diferencias.

Además, espero que descubra algunas partes inesperadas de su código que no funciona, que parecen afectar la pantalla LCD, durante ese proceso de "minimización", y puede realizar la depuración desde allí. Si no, y terminas con solo unas pocas líneas de código en cada ejemplo, una de las cuales funciona y otra que no, es mucho más fácil para otras personas ayudar. Buena suerte!

    
respondido por el SamGibson

Lea otras preguntas en las etiquetas