Forum: Mikrocontroller und Digitale Elektronik AVR asm jmp problem


von zwaergli (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen

Ich habe gerade mit dem Rumpusboard (lochraster.org) auf einem atmega168 
begonnen zu programmieren. Ich benutze dabei dieses Tutorial: 
http://www.mikrocontroller.net/articles/AVR-Tutorial

Mein Ziel ist es, dass nach einem (einmaligen) Tastendruck eine LED 
permanent angeht und das Program dann in einen Endlosloop springt (also 
nicht mehr auf Tastendrücke reagiert).

Dazu habe ich folgenden Code geschrieben:
1
#include <avr/io.h>
2
#include "util.h"
3
4
;configure D as in and out
5
ldi r16, 0b11101000
6
STORE DDRD, r16
7
8
;configure C as in and out
9
ldi r16, 0b010000
10
STORE DDRC, r16
11
12
;configure B as in and out
13
ldi r16, 0b000010
14
STORE DDRB, r16
15
16
;configure pullups in C
17
ldi r16, 0b001111
18
STORE PORTC, r16
19
20
;led off
21
ldi r16, 0x00
22
STORE PORTD, r16
23
24
loop:   sbic 0x06, 0
25
        jmp loop
26
27
        ldi r16, 0b011111
28
        STORE PORTC, r16
29
30
end: jmp end

Der Taster ist dabei auf dem Pin 0 des Portes C und die LED auf Pin 4 
des Portes C.
Das Problem ist nun, dass mein Program nicht wirklich so funktioniert 
wie ich es gerne hätte. Nämlich springt die LED immer dann an, wenn ich 
DEN TASTER GEDRÜCKT HALTE, danach löscht sie wieder ab. Auch springt das 
Program nicht in einen Endlosloop sondern, ich kann den Taster immer 
wieder betätigen und die LED springt an.

Kann mir da jmd. weiterhelfen.
Vielen Dank schon im voraus.

PS: die Schaltung findet ihr hier: 
www.lochraster.org/rumpus/data/rumpus-v2-schematic.pdf
PS2: die makros sind zur transformation der PORT Nr. bei 
unterschiedlichen Befehlen, findet ihr im angehängten util.h

von Mark L. (m2k10) Benutzerseite


Lesenswert?

Die Beschreibung hört sich so an, als wenn dein Controller ständig in 
den Reset geht und wieder von vorne beginnt. In der Schaltung scheint es 
da keinen Pull-up bei Reset zu geben (nach überfliegen) und den internen 
deaktivierst du beim Schreiben auf PortC.

Du könntest entweder einen 10k-Pullup an der Reset-Leitung hinzufügen 
oder den internen für den Pin zuschalten indem du beim Schreiben auf 
PORTC 8 bit verwendest und dabei bit 6 auf 1 setzt. Also:
1
ldi r16, 0b01------           ; '-' meint die obigen 6-bit-Werte
2
STORE PORTC, r16

Mark

von zwaergli (Gast)


Lesenswert?

Vielen Dank für die schnelle Antwort.
An das habe ich wirklich nicht gedacht, habe den Code entsprechend 
geändert, hat aber nichts an der Situation geändert. :(
Könnte es sonst noch etwas sein?

von zwaergli (Gast)


Lesenswert?

Ein weiteres Problem ist noch, dass wenn ich rjmp statt jmp verwende das 
Program die LED aktiviert, d.h. Code auf Zeile 27,28 ausführt und dann 
auch in den Endlosloop springt, der sbic Befehl hingegen wird nicht 
richtig evaluiert. und auch den Befehl rjmp loop scheint er zu 
"ignorieren".
An was kann das liegen, der Unterschied von rjmp und jmp (soweit ich 
gelesen habe) ist ja nur, dass er statt eine absolute eine relative 
Addresse verwendet.

Das ist irgendwie echt komisch.

von Mark L. (m2k10) Benutzerseite


Lesenswert?

jmp benötigt auch zwei Bytes und einen Takt mehr, aber das spielt hier 
keine Rolle, ebensowenig, dass der auf kleineren Controllern nicht 
existiert.
rjmp wäre bei der Sprungweite schon zu bevorzugen, aber deine Probleme 
sollten nicht daran liegen.

Funktionieren denn die Demos für das Board? Kalte Lötstellen, instabile 
Spannung oder so könnten auch eine Erklärung sein.

Ansonsten weiß ich aktuell auch nicht, was das noch sein könnte.

von Steffen H. (avrsteffen)


Lesenswert?

Was ist das, Inline-Assembler?

Diese Art in ASM zu programmieren kenn ich ja noch gar nicht. Wo 
deklarierst du überhaupt deinen Stack? (SPL und SPH)

Steffen

von Eumel (Gast)


Lesenswert?

Bei welchem AVR muss man eigentlich noch den Stack anlegen? Beim Mega8? 
Oder bei nur bei noch älteren?

von Steffen H. (avrsteffen)


Lesenswert?

Ich wüsste nicht, das sich da was geändert hätte.
Ich muss doch initialisieren, oder? Klärt mich bitte auf.
Wo kann man das nachlesen?

Gruß Steffen

von Eumel (Gast)


Lesenswert?

Ich hab das bei noch keinem AVR gemacht.
z.b. beim Tiny13 http://www.atmel.com/Images/doc2535.pdf Seite 11:

"The Stack Pointer points to the data SRAM Stack area where the 
Subroutine and Interrupt
Stacks are located. This Stack space in the data SRAM is automaticall 
defined to the last
address in SRAM during power on reset."

Und ganz taufrisch ist der ja auch nicht mehr ;)

von Steffen H. (avrsteffen)


Lesenswert?

Du hast Recht Eumel. Danke für diesen Hinweis. Nach so vielen Jahren..

Steffen

von Eumel (Gast)


Lesenswert?

Na ja, es schadet ja nicht wenn man es trotzdem macht.

von Jobst M. (jobstens-de)


Lesenswert?

Eumel schrieb:
> Na ja, es schadet ja nicht wenn man es trotzdem macht.

Nur das es in seinem Programm bisher keinerlei Verwendung für den Stack 
gibt und die Initialisierung daher völlig überflüssig ist.

Wäre ja mal interessant zu wissen, um welchen Controller es sich handelt 
...


Gruß

Jobst

von chris (Gast)


Lesenswert?

was ist denn STORE für ein Befehl gehört denn der zu einer Hochsprache?

versuch die STORE mal durch ein OUT x,y zu ersetzen.

Pullups aktiv

ldi    r16   , 0b11111111
out    Portx , r16

ldi    r16   , 0byyyyyyyy
out    DDRX  , r16


Pullups deaktivieren

ldi    r16   , 0b00000000
out    Portx , r16

ldi    r16   , 0byyyyyyyy
out    DDRX  , r16

von Thomas P. (topla)


Lesenswert?

chris schrieb:
> was ist denn STORE für ein Befehl gehört denn der zu einer Hochsprache?

Das ist ein Macro aus der oben anhängenden util.h um den Unfug mit 
out/sts und in/lds je nach Registeradresse zu umgehen. Regt mich bei den 
AVRs auch jedes Mal auf.

Thomas

von Thomas P. (topla)


Lesenswert?

Jobst M. schrieb:

> Wäre ja mal interessant zu wissen, um welchen Controller es sich handelt

Im ersten Beitrag steht, dass es ein ATmega168 ist.

Thomas

von Jobst M. (jobstens-de)


Lesenswert?

Thomas P. schrieb:
> Jobst M. schrieb:
>
>> Wäre ja mal interessant zu wissen, um welchen Controller es sich handelt
>
> Im ersten Beitrag steht, dass es ein ATmega168 ist.

Vielen Dank, ist mir durch die Lappen gegangen ...

Gruß

Jobst

von Karl H. (kbuchegg)


Lesenswert?

Ich denke auch, dass das ein elektrisches Problem oder irgendwas mit dem 
Reset ist.

Hast du einen externen 10k Widerstand von Reset nach Vcc gemacht?
Wenn nicht solltest du den noch machen.


Um dem auf die Spur zu kommen, solltest du als erstes mal die Hypothese 
testen: Wird mein Controller (aus welchem Grund auch immer) ständig 
resettet?

Dazu kannst du zb so vorgehen.
Beim Hochfahren des Programmes, noch ehe es in die Hauptschleife geht, 
schaltest du eine der anderen 3 LEDs ein (zb die an PD3 - das ist LED2; 
den Jumper nicht vergessen), wartest eine kleine Weile und schaltest sie 
danach wieder aus. D.h. legst du Spannung an das Booard an, dann darf 
diese LED nur EINMAL kurz aufblinken. Blinkt die ständig oder zeigt gar 
Dauerleuchten, dann wird der µC ständig resettet und man muss dem auf 
den Grund gehen warum das so ist.


Die Verzögerung kannst du zb so machen
1
...
2
; dein Code
3
;led off
4
ldi r16, 0x00
5
out PORTD, r16
6
....
7
8
; LED an PD3 ein, etwas warten, und wieder aus
9
10
       sbi  PORTD, 3     ; LED ein
11
       ldi  r18, 40
12
       ldi  r17, 0xFF
13
       ldi  r16, 0xFF
14
verz1: dec  r16
15
       brne verz1
16
       dec  r17
17
       brne verz1
18
       dec  r18
19
       brne verz1
20
       cbi  PORTD, 3     ; LED aus
21
22
; dein Code
23
loop:   sbic 0x06, 0
24
        rjmp loop
25
.... dein weitere Code

mit den Zahlenwerten in den Registern ergibt sich bei den 16Mhz vom 
Rumpusboard eine Wartezeit von ca. 0.5 Sekunden. Das sollte also gut zu 
sehen sein. Wenn dein µC noch nicht auf 16Mhz läuft, dann ist das dann 
16 mal länger - also ca 8 Sekunden. Also nicht nervös werden, wenn die 
LED nicht gleich ausgeht, das kann auch an einer falschen Taktrate 
liegen. Aber spätestens nach 8 Sekunden muss die LED ausgehen. Und 
danach darf die LED im Programmlauf nie wieder zu sehen sein, egal was 
du an den Tasten rumspielst - denn das würde bedeuten, dass der µC 
resettet wurde.
Wenn du dieses Verhalten nicht siehst -> dann müssen wir uns überlegen, 
was die Dauerresets auslösen könnte.

Hast du bereits an den Fuses rumgespielt, ausser um jetzt den Takt auf 
Quarz umzustellen?

von Steffen H. (Gast)


Lesenswert?

Jobst M. schrieb:
> Eumel schrieb:
>> Na ja, es schadet ja nicht wenn man es trotzdem macht.
>
> Nur das es in seinem Programm bisher keinerlei Verwendung für den Stack
> gibt und die Initialisierung daher völlig überflüssig ist.

Stack wird bei jmp oder rjmp nicht gebraucht, da hat auch der Jobst M. 
Recht. Was ist nur los mit mir..

Also Programm-technisch sehe ich sonst auch nichts auffälliges. 
Vielleicht doch Hardware? Den Test zum Reset von Karl Heinz ist eine 
gute Idee.


Steffen

von Karl H. (kbuchegg)


Lesenswert?

Eineis ist mir gerade in den Sinn gekommen.

Das hier
1
loop:   sbic 0x06, 0
2
        jmp loop

sollte IMHO auf jeden Fall ein rjmp sein. Ich denke nicht, dass der sbic 
damit klar kommt, dass rjmp und jmp unterschiedliche Befehlslängen (in 
Bytes) haben.

von Mark L. (m2k10) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> Ich denke nicht, dass der sbic damit klar kommt, dass rjmp und jmp
> unterschiedliche Befehlslängen (in Bytes) haben.

Ich hatte da gestern auch mal kurz dran gedacht, irgendwo muss ja ein 
Fehler sein ;-)

Instructionset sagt aber:
PC ← PC + 1, Condition false - no skip
PC ← PC + 2, Skip a one word instruction
PC ← PC + 3, Skip a two word instruction

von Karl H. (kbuchegg)


Lesenswert?

Mark L. schrieb:
> Karl Heinz Buchegger schrieb:
>> Ich denke nicht, dass der sbic damit klar kommt, dass rjmp und jmp
>> unterschiedliche Befehlslängen (in Bytes) haben.
>
> Ich hatte da gestern auch mal kurz dran gedacht, irgendwo muss ja ein
> Fehler sein ;-)
>
> Instructionset sagt aber:
> PC ← PC + 1, Condition false - no skip
> PC ← PC + 2, Skip a one word instruction
> PC ← PC + 3, Skip a two word instruction

Interessant.
Ich hätte nicht gedacht, dass der SBIC das selbsttätig ohne 
Assemblerhilfe macht. (Und auf der anderen Seite muss man bei den OUT 
und STS mit der Adresslage aufpassen wie ein Schlosshund. Das verstehe 
wer wolle)
Wieder was gelernt. Danke.

von Jobst M. (jobstens-de)


Lesenswert?

zwaergli schrieb:
> loop:   sbic 0x06, 0

Was ist 0x06 eigentlich? PINC?
Hat es einen besonderen Grund, daß es so notiert ist?


Karl Heinz Buchegger schrieb:
> (Und auf der anderen Seite muss man bei den OUT
> und STS mit der Adresslage aufpassen wie ein Schlosshund. Das verstehe
> wer wolle)

Da hat man eindeutig beim Design der Assemblersyntax gepennt. Der 8051 
macht auch alles mit MOV - auch wenn dahinter unterschiedliche Codes 
stehen. Das ist Aufgabe des Compilers ...


Gruß

Jobst

von Thomas P. (topla)


Lesenswert?

@zwaergli:
Du hast aber in der IDE (oder was Du hier auch immer benutzt) den 
Prozessor richtig mit ATmega168 eingestellt?
Irgendwie habe ich das Gefühl, der Code wird für einen anderen µC 
erzeugt. So komische Effekte können doch garnicht anders zustande 
kommen.

Und das
sbic 0x06, 0
ist auch komisch, PINC liegt doch nicht auf 0x06??

Thomas

von Ralf G. (ralg)


Lesenswert?

Jobst M. schrieb:
> Was ist 0x06 eigentlich? PINC?
> Hat es einen besonderen Grund, daß es so notiert ist?

Das fiel mir als Erstes negativ auf. PINC sollte man schon verwenden.
Jetzt allerdings das größere Problem:
DDRC und PORTC liegen auf 0x07 und 0x08 (Das ist noch leicht.)
Wenn man jetzt allerdings aus der util.h sich das Makro STORE ansieht...
1
.macro  STORE addr,reg
2
  .if     \addr < 0x60
3
    out    \addr - 0x20,\reg
4
  .else
5
    sts    \addr,\reg
6
  .endif
7
.endm
... werden da jetzt nicht z.B. bei...
1
;configure C as in and out
2
ldi r16, 0b010000
3
STORE DDRC, r16
... von der 0x07 (kleiner 0x60) 0x20 abgezogen und dann das out 
versucht????

Oder 0x06 stimmt nicht.

von Karl H. (kbuchegg)


Lesenswert?

Ralf G. schrieb:

> Oder 0x06 stimmt nicht.

Ich hab jetzt nicht nachgesehen, ob PINC wirklich auf 0x06 liegt.

Aber
1
#include <avr/io.h>
2
...

Seit wann geht das?
Wenn das die Include Files vom C-Compiler sind, dann sind die Adressen 
der Ports dort meines Wissens als Speicheradressen für einen STS Zugriff 
abgelegt. D.h. für OUT bzw. STS müsste das schon richtig sein und STORE 
kommt damit zurecht. (Und der gcc arbeitet mit den Ports erst mal nur 
über Speicherzugriffe. Die Umsetzung einiger STS auf OUT geschieht 
meines Wissens erst ziemlich spät in der Codegenerierung, und ist eher 
als Teil einer Optimierung anzusehen. Und dort erfolgt dann auch die 
Korrektur der Adresse. Johann L. weiß da aber sicher mehr darüber)
Nur kann man dann bei SBIC nicht mehr PINC benutzen, sondern müsste da 
das zusätzliche Makro aus Util.h benutzen.

Dann eben so
1
     SBIC   _SFR_IO_ADDR(PINC), 0

(Mir sowieso unverständlich, warum man im STORE Makro nicht auch dieses 
Makro mitbenutzt hat)


Mein Fazit:
Bei seinen ersten Programmen auf derartige Spompanadeln verzichten.
AVR-Assembler, so wie sich der Hersteller das vorgestellt hat und so wie 
es auch in hunderten Tutorials benutzt wird.

von Spess53 (Gast)


Lesenswert?

Hi

Die Macros sind Müll. Das Original von Atmel sieht so aus:

.MACRO STORE     ;Arguments: Address, Register
  .if  @0>0x3F
          sts  @0, @1
  .else
    out  @0, @1
  .endif
.ENDMACRO

MfG Spess

von Ralf G. (ralg)


Lesenswert?

Spess53 schrieb:
> Das Original von Atmel sieht so aus

Das sieht schon freundlicher aus. Verwenden würde ich es trotzdem nicht!

von Karl H. (kbuchegg)


Lesenswert?

Ralf G. schrieb:
> Spess53 schrieb:
>> Das Original von Atmel sieht so aus
>
> Das sieht schon freundlicher aus. Verwenden würde ich es trotzdem nicht!

Mir ist jetzt nicht klar, wie man dieses Makro korrekt benutzt. Da muss 
man doch als Aufrufer erst recht wieder wissen, ob die Adresse die man 
angibt eine Port-Adresse oder eine Speicheradresse ist.

von Stefan E. (sternst)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Mir ist jetzt nicht klar, wie man dieses Makro korrekt benutzt. Da muss
> man doch als Aufrufer erst recht wieder wissen, ob die Adresse die man
> angibt eine Port-Adresse oder eine Speicheradresse ist.

Das Makro ist für die Atmel-Includes, wo die Symbole wenn möglich mit 
ihrer IO-Adresse angegeben sind, und mit der Memory-Adresse nur in den 
anderen Fällen. Da ist PINC 0x06 (IO-Adresse) und WDTCSR eben 0x60 
(Memory-Adresse).

von Stefan E. (sternst)


Lesenswert?

Spess53 schrieb:
> Die Macros sind Müll. Das Original von Atmel sieht so aus

Er benutzt aber nicht die Atmel-Assembler-Includes, sondern die 
C-Includes der AVR-Libc. Und dafür ist das Makro genau richtig.

von Karl H. (kbuchegg)


Lesenswert?

Stefan Ernst schrieb:
> Karl Heinz Buchegger schrieb:
>> Mir ist jetzt nicht klar, wie man dieses Makro korrekt benutzt. Da muss
>> man doch als Aufrufer erst recht wieder wissen, ob die Adresse die man
>> angibt eine Port-Adresse oder eine Speicheradresse ist.
>
> Das Makro ist für die Atmel-Includes, wo die Symbole wenn möglich mit
> ihrer IO-Adresse angegeben sind, und mit der Memory-Adresse nur in den
> anderen Fällen. Da ist PINC 0x06 (IO-Adresse) und WDTCSR eben 0x60
> (Memory-Adresse).

Danke.
Das erklärt es natürlich.

von Stefan E. (sternst)


Lesenswert?

Karl Heinz Buchegger schrieb:
>> Das Makro ist für die Atmel-Includes, wo die Symbole wenn möglich mit
>> ihrer IO-Adresse angegeben sind, und mit der Memory-Adresse nur in den
>> anderen Fällen. Da ist PINC 0x06 (IO-Adresse) und WDTCSR eben 0x60
>> (Memory-Adresse).
>
> Danke.
> Das erklärt es natürlich.

Das Gleiche kann man übrigens mit den AVR-Libc-Includes bekommen, wenn 
man dem "#include <avr/io.h>" ein "#define __SFR_OFFSET 0" voranstellt. 
Dann kann man sich das _SFR_IO_ADDR() sparen. Aber dann ist das Makro 
natürlich nicht mehr richtig. ;-)

von Spess53 (Gast)


Lesenswert?

Hi

>Mir ist jetzt nicht klar, wie man dieses Makro korrekt benutzt. Da muss
>man doch als Aufrufer erst recht wieder wissen, ob die Adresse die man
>angibt eine Port-Adresse oder eine Speicheradresse ist.

Wieso? In den Include-Dateien sind die Registeradressen der mit in/out 
erreichbaren Register mit den IO-Adressen (0...$3F) angegeben. Die 
Memory-Mapped Register mit der Speicheradresse (>=$60). Also reicht die 
Überprüfung auf <=$3F aus um zwischen in/out und lds/sts zu 
unterscheiden.

MfG Spess

von Ralf G. (ralg)


Lesenswert?

Stefan Ernst schrieb:
> Das Makro ist für die Atmel-Includes, wo die Symbole wenn möglich mit
> ihrer IO-Adresse angegeben sind, und mit der Memory-Adresse nur in den
> anderen Fällen. Da ist PINC 0x06 (IO-Adresse) und WDTCSR eben 0x60
> (Memory-Adresse).

Ja, aber welche Adresse ist es denn nun eigentlich?

Die Definition in 'iomx8.h':
#define PINC    _SFR_IO8 (0x06)
Da müsste jetzt für PINC 0x26 rauskommen.

Und die Rückrechnung:
Karl Heinz Buchegger schrieb:
> SBIC   _SFR_IO_ADDR(PINC), 0

Aber ob so ein Mischmasch die Verwendung von STORE/ LOAD wieder 
einspielt?

Edit:
Hab' ich gerade erst gelesen:

Spess53 schrieb:
> Wieso? In den Include-Dateien sind die Registeradressen der mit in/out
> erreichbaren Register mit den IO-Adressen (0...$3F) angegeben.

... wenn man die Assembler-Includes verwendet. Mit den C-Files wird's 
eben Mist.

von Ralf G. (ralg)


Lesenswert?

zwaergli schrieb:
> An das habe ich wirklich nicht gedacht, habe den Code entsprechend
> geändert

zwaergli schrieb:
> ldi r16, 0b011111
>         STORE PORTC, r16

Hier auch??

von Karl H. (kbuchegg)


Lesenswert?

Ralf G. schrieb:
> zwaergli schrieb:
>> An das habe ich wirklich nicht gedacht, habe den Code entsprechend
>> geändert
>
> zwaergli schrieb:
>> ldi r16, 0b011111
>>         STORE PORTC, r16
>
> Hier auch??

Wobei ich mich gerade frage, ob es wirklich so ist, dass mit dem 0 Bit 
an PC6 im Port Register der Pullup des Reset weggeschaltet wird, oder ob 
der nicht sowieso als Teil der Reset-Logik immer vorhanden ist, solange 
Reset nicht per Fuse abgeschaltet wird.


Externer 10k Pullup drann und das Kopfkratzen hört auf.

von Stefan E. (sternst)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Wobei ich mich gerade frage, ob es wirklich so ist, dass mit dem 0 Bit
> an PC6 im Port Register der Pullup des Reset weggeschaltet wird

Unwahrscheinlich. Zumal das Datenblatt als Default-Inhalt für das Bit 
eine 0 angibt.

von zwaergli (Gast)


Lesenswert?

Hallo zusammen,

Ihr seid, wirklich super, ich hätte nicht gedacht, dass sich aus meinem 
Problem eine so interessante und lebhafte Diskussion entwickeln würde 
^^!

Ich werde mal dem Vorschlag mit dem Reset nachgehen, es könnte natürlich 
gut sein, das es daran liegt.

Nun habe ich aber noch eine Frage zur ganzen Makro, includes usw. Sache, 
ich habe da wirklich keinen Durchblick, die meisten Tutorials im 
Internet sind auf C ausgelegt und auch im Tutorial, das ich verwende, 
das ja von dieser Seite stammt, wird z.B. das ganze (diskutierte) 
"Addressproblem" (für das ich eben dieses anscheinend nicht geeignete 
Makro gefunden habe) nicht erwähnt, geschweige denn das Makro 
_SFR_IO_ADDR verwendet. (Hier nochmal der Link: 
http://www.mikrocontroller.net/articles/AVR-Tutorial:_IO-Grundlagen).

Ich habe da wirklich den Durchblick noch nicht. Welche includes 
verwendet man also in Assembler und wie läuft das mit den IO-Addressen, 
verwendet jmd. z.B. das Makro von Atmel, oder braucht ihr einfach immer 
das _SFR_IO_ADDR Makro? Wie ist das mit diesem Trick #define 
__SFR_OFFSET 0 ?

Könntet ihr mir dazu mal kurz schreiben, wie man das richtig macht, da 
wäre ich sehr froh.

Nochmals vielen Dank für die vielen Antworten!!!

von Hmm (Gast)


Lesenswert?

Falls sich irgendwer fragt, was die von Karl Heinz erwähnten 
"Spompanadeln" sind, der kann sich unter 
http://www.ostarrichi.org/woerterbuch.html auch dieser Spielart der 
deutschen Sprache nähern.

Ich will 'n Almdudler!

von Jobst M. (jobstens-de)


Lesenswert?

zwaergli schrieb:
> Könntet ihr mir dazu mal kurz schreiben, wie man das richtig macht, da
> wäre ich sehr froh.

'Richtig' macht man es so, daß man für den jeweiligen Zugriff den 
'richtigen' Befehl benutzt. Eigentlich etwas, was ein Compiler schnell 
lösen könnte - wurde aber nicht vorgesehen.


Weitere Infos im Datenblatt im Kapitel 'Register Summary'.

Dort stehen einmal die unterschiedlichen Adressen und unten drunter dann 
dies:

2. I/O Registers within the address range 0x00 - 0x1F are directly 
bit-accessible using the SBI and CBI instructions. In these registers, 
the value of single bits can be checked by using the SBIS and SBIC 
instructions.

...

4. When using the I/O specific commands IN and OUT, the I/O addresses 
0x00 - 0x3F must be used. When addressing I/O Registers as data space 
using LD and ST instructions, 0x20 must be added to these addresses. The 
ATmega48A/PA/88A/PA/168A/PA/328/P is a complex microcontroller with more 
peripheral units than can be supported within the 64 location reserved 
in Opcode for the IN and OUT instructions. For the Extended I/O space 
from 0x60 - 0xFF in SRAM, only the ST/STS/STD and LD/LDS/LDD 
instructions can be used.

Die verbleibenden Adressen (ST/LD...) unter 0x20 sind im übrigen die 
Register (R0-R31).

Siehe auch 'AVR Memories' Unterkapitel 'SRAM Data Memory'

Die 64 I/O-Register mitten im Block sind die, die man mit IN und OUT 
ansprechen kann. Und diese werden von diesen Befehlen bei 0 beginnend 
nummeriert (0x00-0x3F).

Total krank und ohne Liebe entworfen.


Gruß

Jobst

von Karl H. (kbuchegg)


Lesenswert?

zwaergli schrieb:

> Könntet ihr mir dazu mal kurz schreiben, wie man das richtig macht, da
> wäre ich sehr froh.

Meiner Meinung nach solltest du am Anfang auf diesen ganzen Häck-Mäck 
verzichten und so programmieren, wie du es im hiesigen Tutorial siehst.
Mit dem original Atmel-Assembler aus dem AVR-Studio.

Denn wie du siehst, gibt es da Fallen, die mit den Makros versteckt 
wurden, die dich aber trotzdem beissen können.

Am Anfang wirst du hauptsächlich an den I/O Registern rumpfriemeln, also 
an Registern die allesamt über OUT erreichbar sind. D.h. noch stellt 
sich dieses Problem für dich gar nicht, weil du bei Systemregistern 
immer OUT nehmen kannst.

Und wenn du dann soweit bist, dass du das erste mal auf Register stösst, 
die nicht mehr mit OUT erreichbar sind, dann hast du genug Erfahrung 
gesammelt, dass du weißt was du tust und warum du es tust.
Aber zur Zeit ist das ein Detail, welches meiner Meinung mehr verwirrt 
als es nützt. Dein Makro löst ein Problem, welches du zur Zeit nicht 
hast und drückt dir dafür andere Probleme aufs Aug, von denen dir noch 
nicht klar ist, woher sie kommen.

von Hannes L. (hannes)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Mit dem original Atmel-Assembler aus dem AVR-Studio.

Richtig!
Das ist der Grund, warum ich mich bisher nicht an dieser Diskussion 
beteiligt habe.

...

von zwaergli (Gast)


Lesenswert?

Vielen Dank, das "Adressproblem" habe ich nun begriffen. Wie steht das 
mit den includes. Sollte ich, wenn ich die richtigen includes verwende 
alle ports usw. mit PORTC, PINC ... direkt ansprechen können? (also ohne 
makros usw.), welches sind die korrekten includes?

Das mit dem Assembler habe ich noch vergessen zu erwähnen, ich arbeite 
unter Linux und verwende dabei avr-gcc und avrdude um das Programm zu 
laden.
Die Fuse-bits sind folgendermassen gesetzt:
low   0xe7
high   0xdf
extended 0x00
lock   0x2f

Weiter habe ich den Vorschlag von Karl Heinz Buchegger umgesetzt (wobei 
ich einen 20MHz Quarz verwende), die LED hat gedimmt geleuchtet (sehr 
schwach), was auf Reset deutet, was mich aber auch erstaunt hat, ist 
dass wie gesagt die LED sich nicht alle 0.5s aber vermutlich viel 
schneller (gedimmt) an und aus schaltet. Auch das anfügen eines weiteren 
branches (mit r19 = 0xFF) also 255 Zyklen mehr) hat nichts geändert, 
(ich habe sogar noch den Output auf den Speaker gegeben, der hat immer 
denselben Pfeifton ausgegeben).

Vermutlich ist also wirklich der Reset das Problem.
Ich habe das Datenblatt nochmals etwas angeschaut, dort ist auf jeden 
Fall ein Pull-up Widerstand eingezeichnet (auf dem Reset-Pin), wie ist 
das nun? Das Problem ist, dass ich auf diesem Board schlecht "einfach" 
einen 10k Widerstand dazulöten kann.

von Karl H. (kbuchegg)


Lesenswert?

zwaergli schrieb:

> Vermutlich ist also wirklich der Reset das Problem.

Es sieht zumindest erst mal danach aus.
Ein per Fuse eingeschalteter Watchdog könnte auch noch diese Symptome 
verursachen.

> Ich habe das Datenblatt nochmals etwas angeschaut, dort ist auf jeden
> Fall ein Pull-up Widerstand eingezeichnet (auf dem Reset-Pin), wie ist
> das nun? Das Problem ist, dass ich auf diesem Board schlecht "einfach"
> einen 10k Widerstand dazulöten kann.

Es muss nicht schön sein, es muss funktionieren.
Einen Widerstand kriegt man immer irgendwo unter. Zumal der nicht 
besonders kritisch auf räumliche Distanz zum µC ist. Einfach mal die 
Reset-Leitung (die geht ja auch zum ISP-Programmer) verfolgen und nach 
einer Stelle suchen, wo in der Nähe ein kleines Plätzchen frei ist, wo 
man den Widerstand einlöten kann und mit Drähtchen an Vcc bzw. diese 
Reset Leitung anschliessen kann. Am ISP Stecker sind beide 'Signale' 
vorhanden, d.h. in dessen Umfeld ist die Chance nicht so schlecht, dass 
du da den R dazuhängen kannst. AChtung auf die zusätzlichen Jumper! Egal 
ob die gesteckt sind oder nicht, du willst IMMER von Reset über den R 
auf Vcc.
Der Reset Taster wäre möglicherweise auch ein gutes Plätzchen. Von dem 
einen Pin vom Taster über den R nach Vcc.


Gewöhn dich daran, dass man im ersten Aufbau einer Platine öfter mal 
irgendwas vergisst, was man danach einfügen oder ändern muss. Und zwar 
mit einem scharfen Messer (zum Auftrennen von Leiterbahnen) und Draht 
(mit dem man die neuen Verbindungen herstellt). Manchmal kommt dann auch 
noch Kleber dazu, mit dem man zb IC auf dem Rücken liegend auf die 
Platine klebt, weil man partout keine Lötaugen mehr hat, etc. etc.

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.