Forum: Mikrocontroller und Digitale Elektronik LCD alternativ anschließen


von Patrick L. (crashdemon)


Lesenswert?

Hallo,

ich habe ein 2x16 Zeichen LCD an einem ATtiny2313 hängen. Damit sich ein 
einfacheres Platinenlayout einstellt habe ich jetzt die Pinbelegung 
alternativ belegt:

PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0
NC  NC  RS  EN  DB4 DB5 DB6 DB7   Jetzt
NC  NC  EN  RS  DB7 DB6 DB5 DB4   Vorher

So brauche ich in Eagle keine Drahtbrücken mehr. Problem sind die genau 
getauschten Datenpins, wie kann man das am elegantesten bewerkstelligen?

von Helfer (Gast)


Lesenswert?

> PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0
> NC  NC  RS  EN  DB4 DB5 DB6 DB7   Jetzt
> NC  NC  EN  RS  DB7 DB6 DB5 DB4   Vorher
                  ^^^^^^^^^^^^^^^

D.h. du musst 4 Bits in Software drehen statt 1:1 den Tutorialcode zu 
übernehmen. Das ist grundsätzlich machbar, aber für Anfänger 
fehlerträchtig.

von Helfer (Gast)


Lesenswert?

Alternative #1: Nimm BASCOM. Dort kannst du die Pinzuordnung beim LCD 
frei konfigurieren.

von Nett gemeint (Gast)


Lesenswert?

Hi
Beschäftige dich doch erst ein mal mit dem Programmieren dann mit dem 
Layout.
Sonst mutiert dein µC als "crashdemon" und du hast probleme und zu viel 
arbeit hinter/vor dir ;)
Grüße

von Patrick L. (crashdemon)


Lesenswert?

> D.h. du musst 4 Bits in Software drehen statt 1:1 den Tutorialcode zu
> übernehmen. Das ist grundsätzlich machbar, aber für Anfänger
> fehlerträchtig.

Hehe, ja. Dachte da an soetwas wie einen Shift

0001
1000

0011
1100

0111
1110

von Patrick L. (crashdemon)


Lesenswert?

Nett gemeint schrieb:
> Hi
> Beschäftige dich doch erst ein mal mit dem Programmieren dann mit dem
> Layout.
> Sonst mutiert dein µC als "crashdemon" und du hast probleme und zu viel
> arbeit hinter/vor dir ;)
> Grüße

Das Programm steht schon, lief früher auf einem Atmega8 auf 
Streifenraster, da es dann mal ein wenig schöner werden sollte, platine 
etc. habe ich es dann auch gleich auf einem ATtiny portiert, der für 
meinen verwendungszweck mehr als ausreichend ist.

von Peter D. (peda)


Lesenswert?

Die Pins füre LCD sind völlig egal, die kannst Du bunt durcheinander 
würfeln Und im h-File legst Du fest, auf welchem Port und Bit jeder 
liegt.

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=102296


Peter

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Patrick Langosch schrieb:
> Dachte da an soetwas wie einen Shift
Das ist garantiert kein Bit-Shift. Beim Schieben bleibt die 
Bitreihenfolge prinzipiell gleich. Was du brauchst, ist ein Bit-Swap...

von Helfer (Gast)


Lesenswert?

Brute Force
1
inline uint8_t swap_nibble(uint8_t in)
2
{
3
  return ((in & (1<<0))<<3) 
4
       | ((in & (1<<1))<<2) 
5
       | ((in & (1<<2))<<1)
6
       | ((in & (1<<3))<<0);
7
}
8
9
// dann 
10
LCD_DATA = (LCD_DATA & 0xF0) | swap_nibble(wert);
11
12
// statt 
13
LCD_DATA = (LCD_DATA & 0xF0) | wert;

von avr (Gast)


Lesenswert?

Hier mal was zum Umdrehn:
1
unsigned char umkehr(unsigned char n){
2
n=((n>>1)&0x55)|((n<<1)&0xaa);
3
n=((n>>2)&0x33)|((n<<2)&0xcc);
4
return (n>>4)|(n<<4);
5
}

Damit machst du aus DB7 DB6 .... DB0
einfach             DB0 DB1 .... DB7

Also alles was gesendet wird umdrehen
und dann High- und Low-Nibble beachten ;)

anr

von Patrick L. (crashdemon)


Lesenswert?

joar, dankeschön werd mal mein Glück versuchen

von holger (Gast)


Lesenswert?

Hier mal was zum Umdrehn:

unsigned char umkehr(unsigned char n){
uint8_t mask, temp;

 mask = 0x01;
 temp = 0;

 do
 {
  if(n & mask) temp |= 0x80;
  mask <<= 1;
  if(mask) temp >>= 1;
 } while(mask);

 return temp;
}

von Peter D. (peda)


Lesenswert?

avr schrieb:
> Hier mal was zum Umdrehn:
1
> unsigned char umkehr(unsigned char n){
2
> n=((n>>1)&0x55)|((n<<1)&0xaa);
3
> n=((n>>2)&0x33)|((n<<2)&0xcc);
4
> return (n>>4)|(n<<4);
5
> }

Wenn man mit Flash nicht sparen muß, kann man es so machen.

Ansonsten besser so:
1
static void lcd_nibble( uint8_t d )
2
{
3
  LCD_D4 = 0; if( d & 1<<4 ) LCD_D4 = 1;
4
  LCD_D5 = 0; if( d & 1<<5 ) LCD_D5 = 1;
5
  LCD_D6 = 0; if( d & 1<<6 ) LCD_D6 = 1;
6
  LCD_D7 = 0; if( d & 1<<7 ) LCD_D7 = 1;
7
8
  LCD_E0 = 1;
9
  _delay_us( 1 );                       // 1us
10
  LCD_E0 = 0;


Peter

von Jürgen W. (juergen_w) Benutzerseite


Lesenswert?

Wenn du den ASCii Code änderst, kannst du dein Code so lassen und die 
Rechenzeit für die Bit -schieberei sparen.


Oder, wenn es nicht allzuviel Text ist einfach als (schon umgewandeltes) 
Hex eingeben.

Ich programmiere zwar ASM, aber in C geht das sicher auch.

von Peter D. (peda)


Lesenswert?

Jürgen W. schrieb:
> Wenn du den ASCii Code änderst, kannst du dein Code so lassen und die
> Rechenzeit für die Bit -schieberei sparen.

Und wenn man kaltes Wasser braucht, stellt man heißes Wasser in den 
Kühlschrank.


Peter

von Fabian (Gast)


Lesenswert?

Alternativ wäre auch eine Look-Up Table. Bei 16Byte ist das noch 
überschaubar.

von Patrick L. (crashdemon)


Lesenswert?

Also irgendwie schein ich da noch eine Bug drin zu haben, zumindest 
zeigt das LCD nur wirres zeugs an. Mit den Änderungen sollte es dann 
doch eig. so aussehen:
1
/******** Befehl an das LCD senden ********/
2
void LCD_command(unsigned char temp1)
3
{
4
  unsigned char temp2 = temp1;
5
 
6
  LCD_PORT &= ~(1 << LCD_RS); // Register Select auf "Transfering Instruction Data" setzen
7
 
8
  temp1 = (temp1 >> 4) & 0x0F; // Oberes Nibble holen + Maskieren
9
  LCD_PORT = (LCD_PORT & 0xF0) | swap_nibble(temp1); // Daten Bits setzen
10
  LCD_enable();
11
 
12
  temp2 = temp2 & 0x0F; // unteres Nibble holen und maskieren
13
  LCD_PORT = (LCD_PORT & 0xF0) | swap_nibble(temp2); // Daten Bits setzen
14
     LCD_enable();
15
   
16
  _delay_us(42);
17
}

mit
1
unsigned char swap_nibble(unsigned char in)
2
{
3
  return((in & (1 << 0)) << 3) | 
4
        ((in & (1 << 1)) << 2) | 
5
        ((in & (1 << 2)) << 1) | 
6
        ((in & (1 << 3)) << 0);
7
}

Die LCD Initialisierung habe ich auch angepasst, die scheint zu 
funktionieren.

von Bernd (Gast)


Lesenswert?

hast du auch bei der Datenausgabe geswapt?

von Patrick L. (crashdemon)


Lesenswert?

jop, deswegen bin ich ja irritiert.
1
/******** Datenbyte an das LCD senden ********/
2
void LCD_data(unsigned char temp1)
3
{
4
  unsigned char temp2 = temp1;
5
 
6
  LCD_PORT |= (1 << LCD_RS); // Register Select auf "Transferring Display Data" setzen
7
 
8
  temp1 = temp1 >> 4;
9
  temp1 = temp1 & 0x0F;
10
  LCD_PORT = (LCD_PORT & 0xF0) | swap_nibble(temp1); // Daten Bits setzen
11
     
12
  LCD_enable();
13
14
  temp2 = temp2 & 0x0F;
15
  LCD_PORT = (LCD_PORT & 0xF0) | swap_nibble(temp2); // Daten Bits setzen
16
     
17
  LCD_enable();
18
   
19
  _delay_us(42);
20
}

von Helfer (Gast)


Lesenswert?

Wenn du mit AVR-GCC-Tutorial/LCD-Ansteuerung arbeitest, bietet sich 
an, die Änderung zentral in lcd_out() zu machen, statt mehrfach in 
LCD_init, LCD_command und LCD_data.

von Helfer (Gast)


Lesenswert?

Der Swapcode ist ja auch falsch. Passt den niemand mehr auf?
1
unsigned char swap_nibble(unsigned char in)
2
{
3
  return((in & (1 << 0)) << 3) | // 0001 => 1000
4
        ((in & (1 << 1)) << 1) | // 0010 => 0100
5
        ((in & (1 << 2)) >> 1) | // 0100 => 0010
6
        ((in & (1 << 3)) >> 3);  // 1000 => 0001
7
}

von Patrick L. (crashdemon)


Lesenswert?

Helfer schrieb:
> Der Swapcode ist ja auch falsch. Passt den niemand mehr auf?

tatsache, jetzt fluppt es

von Vuvuzelatus (Gast)


Lesenswert?

>Alternativ wäre auch eine Look-Up Table. Bei 16Byte ist das noch
>überschaubar.

Keep it simple and stupid :-) Warum blos müssen die Leute für so nen 
Kiki immer gleich nen Code bauen, obwohl es ein kleines Konstantenarray 
kurz und schmerzlos erledigen würde?

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
Noch kein Account? Hier anmelden.