cumi
05.04.2006, 16:59
Hallo Zusammen
Ich krieg es einfach nicht hin, mein LCD anzusteuern. Überall wird geschrieben, dass sei eigentlich nicht so ein Problem, aber bei mir klappts nicht :(
Also das Ganze sieht so aus: Ich habe ein 4x20Zeichen Display. Also 4 Zeilen mit je 20 Zeichen.
Das Datenblatt könnt ihr hier (http://www.shop.robotikhardware.de/shop/catalog/product_info.php?cPath=66&products_id=80) herunterladen.
Ich möchte es im 8-Bit Modus ansteuern. Dann brauche ich das Byte nicht zu zerlegen und für den Moment habe ich genug Ports.
Ich habe das Display folgendermassen mit dem RN-Control verkabelt:
RS auf PORTB, Pin 0
R/W habe ich, da ich nur schreiben möchte auf VSS gelegt (richtig so, oder?)
E auf PORTB, Pin 2
D0-D7 auf PORTC
Dazu erstmal eine Frage. Funktioniert das rein elektronisch? Oder funkt mir da noch irgendwas vom RN-Control rein? Den Motortreiber habe ich entfernt, und alle Jumper rausgezogen.
Mein Code sieht so aus:
b_setH und b_setL ist eine Präprozessordirektiven um ein Bit in einem Byte Hight bzw. Low zu setzten.
Konfiguriert wird das Ding im Haederfile:
m32_lcd.h
#ifndef M32_LCD_H_
#define M32_LCD_H_
// general ---------------------------------------------------------------------
#ifndef F_CPU
#define F_CPU 16000000
#endif
// LCD -------------------------------------------------------------------------
#define CONT_DDR DDRB
#define CONT_PORT PORTB
#define CONT_E 2 // Enable (fallende Flanke)
#define CONT_RS 0 // L:Befehl / H:Daten
#define CONT_RW 1 // H:Read / L:Write
#define DATA_DDR DDRC
#define DATA_PORT PORTC
// EOF -------------------------------------------------------------------------
#endif /*M32_LCD_H_*/
Und hier die Source:
m32_lcd.c
#include <avr/io.h>
#include "m32_lcd.h"
#include "bit.h"
// delay -----------------------------------------------------------------------
void _delay_loop_1(uint8_t __count)
{
__asm__ volatile (
"1: dec %0" "\n\t"
"brne 1b"
: "=r" (__count)
: "0" (__count)
);
}
void _delay_loop_2(uint16_t __count)
{
__asm__ volatile (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__count)
: "0" (__count)
);
}
void _delay_us(double __us)//max: 768us / F_CPU in Mhz
{
uint8_t __ticks;
double __tmp = ((F_CPU) / 3e6) * __us;
if (__tmp < 1.0)
__ticks = 1;
else if (__tmp > 255)
__ticks = 0; // i.e. 256
else
__ticks = (uint8_t)__tmp;
_delay_loop_1(__ticks);
}
void _delay_ms(double __ms) //max: 260ms / F_CPU in Mhz
{
uint16_t __ticks;
double __tmp = ((F_CPU) / 4e3) * __ms;
if (__tmp < 1.0)
__ticks = 1;
else if (__tmp > 65535)
__ticks = 0; // i.e. 65536
else
__ticks = (uint16_t)__tmp;
_delay_loop_2(__ticks);
}
// testing ---------------------------------------------------------------------
void init(void)
{
b_setH(CONT_DDR,CONT_E);
b_setH(CONT_DDR,CONT_RS);
// b_setH(CONT_DDR,CONT_RW);
b_setL(CONT_PORT,CONT_E); // E nicht setzen
b_setL(CONT_PORT,CONT_RS); // RS nicht setzen
// b_setL(CONT_PORT,CONT_RW); // RW nicht setzen
DATA_DDR = 0xff; // Ausgänge
DATA_PORT= 0x00;
}
// lcd -------------------------------------------------------------------------
void lcd_send(uint8_t data, uint8_t rs) //rs: L:Befehl / H:Daten
{
DATA_PORT = data;
if(rs)
b_setH(CONT_PORT,CONT_RS);
else
b_setL(CONT_PORT,CONT_RS);
_delay_us(45); // kurze Verzögerung, wahrscheinlich überflüssig
b_setH(CONT_PORT,CONT_E);
_delay_us(45);
b_setL(CONT_PORT,CONT_E);
_delay_ms(10); // um Befehl auszuführen, wahrscheinlch viel zu lang
}
void lcd_init(void){
lcd_send(0x34,0); // 8-Bit Datenlänge
lcd_send(0x09,0); // 4 Zeilen Modus
lcd_send(0x0F,0); // Display on, Cursor on, Blink on
lcd_send(0x01,0); // Display löschen, Cursor 1. Spalte, 1. Zeile;
}
void lcd_writeC(uint8_t c, uint8_t z, uint8_t s) //c: char, z: Zeile., s: Spalte
{
lcd_send(c,1);
}
// testing ---------------------------------------------------------------------
int main(void)
{
init();
lcd_init();
lcd_send('a',1);
return 0;
}
Für die, die es noch intressiert, die bit.h
#ifndef BIT_H_
#define BIT_H_
// bit.h -----------------------------------------------------------------------
// n ist immer die Bit-Position von Rechts gezählt im Intervall [0..7]
#define b_maske(n) (1 << n) // generiert Make mit 1 bei n
#define b_ifset(b,n) (b & (1 << n) // liefert true wenn n true, sonst false
#define b_setH(b,n) b |= (1 << n) // setzt n auf 1
#define b_setL(b,n) b &= ~(1 << n) // setzt n auf 0
#define b_inv(b,n) b ^= (1 << n) // invertiert n (1->0, 0->1)
// setzt r auf a jedoch mit dem bit n von b als bit n von r
#define b_qset(a,b,n) (a = (b & (1 << n)) | (a & ~(1 << n))) //n = k
// setzt r auf a jedoch mit dem bit k von b als das bit n von r
#define b_qsetL(a,b,n,k) ((b << (n-k)) & (1 << n)) | (a & ~(1 << n)) // n > k
#define b_qsetR(a,b,n,k) ((b >> (k-n)) & (1 << n)) | (a & ~(1 << n)) // k > n
// rotiert a um ein bit
#define b_rotL(a) b_qsetR((a << 1),a,0,7)
#define b_rotR(a) b_qsetL((a >> 1),a,7,0)
// EOF -------------------------------------------------------------------------
#endif /*BIT_H_*/
Die delay-Funktionen habe ich aus der AVR-Lib-C kopiert.
Die Initialisierung habe ich aus dem Datenblatt des Displays abgeschrieben, ich hoffe die stimmt.
Leider sehe ich auf dem Display überhautp nichts. An der Kontrastspannung liget es nicht, das habe ich überprüft.
Hat jemand eine Idee, wieso, dass das nicht funktioniert?
Vielen Dank für eure Hilfe!
Grüsse cumi[/b]
Ich krieg es einfach nicht hin, mein LCD anzusteuern. Überall wird geschrieben, dass sei eigentlich nicht so ein Problem, aber bei mir klappts nicht :(
Also das Ganze sieht so aus: Ich habe ein 4x20Zeichen Display. Also 4 Zeilen mit je 20 Zeichen.
Das Datenblatt könnt ihr hier (http://www.shop.robotikhardware.de/shop/catalog/product_info.php?cPath=66&products_id=80) herunterladen.
Ich möchte es im 8-Bit Modus ansteuern. Dann brauche ich das Byte nicht zu zerlegen und für den Moment habe ich genug Ports.
Ich habe das Display folgendermassen mit dem RN-Control verkabelt:
RS auf PORTB, Pin 0
R/W habe ich, da ich nur schreiben möchte auf VSS gelegt (richtig so, oder?)
E auf PORTB, Pin 2
D0-D7 auf PORTC
Dazu erstmal eine Frage. Funktioniert das rein elektronisch? Oder funkt mir da noch irgendwas vom RN-Control rein? Den Motortreiber habe ich entfernt, und alle Jumper rausgezogen.
Mein Code sieht so aus:
b_setH und b_setL ist eine Präprozessordirektiven um ein Bit in einem Byte Hight bzw. Low zu setzten.
Konfiguriert wird das Ding im Haederfile:
m32_lcd.h
#ifndef M32_LCD_H_
#define M32_LCD_H_
// general ---------------------------------------------------------------------
#ifndef F_CPU
#define F_CPU 16000000
#endif
// LCD -------------------------------------------------------------------------
#define CONT_DDR DDRB
#define CONT_PORT PORTB
#define CONT_E 2 // Enable (fallende Flanke)
#define CONT_RS 0 // L:Befehl / H:Daten
#define CONT_RW 1 // H:Read / L:Write
#define DATA_DDR DDRC
#define DATA_PORT PORTC
// EOF -------------------------------------------------------------------------
#endif /*M32_LCD_H_*/
Und hier die Source:
m32_lcd.c
#include <avr/io.h>
#include "m32_lcd.h"
#include "bit.h"
// delay -----------------------------------------------------------------------
void _delay_loop_1(uint8_t __count)
{
__asm__ volatile (
"1: dec %0" "\n\t"
"brne 1b"
: "=r" (__count)
: "0" (__count)
);
}
void _delay_loop_2(uint16_t __count)
{
__asm__ volatile (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__count)
: "0" (__count)
);
}
void _delay_us(double __us)//max: 768us / F_CPU in Mhz
{
uint8_t __ticks;
double __tmp = ((F_CPU) / 3e6) * __us;
if (__tmp < 1.0)
__ticks = 1;
else if (__tmp > 255)
__ticks = 0; // i.e. 256
else
__ticks = (uint8_t)__tmp;
_delay_loop_1(__ticks);
}
void _delay_ms(double __ms) //max: 260ms / F_CPU in Mhz
{
uint16_t __ticks;
double __tmp = ((F_CPU) / 4e3) * __ms;
if (__tmp < 1.0)
__ticks = 1;
else if (__tmp > 65535)
__ticks = 0; // i.e. 65536
else
__ticks = (uint16_t)__tmp;
_delay_loop_2(__ticks);
}
// testing ---------------------------------------------------------------------
void init(void)
{
b_setH(CONT_DDR,CONT_E);
b_setH(CONT_DDR,CONT_RS);
// b_setH(CONT_DDR,CONT_RW);
b_setL(CONT_PORT,CONT_E); // E nicht setzen
b_setL(CONT_PORT,CONT_RS); // RS nicht setzen
// b_setL(CONT_PORT,CONT_RW); // RW nicht setzen
DATA_DDR = 0xff; // Ausgänge
DATA_PORT= 0x00;
}
// lcd -------------------------------------------------------------------------
void lcd_send(uint8_t data, uint8_t rs) //rs: L:Befehl / H:Daten
{
DATA_PORT = data;
if(rs)
b_setH(CONT_PORT,CONT_RS);
else
b_setL(CONT_PORT,CONT_RS);
_delay_us(45); // kurze Verzögerung, wahrscheinlich überflüssig
b_setH(CONT_PORT,CONT_E);
_delay_us(45);
b_setL(CONT_PORT,CONT_E);
_delay_ms(10); // um Befehl auszuführen, wahrscheinlch viel zu lang
}
void lcd_init(void){
lcd_send(0x34,0); // 8-Bit Datenlänge
lcd_send(0x09,0); // 4 Zeilen Modus
lcd_send(0x0F,0); // Display on, Cursor on, Blink on
lcd_send(0x01,0); // Display löschen, Cursor 1. Spalte, 1. Zeile;
}
void lcd_writeC(uint8_t c, uint8_t z, uint8_t s) //c: char, z: Zeile., s: Spalte
{
lcd_send(c,1);
}
// testing ---------------------------------------------------------------------
int main(void)
{
init();
lcd_init();
lcd_send('a',1);
return 0;
}
Für die, die es noch intressiert, die bit.h
#ifndef BIT_H_
#define BIT_H_
// bit.h -----------------------------------------------------------------------
// n ist immer die Bit-Position von Rechts gezählt im Intervall [0..7]
#define b_maske(n) (1 << n) // generiert Make mit 1 bei n
#define b_ifset(b,n) (b & (1 << n) // liefert true wenn n true, sonst false
#define b_setH(b,n) b |= (1 << n) // setzt n auf 1
#define b_setL(b,n) b &= ~(1 << n) // setzt n auf 0
#define b_inv(b,n) b ^= (1 << n) // invertiert n (1->0, 0->1)
// setzt r auf a jedoch mit dem bit n von b als bit n von r
#define b_qset(a,b,n) (a = (b & (1 << n)) | (a & ~(1 << n))) //n = k
// setzt r auf a jedoch mit dem bit k von b als das bit n von r
#define b_qsetL(a,b,n,k) ((b << (n-k)) & (1 << n)) | (a & ~(1 << n)) // n > k
#define b_qsetR(a,b,n,k) ((b >> (k-n)) & (1 << n)) | (a & ~(1 << n)) // k > n
// rotiert a um ein bit
#define b_rotL(a) b_qsetR((a << 1),a,0,7)
#define b_rotR(a) b_qsetL((a >> 1),a,7,0)
// EOF -------------------------------------------------------------------------
#endif /*BIT_H_*/
Die delay-Funktionen habe ich aus der AVR-Lib-C kopiert.
Die Initialisierung habe ich aus dem Datenblatt des Displays abgeschrieben, ich hoffe die stimmt.
Leider sehe ich auf dem Display überhautp nichts. An der Kontrastspannung liget es nicht, das habe ich überprüft.
Hat jemand eine Idee, wieso, dass das nicht funktioniert?
Vielen Dank für eure Hilfe!
Grüsse cumi[/b]