Vad är det för fel på min LCD-kod?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
ASTRX
Inlägg: 68
Blev medlem: 12 januari 2005, 16:58:13

Vad är det för fel på min LCD-kod?

Inlägg av ASTRX »

Jag har kopplat in databussen på min LCD (hd44780) på PORTB på en ATmega16. R/W och Kontrasten går till jord. E ligger på D0, RS på D1.
Tycker att min kod borde fungera, men jag får bara massa konstiga utskrifter. Inga tecken utan teckenrutor som tänd släcks delvis osv. Detta är mitt förta riktiga försök med AVR-arkitekturen. har läst massa i datablad m.m., men antagligen har jag missat nåt.
Om nån skulle vilja hjälpa till att felsöka min kod vore det guld iaf. programmet skall bara skriva ut två skärmar om och om igen:

display_test.c

Kod: Markera allt

#include <avr/delay.h>
#include "lcd.h"

#define F_CPU 1000000

int main()
{
    int i;

    _delay_ms(50);

	init_display();
	
	while(1){
		printrow("-Ojojojo            ",1);
		printrow("-ojojojoj            ",2);

		for(i=0;i<20;i++)
			_delay_ms(200);

		printrow("halaaaashiii      ",1);
		printrow("dfhshshsh        ",2);
	}

	return 0;
}
lcd.h

Kod: Markera allt

extern void init_display();
extern void clear_display();
extern void move_cursor(unsigned char);
extern void printchar(char);
extern void printrow(char text[], int);
lcd.c

Kod: Markera allt

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

void init_display()
{
	DDRD=0x03;		  // Sätter port D till utport
	DDRB=0xFF;		  // Sätter port D till utoprt
	
	PORTD=0b00000000; // RS=0 (instruktioner), RW=0 (write)
	PORTB=0b00110000; // Instruktionen för att starta 
	PORTD=0b00000001; // E=1 ger puls
	_delay_ms(0.01);  // Väntar 10 mikroseks då E regisreras
	PORTD=0b00000000; // E=0 avslutar puls
	_delay_ms(20);	  // Väntar 100 mikrosek. då instruktionen skall exekveras

	PORTB=0b00110000;
	PORTD=0b00000001; 
	_delay_ms(0.01); 
	PORTD=0b00000000; 
	_delay_ms(1);	

	PORTB=0b00110000; 
	PORTD=0b00000001;
	_delay_ms(0.01); 
	PORTD=0b00000000; 
	_delay_ms(0.1);	

	PORTB=0b00111000; 
	PORTD=0b00000001; 
	_delay_ms(0.01);  
	PORTD=0b00000000; 
	_delay_ms(0.1);	

	PORTB=0b00001000; 
	PORTD=0b00000001; 
	_delay_ms(0.01);  
	PORTD=0b00000000; 
	_delay_ms(0.1);	 

	PORTB=0b00000110; 
	PORTD=0b00000001;
	_delay_ms(0.01); 
	PORTD=0b00000000; 
	_delay_ms(0.1);



}


void clear_display()
{
	PORTD=0b00000000;
	PORTB=0b00000001;
	PORTD=0b00000001;
	_delay_ms(0.01); 
	PORTD=0b00000000;
	_delay_ms(5);	 
}

void move_cursor(unsigned char adress)
{
	PORTD=0b00000000;
	PORTB=adress;	 
	PORTD=0b00000001;
	_delay_ms(0.01);  
	PORTD=0b00000000; 
	_delay_ms(0.1);	

}

void printchar(char c)
{
	PORTD=0b00000010; // RS=1 (data), RW=0 (write)
	PORTB=c;	  	  // tecken som skall skrivas ut 
	PORTD=0b00000011; 
	_delay_ms(0.01); 
	PORTD=0b00000010; 
	_delay_ms(0.1);	
}


printrow(char text[], int row)
{
	int i;
	unsigned char disp_adress;
	
	if(row==2)						// sätt skrivadress till rad 2
		disp_adress=0b11000000;
	else if(row==3)				       // sätt skrivadress till rad 3
		disp_adress=0b10010000;
	else if(row==4)				       // sätt skrivadress till rad 4
		disp_adress=0b11010000;
	else						       // annars rad 1
		disp_adress=0b10000000;

	move_cursor(disp_adress);

	
	for(i=0;i<20;i++)
		printchar(text[i]);
}
vukan
Inlägg: 138
Blev medlem: 12 april 2005, 14:28:19
Ort: Huddinge

Inlägg av vukan »

har själv skrivit ett eget litet program för att skriva ut på lcd'n och så här börjar min funktion för att skriva ut text:
void lcdtext(char *text){

while( *text != '\0' ) {

PORTA = *text++;
med globala deklarationer:
void lcdtext(char *text);
char *namn1 = "test lcd";
anrop av funktionen:
lcdtext(namn1);
kanske kan vara till någon hjälp?
macgyver
Inlägg: 321
Blev medlem: 8 juni 2005, 00:24:09
Ort: Göteborg
Kontakt:

Inlägg av macgyver »

om du använder WinAVR skulle jag föreslå att du testar att ta bort alla printrow

och prova istället:

for(i=0;i<20;i++) {
printchar('A');
}

fungerar det?
frejo
Inlägg: 496
Blev medlem: 21 april 2004, 21:43:01
Ort: Linköping

Inlägg av frejo »

jag skulle rent spotant använda _delay_us iställey för _delay_ms(0.X)
visserligen tar _delay_ms double men jag vet inte hur bra det egentligen funkar med så små tal.
bearing
Inlägg: 11340
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Inlägg av bearing »

Min display hämtar datan på E:S negativa flank har jag för mig, så du kanske ska låta E ligga högt och sen sänka den när du lagt ut data.

Testa att öka dina delayer, det brukar komma konstiga tecken när någon av dem är för kort, använd höga delayer i början (typ 10ggr så stora)
Om du inte vet på vilken flank datan hämtas på kan du lägga delayer efter varje ändring av E så borde det funka ändå.

Enklaste sättet att testa olika delayer är att använda konstanter. Gör även ett makro för att strobea E så blir även det lätt att ändra.

Kan även vara något fel med init(). Har tyvärr inte orkat kolla igenom den. Ett tips är att lägga in att displayen ska visa markör i init så ser du iaf om init har lyckats.

När du fått det att funka kan du sedan sänka delayerna och testa hur E egentligen ska strobeas.

ps. du kommer bara hinna se första skärmen eftersom det bara är en delay efter den, inte efter andra skärmen. ds.
ASTRX
Inlägg: 68
Blev medlem: 12 januari 2005, 16:58:13

Inlägg av ASTRX »

Mycket nyttiga saker ni påpekar. vad gäller init_display() så är den inte som jag skulle velat. hade en egenskriven kommando-sekvens som jag använt för att initiera displayen i andra sammanhang som fungerat då. Denna skijlde sig från den som fanns i wiki:n (som jag förövrigt inte fann någon logik i), så jag testade den som fanns där.

Hade en fundering till. Jag behöver väl inte koppla in mer än VCC och GND utöver displayen i uC:n? kör ju med intern oscillator.

återkommer när jag provat runt lite. men nu ska jag ut och fira avslutad tentaperiod!!! :D
ASTRX
Inlägg: 68
Blev medlem: 12 januari 2005, 16:58:13

Inlägg av ASTRX »

Grr jag tror jag blir tokig. först så slutade min atmega16 helt plötsligt att fungera. den hittas inte när den sitter i STK500:n och den kör inte sitt program. och jag har ju varit überförsiktig med den...

Jag tycker jag har varit försiktig men ändå lyckats förstöra 2st uC:s. en pajj och en avbrutna ben =/

Så då testade jag med min ATmega8515. när jag simulerar mitt numera förenklade program så funkar det som det sak. men när jag sedan kopplar in den till vald port på STK:n så lyser inte rätt leds när jag anslutit dem till rätt port.

Jag vill så gärna få det att fungera och jag har ju fått en LCD att fungera via paralellporten. så ***** svårt kan det inte vara...

EDIT: Nu har jag testat med lite lösa leds på portarna, och kommit fram till att det är stk:n som visar fel. därmed kan jag ju konstatera att hårdvaran fungerar som den ska och att uC:n ger rätt värden vid 1 och 0.

någon som ser programfelet?


den aktuella koden:

Kod: Markera allt

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

#define DELAY 1000
#define CLR_DELAY 1000

void inline strobe()
{
	PORTD |= 0x01;         // E=1 ger puls
	_delay_ms(1000);  // Väntar då E regisreras
	PORTD &=~0x01;		  // E=0 avslutar puls
}


void clear_display()
{
	PORTD &=~0x02; 		  // RS=0 (instruktioner)
	PORTB=0b00000001; 		   
	strobe();
	_delay_ms(10000);
}


void init_display()
{
	DDRD=0x03;		  // Sätter port D till utport
	DDRB=0xFF;		  // Sätter port B till utport
	
	PORTD &=~0x02; 		  // RS=0 (instruktioner)
	PORTB=0b00001111; // Instruktionen för att starta 
	strobe();
	_delay_ms(10000);	  

	PORTB=0b00111000; // Instruktionen för function set 
	strobe();
	_delay_ms(10000);	 	  

	clear_display(); // Instruktion för att cleara display	   


}


void move_cursor(unsigned char adress)
{
	PORTD &=~0x02; 		  // RS=0 (instruktioner)
	PORTB=adress;	 	
	strobe();
	_delay_us(DELAY);

}

void printchar(unsigned char c)
{
	PORTD |= 0x02; 		  // RS=0 (instruktioner)
	PORTB=c;	 	 
	strobe();
	_delay_ms(DELAY);	 
}


void printstr(unsigned char *text, int row)
{
	int i=0;
	unsigned char disp_adress;
	
	if(row==2){						
		disp_adress=0b11000000;
	}
	else if(row==3){				
		disp_adress=0b10010000;
	}
	else if(row==4){			
		disp_adress=0b11010000;
	}
	else{						
		disp_adress=0b10000000;
	}

	move_cursor(disp_adress);

	
	while(*text!='\0' || i<20){
		printchar(*text++);
		i++;
	}
}

Kod: Markera allt

#include <avr/delay.h>
#include "lcd.h"

#define F_CPU 1000000UL
#define START_DELAY 1000

int main()
{
    int i;

    _delay_ms(START_DELAY);

	init_display();

	return 0;
}
Användarvisningsbild
Xyzzy
Inlägg: 1230
Blev medlem: 30 januari 2004, 22:31:07
Ort: Uppsala, Sweden

Inlägg av Xyzzy »

ASTRX skrev:EDIT: Nu har jag testat med lite lösa leds på portarna, och kommit fram till att det är stk:n som visar fel. därmed kan jag ju konstatera att hårdvaran fungerar som den ska och att uC:n ger rätt värden vid 1 och 0.
Du vet att LEDarna på STKn är inverterade? (hög utgång resulterar i släkt LED och vice versa) - annars är det dax att läsa "manulen".
Skriv svar