Hallo.... Ich programmiere derzeit an einem, für mich, "grösseren" Programm, und jetzt werden meine register knapp. Den Y und Z Pointer-Register benutze ich auch. Den X wollte ich mir noch freihalten für zukünftige Adressierungen. Nun möchte ich evt Register unterhalb r16 benutzen, allerdings habe ich nicht gefunden, WAS mann mit den unteren (r0-r15) Register NICHT machen kann. Wo finde ich die Informationen über die unteren register?
@André Menzel (killroymenzel) >Den Y und Z Pointer-Register benutze ich auch. >Den X wollte ich mir noch freihalten für zukünftige Adressierungen. Die muss man selten exclusiv freihalten, es reicht, sie in der jeweiligen Funktion zu nutzen. Die meisten Daten packt man so oser so besser in den SRAM und lädt sie bei Bedarf in die Register. >Nun möchte ich evt Register unterhalb r16 benutzen, allerdings habe ich >nicht gefunden, WAS mann mit den unteren (r0-r15) Register NICHT machen >kann. ldi, cpi ect. geht nicht. >Wo finde ich die Informationen über die unteren register? Im Assembler Instruction Set Manual vom AVR. Gibts bei Atmel zum Download.
Danke Falk........ Jetzt studiere ich erst mal das Instruction Set Nomenclature. André
In den meisten "größeren" Programmen empfiehlt es sich öfter gebrauchte Programmabläufe als Unterprogramme (mit "rcall") aufzurufen. Dabei muss man sich vorher überlegen, welche Daten in welchen Registern übergeben werden - und in welchen Registern das Ergebnis erscheinen soll. Alle anderen Register, die man im Unterprogramm benötigt, werden zu Anfang des Unterprogramms mit "push" auf dem Stack gesichert und vor dem Ende ("ret") mit "pop" so wiederhergestellt, wie sie vorher waren.
Mit den unteren Registern r0...r15 kannst Du alles machen außer:
1 | ldi |
2 | sbr + cbr |
3 | ser |
4 | cpi |
5 | subi |
6 | sbci |
7 | andi + ori |
8 | adiw + sbiw |
Diese Befehle stehen nur für r16...r31 zur Verfügung. Natürlich kann man auch r0 z. B. mit einem konstanten Wert laden; es erfordert halt zwei Instruktionen:
1 | ldi ZL, 248 |
2 | mov r0, ZL |
André Menzel schrieb: > Nun möchte ich evt Register unterhalb r16 benutzen, allerdings habe ich > nicht gefunden, WAS mann mit den unteren (r0-r15) Register NICHT machen > kann. Operationen mit "immediate" Operatoren, also Konstanten, die Teil des Befehlswortes sind. Also alles, was prinzipiell so aussieht Befehl Register,Konstante als da wären: ldi andi ori subi sbci sbr cbr Dazu kommen noch Befehle, die zwar auf Quelltextebene nicht sofort erkennbar dieses Muster haben, aber auf Opcode-Ebene der gleichen Klasse angehören. Dazu fällt mit im Moment nur ein Vertreter ein: ser Und, last but not least, ist auch die Verwendung bei der Multiplikation nur eingeschränkt möglich, während "mul" auch mit diesen Registern arbeitet, sind alle anderen Multiplikationsoperationen dazu nicht in der Lage.
Ich danke euch allen..... Wenn mein Programm wieder läuft, werde ich es hier auch mal vorstellen. Es ist eine Uhr mit normaler Weckfunktion Und einen Kalender, der mich daran erinnert den Müll, Papier und Gelbe Sack rauszubringen. Verwendung findet: DS1307 mit Batterie AT24C32 für den Kalender DS18B20 als Raumtemperatur LCD 16×2 zur Anzeige Derzeit noch mit einem ATMega128, Da ich noch nicht weiß wie groß das Programm wird. Momentan bin ich bei 9k Gesteuert bzw eingestellt wird das ganze mit dem PC-Terminal Ich hoffe ich schaffe das am Wochenende zum Laufen zu bekommen. später soll das ganze auf große 16 Segment oder DOTMatrix angezeigt werden. Und evt. mit SD und Netzwerk ausgestattet werden. Andre
ich mache das so
1 | .dseg |
2 | Ergebniss0: .byte 1 ;Reserviert jeweils 1 Byte im SRAM |
3 | Ergebniss1: .byte 1 |
4 | Ergebniss2: .byte 1 |
5 | Ergebniss3: .byte 1 |
6 | Ergebniss4: .byte 1 |
7 | Ergebniss5: .byte 1 |
8 | Ergebniss6: .byte 1 |
9 | Ergebniss7: .byte 1 |
10 | |
11 | Berechnung: |
12 | sts Ergebniss1, temp ;Ergebniss(Register) im SRAM speichern |
nachdem man es also im SRAM abgelegt hat kann man temp wieder anderweitig nutzen. Und wenn man das Ergebnis wieder braucht holt man es sich wieder in ein Register zurück.
1 | lds temp, Ergebniss1 |
Derzeit sieht das bei mir so aus:
1 | ;---------------------- |
2 | ;Register Defs |
3 | ;---------------------- |
4 | .def Null = r0 |
5 | .def DayOld = r1 ; |
6 | .def RTC_count = r2 ; |
7 | .def Adr1 = r3 ;TWI Word Adresse 1 |
8 | .def Adr2 = r4 ;TWI Word Adresse 2 (für EEProm) |
9 | .def full = r5 |
10 | .def half = r6 |
11 | .def accu = r16 ;Hauptarbeitsregister |
12 | .def temp = r17 ;Zählregister |
13 | .def index = r18 ;Hauptindex |
14 | .def IRQ_index = r19 ;IRQ sekundenzähler |
15 | .def TWI_IC = r20 ;TWI Ic Adresse |
16 | .def Flag = r23 ;Flag |
17 | |
18 | .equ restmuell = 0 ;restmuell rausstellen |
19 | .equ papiertonne = 1 ;Papiertonne rausstellen |
20 | .equ gelbersack = 2 ;Gelber Sack rausstellen |
21 | .equ WireError = 3 ;One Wire presence Error |
22 | .equ Flash_RAM = 4 ;Ausgabe aus Flash oder Ram |
23 | .equ LCD_RS232 = 5 ;Ausgabe auf LCD oder UART |
24 | .equ TWI_Adr = 6 ;2 Wordadresse nötig? |
25 | .equ Wecker_on = 7 ;Wecker ist aus oder an |
26 | |
27 | .def rawlow = r24 ;Rohwert DS18B20 LSB |
28 | .def rawhigh = r25 ;Rohwert DS18B20 MSB |
29 | .def nachkomma = r26 |
30 | |
31 | .equ DQ = 7 ;Datenleitung des Ds18B20 |
32 | .equ DS_DDR = DDRC ;Port des DS18B20 |
33 | .equ DS_Port = PortC ; |
34 | .equ DS_Pin = PinC ; |
35 | .equ LCD = PortB ;LCD-Datenport |
36 | .equ LCDDDR = DDRB ; |
37 | .equ LCMD = PortA ;LCD-kommandoport |
38 | .equ LCMDDR = DDRA ; |
39 | .equ EN = 1 ;Enable-Leitung |
40 | .equ RS = 0 ;Kommando / Daten Leitung |
41 | |
42 | .equ XTAL = 4000000 ;Quartzfrequenz |
43 | .equ BAUD = 19200 ;Baudrate für UART |
44 | |
45 | .equ DS1307 = 0xD0 ;TWI Adresse |
46 | .equ AT24C32 = 0xA0 ;TWI Adresse |
47 | |
48 | |
49 | /************************************************ |
50 | * Speicherreservierung im SRAM * |
51 | ************************************************/ |
52 | .dseg |
53 | Wecker_copy: .byte 5 ;Wecker Speicher |
54 | TWI_copy: .byte 32 ;I²C Temp Speicher |
55 | RomCopy: .byte 20 ;RomAdresse DS18B20 |
56 | Tempcopy: .byte 10 ;+xx,x°C |
57 | Timecopy: .byte 15 ;xx:xx:xx_ |
58 | DateCopy: .byte 15 ;xx.xx.20xx |
59 | DayCopy: .byte 20 ;Mo____ |
60 | RTC_Copy: .byte 10 ;Speicher zum RTC einstellen |
61 | CompareCopy: .byte 5 ;temporärer Speicher |
:
Bearbeitet durch User
Sprachenmix bei Bezeichnern ist allgemeine ein schlechter Stil. Lege
dich doch auf eine Sprache fest.
Vor allem innerhalb EINER Variablen ist es übel:
> Wecker_on
Und ist es wirklich Sinnvoll konkrete Ereignisse fest
einzuprogrammieren? Wenn dann würde man doch das Definieren von
beliebigen Terminen bzw. Erinnerungen vorsehen. Selbst wenn es keine
Interaktion von aussen ist, sollte man einen solchen Mechanismus
wenigstens innerhalb des Programmes vorsehen.
:
Bearbeitet durch User
cyblord ---- schrieb: > Sprachenmix bei Bezeichnern ist allgemeine ein schlechter Stil. Lege > dich doch auf eine Sprache fest. Da muss ich dir leider rechtgeben. Allerdings ist das Programm "naturgewachsen", so dass noch viiel schlimmere Dinge passiert sind......
1 | Beispiel: |
2 | LCD_Tag: ldi zl,low(Wochentag*2) |
3 | ldi zh,high(Wochentag*2) |
4 | rjmp LCD_string |
5 | LCD_Datum: ldi zl,low(Datum*2) |
6 | ldi zh,high(Datum*2) |
7 | rjmp LCD_string |
8 | LCD_Zeit: ldi zl,low(Uhrzeit*2) |
9 | ldi zh,high(Uhrzeit*2) |
10 | rjmp LCD_string |
11 | LCD_Time: rcall LCD_home |
12 | ldi zl,low(TimeCopy) |
13 | ldi zh,high(TimeCopy) |
14 | rjmp LCD_stringram |
15 | LCD_Temp: cursor,9,0 |
16 | ldi zl,low(tempcopy) |
17 | ldi zh,high(tempcopy) |
18 | rjmp LCD_stringram |
19 | LCD_Day: rcall LCD_2z |
20 | ldi zl,low(DayCopy) |
21 | ldi zh,high(DayCopy) |
22 | rjmp LCD_stringram |
23 | LCD_Date: cursor,6,1 |
24 | ldi zl,low(DateCopy) |
25 | ldi zh,high(DateCopy) |
26 | rjmp LCD_stringram |
ABER..... Wenn ich das ganze Programm zum laufen bekomme, werde ich organisatorisch noch viel zu ändern habe.
:
Bearbeitet durch User
killroymenzel schrieb: > ABER..... Wenn ich das ganze Programm zum laufen bekomme, werde ich > organisatorisch noch viel zu ändern habe. Die Frage ist, ob und in welcher Zeit du das Programm in seiner aktuellen Form zum Laufen bekommst. Der Ansatz "Ich mach mal alles Quick & Dirty, und am Schluss räume ich auf" funktioniert halt bei größeren Projekten nicht mehr wirklich. Zumal das Aufräumen in der Praxis sowieso oft weg fällt, weil das nächste Projekt schon ruft. Coding Conventions und guten Programmierstil muss man soweit verinnerlichen, dass man das ganz automatisch macht ;). Mit freundlichen Grüßen, Karol Babioch
:
Bearbeitet durch User
Da gebe ich dir recht..... Ich habe die ganzen kleinen LCD Routinen schon wieder rausgeschmissen. ... Ich habe auch meine eigenen kleinen libs geschrieben, so dass ich bei bedarf nur noch die Sachen auf include setzen muss. So wie z.B. TWI LCD UART OneWire Es sieht mittlerweile auch schon ganz organisiert aus. Andre
killroymenzel schrieb: > Ich habe die ganzen kleinen LCD Routinen schon wieder rausgeschmissen. Das z.B. ist nicht einmal unbedingt notwendig. Sofern es Sinn macht entsprechende Sprungmarken anzulegen (weil man darauf referenziert), macht es ja nichts, wenn es davon viele gibt. Die Kunst ist es alles so lokal wie möglich zu halten, damit es nicht zu Namenskonflikten und anderen Nebeneffekten kommt. Und da sind die Assembler i.d.R. nicht annähernd so mächtig wie C und andere Hochsprachen. Soweit ich weiß (nie wirklich damit gearbeitet) bietet der AVR Assembler, welcher mit dem Atmel Studio mitgeliefert wird, hierfür keine Möglichkeiten. avr-as hingegen bietet Möglichkeiten, um externe Funktionen mittels "global" entsprechend zu markieren, sodass ein Großteil der internen Details eines Moduls verborgen werden kann. Mit freundlichen Grüßen, Karol Babioch
:
Bearbeitet durch User
killroymenzel schrieb: > Momentan bin ich bei 9k Für Assembler ist das schon recht heftig. Da ist bestimmt viel Copy&Paste drin, aber kaum Unterfunktionen. Oder meinst Du die Größe des Hex. Das Hex ist etwa 2,8 mal so groß, wie der wirkliche Code.
Peter Dannegger schrieb: > Oder meinst Du die Größe des Hex. Das Hex ist etwa 2,8 mal so groß, wie > der wirkliche Code. Wie kommst du zu dieser Zahl? Doppelt so viele Bytes wegen Hexdarstellung + Overhead durch Adressen und Prüfsummen?
Ja... ich meine das hex file...... Ich werde es heute abend testen und wenn es läuft lade ich es mal hoch..... Dann könnt ihr much zerreißen. ..... ;-) Andre
Hi >Derzeit sieht das bei mir so aus: >;---------------------- >;Register Defs >;---------------------- >.def Null = r0 >.def DayOld = r1 ; Würde ich nicht machen. R1 und R2 werden bei Benutzung des Hardwaremultiplizierers zerstört. Hier Beitrag "Kalender/Datum/Zeit-Funktionen in Assembler" hatte ich vor längerer Zeit mal einige Routinen zu Datum/Uhrzeit veröffentlicht. Evtl. kannst du etwas davon gebrauchen. MfG Spess
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.