Hallo allemaal,
Zal me eerst even voorstellen, ik ben Jeroen, kom uit Almere, en kwam eigelijk uit wanhoop op deze site terecht 
Ik zit op de Hogeschool van Amsterdam als eerstejaars bij de opleiding Elektrotechniek en we kregen daar een project waarbij ik o.a. een menu kan maken op een LCD scherm(MC1602-syr) door middel van het programmeren in C voor de Microcontroller.(Atmega32) Alleen dat wilt niet helemaal werken :\
Wat ik nodig heb voor mijn menu is drie knoppen en een ADC.
Die knoppen en ADC houden de pinnen bij de poorten A en D in beslag en kan ik dus alleen 8 dataingangen aansluiten op de C poort.
Ik ben al twee weken bezig en ik heb verschillende methode's geprobeerd.
De dataingangen van het LCD waren aangesloten op poort PC7 t/m PC0. Toen kwam het probleem van de JTAG debugger. Deze was uitgezet. Alsnog geen beeld maar alleen blokjes. Als ik de tekst 'LCD' in een while loop zet werk het wel.
Toen heb ik, als test, de Dataingangen aangesloten op poort D van de microcontroller(ook in de code gewijzigd natuurlijk) en daar kwam LCD uit. Het werkt dus wel.
Daarna heb ik geprobeerd , op de D poort , met een while loop tekst, een knopje aan te sluiten(op Int0 / PD3) om de tekst te laten veranderen.(Zie code onderaan) Dit is nog niet gelukt.
Toen kwam ik erachter dat je het LCD scherm ook kan instellen op een 4-bits dataingang. Met de 4bits dataingang LCDscherm is het mogelijk die aan te sluiten op de D poort van de microcontroller en ook de knoppen te gebruiken die ook op de Cpoort aangesloten zitten. Dat klonk mooi in de oren. Alleen het werkt niet..
Ik heb geen idee wat ik fout doe en ik kom er níet uit. Kan iemand mij helpen?
Hieronder de datasheet van de Atmega32 en het LCD schema en de software code geprogrammeerd in C.
http://www.atmel.com/dyn/resources/prod_documents/doc2503.pdf
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#define lcdcommand(d) (lcdwrite((d),PORTB&0xFE)); // RS low
#define lcdputc(d) (lcdwrite((d),PORTB|0x01)); // RS high
volatile int i=0;
void printMenu(void);
void lcdputstring(char *s);
ISR(INT0_vect){
i++;
if (i==3){
i=0;
}
}
void lcdwrite(char d, char type){
PORTB = type; // RS low or high
PORTB = PORTB|0x02; // make E high
PORTD = d; // assign data
PORTB = PORTB&0xFD; // make E low
_delay_us(1520); // wait 1,52 ms worst case delay
}
void initlcd(void)
{
DDRD = 0xF0; // pd7...pd4 output
DDRB = DDRB|0x03; // pin 0 and 1 port B: RS en E
_delay_ms(15);
lcdcommand(0x38);
lcdcommand(0x38);
lcdcommand(0x38);
lcdcommand(0x20); // set 4-bit
lcdcommand(0x28); // 4-bit, 2 lines, 5x8
lcdcommand(0x0C); // display on, cursor off
lcdcommand(0x06); // write right
lcdcommand(0x01); // clear display
}
int main(void){
initlcd(); // initialization LCD
printMenu();
sei();
while (1) {
PORTD &= 0x0F
PORTD >> 4
PORTD &= 0x0F
void printMenu(void);
{
if (i==0){
lcdcommand(0x01); // clear display
lcdputc('T'); // write text
lcdputc('E');
lcdputc('S');
lcdputc('T');
}
if (i==1){
lcdcommand(0x01); // clear display
lcdputc('T'); // write text
lcdputc('E');
lcdputc('S');
lcdputc('T');
lcdputc('1');
lcdcommand(0xC0);
lcdputc('*');
}
if (i==2){
lcdcommand(0x01); // clear display
lcdputc('T'); // write text
lcdputc('E');
lcdputc('S');
lcdputc('T');
lcdputc('2');
lcdcommand(0xC0);
}
}
asm volatile ("nop");
}
}
Alvast bedankt allemaal !
Ik heb je code niet heel goed bekeken, maar de volgende 2 dingen vielen mij meteen op:
- je hebt interrupts niet aan gezet met sei();
- De functie printmenu moet in de while loop.
Owja die sei();
Overheen gekeken ..
Bedankt Atom, heb je tips uitgevoerd, geeft geen foutmeldingen in AVR Studio. Kan het alleen op het moment nog niet uittesten op de microcontroller, zit zonder programmer op het moment.
Ziet iemand anders nog fouten waardoor het niet werkt?
Tips gewaardeerd 
Code gewijzigd in openingspost
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
Verander je [ quote ] tag in [ code ] (zonder de spaties), dan wordt je code beter leesbaar. Dan krijg je zoiets:
void lcdwrite(char d, char type)
{
PORTB = type; // RS low or high
PORTB = PORTB | 0x02; // make E high
PORTD = d; // assign data
PORTB = PORTB & 0xFD; // make E low
_delay_us(1520); // wait 1,52 ms worst case delay
}
void initlcd(void)
{
DDRD = 0xF0; // pd7...pd4 output
DDRB = DDRB | 0x03; // pin 0 and 1 port B: RS en E
_delay_ms(15);
lcdcommand(0x38);
lcdcommand(0x38);
lcdcommand(0x38);
lcdcommand(0x20); // set 4-bit
// enz...
}
Dat kan nooit goed gaan. Ofwel gebruik je 8-bit mode, en dan schakel je PD0 ... PD7 als uitgang. Ofwel doe je aan 4-bit mode, maar dan moet je voor elke byte eerst de high-nibble versturen, gevolgd door de low-nibble.
Hou daar rekening mee bij het initialiseren. Na de laatste instructie hierboven, moet je alle volgende instructies in 4-bit mode uitvoeren!
Die code is toch goed?
Ik maak van DDRD de poorten
PD7 PD6 PD5 en PD4 m'n uitgangspoorten
en bij lcdcommand(0x20) laat ik weten dat het een 4-bit is.
Hoe werkt dat dan met die nibble? Dat snap ik niet.
Heb nu juist voor de mogelijkheid gekozen voor 4-bit data omdat ik bij een 8bit data te weinig knoppen heb, ik heb er namelijk 3 nodig.
Hmm byte splitsen? Daar had ik nog niets over gelezen.
Nu ik erover nadenk is dat best logisch aangezien je geen 8 bits meer heb waardoor ik alle bits in 1 keer kan versturen..
Dus als ik het goed heb, als ik een U wil plaatsen op m'n LCD
U = 0101 0101
Moet ik eerst 0101 moet versturen (van rechts)
en dan 0101 moet versturen (van links)?
Dan ga ik daar even mee spelen ^^
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
Op 14 april 2009 14:58:07 schreef pros:
Zo is het, ja. Eerst de high-nibble, gevolgd door de low-nibble.
Ik kreeg eerst gewoon zwarte blokjes op m'n scherm, dus dat ie gewoon aan is.
N.a.v. de high nibble low libble theorie had ik het volgende gedaan in de While(1){ } :
PORTD &= 0x0F
PORTD >> 4
PORTD &= 0x0F
zodat:
U = 0101 0101
0000 1111
----------
0000 0101
word verstuurd
dan 0101 0101 vier naar rechts verschoven
U = 0000 0101
0000 1111
----------
0000 0101
Wat een U zou moeten geven op het LCD scherm.
Alleen wat ik nu heb is 1 knipperend blokje.
Code geupdate in openingspost [/code]
PORTD &= 0x0F
PORTD >> 4
PORTD &= 0x0F
Dat gaat niet werken: de &= operatie is een assignment, dus na "PORTD &= 0xf" ben je de hoogste 4 bits kwijt; daarna shiften zonder op slaan is ook niet zo zinnig (waar blijft het resultaat?)
en daarna opnieuw een &= waarbij er dus effectief niks veranderd (omdat de shift geen assignment doet; als de shift wel wat deed, was PORTD nu 0000)
Je moet in twee stappen iets aan PORTD assignen:
Eest het hoge nibble: PORTD = (d & 0xF0)>>4;
En dan het lage nibble: PORTD = (d & 0x0F);
met de juiste delays en enable-flag-toggling...
je code wordt dan dus iets als:
void lcdwrite4bit(char d, char type){
PORTB = type; // RS low or high
PORTB |= 0x02; // make E high
PORTD = (d & 0xF0)>>4; // send high nibble
PORTB &= (~0x02); // make E low
_delay_us(10); // ofzo?
PORTB |= 0x02; // make E high
PORTD = (d & 0x0F); // send low nibble
PORTB &= (~0x02); // make E low
_delay_us(1520); // wait 1,52 ms worst case delay
}
Edit: Oh ja, en je hebt de "De functie printmenu moet in de while loop" iets te letterlijk genomen... De implementatie van de functie mag natuurlijk gewoon buiten de main() functie, dat houdt de boel wel zo geordend. Er werd bedoeld om de functie-aanroep binnen de while lus te zetten, de "printMenu();" in de main() dus een paar regels naar beneden...
[Bericht gewijzigd door KaRaMBa op (14%)]
Bedankt voor je hulp en uitleg! Het is zo een stuk duidelijker. Ik ga het morgen even uittesten, dan heb ik een programmer tot m'n beschikking. Zal zo snel mogelijk laten horen of het is gelukt!
void lcdwrite4bit(char d, char type){
PORTB = type; // RS low or high
PORTB |= 0x02; // make E high
PORTD = (d & 0xF0)>>4; // send high nibble
PORTB &= (~0x02); // make E low
_delay_us(10); // ofzo?
PORTB |= 0x02; // make E high
PORTD = (d & 0x0F); // send low nibble
PORTB &= (~0x02); // make E low
_delay_us(1520); // wait 1,52 ms worst case delay
}
Deze code gebruikt , beetje gespeelt met de delay, is nu 50. Maar krijg nog steeds geen tekst op m'n scherm, alleen blokjes..
Geen idee waarom xD Waar kan ik nog naar kijken?
Gatze
Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously
Dat er nog zwarte blokjes op je display staan, betekent dat hij nog niet goed geinitialiseerd is. Als ik de datasheet erop nakijk is de timing niet helemaal goed bij het initialiseren. Dit heb ik uit de datasheet. http://www.uploadarchief.net/files/download/timingopstarten.jpg
Misschien dat dit helpt.
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
@J-r0en: Verwijder alles uit je broncode, dat niets met de LCD-sturing te maken heeft, en post die even (of plaats die elders, en post een link). Nu kunnen we enkel wat rondtasten in het duister...
Kleine update, we hebben uiteindelijk maar gewoon gekozen voor een 8bit op de D poort vanwege achterstand op het project. 1 interrupt gebruikt van Int2.
Dit werkt overigens, en we zijn van plan een tweede knop aan te sluiten op een poort die eigelijk geen interrupt is.
Henry S.
Moderator
Confucius says chà bù duo. Deze post is niet door ChatGPT gegenereerd. De 2019 CO labvoeding.
4 topics over 1 project is niet nodig: http://www.circuitsonline.net/forum/view/73201
Slotje.