Hallo zusammen,
Blieb bei meinem Projekt grad bei SRAM hängen.
Zunächst mal möchte ich sagen, das ich das SRAM zum ersten mal nutze.
Hab bis jetzt alles mit Registern gemacht. Aber da meine Projekte immer
umfangreicher werden, muss ich nun das SRAM benützen, um etwas Übersicht
zu gewinnnen.
Zur Frage:
Spielt generell es ein Rolle WO ich die Assemblerdirektive;
.dseg
count: .BYTE 1
im Code selbst hinschreibe?
Also ich meine nicht direkt im Code, sondern dort wo ich die Register
deklariere also Am Ganz am Anfang, oder erst am Schluss?
Ich hab bei den ersten Versionen, das Codesegment ganz am Anfang
deklariert, dann hat aber das Programm nicht mehr Funktioniert.
Hab ich es entfernt ging wieder alles wunderbar.
Schreibe ich es am Schluss funktioniert alles wie gewünscht, waber warum
ist das SO? Oder mache ich sonst was verkehrt.
Mein Code (der Funktionsfähige =)
1 | .nolist
| 2 | .include "/home/lukas/Dokumente/AVR/includes/m8def.inc"
| 3 | .list
| 4 |
| 5 | ;Register
| 6 |
| 7 | .def t1 = r16 ; temp Register
| 8 | .def z1 = r17 ; Zähler 1 für die Zeitmessung
| 9 | .def stat = r18 ; Status
| 10 | .def z2 = r19 ; Timer für Warteschleifen
| 11 | .def z3 = r20 ; Impulszähler
| 12 |
| 13 | ;Konstanten
| 14 | .equ PD = PORTD
| 15 | .equ DD = DDRD
| 16 |
| 17 | .equ PB = PORTB
| 18 | .equ DB = DDRB
| 19 |
| 20 | .equ F_CPU = 4000000 ; Systemtakt in Hz
| 21 | .equ BAUD = 9600 ; Baudrate
| 22 |
| 23 |
| 24 | ; Berechnungen
| 25 | .equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1) ; clever runden
| 26 | .equ BAUD_REAL = (F_CPU/(16*(UBRR_VAL+1))) ; Reale Baudrate
| 27 | .equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000) ; Fehler in Promille
| 28 |
| 29 | .if ((BAUD_ERROR>10) || (BAUD_ERROR<-10)) ; max. +/-10 Promille Fehler
| 30 | .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
| 31 | .endif
| 32 |
| 33 | ;Vektoren
| 34 | .org 0x0000
| 35 | rjmp configurations
| 36 | .org 0x0001
| 37 | rjmp int_1
| 38 | .org 0x0009
| 39 | rjmp timer0_overflow
| 40 |
| 41 | ;Interrupts
| 42 | int_1:
| 43 |
| 44 | ldi stat,1 ; Wenn Interrupt ausgelöst stat auf 1
| 45 | reti
| 46 |
| 47 | timer0_overflow:
| 48 |
| 49 | inc z2
| 50 | inc z1
| 51 |
| 52 | reti
| 53 |
| 54 | ;Sprungprgramme:
| 55 |
| 56 |
| 57 |
| 58 |
| 59 | configurations:
| 60 |
| 61 | ldi t1,LOW(RAMEND) ;Stackpointer LOW
| 62 | out SPL,t1
| 63 |
| 64 | ldi t1,HIGH(RAMEND) ;Stackpointer HIGH
| 65 | out SPH,t1
| 66 |
| 67 | ldi t1,0x00 ;PortD als Eingang
| 68 | out DD,t1
| 69 |
| 70 | ldi t1,0xFF ;Pullups PortD aktivieren
| 71 | out PD,t1
| 72 |
| 73 | ldi t1,0xFF ;PortB als Ausgang
| 74 | out DB,t1
| 75 |
| 76 | ldi t1,0xFF ;PortB Pullups deaktiviert
| 77 | out PB,t1
| 78 |
| 79 | ldi t1,(1<<ISC01)|(1<<ISC00) ; Interrupt auf steigende flanke
| 80 | out MCUCR,t1
| 81 |
| 82 | ldi t1,(1<<INT0) ; Interrupt auf INT0 aka PortD 2
| 83 | out GICR,t1
| 84 |
| 85 | ldi t1,(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0) ;Senden aktivieren UART
| 86 | out UCSRC,t1
| 87 |
| 88 | sbi UCSRB,TXEN
| 89 |
| 90 | ldi t1,(0<<CS02)|(1<<CS01)|(1<<CS00) ; Timer teiler 64
| 91 | out TCCR0,t1
| 92 |
| 93 | ldi t1,(1<<TOIE0) ; Interrupt bei Timer Interrupt
| 94 | out TIMSK,t1
| 95 |
| 96 | clr stat ; Alles auf null sezen
| 97 | clr z2
| 98 | clr z1
| 99 | clr z3
| 100 |
| 101 | sei ; Aktiviere Interrupts
| 102 |
| 103 | main:
| 104 |
| 105 | cpi stat,1 ;Wenn interrupt hat ausgelöst!
| 106 | breq i_1
| 107 | rjmp main
| 108 | i_1:
| 109 | clr stat ; stat auf null setzen
| 110 | clr z2 ; Timer auf null setzen für Wartezeit
| 111 | i_2:
| 112 | cpi stat,1 ; Prüfen ob Interrupt wären der Wartezeit ausgelöst hat!
| 113 | breq i_1 ; Wenn ausgelöst, springe zurück zu i_1
| 114 | cpi z2,10 ; Wenn wärend der Wartezeit kein Interrupt stattfand, wird der Impuls registriert!
| 115 | breq impuls
| 116 | rjmp i_2 ;
| 117 | impuls:
| 118 | cpi z3,0
| 119 | breq m_start
| 120 | m_ret:
| 121 | cpi z3,10 ; z3 Inkrementieren bis 10 Impulse
| 122 | brsh end
| 123 | inc z3
| 124 | clr stat
| 125 | rjmp main ; Zurück zu Anfang
| 126 | m_start:
| 127 | clr z1 ; Beim start, Zeitmessung beginnen
| 128 | rjmp m_ret ; Zurück zum Impuszähler
| 129 |
| 130 | end:
| 131 | sts count,z1
| 132 | cbi PB,0
| 133 | w_1:
| 134 | clr z2
| 135 | w_2:
| 136 | cpi z2,10
| 137 | breq w_3
| 138 | rjmp w_2
| 139 | w_3:
| 140 | sbi PB,0
| 141 | clr z3 ; Impulszähler auf null setzen
| 142 | clr stat
| 143 | rjmp main
| 144 |
| 145 | .dseg
| 146 | count: .BYTE 1
|
Lukas G. schrieb:
> Spielt generell es ein Rolle WO ich die Assemblerdirektive;
>
> .dseg
> count: .BYTE 1
>
> im Code selbst hinschreibe?
Vom Prinzip her ist es wurscht.
Alles was unter .dseg kommt wird gesammelt und dem SRAM zugewiesen (in
der Reihenfolge in der es von oben nach unten auftaucht)
Alles was unter .csef definiert wird, wird genaso gesammelt und dem
Flash zugewiesen (wieder von oben nach unten).
.dseg bzw. .cseg sind also so ähnlich wie Umschalter, die bestimmen
wohin das Nachfolgende gehört. Entweder SRAM oder Flash.
> Also ich meine nicht direkt im Code, sondern dort wo ich die Register
> deklariere also Am Ganz am Anfang, oder erst am Schluss?
Die Register definierst du sowieso nicht. Die gibt es schon. Was du
vereinbarst, das sind andere Namen für die Register. Da geht es aber
nicht darum, dass dafür irgendwelcher Code generiert werden soll oder
dass irgendwelche Speicherreservierungen im SRAM gemacht werden sollen,
sondern es geht einzig und alleine um eine Vereinabarung zwischen dir
und dem Assembler-Übersetzungspogramm "Hör mal. Wenn ich in Zukunft
'hamstibamsti' schreibe, dann meine ich damit das Register r18". Das
kann daher stehen wo es will, solange es nur vor der ersten Verwendung
des somit neu bekannt gemachten Namens passiert.
> Ich hab bei den ersten Versionen, das Codesegment ganz am Anfang
> deklariert, dann hat aber das Programm nicht mehr Funktioniert.
Was jetzt. Codesegment (.cseg) oder Datensegment (.dseg). Wenn weder das
eine noch das andere angegeben ist, dann ist automatisch das Codesegment
erst mal das 'aktive Segment'.
> Schreibe ich es am Schluss funktioniert alles wie gewünscht, waber warum
> ist das SO?
Weil du irgendeinen Fehler gemacht hast. Dann kann man aber nicht
eruieren, wenn du die Version zeigst, die dann letzten Endes
funktioniert.
Hallo,
.dseg ist das Datensegment, also der Ram. Kannst Du prinzipiell an
beliebige Stelle schreiben, Du mußt nur daran denken, wieder auf .cseg
(Codesegmeht) zu schalten, bevor Du wieder mit Programmcode schreibst.
Bei mir landen die .dseg-Sachen auch bei den Registerdefinitionen, vor
dem Begin der Vektoren steht dann generll bei mir
.cseg
;Vektoren
.org 0x0000
rjmp configurations
.org 0x0001
rjmp int_1
.org 0x0009
rjmp timer0_overflow
um bei Deinem Progarmm zu bleiben.
Gruß aus Berlin
Michael
Ich glaub ich weis vo der Hund begraben liegt.
.cseg
Muss ich also in demfall anwenden wie .nolist & .list
Habs gerade ausprobiert, und es hat Funktioniert!
Komischerweise steht davon im Tutorial nichts. Aber dort ist .dseg ja
auch am Schluss...
Besten dank für die Hilfe
mfg Lukas
Hallo,
Karl Heinz war wieder ausführlicher sehe ich gerade.
Ein Tipp von mir ganz allgemein:
verfalle nicht in den Trend, wenig tippen zu wollen.
Dann über lieber den Umgang nit Ctrl-c/ctrl-v, also kopieren/einfügen.
.equ PD = PORTD
.equ DD = DDRD
.equ PB = PORTB
.equ DB = DDRB
wenn schon, dann bei Deinem Programm:
.equ KEY_PORT = PORTD
.equ KEY_DDR = DDRD
.equ KEY_PIN = PIND
.equ LED_PORT = PORTB
.equ LED_DDR = DDRB
.equ LED_PIN = PB0
...
ldi t1,0x00 ;PortD als Eingang
out KEY_DDR,t1
ldi t1,0xFF ;Pullups PortD aktivieren
out KEY_PORT,t1
ldi t1,0xFF ;PortB als Ausgang
out LED_DDR,t1
ldi t1,0xFF ;PortB Pullups deaktiviert
out LED_PORT,t1
...
sts count,z1
cbi LED_PORT,LED_PIN
w_1:
clr z2
w_2:
cpi z2,10
breq w_3
rjmp w_2
w_3:
sbi LED_PORT,LED_PIN
clr z3 ; Impulszähler auf null setzen
clr stat
Ich habe nur eine Beispielstelle genommen.
Wenn Du jetzt die LED statt an PB0 an PC2 hängst, muß Du nur
.equ LED_PORT = PORTB
.equ LED_DDR = DDRB
.equ LED_PIN = PB0
in
.equ LED_PORT = PORTC
.equ LED_DDR = DDRC
.equ LED_PIN = PC2
"Spechende Namen" sind eine sehr praktische Hilfe, wenn man was ändern
will oder nach 2 Jahren wieder in das Programm schaut.
Gruß aus Berlin
Michael
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|