Sida 1 av 1

LCD-programsproblem AVR C

Postat: 2 mars 2007, 18:36:38
av klintan
Har nu försökt få igång min LCD i några veckor, först med färdigskrivna moduler och 4-bit mode sedan övergått till att skriva sjelv i 4 bits mode, men nu har jag övergett och gått över till 8 bitars för att försöka.
Allt inkopplat på en STK500 kopplingen är checkad 10tals ggr.

Iaf koden

Kod: Markera allt

/* 
R/W - Jord
RS - PC0
E - PC2
D0 - PD0
D1 - PD1
D2 - PD2
D3 - PD3
D4 - PD4
D5 - PD5
D6 - PD6
D7 - PD7
*/

#define F_CPU 1000000UL
#include <io.h>
#include <util/delay.h>

#define LCD PORTD
#define LCD_DDRX DDRD
#define E PC2 //definerar PORT PC2 till E
#define RS PC0 //definerar PORT PC0 til RS

void toggle_enable(void){

DDRC = 0xFF; //alla DDRC till utgångar
_delay_ms(1);
PORTC &= ~(1 << E); //sätter E till 0
_delay_ms(1);
PORTC |= (1 << E); //sätter E till 1
_delay_ms(1);
PORTC &= ~(1 << E);    // sätter E till 0 
_delay_ms(1);
}



void write_lcd(unsigned char byte){
DDRC = 0xFF; //alla DDRC till utgångar 
PORTC &= ~(1 << RS);
LCD_DDRX = 0xFF; //lcd port till utgång
LCD = 0X00;
LCD = byte;

toggle_enable();
}

void write_data(unsigned char byte){
DDRC = 0xFF; //alla DDRC till utgångar
PORTC |= (1 << RS);
LCD_DDRX = 0xFF; //lcd port till utgång
LCD = 0X00; // nollställ LCD
LCD = byte;

toggle_enable();
}

void lcd_init(void){

LCD_DDRX=0xFF; 
LCD=0x00; 
_delay_ms(100);
 
   write_lcd(0x30); //initieringsslinga 8 bitar, efter stromboms manual
   _delay_ms(10); 
   write_lcd(0x30); 
   _delay_ms(10); 
   write_lcd(0x30); 
   _delay_ms(10); 
   write_lcd(0x38); 
   _delay_ms(10); 
   write_lcd(0x08); 
   _delay_ms(10); 
   write_lcd(0x01); 
   _delay_ms(10); 
   write_lcd(0x06); 
   _delay_ms(10); 
   write_lcd(0x01);
   _delay_ms(10);
   write_lcd(0x0F);
   }
   
int main(void){ //huvudprogram
_delay_ms(100);

lcd_init(); //initiera

_delay_ms(1);
write_lcd(0x0F); //sätt på LCD med blinkande cursor
_delay_ms(1);
PORTC |= (1 << RS); //sätt RS hög för säkerhets skull(om det inte funkat i write_data funktionen
write_data(0x30);
PORTC &= ~(1 << E);    // sätter E till 0 
while(1){}
}

Har snott delar av uppbyggnad och kod från gunne. Samt andra aktörer på internet, bara ersatt med den inbyggda delayrutinen för att komma ifrån att det skulle vara något fel på klockkoden. Dessutom testad de flesta portar och delayer för hand och de har då funkat.

Nu till problemen: I AVRstudio och debuggern ser det hela ut att fungera fint, Enable signalen pulsar efter varje utlagd data. Men på slutet då RS borde vara hög är den låg, samtidigt så är de portarna där de borde ligga en 1 där flaxar spänningen mellan 1- 4 volt. vilket är skumt?

Just nu händer inget alls det är endast en rad svarta fyrkanter överst (med stark kontrast påskruvad)
Det händer inte det minsta när jag kör koden, förut när jag kört 4 bitars mode å andra koder har de iaf blivit dubbla rader med fyrkanter och lite flaxande.

Funderar på att köpa en ny display och fortsätta labba för att utesluta fel på displayen, annars är det bara glapp som ja kan tänka mig är fel. Har försökt så många ggr snart så att det nästan borde fungera av ren tur.

Kan tillägga att jag läst igenom databladet ett antal ggr, ett antal tutorials på internet, samt sodjans Epemag pdf. Alla mkt bra och det får väl bli sista alternativet att köpa en DIP och köra för hand för att sedan försöka igen på AVRen.

Tacksam för alla förslag på vad som kan vara fel, kommentarer på koden samt egna koder som körs i 8bits mode.

Postat: 2 mars 2007, 19:13:33
av thepirateboy
Du kan ju få min kod att testa med om du vill, den vet jag funkar iaf.

Postat: 3 mars 2007, 00:17:59
av oJsan
Kan inte hitta några direkta fel när jag kikar, men det kan ju tänkas att du kopplat fel även fast du kopplat som du _tycker_ att du ska ha kopplat... om du förstår vad jag menar.
På ett par ställen står det "LCD = 0X00;"... känns som att kompilatorn borde klaga på stort X, borde vara ett litet istället... dessa två ställen där LCD sätts till 0 är för övrigt också onödiga. Riktningsregisterna LCD_DDRX och DDRC behöver bara sättas en gång, lämpligast i lcd_init(). Det borde dock inte skada att ha det med, som det är nu.

Ett kopplingsschema skulle vara bra att för att lättare kunna felsöka, samt kanske ett foto av uppkopplingen?

Postat: 3 mars 2007, 01:11:42
av mullemeck
går inte E signalen på fallande flanker?
som jag ser det så kan det hända 2ggr direkt efter varandra kan vara att den inte gillar det.

Postat: 3 mars 2007, 09:33:20
av oJsan
2ggr efter varandra, var då? Om du menar positiv och sedan negativ flank som "två flanker" så är det ändå helt okey, displayen klockar bara på den ena typen.

Postat: 3 mars 2007, 09:53:43
av Icecap
Displayen samplar inputdata på fallande flanken.

Postat: 3 mars 2007, 12:48:30
av klintan
Tar ett foto på kopplingen och återkommer snarast.
Bild

Detta är uppkopplingen, 1 = PC0 2 = PC1 osv.. för dem som inte har STK500. Bilder på uppkopplingen kmr snart.

Edit: Ser genast ett fel på bilden de står att en pinne från potentiometern skall gå till PC5 eller nåt de är fel :P

Bild
Bild
Bild

Svårt att se på dessa bilder hur jag kopplat iofs. Men då antar jag de är något glapp någonstans kanske, kasst kopplingsdäck? de är från kjell dom från elfa är mkt bättre men. får kolla kopplingen nåra ggr till :) tack för all hjälp hittills.


Säg till om ni vill ha bilderna mindre?

Postat: 3 mars 2007, 14:07:23
av mullemeck
Första felet jag ser att i kopplingsschemat går RS och E till PC7 och PC5 i din kod har du dem på PC0 och PC2

Postat: 3 mars 2007, 15:38:49
av klintan
såg det. har ändrat fortfarande ingenting, beställde en ny display från elektroform igår så hoppas väl få den i veckan får koppla upp en ny koppling då. tänkte installera om Winavr och AVRstudio också. för att utesluta alla fel.

Postat: 13 mars 2007, 21:22:11
av klintan
Tänkte återuppliva tråden för några fler förslag, koden funkar helt perfekt när man simulerar i AVRstudio har satt alla delays till 5000 ms för att kunna se allt, när aj stegar fram så sker allt precis enligt datablad vid initieringen. Så till problemet, när ja laddar upp programmet till atmegan, (128, på stk501) och testar på det inbyggda LEDsen samt en egeninkopplad LED på enable utgången så blinkar endast LED5 och LED4 och när de är släckta blinkar enable, så det är ingen fel på den. Detta sker till synes i all oändlighet, hur kan min kod orsaka detta? :S förstår absolut ingenting.

Har även tagit bort while(1){} på slutet samt köpt en helt ny LCD iofs 20*4 raders men HD44780 krets iaf.

Postat: 13 mars 2007, 22:02:50
av oJsan
...så det är ingen fel på den
Men dåså! =)

..så blinkar endast LED5 och LED4 och när de är släckta blinkar enable
Ursäkta, men jag förstår inte alls hur du menar?! Du kan mena många olika saker. Bättre förklaring tack!

Skriv ett program som ser ut enbart såhär typ:

unsigned char tmp=0;
init_io(); //set ports as outputs
while(1)
{
PORTx=tmp++;
delay_ms(10);
}

Och låt PORTx vara PORTA, PORTB, PORTC, PORTD, PORTE, PORTF, bara för att kolla att du verkligen kopplat rätt, att alla ben verkligen går att använda som utgångar samt att du inte råkat elda upp någon utgångsdrivare.

Postat: 13 mars 2007, 22:42:33
av klintan
Alltså , på de 8 ledsen på STK500 så blinkar endast LED4 och LED5 exakt samma takt, alltså bättre förklarat, PD4 och PD5 blir låga samtidigt, sedan höga, när dessa är låga så går PC0 hög.

Skall testa programmet återkommer

edit1: ok har nog hittat felet nu, efter att ha testat att köra lite mer för hand å testat varje Port för sig, visar det sig att den på något sätt fastnar i funktionen toggle_enable, och sedan loopar den i all oändlighet? Får väl köra utan den för hand bara för att testa om det funkar , men skulle ändå vara tacksam om någon kunde förklarar varför den hoppar in i den å aldrig kommer därifrån ? äre nåt konstigt med min AVR eller är det något vaj på just den kodsnutten?


edit2: YES fick de till slut att funka. Men en himla jobbigt å ful kod, skall försöka förbättra den ett steg i taget för att se vad det är som pajar ihop.

Kod: Markera allt

#define F_CPU 1000000UL /* 1 MHz Internal Oscillator */
#include <io.h>
#include <util/delay.h>
#define E PC2
#define RS PC0

int main()
{
DDRC = 0xFF; // sätt alla PCx till utgångar
PORTC = 0x00; // sätt alla PCx låga
DDRA = 0xFF; // sätt alla PAx till utgångar
PORTA = 0x00; // sätt alla PAx låga

_delay_ms(5000);

PORTC &= ~(1 << RS); //sätt RS låg för instruktioner
PORTC &= ~(1 << E); //sätt E låg och skicka nästa instruktion

_delay_ms(5000);

PORTA = 0X30; // 1

_delay_ms(5000);

PORTC |= (1 << E); //sätt E hög och sänd datan
_delay_ms(5000); 		// vänta och sen...
PORTC &= ~(1 << E); //sätt E låg och skicka nästa instruktion

_delay_ms(5000);

PORTA = 0x30;  // 2
_delay_ms(5000);

PORTC |= (1 << E); //sätt E hög och sänd datan
_delay_ms(5000); 		// vänta och sen...
PORTC &= ~(1 << E); //sätt E låg och skicka nästa instruktion

_delay_ms(5000);

PORTA = 0x30; // 3

_delay_ms(5000);

PORTC |= (1 << E); //sätt E hög och sänd datan
_delay_ms(5000); 		// vänta och sen...
PORTC &= ~(1 << E); //sätt E låg och skicka nästa instruktion

_delay_ms(5000);

PORTA = 0x38; // 4

_delay_ms(5000);
PORTC |= (1 << E); //sätt E hög och sänd datan
_delay_ms(5000); 		// vänta och sen...
PORTC &= ~(1 << E); //sätt E låg och skicka nästa instruktion

_delay_ms(5000);

PORTA = 0x08; // 5

_delay_ms(5000);
PORTC |= (1 << E); //sätt E hög och sänd datan
_delay_ms(5000); 		// vänta och sen...
PORTC &= ~(1 << E); //sätt E låg och skicka nästa instruktion

_delay_ms(5000);

PORTA = 0x01; // 6
_delay_ms(5000);
PORTC |= (1 << E); //sätt E hög och sänd datan
_delay_ms(5000); 		// vänta och sen...
PORTC &= ~(1 << E); //sätt E låg och skicka nästa instruktion

_delay_ms(5000);

PORTA = 0X06; // 7
_delay_ms(5000);
PORTC |= (1 << E); //sätt E hög och sänd datan
_delay_ms(5000); 		// vänta och sen...
PORTC &= ~(1 << E); //sätt E låg och skicka nästa instruktion

_delay_ms(5000);
PORTA = 0x0F;
PORTC |= (1 << E); //sätt E hög och sänd datan
_delay_ms(5000); 		// vänta och sen...
PORTC &= ~(1 << E); //sätt E låg och skicka nästa instruktion
_delay_ms(5000);
PORTC |= (1 << RS); // sätt RS till hög för data 
// skicka data till displayen:
PORTA = 0x30;
PORTC |= (1 << E); //sätt E hög och sänd datan
_delay_ms(5000); 		// vänta och sen...
PORTC &= ~(1 << E); //sätt E låg och skicka nästa instruktion
PORTA = 0x40;
PORTC |= (1 << E); //sätt E hög och sänd datan
_delay_ms(5000); 		// vänta och sen...
PORTC &= ~(1 << E); //sätt E låg och skicka nästa instruktion
PORTA = 0x40;
PORTC |= (1 << E); //sätt E hög och sänd datan
_delay_ms(5000); 		// vänta och sen...
PORTC &= ~(1 << E); //sätt E låg och skicka nästa instruktion
while(1){}
}