Hallo, ich habe die Platine (16MHz) aus dem Shop hier und möchte einen LCD anschließen. Dafür habe ich mich für den Port B entschieden. Soweit so gut, wenn ich Spannung anlege, dann sehe ich auf dem LCD in der 1. und 3. Zeile einen schwarzen Balken. Was mich aber verwundert, ist dass die LED auf der Entwicklungsplatine nicht leuchtet! Ich habe nachgemessen, Spannung liegt an PB01 an, aber trotzdem leuchtet die LED nicht! Ich dachte mir vielleicht ist mein Mikrocontroller kaputt, da ich ja das LCD weder initialisieren, noch sonst was kann. Kann das sein? Was allerdings (zumindest meiner Meinung nach) dagegenspricht, ist, dass ich den Mikrocontroller ja programmieren kann, also Programme in den Controller + Speicher schreiben sowie auch lesen kann - das scheint einwandfrei zu funktionieren. An was kann denn das Problem liegen? Ist es möglich, dass der Controller kaputt ist? Oder soll ich das LCD, das derzeit an den PortB's liegt, an einen anderen Port (D) anschließen? Vielen Dank für Eure Hilfe Markus
Was noch zu sagen wäre: Falsch angeschlossen ist das Ding ja nicht, ich habe alle Ports so angeschlossen, wie im AVR-Tutorial beschrieben, nur anstatt der D's eben die B-Ports genommen.
Hi Markus, ich kenne die Platine jetzt zwar nicht, aber zur LED: Vielleicht hängt die ja schon fest an Vcc und geht somit nur an, wenn Du den Port-Pin auf Low ziehst, anstatt auf High? Sebastian
Du kannst dir bei Olimex die Doku zu der Platine runterladen. Dann siehst du, dass die LED nach + angeschlossen ist, daher nur leuchtet wenn der Ausgang auf Low liegt. Eigentlich ist es egal an welchen Port das LCD hängt, sofern du das in der LCD-Bibliothek richtig änderst. Du solltest dort auch die delay() Routine anpassen, da die wahrscheinlich für 4MHz ausgelegt ist, und sonst das Timing nicht passt.
Ich habe ein bisschen im Forum gesurft (bin leider gerade nicht daheim, sonst hätte ich das mit dem delay schon ausprobiert) und bin darauf gestoßen, dass es evtl. auch was mit der Hintergrundbeleuchtung zu tun haben könnte (habe ein LCD mit 16 pins) - kann das sein, oder dürften dann gar keine Balken in der 1. und 3. Zeile erscheinen? Vielen Dank schon einmal für Eure Antworten. Grüßle Markus
Aber es scheint so, als schließt ihr einen defekten Mikrocontroller aus, richtig? Das wäre schon mal ne gute Nachricht.
So langsam krieg ich echt nen Koller. Das mit dem Delay hat nicht so wirklich funktioniert (muss ich da vielleicht irgendwelche FuseBits noch setzen, oder was weiß ich)? Ich würd jetzt gern einfach mal testen, ob mein Mikrocontroller funktioniert und würd gerne die LED an PB01 testen (wie oben beschrieben). Könnte mir da vielleicht jemand helfen mit ein bisschen Code? Vielen vielen Dank Der enttäuschte Markus
Kanns dir nur für gcc aufschreiben:
#include <avr/io.h>
void main(void)
{
DDRB=1;
PORTB=0;
oder korrekter:
PORTB&=~_BV(0);
}
Wie ich oben schon geschrieben habe, der Pin muss auf 0!!!!
Sorry, loop sollte drüber:
void main(void)
{
DDRB=1;
PORTB=0; // LED aus (einfache Methode)
for (;;)
{
PORTB|=_BV(0); // setzt pin auf high, also LED aus
// da kannst dein delay rein
PORTB&=~_BV(0); // pin auf low, also LED ein
}
}
}
Ha, ich werd verrückt. Vielen Dank, Fritz, die LED leuchtet wirklich!!! Juhu! Damit wäre einmal sichergestellt, dass der Mikrocontroller nicht im Eimer ist! Jetzt muss nur noch der LCD funktionieren. Nochmal meine Frage von vorhin: Kann es vielleicht daran liegen, dass ich an der Kontrastspannung herumspielen muss? Aber warum werden dann nur in der 1. und 3. Zeile schwarze Balken angezeigt und nicht in allen Zeilen? Ist dann doch unwahrscheinlich, oder?
Wenn der LCD-Controller Strom kriegt, dann sieht man die schwarzen Balken. Oder wenn er per Software initialisiert wird, hab ich vergessen. Auf jeden Fall passt der Kontrast wenn du was siehst. Mit lcd_clrscr oder wie es bei dir heisst, sollten die weggehen, vorher musst aber noch sowas wie lcd_init machen.
Ja, genau und das ist das Problem. Mit folgendem Code tut sich rein gar
nichts (außer den schwarzen Balken) :-(((
.include "2313def.inc"
.def temp1 = r16
.def temp2 = r17
.def temp3 = r18
ldi temp1, LOW(RAMEND) ; LOW-Byte der obersten
;RAM-Adresse
out SPL, temp1
ldi temp1, 0xFF ;Port D = Ausgang
out DDRB, temp1
rcall lcd_init ;Display initialisieren
rcall lcd_clear ;Display löschen
ldi temp1, 'T' ;Zeichen anzeigen
rcall lcd_data
ldi temp1, 'e' ;Zeichen anzeigen
rcall lcd_data
ldi temp1, 's' ;Zeichen anzeigen
rcall lcd_data
ldi temp1, 't' ;Zeichen anzeigen
rcall lcd_data
loop:
rjmp loop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; LCD-Routinen ;;
;; ============ ;;
;; (c)andreas-s@web.de ;;
;; ;;
;; 4bit-Interface ;;
;; DB4-DB7: PB0-PB3 ;;
;; RS: PB4 ;;
;; E: PB5 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;sendet ein Datenbyte an das LCD
lcd_data:
mov temp2, temp1 ;"Sicherungskopie" für
;die Übertragung des 2.Nibbles
swap temp1 ;Vertauschen
andi temp1, 0b00001111 ;oberes Nibble auf Null setzen
sbr temp1, 1<<4 ;entspricht 0b00010000
out PORTB, temp1 ;ausgeben
rcall lcd_enable ;Enable-Routine aufrufen
;2. Nibble, kein swap da es
schon
;an der richtigen stelle ist
andi temp2, 0b00001111 ;obere Hälfte auf Null setzen
sbr temp2, 1<<4 ;entspricht 0b00010000
out PORTB, temp2 ;ausgeben
rcall lcd_enable ;Enable-Routine aufrufen
rcall delay50us ;Delay-Routine aufrufen
rcall delay50us
rcall delay50us
ret ;zurück zum Hauptprogramm
;sendet einen Befehl an das LCD
lcd_command: ;wie lcd_data, nur ohne RS zu
setzen
mov temp2, temp1
swap temp1
andi temp1, 0b00001111
out PORTB, temp1
rcall lcd_enable
andi temp2, 0b00001111
out PORTB, temp2
rcall lcd_enable
rcall delay50us
rcall delay50us
rcall delay50us
ret
;erzeugt den Enable-Puls
lcd_enable:
sbi PORTB, 5 ;Enable high
nop ;3 Taktzyklen warten
nop
nop
nop
nop
nop
cbi PORTB, 5 ;Enable wieder low
ret ;Und wieder zurück
;Pause nach jeder Übertragung
delay50us: ;50us Pause
ldi temp1, $42
delay50us_:dec temp1
brne delay50us_
ret ;wieder zurück
;Längere Pause für manche Befehle
delay5ms: ;5ms Pause
ldi temp1, $21
WGLOOP0: ldi temp2, $C9
WGLOOP1: dec temp2
brne WGLOOP1
dec temp1
brne WGLOOP0
ret ;wieder zurück
;Initialisierung: muss ganz am Anfang des Programms aufgerufen werden
lcd_init:
ldi temp3,50
powerupwait:
rcall delay5ms
rcall delay5ms
rcall delay5ms
dec temp3
brne powerupwait
ldi temp1, 0b00000011 ;muss 3mal hintereinander
gesendet
out PORTB, temp1 ;werden zur Initialisierung
rcall lcd_enable ;1
rcall delay5ms
rcall delay5ms
rcall delay5ms
rcall lcd_enable ;2
rcall delay5ms
rcall delay5ms
rcall delay5ms
rcall lcd_enable ;und 3!
rcall delay5ms
rcall delay5ms
rcall delay5ms
ldi temp1, 0b00000010 ;4bit-Modus einstellen
out PORTB, temp1
rcall lcd_enable
rcall delay5ms
rcall delay5ms
rcall delay5ms
ldi temp1, 0b00101000 ;noch was einstellen...
rcall lcd_command
ldi temp1, 0b00001100 ;...nochwas...
rcall lcd_command
ldi temp1, 0b00000100 ;endlich fertig
rcall lcd_command
ret
;Sendet den Befehl zur Löschung des Displays
lcd_clear:
ldi temp1, 0b00000001 ;Display löschen
rcall lcd_command
rcall delay5ms
rcall delay5ms
rcall delay5ms
ret
Beziehungsweise analog dazu mit der originalen, unveränderten Peter Fleury Bibliothek: /*********************************************************************** ** Title: testing output to a HD44780 based LCD display. Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury File: $Id: test_lcd.c,v 1.3 2003/12/10 19:32:48 peter Exp $ Software: AVR-GCC 3.3 Hardware: HD44780 compatible LCD text display ATS90S8515/ATmega if memory-mapped LCD interface is used any AVR with 7 free I/O pins if 4-bit IO port mode is used ************************************************************************ **/ #include <stdlib.h> #include <avr/io.h> #include "lcd.h" /* ** constant definitions */ /* ** function prototypes */ int main(void) { char buffer[7]; int num=134; /* initialize display, cursor off */ lcd_init(LCD_DISP_ON); for (;;) { /* loop forever */ /* * Test 1: write text to display */ /* clear display and home cursor */ lcd_clrscr(); /* put string to display (line 1) with linefeed */ lcd_puts("LCD Test Line 1\n"); /* cursor is now on second line, write second line */ lcd_puts("Line 2"); /* move cursor to position 8 on line 2 */ lcd_gotoxy(7,1); /* write single char to display */ lcd_putc(':'); } }
es gibt bei der Fleury bibliothek ein lcd.h da musst du einstellen ob du memory maped oder i/o machst. Ich hab die delay routine auch an die 8MHz angepasst.
Da ich mich jetzt voll auf Fleurys Bibliothek konzentrieren möchten, werde ich nun den Pin PB5 mit R/W (das war ja bisher auf GND gesetzt - wegen Tutorial) und den Pin PB6 mit Enable (war davor PB5) verbinden. So wie es eben in Fleurys Anleitung steht (http://homepage.sunrise.ch/mysunrise/pfleury/avr-lcd44780.html). Ich melde mich dann gleich wieder.
Jippie, es funktioniert!!! Fritz vielen Dank für deine aufopferungsvolle Hilfe - das hat mir mehr als geholfen. Wenn ich noch ein paar Fragen habe, darf ich dich dann fragen :-P? Tausend Dank an allen, die sich die Mühe gemacht haben, mir zu helfen. Nun bin ich fast fertig mit meinem LCD (naja, gut, schon noch ein Stück, aber mal schaun). Danke Markus
Ich versuche nun, in mein EEPROM mit folgender Funktion die Zahl 732
hineinzuschreiben:
#include <stdlib.h>
#include <avr/io.h>
#include <inttypes.h>
#include <eeprom.h>
#include "lcd.h"
#define EEPROM_SECTION _attribute_ ((section (".eeprom")))
uint16_t eeprom_var1 EEPROM_SECTION = 1027;
int main(void)
{
char buffer[20];
uint16_t state1=732;
eeprom_write_byte(&eeprom_var1, state1);
/* initialize display, cursor off */
lcd_init(LCD_DISP_ON);
lcd_clrscr();
...
}
Dann hatte ich versucht, die Zahl mittels
int main(void)
{
char buffer[20];
uint16_t state1=732;
/* initialize display, cursor off */
lcd_init(LCD_DISP_ON);
lcd_clrscr();
state1 = eeprom_read_word(&eeprom_var1);
for (;;) {
...
}
auszulesen, und mittels
itoa( state1 , buffer, 20);
/* put converted string to display */
lcd_puts(buffer);
auf den LCD zu schreiben. Doch auf dem LCD sehe ich nur 839f anstatt
732.
Die Zahl state1 muss bis zu 36600 groß werden, darum habe ich mich für
einen uint16_t entschieden - ich hoffe, das war richtig.
Warum aber zeigt mein LCD nun das falsche an?
Ich meinte natürlich itoa (state1, buffer, 10). Und habe dabei auch state1 nicht auf 732, sondern auf die Höchstzahl 36600 gebracht. Auf dem LCD habe ich dann nur -1 anstatt 36600 gesehen. Wahrscheinlich kann ich mit eeprom_write_byte(&eeprom_var1, state1); keine so großen Werte speichern, sondern nur Byte-Werte von 0-255, oder? Wie löse ich dann das Problem? Oder muss ich beim Wertebereich 0-36600 einfach einen anderen Variablentyp nehmen? Aber welchen? Vielen Dank Markus
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.