Forum: Mikrocontroller und Digitale Elektronik AVR-ASM Knobelei : Bitmanipulation am LCD im 4-Bit Mode


von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

Hallo zusammen,

habe da etwas zum Knobeln in einem AVR-Assemblerprogramm.

Also ein HD44780 kompatibles LCD im 4-Bit Mode erwartet ja D7-D4,
also das High-Nibble und danach das Low-Nibble D3-D0. Allerdings dieses 
Low-Nibble auch wieder an der High-Nibble Position P7-P4. Man würde 
also mit dem SWAP-Befehl um die Bits D3-D0 zu senden, einfach das 
Low-Nibble und High-Nibble tauschen und die Sache wäre erledigt.
Nun habe ich jedoch auf Grund eines vorgegebenen Layouts, das sich die 
Datenbits D7-D4 an den Portbits so anliegen müssen.

P7 P6 P5 P4  P3 P2 P1 P0
XX XX D4 D5  D6 D7 XX XX

XX bedeutet diese Bits müssen am Ende unverändert bleiben.

Der Weg der mir einfällt wäre die Bits D7 mit D6 tauschen sowie D5 mit 
D4.

P7 P6 P5 P4  P3 P2 P1 P0
D6 D7 D4 D5  YY YY YY YY

YY bedeutet erstmal irrelevant

Danach müsste das High-Nibble ins Low-Nibble kopiert werden

P7 P6 P5 P4  P3 P2 P1 P0
D6 D7 D4 D5  D6 D7 D4 D5

und hiernach P7, P6, P1, P0 verodert so das diese am Ende halt 
unverändert bleiben.

P7 P6 P5 P4  P3 P2 P1 P0
XX XX D4 D5  D6 D7 XX XX


Nur wie mach ich das in AVR-ASM ?

Der erste Schritt ist hierbei für mich ein riesen Problem.
Nämlich D7 mit D6 tauschen sowie D5 mit D4.

Ich schiebe schon einige Stunden Bits hin und her, rotiere diese, 
tausche die Nibbles, arbeite mit dem T-Flag, aber bekomms einfach nicht 
hin.


Bernd_Stein

von der alte Hanns (Gast)


Lesenswert?

Ist die Frage akademisch oder praktisch gemeint?
Im letzteren Fall biete ich etwas in der Art an:
1
LCDb:   ; byte
2
  push  tmp0
3
  swap  tmp0
4
  rcall  LCDn
5
  pop  tmp0
6
LCDn:  ; nibble
7
  sbi  PORT_LCDen,LCDen
8
  cbi  PORT_LCDd3,LCDd3
9
  sbrc  tmp0,3
10
   sbi  PORT_LCDd3,LCDd3
11
  cbi  PORT_LCDd2,LCDd2
12
  sbrc  tmp0,2
13
   sbi  PORT_LCDd2,LCDd2
14
...
15
...
16
  ret

von spess53 (Gast)


Lesenswert?

Hi

>Ich schiebe schon einige Stunden Bits hin und her, rotiere diese,
>tausche die Nibbles, arbeite mit dem T-Flag, aber bekomms einfach nicht
>hin.

Dann spiegel doch einfach erst mal dein Byte, das du ausgeben willst:

[asm]
; Byte in r16
mirror_fast:          push r17
                      swap r16
                      mov r17,r16

                      lsr r16
                      lsr r16
                      lsl r17
                      lsl r17
                      andi r16,$33
                      andi r17,$CC

                      or r16,r17
                      mov r17,r16

                      lsr r16
                      lsl r17
                      andi r16,$55
                      andi r17,$AA
                      or r16,r17
                      pop r17
                      ret
[/asm]

Und dann schiebst du die Nibble zur Ausgabe an die richtige Stelle.

MfG Spess

von Winfried J. (Firma: Nisch-Aufzüge) (winne) Benutzerseite


Lesenswert?

meine lösung wären 2 Variablen typ Char und 6*ROR



RRR char  'Rotationsregister
PSHADOW char 'Port_Schattenregister


LDA ausgabechar
ROR
ROR
STA RRR
LDA PORTA
AND 0xC3
STA PSHaDOW
LDA RRR
AND 0x3C
OR  PSCHADOW
STA PORTA
LDA RR
ROR
ROR
ROR
ROR
AND 0x3C
OR PSCHADOW
STA PORTA

: Bearbeitet durch User
von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

Das kann doch nicht wahr sein !!!
Drei Lösungen in wenigen Minuten.
Ich Danke Euch erstmal, aber mir raucht der Kopf und ich hoffe morgen 
Zeit für die Analyse zu haben.


Bernd_Stein

von der alte Hanns (Gast)


Angehängte Dateien:

Lesenswert?

Da es anscheinend um eine praktische Frage geht, anbei etwas 
Ausführlicheres.

von c-hater (Gast)


Lesenswert?

Bernd Stein schrieb:

> Also ein HD44780 kompatibles LCD im 4-Bit Mode erwartet ja D7-D4,
> also das High-Nibble und danach das Low-Nibble D3-D0. Allerdings dieses
> Low-Nibble auch wieder an der High-Nibble Position P7-P4. Man würde
> also mit dem SWAP-Befehl um die Bits D3-D0 zu senden, einfach das
> Low-Nibble und High-Nibble tauschen und die Sache wäre erledigt.
> Nun habe ich jedoch auf Grund eines vorgegebenen Layouts, das sich die
> Datenbits D7-D4 an den Portbits so anliegen müssen.
>
> P7 P6 P5 P4  P3 P2 P1 P0
> XX XX D4 D5  D6 D7 XX XX

Welcher grenzdebile Vollidiot hat denn dieses Layout so vorgegeben, wie 
es ungünstiger kaum vorliegen kann (und zwar für praktisch jede 
beliebige Architektur gleich ungünstig)?

Wenn du den Kerl gefunden hast, dann laß' den doch das Problem lösen...

> Ich schiebe schon einige Stunden Bits hin und her, rotiere diese,
> tausche die Nibbles, arbeite mit dem T-Flag, aber bekomms einfach nicht
> hin.

Tja, keine Arme, keine Kekse. Bist du eventuell mit dem Typen verwandt, 
der das Layout vorgegeben hat oder sogar mit ihm identisch? Wundern 
würde mich das nicht...

Wie auch immer: Für jeden, der überhaupt programmieren kann, ist es 
natürlich kein Problem, irgendeine Lösung zu finden. Wer das nicht 
schafft, kann einfach nicht programmieren. Ende der Ansage.

Ein klein wenig anders ist die Lage, wenn nicht irgendeine, sondern die 
schnellstmögliche Lösung gesucht ist. Da wären dann erstmal einige 
Randbedingungen zu klären. Aber wenn man diese mal so vorgibt, daß die 
Quelldaten wie gezeichnet in einem Register vorliegen und wie benötigt 
in einem anderen erscheinen sollen, wäre beim AVR wohl der Weg über das 
T-Flag der schnellste, viermal bst/bld, also acht Takte insgesamt.

von der alte Hanns (Gast)


Lesenswert?

c-hater, liebenswürdig wie immer.

>natürlich kein Problem, irgendeine Lösung zu finden
Genau, das schaffe sogar ich und biete es hier an, ohne Anspruch auf 
Schnelligkeit oder gar Genialität.

von Winfried J. (Firma: Nisch-Aufzüge) (winne) Benutzerseite


Lesenswert?

C-hater Quatschkopf

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@c-hater (Gast)

>> P7 P6 P5 P4  P3 P2 P1 P0
>> XX XX D4 D5  D6 D7 XX XX

>Welcher grenzdebile Vollidiot hat denn dieses Layout so vorgegeben, wie
>es ungünstiger kaum vorliegen kann (und zwar für praktisch jede
>beliebige Architektur gleich ungünstig)?

Was bist du denn für ein Mädchen? Selbst der älteste 8051 kann die paar 
Bits problemlos und nahezu in Null,Nix vertauschen. Aber das lernst du 
auch noch, wenn du mal aus der Programmiererpubertät rausgekommen bist 
und die ASM-Pickel langsam zurück gehen. Dann lernst du auch was über 
Hochsprachen und deren Vorteile ;-)

von der alte Hanns (Gast)


Lesenswert?

Eine dumme Frage, da nun schon der Zweite die Schnelligkeit betont: ist 
diese so wichtig bei einer Ausgabe auf LCD?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

der alte Hanns schrieb:
> Genau, das schaffe sogar ich und biete es hier an, ohne Anspruch auf
> Schnelligkeit oder gar Genialität.

 Gut gemacht, keine Einwände.
 Hatte auch mal so etwas ähnliches, beim ATTiny2313. Danach habe ich
 es verglichen, da der LcdPort auch Steuerleitungen hatte, müßte ich
 Port einlesen, AND Steuerleitungen, OR Dataleitungen - am Ende war es
 mit einzelnen bits viel übersichtlicher.

von Bernd K. (prof7bit)


Lesenswert?

16 byte lookup table?

von Besucher (Gast)


Lesenswert?

Bernd Stein schrieb:
> Nur wie mach ich das in AVR-ASM ?
>
> Der erste Schritt ist hierbei für mich ein riesen Problem.
> Nämlich D7 mit D6 tauschen sowie D5 mit D4.
>
> Ich schiebe schon einige Stunden Bits hin und her, rotiere diese,
> tausche die Nibbles, arbeite mit dem T-Flag, aber bekomms einfach nicht
> hin.

Falls es tatsächlich schnell sein muß: Da böte es sich an, die 
anzuzeigenden Texte gleich mit gespiegelten/rotierten Bitmustern zu 
erzeugen. Für Textkonstanten ist das ja kein Problem, für Ziffern kann 
man sich eine Tabelle anlegen.

von der alte Hanns (Gast)


Lesenswert?

an Marc Veseley

Bei mir war der Ursprung, dass ich für eine temporäre Hilfsanzeige 
'übriggebliebene Pins zusammenklauben' musste, später fand ich es, wie 
Sie, übersichtlicher und blieb generell dabei; nichts mit 'Null,Nix' 
oder 'schnellstmöglich'.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

der alte Hanns schrieb:
> Bei mir war der Ursprung, dass ich für eine temporäre Hilfsanzeige
> 'übriggebliebene Pins zusammenklauben' musste,

 LOL.
 Bei mir auch.

von Peter D. (peda)


Lesenswert?

Da LCD-Ausgaben nicht zeitkritisch sind, habe ich meine Routine so 
geschrieben, daß sie mit beliebigen 6 Pins zurechtkommt.
Auch von verschiedenen Ports, wenn z.B. Pins durch Spezialfunktionen 
(UART, I2C, Timer usw.) belegt sind.

Man kann also völlig problemlos auf das Layout optimieren, auch wenn das 
den ewigen Nörglern nicht gefällt.
1
static void lcd_nibble( uint8_t d )
2
{
3
  LCD_D7 = 0; if( d & 1<<7 ) LCD_D7 = 1;
4
  LCD_D6 = 0; if( d & 1<<6 ) LCD_D6 = 1;
5
  LCD_D5 = 0; if( d & 1<<5 ) LCD_D5 = 1;
6
  LCD_D4 = 0; if( d & 1<<4 ) LCD_D4 = 1;
7
  LCD_E0 = 1;
8
  _delay_us( LCD_TIME_ENA );
9
  LCD_E0 = 0;
10
}
Der C-Compiler übersetzt das sehr effizient in Bitbefehle (CBI, SBI).
1
static void lcd_nibble( uint8_t d )
2
{
3
  LCD_D7 = 0; if( d & 1<<7 ) LCD_D7 = 1;
4
  42:  c5 98         cbi  0x18, 5  ; 24
5
  44:  87 fd         sbrc  r24, 7
6
  46:  c5 9a         sbi  0x18, 5  ; 24
7
  LCD_D6 = 0; if( d & 1<<6 ) LCD_D6 = 1;
8
  48:  c3 98         cbi  0x18, 3  ; 24
9
  4a:  86 fd         sbrc  r24, 6
10
  4c:  c3 9a         sbi  0x18, 3  ; 24
11
  LCD_D5 = 0; if( d & 1<<5 ) LCD_D5 = 1;
12
  4e:  c4 98         cbi  0x18, 4  ; 24
13
  50:  85 fd         sbrc  r24, 5
14
  52:  c4 9a         sbi  0x18, 4  ; 24
15
  LCD_D4 = 0; if( d & 1<<4 ) LCD_D4 = 1;
16
  54:  c0 98         cbi  0x18, 0  ; 24
17
  56:  84 fd         sbrc  r24, 4
18
  58:  c0 9a         sbi  0x18, 0  ; 24
19
  LCD_E0 = 1;
20
  5a:  c1 9a         sbi  0x18, 1  ; 24
21
  5c:  82 e0         ldi  r24, 0x02  ; 2
22
  5e:  8a 95         dec  r24
23
  60:  f1 f7         brne  .-4  ; 0x5e <lcd_nibble+0x1c>
24
  _delay_us( LCD_TIME_ENA );
25
  LCD_E0 = 0;
26
  62:  c1 98         cbi  0x18, 1  ; 24
27
}
28
  64:  08 95         ret

von Winfried J. (Firma: Nisch-Aufzüge) (winne) Benutzerseite


Lesenswert?

EDIT (sorry ich habe schon ein Weile nichts mehr in AVR ASM gemacht, 
weshalb die mnemonics durchgewürfelt mit anderen ASM...

das prinzip bleibt



meine lösung wären 3 register ( r25, r26, r26  statt variablen und akku 
) und 7*ROR (ROR durch carry läuft)


r26               'Rotationsregister
r25               'maskiertes Port_Schattenregister
r1                'hilfsregister für verknüpung des ersten nibbels

CLC               'der ordnung halber
IN r25,PORTA      'port einlesen
ANDI r25,0xC3     'maskieren
LD r26,x+         'auszugebender char ausspeicherholen
ROR r26           'rotieren
ROR r26
ST r1,r26         'ins zwischenregister copieren
ANDI r1,0x3C      'dort maskieren
OR  r1,r25        'verknüpfen mit maskierten portschattenregister
OUT PORTA,r1      'ausgeben
ROR r26           'rotiern
ROR r26           'rotiern
ROR r26           'rotiern
ROR r26           'rotiern
ROR r26           'rotiern und noch einmal fürs carry
CLC               'der ordnung halber
ANDI r26,0x3C     'kann glleich hier maskiert werden
OR r26,r25        'mit maskierten portschattenregister verknüpft
OUT PORTA,r26     'das kennst du schon

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Peter Dannegger schrieb:
> LCD_D7 = 0; if( d & 1<<7 ) LCD_D7 = 1;

Winfried J. schrieb:
> ROR r26           'rotiern und noch einmal fürs carry
> CLC               'der ordnung halber
> ANDI r26,0x3C     'kann glleich hier maskiert werden
> OR r26,r25        'mit maskierten portschattenregister verknüpft

 LOL.
 Und wenn die PORTS/PINS für LCD geändert werden ?

 ASM .equ = DefLCD.h
 Viel übersichtlicher, keine fummelei mit shift (Constant),
 ANDI mit Constant...

Peter Dannegger schrieb:
> LCD_D7 = 0; if( d & 1<<7 ) LCD_D7 = 1;
>   42:  c5 98         cbi  0x18, 5  ; 24
>   44:  87 fd         sbrc  r24, 7
>   46:  c5 9a         sbi  0x18, 5  ; 24

 Nur dass Databit 7 auf Portbit 3 geht.

: Bearbeitet durch User
von Winfried J. (Firma: Nisch-Aufzüge) (winne) Benutzerseite


Lesenswert?

Marc Vesely schrieb:
> Peter Dannegger schrieb:
>> LCD_D7 = 0; if( d & 1<<7 ) LCD_D7 = 1;
>
> Winfried J. schrieb:
>> ROR r26           'rotiern und noch einmal fürs carry
>> CLC               'der ordnung halber
>> ANDI r26,0x3C     'kann glleich hier maskiert werden
>> OR r26,r25        'mit maskierten portschattenregister verknüpft
>
>  LOL.
>  Und wenn die PORTS/PINS für LCD geändert werden ?
>
>  ASM .equ = DefLCD.h
>  Viel übersichtlicher, keine fummelei mit shift (Constant),
>  ANDI mit Constant...

erst lesen dann posten !

Bernd Stein schrieb:
> Nun habe ich jedoch auf Grund eines vorgegebenen Layouts, das sich die
> Datenbits D7-D4 an den Portbits so anliegen müssen.
>
> P7 P6 P5 P4  P3 P2 P1 P0
> XX XX D4 D5  D6 D7 XX XX

Dies ist nur ein Q&D-Vorschlag für diese spezielle Problem
wer ASM popelt baut kein universaleierlegendes Wollmilchvieh
Wer C nimmt (ich auch)  schaut nur noch selten was der Compiler 
produziert, obwohl das leh(h-/e+)rreich sein kann ;)

Natürlich kann man auch Einzelbits testen und manipulieren.
Ob das weniger Takte oder Flash benötigt ist aber noch nicht ausgemacht.

Weil: acht Bittest, acht bedingte Verzweigungen und acht 
Bitmanipulationen
da lohnt sich schon fast eine loop.

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Marc Vesely schrieb:
>
> Peter Dannegger schrieb:
>> LCD_D7 = 0; if( d & 1<<7 ) LCD_D7 = 1;
>>   42:  c5 98         cbi  0x18, 5  ; 24
>>   44:  87 fd         sbrc  r24, 7
>>   46:  c5 9a         sbi  0x18, 5  ; 24
>
>  Nur dass Databit 7 auf Portbit 3 geht.

 Sollte Portbit 2 heissen. Auch deswegen ist ein #define oder .equ
 nützlich.


Winfried J. schrieb:
> weil acht bittest , acht bedingte verzweigungen und acht bit
> manipulationen
> da lohnt sich schon fast eine loop

 Es werden keine 8 bits gesendet, sondern 2 Nibbles.
 Und deine Lösung ist keine Lösung, sondern zusammengewürfelltes
 Unsinn.
1
> ST r1,r26         'ins zwischenregister copieren
2
> ANDI r1,0x3C      'dort maskieren

 ST als Befehl existiert beim AVR nicht.
 r1 und ANDI passen schon mal nicht zusammen.

Winfried J. schrieb:
> ROR r26           'rotiern und noch einmal fürs carry
> CLC               'der ordnung halber

 Warum ?

Winfried J. schrieb:
> erst lesen dann posten !

 Erst lernen, dann posten !

: Bearbeitet durch User
von Winfried J. (Firma: Nisch-Aufzüge) (winne) Benutzerseite


Lesenswert?

http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_STD.html

weil ROR durchs carry lauft und sonst ein bit verloren geht

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Winfried J. schrieb:
> weil ROR durchs carry lauft und sonst ein bit verloren geht

 Nein, warum CLC vor ANDI ?

von spess53 (Gast)


Lesenswert?

Hi

Mal ehrlich, der TO hat sich 21:09 für heute verabschiedet. Anscheinend 
dient das Forum für einige eher zur Selbstdarstellungen.

MfG Spess

von Winfried J. (Firma: Nisch-Aufzüge) (winne) Benutzerseite


Lesenswert?

lediglich um ein leeres carryflag zu hinterlassen wenn die procedur 
beendet ist . ANDI hat keinen einfluss aufs carry ebenso wir or und out.
Daher ist egal wann du aufräumst nicht aber ob du es tust du kannst 
natürlich auch noch 2 mal rotiren und auf clc ganz verzichten dann ist 
alles beim alten.

Wie gesagt eine möglichkeit.
sollten noch Kinken drinn sein kann man das beheben. Ich wollte nur ein 
prinzipeillen Lösungsansatz bieten, für genau diese konstellation. Siehe 
oben.
Ich selbst tendiere dazu einen Port fürs LCD zu reservieren. Dann brauch 
ich nur zu definieren welchen. Da aber die HW Funktionalität der IO/Pins 
nicht unendlich flexibel ist... und  Layout meist vor der SW entwickelt 
wird, kann man wie der TO gebunden werden, sein, oder sich selbst binden 
und muss dann ....
 Wer hingegen wie Peter seit Jahren HW und SW entwickelt ist natürlich 
eingeschossen und hat bewährte Konzepte. ;)

Namaste

von Winfried J. (Firma: Nisch-Aufzüge) (winne) Benutzerseite


Lesenswert?

spess53 schrieb:
> Hi
>
> Mal ehrlich, der TO hat sich 21:09 für heute verabschiedet. Anscheinend
> dient das Forum für einige eher zur Selbstdarstellungen.
>
> MfG Spess

war keine absicht, wollte nur meinen Schuss aus der hüfte aufräumen, 
aber warum nicht ... drüber reden?

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Marc Vesely schrieb:
> Peter Dannegger schrieb:
>> LCD_D7 = 0; if( d & 1<<7 ) LCD_D7 = 1;
>>   42:  c5 98         cbi  0x18, 5  ; 24
>>   44:  87 fd         sbrc  r24, 7
>>   46:  c5 9a         sbi  0x18, 5  ; 24
>
>  Nur dass Databit 7 auf Portbit 3 geht.

Das Listing entspricht dem Schaltplan, wie ich den Code mal verwendet 
habe.
Die Definitionen LCD_D7 .. LCD_D4 muß natürlich jeder an seine Schaltung 
anpassen.
Ich wollte damit nur das Prinzip verdeutlichen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Wenn es nicht glichtfrei sein muß, kann man den Code von Peter nehmen.

Wenn Glitches vermieden werden müssen, dann:
 
1
unsigned char D, P;
2
3
void bits (void)
4
{
5
    // P7 P6 P5 P4  P3 P2 P1 P0
6
    // XX XX D4 D5  D6 D7 XX XX
7
    P = __builtin_avr_insert_bits (0xff4567ff, D, P);
8
}

Man kann die gewünschte Umsortierung also direkt eintippseln und avr-gcc 
kümmert sich um den Rest:
 
1
bits:
2
  lds r24,D
3
  lds r25,P
4
5
  bst r24,4
6
  bld r25,5
7
  bst r24,5
8
  bld r25,4
9
  bst r24,6
10
  bld r25,3
11
  bst r24,7
12
  bld r25,2
13
14
  sts P,r25
15
  ret

Hätt man auch selber drauf kommen können. jaja, nachher ist man immer 
schlauer ;-)

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Peter Dannegger schrieb:
> Die Definitionen LCD_D7 .. LCD_D4 muß natürlich jeder an seine Schaltung
> anpassen.
> Ich wollte damit nur das Prinzip verdeutlichen.
 Nichts dagegen anzuwenden, ich habe mich beim PortPin auch vertippt,
 deswegen ist .h Datei oder .equ viel besser - was ja dein Schnipsel
 auch tut - aber auch der vom alten Hanns.
 Nur eine Frage des Geschmacks - ASM oder C.


Johann L. schrieb:
> Wenn es nicht glichtfrei sein muß, kann man den Code von Peter nehmen.

> Wenn Glitches vermieden werden müssen, dann:
 Glitches von 2us Dauer ?
 Beim LCD ?

Johann L. schrieb:
1
bits:
2
...
3
...
4
  bld r25,3
5
  bst r24,7
6
  bld r25,2
7
8
  sts P,r25
9
  ret
>
> Hätt man auch selber drauf kommen können. jaja, nachher ist man immer
> schlauer ;-)

 Auweia.
 No comment.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Marc Vesely schrieb:

>> Wenn Glitches vermieden werden müssen, dann:
>  Glitches von 2us Dauer ?
>  Beim LCD ?

Nicht nur. Denk mal über den Tellerrand hinaus. DAC zum Beispiel

> Johann L. schrieb:
1
...
2
    P = __builtin_avr_insert_bits (0xff4567ff, D, P);
3
...

das ist ja mal geil. Sollte ich im Hinterstübchen halten.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Karl Heinz schrieb:
>>> Wenn Glitches vermieden werden müssen, dann:
>>  Glitches von 2us Dauer ?
>>  Beim LCD ?
>
> Nicht nur. Denk mal über den Tellerrand hinaus. DAC zum Beispiel
 Ich kann mir viele Beispiele ausdenken, wo 2us Glitches störend sind,
 aber nicht bei der LCD-Ausgabe.

Karl Heinz schrieb:
> P = __builtin_avr_insert_bits (0xff4567ff, D, P);
> ...
>
> das ist ja mal geil. Sollte ich im Hinterstübchen halten.
 Hehe.
 Das kannte ich schon, war in irgendeinem Forum schon vor 2 Jahren
 oder so.
 Kann sicher nützlich sein, mein No comment war wegen Bit Nummerierung
 und  späterer Änderung.

von Peter D. (peda)


Lesenswert?

Johann L. schrieb:
> P = __builtin_avr_insert_bits (0xff4567ff, D, P);

Mit welchem Compiler soll das denn gehen?
1
D:\AVR-C\Test1/main.c:12: undefined reference to `__builtin_avr_insert_bits'

von Karl H. (kbuchegg)


Lesenswert?

Zumindest beim GCC 4.7.1 ist es in der Doku drinnen.
https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/AVR-Built_002din-Functions.html

Ob das frühere Versionen auch können, weiss ich nicht.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

AVR-spezifische built-in Funktionen hat's seit 4.7, siehe 4.7 Release 
Notes:

http://gcc.gnu.org/gcc-4.7/changes.html

"New Targets and Target Specific Improvements" -> "AVR"

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Angehängte Dateien:

Lesenswert?

spess53 schrieb:
> Dann spiegel doch einfach erst mal dein Byte, das du ausgeben willst:
>
Was genau ist spiegeln ?
Kopieren ?
Also r16 auf den Stack legen ?

1
.nolist
2
.include "m8def.inc"     ;ATmega8 Labelzuweisungen 
3
.list;
4
;
5
;Stackpointer initialisieren
6
;
7
  ldi   r16, low (ramend)
8
        ldi   r17, high(ramend)
9
        out   spl, r16
10
        out   sph, r17                        
11
12
  ldi   r16,0b01011010  ;Anfangswert 
13
14
15
; Byte in r16
16
mirror_fast:
17
          push r16
18
    swap r16
19
          mov r17,r16
20
          lsr r16
21
          lsr r16
22
          lsl r17
23
          lsl r17
24
          andi r16,$33
25
          andi r17,$CC
26
          or r16,r17
27
          mov r17,r16
28
          lsr r16
29
          lsl r17
30
          andi r16,$55
31
          andi r17,$AA
32
;geaenderter bzw. erweiterter Teil
33
  or   r17,r16
34
  lsl  r17
35
  lsl  r17
36
  andi r17,$3C
37
        pop  r16
38
  andi r16,$C3
39
  or   r16,r17        
40
41
          ret
>
> Und dann schiebst du die Nibble zur Ausgabe an die richtige Stelle.
>
Es war zwar noch ein bischen mehr zu machen, aber laut Simulator und 
vergleich mit Papier und Bleistift scheint es zu funktionieren.
Danke.

@der alte Hanns
Du hast zwar zuerst gepostet aber dieser Code sah erstmal überschaubarer 
aus. Es ist wiklich eine praktische Umsetzung eines vorgegebenen 
Layouts, aber das weißt Du jetzt sicherlich schon. Werde mich evtl. 
gleich noch motivieren Deinen angehangenen Code durch zu arbeiten.
Danke.

@Winfried J.
Auch Dir danke ich und werde wohl erst übermorgen dazu kommen Deinen 
Code zu testen.

Ich sehe grad das der Code trotz Korretur immer noch nicht sauber 
formatiert ist. Habe diesen direkt aus dem AVR-Studio kopiert und dann 
die Stellen formatiert, die jetzt immer noch aus der Reihe tanzen.


Bernd_Stein

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Angehängte Dateien:

Lesenswert?

Bernd Stein schrieb:
> Ich sehe grad das der Code trotz Korretur immer noch nicht sauber
> formatiert ist. Habe diesen direkt aus dem AVR-Studio kopiert und dann
> die Stellen formatiert, die jetzt immer noch aus der Reihe tanzen.
>
Habe mich ein wenig erinnert.
Also im AVR-Studio unter Edit => Show Whitespace, kann man gut sehen ob 
die Tabs mit Leerzeichen ausgefüllt werden oder nicht ( .... ) bzw. ( >> 
>> ).

Um die Tabs mit Leerzeichen zu füllen muß unter Tools => Options => 
Editor das Häkchen bei Replace tabs with space gesetzt werden.
Leider wirkt sich das nicht sofort aus, so das das AVR-Studio erst 
geschlossen und wieder geöffnet werden muss.


Bernd_Stein

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Bernd Stein schrieb:
> Was genau ist spiegeln ?
>
>
1
> ; Byte in r16
2
> mirror_fast:
3
>           push r16
4
>     swap r16
5
>           mov r17,r16
6
>           lsr r16
7
>           lsr r16
8
>           lsl r17
9
>           lsl r17
10
>           andi r16,$33
11
>           andi r17,$CC
12
>           or r16,r17
13
>           mov r17,r16
14
>           lsr r16
15
>           lsl r17
16
>           andi r16,$55
17
>           andi r17,$AA
18
> ;geaenderter bzw. erweiterter Teil
19
>   or   r17,r16
20
>   lsl  r17
21
>   lsl  r17
22
>   andi r17,$3C
23
>         pop  r16
24
>   andi r16,$C3
25
>   or   r16,r17
26
>           ret
27
>

Oder so:
 
1
uint8_t mirror_faster (uint8_t val)
2
{
3
    return __builtin_avr_insert_bits (0x01234567, val, 0);
4
}

-->
 
1
mirror_faster:
2
  lsl r24
3
  adc r24,__zero_reg__
4
  mov __tmp_reg__,r24
5
  bst r0,1
6
  bld r24,7
7
  bst r0,2
8
  bld r24,6
9
  bst r0,3
10
  bld r24,5
11
  bst r0,5
12
  bld r24,3
13
  bst r0,6
14
  bld r24,2
15
  bst r0,7
16
  bld r24,1
17
  ret
 
:-P
 
Geht übrigens noch schneller weil man mirror_faster() im Gegensatz zu 
einer Assemblerfunktion inlinen kann.

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

Johann L. schrieb:
> Bernd Stein schrieb:
>> Was genau ist spiegeln ?
>>
Weiß ich jetzt immer noch nicht genau.
Bitte kein C oder andere Programmiersprachen, davon habe ich keine 
Ahnung und das wird mir dann zu krüptisch, deshalb auch im Titel :

*AVR-ASM...*

Was soll zero_reg_ sein ?
Ein Register mit Inhalt Null ?

Warum und wo wird _tmp_reg_ noch benutzt ?

> Oder so:
>  uint8_t mirror_faster (uint8_t val)
> {
>     return __builtin_avr_insert_bits (0x01234567, val, 0);
> }
>
> -->
>  mirror_faster:
>   lsl r24
>   adc r24,__zero_reg__
>   mov _tmp_reg_,r24
>   bst r0,1
>   bld r24,7
>   bst r0,2
>   bld r24,6
>   bst r0,3
>   bld r24,5
>   bst r0,5
>   bld r24,3
>   bst r0,6
>   bld r24,2
>   bst r0,7
>   bld r24,1
>   ret
>
> :-P
>
> Geht übrigens noch schneller weil man mirror_faster() im Gegensatz zu
> einer Assemblerfunktion inlinen kann.
>
Was bedeutet inlinen ?
Tut mir leid. Dein Beispiel ist mir zu undurchsichtig.
Ich übe mich noch in AVR-ASM ;-)


Bernd_Stein

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Bernd Stein schrieb:
> Was bedeutet inlinen ?
> Tut mir leid. Dein Beispiel ist mir zu undurchsichtig.
> Ich übe mich noch in AVR-ASM ;-)

 Ja, dann probiere es mal mit ASM von der alte Hanns, wenn du schon
 kein C willst, ansonsten ist Schnippsel von PeDa genauso klar.
 Bei einem so verdrehtem Layout wie deinem, schiebt man nicht rum,
 sondern setzt mit .EQU Anweisungen welches Datenbit auf welches
 Portbit geht. Dann werden die bits in der Ausgaberoutine einzeln
 gesetzt und fertig.
 Eventuell kann man vorher mit einer Maske die Databits ausblenden,
 Databits einzeln setzen und dann das Ganze auf einmal zum Port
 schicken (um eventuelle Glitches zu vermeiden). ;-D
 Etwa so:
1
;* (c) Copyleft by der alte Hanns
2
;*     All Wrongs reserved by ich
3
.include  "m88def.inc"
4
;*** Benutzte Ports
5
.equ  DDR_LCD  = DDRB
6
.equ  PORT_LCD  = PORTB
7
8
;*** Kontrollbits
9
.equ  LCDrs  = 0
10
.equ  LCDen  = 1
11
.equ  SteuerMask = 0xC3
12
13
;*** Databits
14
.equ  LCDd3    = 2
15
.equ  LCDd2    = 3
16
.equ  LCDd1    = 4
17
.equ  LCDd0    = 5
18
19
;*** Arbeitsregister
20
.def  tmp0  = r16
21
.def  tmp1  = r17
22
23
TstLCD:
24
;*** DataPins als Ausgang
25
    ldi  tmp0, 1<<LCDd3 | 1<<LCDd2 | 1<<LCDd1 | 1<<LCDd0
26
;*** KontrollPins als Ausgang
27
    ori  tmp0, 1<<LCDrs | 1<<LCDen
28
    out  DDR_LCD, tmp0
29
30
;*** Loop zum testen
31
T_1:
32
    ldi  tmp0, 0x53
33
    rcall  LCD_Datbyt
34
    rjmp  T_1
35
36
;****  Ausgaberoutine (KontrollByte)
37
LCD_Ctrlbyt:
38
    cbi  PORT_LCD, LCDrs
39
    rjmp  LCDb
40
;****  Ausgaberoutine (DataByte)
41
LCD_Datbyt:
42
    sbi  PORT_LCD, LCDrs
43
LCDb:
44
    push  tmp0
45
    swap  tmp0
46
    rcall  LCDn
47
    pop  tmp0
48
;****  Ausgaberoutine (Nibble)
49
LCDn:
50
    in  tmp1, PORT_LCD
51
;* Kontrollbits ausblenden
52
    andi  tmp1, SteuerMask
53
;* Und bit fur bit prufen...
54
    sbrc  tmp0, 3
55
    sbr  tmp1, 1<<LCDd3
56
    sbrc  tmp0, 2
57
    sbr  tmp1, 1<<LCDd2
58
    sbrc  tmp0, 1
59
    sbr  tmp1, 1<<LCDd1
60
    sbrc  tmp0, 0
61
    sbr  tmp1, 1<<LCDd0
62
;* ENABLE auf 1
63
    sbr  tmp1, 1<<LCDen
64
    out  PORT_LCD, tmp1
65
;* min. 250ns fur ENABLE, wenn ich mich recht erinnere
66
    nop
67
    nop
68
;* ENABLE wieder auf Null
69
    cbi  PORT_LCD, LCDen
70
  ret

 Nichts mit spiegeln, schieben und sonstigem. Sollte sich dein Layout
 (zum Besseren) ändern, einfach nur die paar .EQU Anweisungen
 entsprechenden ändern.

von der alte Hanns (Gast)


Lesenswert?

disclaimer: none. Sue me.

von der alte Hanns (Gast)


Lesenswert?

Etwas vom alten Hiddigeigei, ist auch mein letzter Beitrag, versprochen:

Von des Turmes höchster Spitze
Schau' ich in die Welt herein,
Schaue auf erhab'nem Sitze
In das Treiben der Partein.

Und die Katzenaugen sehen,
Und die Katzenseele lacht,
Wie das Völklein der Pygmäen
Unten dumme Sachen macht.

Doch was nützt's? ich kann den Haufen
Nicht auf meinen Standpunkt ziehn,
Und so laß ich ihn denn laufen,
's ist wahrhaft nicht schad' um ihn.

Menschentun ist ein Verkehrtes,
Menschentun ist Ach und Krach;
Im Bewußtsein seines Wertes
Sitzt der Kater auf dem Dach! –

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Angehängte Dateien:

Lesenswert?

Danke nochmal an alle die hier sinnvoll mitgewirkt haben.
Die Methode von Johann L. gefällt mir am besten.
1
.nolist
2
.include "m8def.inc"        ;ATmega8 Labelzuweisungen 
3
.list;
4
;Stackpointer initialisieren
5
;
6
    ldi  r16, low (ramend)
7
    ldi  r17, high(ramend)
8
    out  spl, r16
9
    out  sph, r17                        
10
11
    ldi  r18,0b01011010  ;Wert ( $5A )
12
    in   r16,pind       ;Portzustand kopieren
13
    seh                 ;High-Nibble FLAG setzen (HalfCarryFlag missbraucht)
14
lcdo20:;Bits auf jeweiligen Portpinnen verdrahten
15
    bst  r18,7          ;Bit7 an... 
16
    bld  r16,2          ;...Portpin 2
17
    bst  r18,6          ;Bit6 an...
18
    bld  r16,3          ;...Portpin 3
19
    bst  r18,5          ;Bit5 an...
20
    bld  r16,4          ;...Portpin 4
21
    bst  r18,4          ;Bit4 an...
22
    bld  r16,5          ;...Portpin 5
23
    out  portd,r16      ;Daten/Befehlsbyte ausgeben
24
    sbi  portd,6        ;E auf High setzen
25
    cbi  portd,6        ;E wieder auf Low setzen
26
    brhc lcdo20_exit    ;Low-Nibble gesendet, dann fertig
27
    clh                 ;High-Nibble Flag loeschen und nun Low-Nibble...
28
    swap r18            ;...bearbeiten und dazu eben noch mal...
29
    brhc lcdo20         ;...die Schleife durchlaufen
30
lcdo20_exit:
31
    ret

Bernd_Stein

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Bernd Stein schrieb:
> Die Methode von Johann L. gefällt mir am besten.

 LOL.
 Ich hoffe, ihr beide lernt es noch zu lebzeiten.
 Und wenn das funktionieren sollte, erschiesse ich mich öffentlich.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Marc Vesely schrieb:
> LOL.
 Will meinen Beitrag nicht löschen, aber damit es nicht
 ohne Begründung bleibt und weil du sagst, dass du
 neu in Assembler bist:


Marc Vesely schrieb:
> Ich hoffe, ihr beide lernt es noch zu lebzeiten.

 Warum dein Programm nicht gut ist:
  a) Was glaubst du, warum es in C .h Datei gibt und wozu
     .equ in Assembler dient ?
     (auch Assembler kennt .h oder .inc Dateien).
  b) Dieses direktes setzen mit
       bst  r18,7          ;Bit7 an...
       bld  r16,2          ;...Portpin 2
     ist somit auch schlecht, sobald da irgendein Pin geändert
     werden soll, wirst du dir die Haare vom Kopf fressen.
     Und man ändert nicht etwas mitten im Programm wenn es
     am Anfang oder in einer besonderer Datei übersichtlicher
     definiert werden kann. Sollte dein Programm mit der Zeit
     größer werden, wirst du die entsprechende Zeile Nr.10047
     kaum finden oder einfach übersehen.
  c) der alte Hanns, PeDa und ich senden dir etwas das
     einfach geändert und angepasst werden kann, aber du
     hältst an den (so nicht funktionierenden) Zeilen
     von Johann L. fest.
     Wobei ich nicht sagen will, dass die Methode mit
     bld und bst schlechter ist, nur mag ich persönlich
     einfach nicht mit T-Flag rumspielen - Compiler benutzen
     T-Flag manchmal, auch sind die beiden Befehlsabkürzungen,
     zumindest für mich, unlogisch.
     .
  d) Etwas zweimal (unnötig) setzen und rücksetzen, zweimal etwas
     (unnötig) abfragen, anstatt einfach die entsprechende Routine
     aufzurufen und dann durchzufallen ist auch schlecht.
     Man muß nicht etwas das funktioniert und gut ist, mit
     Gewalt ändern und schlechter machen, nur um zu sagen:
     - Ich habe das selbst geschrieben.
  e) Programmteile die eine gewisse Aufgabe erfüllen, schreibt
     man als Routinen (Unterprogramme) und versucht nachher
     eine Bibliothek daraus zu machen. Bloßes aneinanderreihen
     von Programmzeilen bringt bestimmt keine Vorteile, das wirst
     du spätestens dann merken, wenn du nach 2-3 Monaten etwas
     in deinem Code ändern oder an einem gemeinsamen Projekt
     teilnehmen willst.


Marc Vesely schrieb:
>  Und wenn das funktionieren sollte, erschiesse ich mich öffentlich.

 Warum dein Programm nicht funktionieren wird:
   a) Weil Enable mindestens 250ns dauern muss, bei dir
      wird das mit 8MHz schon ziemlich knapp und beim LCD ist
      Einhaltung der Mindestzeiten äußerst wichtig. Es gibt keinen
      Befehl der schneller als 35us ist, mit Cursor dauert es
      sogar über 1ms, LCD ist halt langsam, gewöhne dich dran.
      Ich hatte mal ein Graphic Display, da war die Zeit
      zwischen 2 aufeinanderfolgenden Enable min. 1250ns.
   b) Weil RS auf Log.1 für Daten und auf Log.0 für
      Befehl gesetzt werden muss und bei dir sehe ich nicht,
      daß RS auf irgendeinen definierten Pegel gesetzt wird.

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Angehängte Dateien:

Lesenswert?

Marc Vesely schrieb:
> Will meinen Beitrag nicht löschen, aber damit es nicht
>  ohne Begründung bleibt und weil du sagst, dass du
>  neu in Assembler bist:
>
Danke.
Deine Beründungen haben mir etwas die Augen geöffnet. Trotzdem fehlt mir 
der totale Durchblick.

> ;*** Kontrollbits
> .equ  LCDrs  = 0
> .equ  LCDen  = 1
> ;*** KontrollPins als Ausgang
>     ori  tmp0, 1<<LCDrs | 1<<LCDen
>     out  DDR_LCD, tmp0
>
Mit so etwas tue ich mich noch schwer.
In r16 bzw. tmp0 werden da die Bitpositionen 0 und 1 auf 1 gesetzt oder 
nur Bitpositon 1 ( LCDen ) - und Bitposition 0 ( LCDrs ) bleibt erhalten 
?

Also, ich habe in einem für mich riesen Programm einige Änderungen 
vorzunehmen, da einige Pinne durch das Layout anders verdrahtet sind.

Ich bin so vorgegangen, das ich z.B. nach " portb, ddrb, pinb " gesucht 
habe und dann versuche die Programmabschnitte umzuschreiben.

        ALT  NEU
LCD_D7  PB5  PD2
LCD_D6  PB4  PD3
LCD_D5  PB3  PD4
LCD_D4  PB2  PD5

LCD_RS  PC4  PD7
LCE_E   PC5  PD6

Um mal den Programmierstil zu zeigen hier ein Ausschnitt aus dem 
Orginalcode in dem ich zum Zeitpunkt der Threaderstellung feststeckte :
1
;
2
; LCD-Ausgabe eines Zeichens im 4-Bit Mode (Sensormodul2)
3
; Register: r16
4
;           r17 <- 0 = Befehlsbyte, 1 = Datenbyte
5
;           r18 <- LCD-Daten oder -Befehl
6
;
7
lcdout: tst     r17    ;Datenbyte?
8
        brne    lcdo10          ;ja -> weiter
9
        cbi     portc, 4        ;LCD in Befehlsmodus setzen
10
        rjmp    lcdo20
11
lcdo10: sbi     portc, 4        ;LCD in Datenmodus setzen
12
lcdo20: mov     r16, r18        ;Datenbyte kopieren
13
        ror     r18             ;oberes Nibble an die richtige
14
        ror     r18             ;Position schieben
15
        andi    r18, 0x3c       ;Nibble filtern
16
        ori     r18, 0x03       ;Pullup für Al1 und Al2 setzen
17
        out     portb, r18      ;Daten/Befehlsbyte ausgeben
18
        sbi     portc, 5        ;E auf High setzen
19
        cbi     portc, 5        ;E wieder auf Low setzen
20
;
21
        mov     r18, r16        ;Datenbyte kopieren
22
        rol     r18             ;unteres Nibble an die richtige
23
        rol     r18             ;Position schieben
24
        andi    r18, 0x3c       ;Nibble filtern
25
        ori     r18, 0x03       ;Pullup für Al1 und Al2 setzen
26
        out     portb, r18      ;Daten/Befehlsbyte ausgeben
27
        sbi     portc, 5        ;E auf High setzen
28
        cbi     portc, 5        ;E wieder auf Low setzen
29
        ret

Mir ist es auch wichtig, Code so zu schreiben, das er einfach angepasst 
werden kann. Nur muss ich dies erstmal lernen.
Ich hänge mal den gesamten Code an, weil dies für den Einen oder Anderen 
von Vorteil ist, um mein Problem besser zu verstehen.

Hier der Link zu dem wirklich sehr schönen und auch funktionierenden 
Projekt :
Leider kommt man nicht direkt mit diesem Link dort hin. Also es geht um 
das Temperaturmesssystem und dort für mich nun nur um das 
*SENSORMODUL 2/3.* bzw. SENSORMODUL 2.

http://s-huehn.de/elektronik/

Habe das SENSORMODUL2 nochmal gebaut nun aber nicht gefädelt,
sondern mit einem Layout, um es auch für Andere einfach nachbaubar bzw. 
nachbausicherer zu machen.

Bernd_Stein

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Bernd K. schrieb:
> 16 byte lookup table?

Hehehe, ist leider völlig untergegangen, dabei so simpel und an so gut 
wie jede Portkonfiguration einfachst anpassbar. Auch bei mir die 
Standardlösungen auch für exotische ROM Ausführungen des LCD 
Controllers.

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Bernd Stein schrieb:
>>     ldi  tmp0, 1<<LCDd3 | 1<<LCDd2 | 1<<LCDd1 | 1<<LCDd0
>>     ori  tmp0, 1<<LCDrs | 1<<LCDen
>>
> Mit so etwas tue ich mich noch schwer.
> In r16 bzw. tmp0 werden da die Bitpositionen 0 und 1 auf 1 gesetzt oder
> nur Bitpositon 1 ( LCDen ) - und Bitposition 0 ( LCDrs ) bleibt erhalten
> ?
 "|" steht fur OR, somit werden beide Pins auf 1 gesetzt (Ausgang).
 Könnte das alles auch in der ersten Zeile setzen, aber ich wollte es
 dir übersichtlicher machen.


Bernd Stein schrieb:
>         ALT  NEU
> LCD_D7  PB5  PD2
> LCD_D6  PB4  PD3
> LCD_D5  PB3  PD4
> LCD_D4  PB2  PD5
 Auch schlecht, versuche diese 4 Pins entweder im oberen oder unteren
 Nibble zu plazieren. Damit ersparst du dir später unnötige Schieberei.

Bernd Stein schrieb:
> lcdout: tst     r17    ;Datenbyte?
>         brne    lcdo10          ;ja -> weiter
 Auch nicht besonders gut, so etwas sollte man grundsätzlich nicht
 machen. Erstens braucht man nicht ein ganzes Register um so etwas
 abzufragen (vor allem nicht r17, r16-r31 sind kostbar), zweitens
 ist es besser Befehls- und Datenausgabe getrennt aufzurufen, da
 sieht man wenigstens was ausgegeben werden soll.

Bernd Stein schrieb:
> Ich hänge mal den gesamten Code an, weil dies für den Einen oder Anderen
> von Vorteil ist, um mein Problem besser zu verstehen.
 Bin nicht durch diesen Code durch, eben aus der schon genannten 
Gründen:
> (auch Assembler kennt .h oder .inc Dateien).

 Also, die ganzen .equ, #define und Variablen in eine oder zwei
 .inc oder .h Datei packen wäre viel besser. Warum ?
   a) Dein Programm, zumindest die wichtigen Teile davon wird viel
      übersichtlicher.
   b) Solltest du irgendwann mal in irgendeinem Programm noch die
      LCD Ausgabe oder Sensor Abfrage brauchen, ist es einfacher:
        I) Durch 4785 Zeilen Code durchzugehen, die benötigten Zeilen
           mit Copy&Paste ins neue Program ?
       II) Einfach eine Datei mit .include einbinden ?

 EDIT:
 Ich glaub's nicht, dieses Programm hat tatsächlich 4785 Zeilen !

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Marc Vesely schrieb:
> Bernd Stein schrieb:
>> Die Methode von Johann L. gefällt mir am besten.
>
>  LOL.
>  Ich hoffe, ihr beide lernt es noch zu lebzeiten.
>  Und wenn das funktionieren sollte, erschiesse ich mich öffentlich.

Oje, welche Laus hat dir denn an der Leber geknabbert?

...da kann man echt froh sein, wenn man nicht mit so nem arroganten 
GRÖPAZ zusammen arbeiten muss.

Aber zu Sache.

Glitches:
Es ist ein Unterschied, ob man Glitches nicht berücksichtigt, weil sie 
nicht berücksichtigt werden müssen, oder ob man sie nicht 
berücksichtigt, weil man sich keine Gedanken darüber gemacht hat.

Man wird doch noch drauf hinweisen dürfen?


Zum Code:
Dass man Code beliebig mit Makros verunstalten und verallgemeinern kann 
ist hier wohl jedem klar.  Es ging aber zunächst mal nur um eine 
Befehlssequenz als solche, die die gewünschte Abbildung erledigt.  Und 
für den Überblick ist eine explizite Sequenz erst mal einfacher zu 
erfassen als ein 
super-duper-allgemein-und-auch-für-haste-nicht-gesehn-verwendbarer Code.

Übrigens ist der von mir gepostete Code nicht von mir sondern von GCC. 
Beschwer dich also bei den GCC-Entwicklern darüber.

Marc Vesely schrieb:
> nur mag ich persönlich einfach nicht mit T-Flag rumspielen

ok, alles klar

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Johann L. schrieb:
> Oje, welche Laus hat dir denn an der Leber geknabbert?
 Keine Ahnung, bin sonst ein ganz netter Kerl.

Johann L. schrieb:
> Glitches:
> ...
> Man wird doch noch drauf hinweisen dürfen?
 Hmmm, jein.
 Radio Eriwan:
 Im Prinzip ja, aber bei der LCD Ausgabe...

Johann L. schrieb:
> Dass man Code beliebig mit Makros verunstalten und verallgemeinern kann
> ist hier wohl jedem klar.
 Ein bisschen hart formuliert, finde ich.

> Es ging aber zunächst mal nur um eine
> Befehlssequenz als solche, die die gewünschte Abbildung erledigt.  Und
> für den Überblick ist eine explizite Sequenz erst mal einfacher zu
> erfassen als ein
 Da kann ich mich nur mit dem ersten Teil einverstanden erklären.
 Für mich ist
    cbi  LCD_Port, LCD_RS
 leichter zu verstehen als
    cbi  PortB, 6

Johann L. schrieb:
> Übrigens ist der von mir gepostete Code nicht von mir sondern von GCC.
> Beschwer dich also bei den GCC-Entwicklern darüber.
 Meine Bemerkung betraff nicht deinen oder GCC Code, sondern die direkte
 Adressierung der Portbits.

 Natürlich steht es jedem frei, Portbits direkt zu adressieren oder den
 bits sinnvolle Namen zu geben. Aber TO fängt ja gerade mit Assembler
 an und da ist es besser, richtig anzufangen. Und bei solch verdrehtem
 Layout fährt er mit Pinnamen weitaus besser als mit Pinnummern.

Johann L. schrieb:
> ...da kann man echt froh sein, wenn man nicht mit so nem arroganten
> GRÖPAZ zusammen arbeiten muss.
 Halte mich weder für GRÖPAZ, noch bin ich arrogant, versuche immer
 zu helfen, manchmal mit Erfolg, manchmal ohne. Unterschätze niemanden,
 habe aber auch kein Problem jemandem die Wahrheit zu sagen, und auch
 kein Problem von jemandem die Wahrheit zu hören.

: Bearbeitet durch User
von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

>>
>> ;*** Kontrollbits
>> .equ  LCDrs  = 0
>> .equ  LCDen  = 1
>> ;*** KontrollPins als Ausgang
>>     ori  tmp0, 1<<LCDrs | 1<<LCDen
>>     out  DDR_LCD, tmp0
>>
Habe jetzt erst gelesen, das es hier weiter geht. Jetzt ist auch der 
Haken für " E-Mail-Benachrichtigung einschalten " gesetzt.

Nun nochmal konkret.

LCDrs ist ja Null, also wird ja diese Bitposition ( Bit0 ) so gelassen 
und nur Bitposition ( Bit1 ) eins gesetzt, da ja LCDen Eins ist und die 
Veroderung ( | ) dies bewirkt.

oder

Die Bitpositionen ( Bit0 und Bit1 ) werden auf Eins gesetz, weil LCDrs 
die Bitposition0 ist und LCDen die Bitposition1 und diese mit 1<< durch 
die Veroderung überschrieben werden.

Was ist jetzt richtig ?
Bin nämlich jetzt so verwirrt, weil Du unteres Beispiel mit dem darunter 
geschriebenen Text eklärst.

Marc Vesely schrieb:
>>>     ldi  tmp0, 1<<LCDd3 | 1<<LCDd2 | 1<<LCDd1 | 1<<LCDd0
>>>     ori  tmp0, 1<<LCDrs | 1<<LCDen
>>>
>>>
>>> "|" steht fur OR, somit werden beide Pins auf 1 gesetzt (Ausgang).
>>>  Könnte das alles auch in der ersten Zeile setzen, aber ich wollte es
>>>  dir übersichtlicher machen.
>>>
Beitrag "Re: AVR-ASM Knobelei : Bitmanipulation am LCD im 4-Bit Mode"

Was würde
          ori  tmp0, 0<<LCDrs | 1<<LCDen
bewirken ?

Die Null bei LCDrs ist beabsichtigt.



Bernd_Stein

von Karl H. (kbuchegg)


Lesenswert?

Bernd Stein schrieb:

> Nun nochmal konkret.

Da steht  1 << LCDrs

Das dröseln wir mal auf. << ist die binäre Schiebeoperation. Der linke 
Operand wird um so viele Stellen nach links geschoben, wie der rechte 
Operand angibt.

Links steht 1. In Bits aufgedröselt also
1
   0000 0001
(Ich mach zwischen die Nibble ein Leerzeichen rein. 4 Bits zählen sich 
leichter als 8)

dieses Bitmuster wird als nach links geschoben. Wegen den <<.
Um wieviele Stellen wird nach links geschoben?
Um LCDrs Stellen.
Was war nochmal LCDrs?
1
.equ LCDrs = 0
aha. LCDrs ist nichts anderes als 'ein anderer Name' für 0.
D.h. das Bitmuster soll um 0 stellen nach links geschoben werden.
Das ist aber einfach, dann wenn ich was um 0 STellen nach links schiebe, 
dann verändert sich ja nichts.
Das erste Teilergebnis ist also das Bitmuster
1
  0000 0001

Aber. Der Ausdruck geht ja noch weiter. Da gibt es noch den zweiten 
Teilausdruck
1
  1 << LCDen

was kommt da raus?
Wieder. Es beginnt mit dem linken Teil, der 1 ist. Oder in binärer Form, 
als Bits aufgedröselt
1
   0000 0001

Dieses Bitmuster soll wieder nach links geschoben werden. Um wieviele 
Stellen? Um LCDen Stellen. LCDen war was?
1
.equ LCDen = 1

Aha. LCDen ist nur ein anderer Name für 1. D.h. das Bitmuster soll also 
um 1 Stelle nach links geschoben werden.
Das Bitmuster war
1
   0000 0001
um eine Stelle nach links geschoben, ist das also
1
   0000 0010

Gut. Damit sind die beiden Teilausdrücke erledigt. Jetzt werden sie noch 
miteinander verodert.
1
   0000 0001
2
|  0000 0010
3
  -----------
4
   0000 0011
5
6
(einfach in jeder Spalte auf die beiden Bits eine Oder Operation anwenden)

Das Ergebnis ist als ein Byte, in dem die beiden Bits 0 und 1 auf 1 
gesetzt sind und alle anderen Bits 0 sind. Die Bits 0 und 1 deswegen, 
weil LCDrs für die Bitposition 0 steht und LCDen für die Bitposition 1. 
Wären die .equ andere
1
.equ LCDrs = 4
2
.equ LCDen = 7
dann würde da eben ein Byte rauskommen, bei dem an den Bitpositionen 4 
bzw. 7 ein 1 Bit steht und alle anderen 0 sind.

Aber egal wie, damit ist bekannt, was das Ergebnis des Ausdrucks
1
     .........   , ( 1 << LCDrs ) | ( 1 << LCDen )
ist. Das ist ein Byte, in dem bestimmte Bits auf 1 sind und alle anderen 
auf 0.
Und damit wird dann eben je nach der ....... Operation weiter gemacht.


> Was würde
>           ori  tmp0, 0<<LCDrs | 1<<LCDen
> bewirken ?
>
> Die Null bei LCDrs ist beabsichtigt.

Das Bitmuster
1
   0000 0000
kannst du nach links bzw. nach rechts schieben so oft und solange du 
lustig bist. Das Ergebnis davon wird wieder immer nur das Bitmuster
1
  0000 0000
sein. Aus genau dem gleichen Grund kann man auch jede Zahl mit 0 
multiplizieren und das Ergebnis davon wird trotzdem einfach nur 0 sein.

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Bernd Stein schrieb:
> Was würde
>           ori  tmp0, 0<<LCDrs | 1<<LCDen
> bewirken ?
>
> Die Null bei LCDrs ist beabsichtigt.

 LCDen geht auf 1, LCDrs bleibt unverändert.

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

Karl Heinz schrieb:

Beitrag "Re: AVR-ASM Knobelei : Bitmanipulation am LCD im 4-Bit Mode"

Danke für diese ausführliche Erklärung, die erstmal keine Frage offen 
läßt. Werde mal ein paar solcher Sachen simulieren und dann ja merken, 
ob ich es wirklich verstanden habe.

Vielen Dank nochmal.


Bis dann
        Bernd_Stein

: Bearbeitet durch User
von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

habe das Orginalprogramm jetzt soweit an das Layout angepasst, das ich 
sieben Temperatursensoren angezeigt bekomme ( An jedem Bus nur ein 
Temperatursensor ) nur der Bus_4  bei mir PortC2 funktioniert nicht.

Am Sensor selbst liegt es nicht, da ich ihn getauscht und er an einem 
anderem Bus ( anderen Aderpaar ) funktioniert. Es wird ein 25-poliges 
Flachbandkabel von ca. 1,5m länge verwendet und das Aderpaar an dem der 
Temp.Sensor dran ist ist i.O.

Ich vermute also, das der Fehler weiterhin in der Software ist.
Nur finde ich diesen nicht, bin ich zu sehr auf PortC2 versteift der 
bei mir dem Bus_4 zugeordnet ist ?

Habe leider keine Ahnung von dem 1-Wire-Bus von DALLAS, aber da ja 
sieben andere Temp.Sensoren funktionieren, denke ich das dies doch 
richtig implementiert wurde ( nicht von mir ).
Im Anhang das von mir veränderte Programm und hier noch der Link zu dem 
SensorModul2.

*Es gilt noch zu beachten, das ich nur den Code bezüglich dem 
SensorModul2 geändert habe.*

Hier unter Temperraturmesssytem =>  Kapitel 3: Sensormodul 2/3 zu 
finden.

http://s-huehn.de/elektronik/


Bernd_Stein

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Bernd Stein schrieb:
> Ich vermute also, das der Fehler weiterhin in der Software ist.
> Nur finde ich diesen nicht, bin ich zu sehr auf PortC2 versteift der
> bei mir dem Bus_4 zugeordnet ist ?
1
ow3rea: 
2
    sbi   ddrc,2            ;Port auf Ausgang Low setzen
3
    rcall w002us            ;2µs warten
4
    cbi   ddrc,2            ;Port auf Eingang setzen
5
    rcall w005us            ;4,5µs warten (Pause)
6
    rcall w005us            ;4,5µs warten (Pause)
7
    in    r17,pinc          ;Port lessen
8
;******************* FEHLER ********************
9
    andi  r17,0x01          ;Portpin selektieren
10
;******************* FEHLER ********************
11
    clc                     ;Carry löschen (= 0)
12
    breq  ow3r10            ;Port = 0? ja -> weiter

 In Ordnung ?

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

Marc Vesely schrieb:
1
> ow3rea:
2
>     sbi   ddrc,2            ;Port auf Ausgang Low setzen
3
>     rcall w002us            ;2µs warten
4
>     cbi   ddrc,2            ;Port auf Eingang setzen
5
>     rcall w005us            ;4,5µs warten (Pause)
6
>     rcall w005us            ;4,5µs warten (Pause)
7
>     in    r17,pinc          ;Port lessen
8
> ;******************* FEHLER ********************
9
>     andi  r17,0x01          ;Portpin selektieren
10
> ;******************* FEHLER ********************
11
>     clc                     ;Carry löschen (= 0)
12
>     breq  ow3r10            ;Port = 0? ja -> weiter
13
>
Vielen vielen Dank, das Du mich direkt mit der Nase darauf gestossen 
hast, sonst hätte ich es wahrscheinlich noch huntert mal übersehen.
Das war wirklich die einzige Stelle im Programm, die diesen Fehler 
verursachte. Bitposition2 bzw. Bit2 hat natürlich die Wertigkeit 0x04.

Irgendwie muß ich wohl immer die 2 als Wert gesehen haben und nicht als 
Bitpostition bzw. Bit und mein Gehirn machte daher immer 2^1 daraus, 
also 2 hoch 1, was ja den Wert 2 ergibt. Aber es ging ja um die 
Bitposition2 bzw.*Bit2* und nicht um den Wert 2.

Warum ich gerade in dieser Programmpassage diesen Gedankengang hatte und 
nicht bei den anderen identischen, kann ich mir nur so erklären, das 
sich irgendwie alles um die 2 ( PortC2 ) drehte.

Kannst Du mir bitte noch schreiben, wie Du vorgegangen bist, das Du den 
Fehler so schnell ( < 20 min ) gefunden hast ?



Bernd_Stein

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Bernd Stein schrieb:
> Kannst Du mir bitte noch schreiben, wie Du vorgegangen bist, das Du den
> Fehler so schnell ( < 20 min ) gefunden hast ?
 Weil ich klug bin ?

 Nö, im Ernst, deswegen soll man Programmteile trennen, Unterprogramme
 benutzen, Kommentare schreiben etc. Bei dem geposteten Programm ist
 das alles OK, war nicht so schwer.

 Abschnitt mit 1-Wire Routinen gefunden.
 Geguckt was die anderen bits machen, mit bit2 verglichen und...

Bernd Stein schrieb:
> Vielen vielen Dank, das Du mich direkt mit der Nase darauf gestossen
> hast, sonst hätte ich es wahrscheinlich noch huntert mal übersehen.
 Bist nicht der einzige, dem es so geht, was glaubst warum ich so wenig
 Haare auf dem Kopf habe ?

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

Bernd Stein schrieb:
> Habe das SENSORMODUL2 nochmal gebaut nun aber nicht gefädelt,
> sondern mit einem Layout, um es auch für Andere einfach nachbaubar bzw.
> nachbausicherer zu machen.
>
Und nochmals Danke an alle, die dazu beigetragen haben dies 
fertigstellen zu können.

Hier nun der dazu passende Link :

Beitrag "Temperaturmesssystem Sensormodul 2 mit ATmega 8 in AVR-ASM"


Bernd_Stein

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.