Nabend zusammen,
ich hatte bis jetzt nur mit dem ATmega8 rumgespielt, da der im Tutorial
genutzt wird und da der Code nicht erst noch groß angepasst werden muss.
Zum grundlegenden Programmieren und lernen in Assembler fand ich das bis
jetzt besser, da ich mich dann nicht mit den Unterschieden der einzelnen
µC herum ärgern musste.
Da ich mir nun aber den AVR Dragon geleistet habe, musste natürlich auch
ein neuer µC Typ her, der das debuggen unterstützt. Da ist dann die Wahl
auf den ATmega88 gefallen, da der PIN-Kompatibel zum ATmega8 ist.
Als erstes habe ich mal versuchsweise ein bestehendes ATmega8 Projekt
für den ATmega88 ohne anpassung kompilieren wollen. Das ist natürlich
wie zu erwarten erstmal gründlich in die Hose gegangen. Somit bestätigte
sich die aussagen im Forum, das man nicht einfach bestehenden Code auf
einen anderen µC umstellen kann. Gut das soll auch nicht das Problem
sein, denn so bin ich nun gezwungen mich noch besser und intensiver mit
dem Datenblatt des ATmega88 auseinander zu setzen, was einem den
Controller und die Technik noch besser in das Gehirn meiselt.
Da ich in dem ATmega8 Projekt einen ADC drinne habe und das natürlich
gleich vom Kompiler am meisten bemeckert wurde, musste auch gleich das
Kapitel in dem Datenblatt herhalten. Dort sind mir dann auch ein paar
Unterschiede schon aufgefallen.
Mein Ziel ist es nun, das ich den ATmega88 und eventuell den ATmega168
als allround Controller nutzen möchte. Da aber Assembler ja keine so
schönen Libs bietet, wie es in C der fall ist, ist es natürlich
erstrebenswert wiederverwertbaren Code zu schreiben.
Das soll mal zum einstand gewesen sein. Nicht das ich euch noch
Informationen vorenthalte :-). Nun aber weiter zu dem Thema wo ich
eigentlich hin möchte.
Wie handhabt Ihr das? Ich denke ja nicht, das Ihr bei jedem Projekt, was
Ihr anfangen wollt, immer bei Null mit dem Code beginnt. Ich denke da
schon eher, das Ihr da irgendwelche Templates zurecht gebaut habt, die
euch das Grundgerüst zur verfügung stellen.
Gibt es da zufällig nette Beispiele, wie so ein Grundgerüst aufgebaut
sein kann, oder gibt es da auch schon fertiges im Internet, was man am
besten verwenden sollte. Das soll jetzt nicht bedeuten, das ich mir das
einfach per Copy&Paste kopieren möchte und dann nach mir die sinnflut
und ich will schnelle erfolge haben, sondern ich möchte einfach
inspirationen haben, wie ich mir meine eigenen Grundgerüste aufbauen
kann.
Wenn man Klassenorientiert programmieren kann, möchte man immer alles in
kleine teilbereiche zerlegen. Da finde ich im moment noch sehr schlecht
den Anfang. Zum Beispiel möchte ich mir jetzt eine Include Datei
erstellen, in der ich die Grundfunktionen des ADC fertig anlege. Also
das Initialisieren, den PORT-PIN auswählen zu können, den man Samplen
möchte usw.
Genau da habe ich nun auch im Datenblatt gelesen, das man den ADV im
Stromsparmodus explizit ausschalten soll. Das ist dann in meinen Augen
eine eigene Methode, die meine Include anbieten soll.
Hier mal etwas exemplarischen Code, wie ich mir den vorstelle.
1
ADC_ON:
2
ldi r16, (1<<ADEN)
3
out ADCSRA, r16
4
ret
5
6
ADC_OFF:
7
ldi r16, (0<<ADEN)
8
out ADCSRA, r16
9
ret
10
11
ADC_INIT:
12
rcall ADC_ON
13
...
14
ret
15
16
ADC_SLEEP:
17
rcall ADC_OFF
18
...
19
ret
20
21
usw...
Wie Ihr seht, schwirren mir da gerade sehr viele Gedanken durch den
Kopf. Ich komme eben aus der C# Welt und da ist alles in Klassen
versteckt. Da ist Assembler schon ein hartes Stück zum sich umgewöhnen.
Ich würde mich daher sehr freuen, wenn Ihr ein bisschen aus dem
Nähkästchen plaudert, wie Ihr das Professionell handhabt.
Grüße
Stephan
Hi
>Wenn man Klassenorientiert programmieren kann, möchte man immer alles in>kleine teilbereiche zerlegen. Da finde ich im moment noch sehr schlecht>den Anfang. Zum Beispiel möchte ich mir jetzt eine Include Datei>erstellen, in der ich die Grundfunktionen des ADC fertig anlege. Also>das Initialisieren, den PORT-PIN auswählen zu können, den man Samplen>möchte usw.
Kann man machen, wenn man lang genug mit Assembler programmiert hat und
dabei bleiben will.
Vor allem sollte man sein Werkzeug kennen:
>ADC_ON:> ldi r16, (1<<ADEN)> out ADCSRA, r16> ret
Zum einen machst du damit alle anderen Bits in ADCSRA platt und 'out'
funktioniert für ADCSRA beim ATMega8 aber nicht z.B. beim ATMega88.
MfG Spess
Für I/O nutzt man am besten Makros:
http://www.mikrocontroller.net/articles/AVR_Assembler_Makros#I.2FO
Die Defines von Atmel sind schon relativ portabel solange man keinen
größeren Umstieg von älteren zu neueren µCs macht. Von Atmega8-88 muss
man leider ein paar Register ändern. Von Atmega88-644 keine falls man
die I/O Makros benutzt hat.
spess53 schrieb:> Hi>>>Wenn man Klassenorientiert programmieren kann, möchte man immer alles in>>kleine teilbereiche zerlegen. Da finde ich im moment noch sehr schlecht>>den Anfang. Zum Beispiel möchte ich mir jetzt eine Include Datei>>erstellen, in der ich die Grundfunktionen des ADC fertig anlege. Also>>das Initialisieren, den PORT-PIN auswählen zu können, den man Samplen>>möchte usw.>> Kann man machen, wenn man lang genug mit Assembler programmiert hat und> dabei bleiben will.
Für mich steht jetzt schon fest, das ich wohl bei Assembler bleiben
werde. Auch wenn C eine verlockende schnelligkeit bietet um da etwas in
den Controller zu bekommen, hat es mir Assembler mehr angetan.
> Vor allem sollte man sein Werkzeug kennen:>>>ADC_ON:>> ldi r16, (1<<ADEN)>> out ADCSRA, r16>> ret>> Zum einen machst du damit alle anderen Bits in ADCSRA platt und 'out'> funktioniert für ADCSRA beim ATMega8 aber nicht z.B. beim ATMega88.
Danke für den Hinweis. Dann weiß ich gleich wo ich noch weiter lesen
muss.
Samuel K. schrieb:> Für I/O nutzt man am besten Makros:> http://www.mikrocontroller.net/articles/AVR_Assembler_Makros#I.2FO> Die Defines von Atmel sind schon relativ portabel solange man keinen> größeren Umstieg von älteren zu neueren µCs macht. Von Atmega8-88 muss> man leider ein paar Register ändern. Von Atmega88-644 keine falls man> die I/O Makros benutzt hat.
Auch Dir danke. Das mit den Makros muss ich mir dann mal noch genau
ansehen.
@spess53,
>Vor allem sollte man sein Werkzeug kennen:>>ADC_ON:>> ldi r16, (1<<ADEN)>> out ADCSRA, r16>> ret>Zum einen machst du damit alle anderen Bits in ADCSRA platt und 'out'>funktioniert für ADCSRA beim ATMega8 aber nicht z.B. beim ATMega88.
Ich habe darüber nochmal nachgedacht, was Du gesagt hast.
Hier mal ein Stück Code was die anderen Bits nicht überschreiben sollte.
Als erstes muss ich das Register auslesen, das ich die alten zustände
erhalten kann um dann ein Bit ändern zu können.
Liege ich da richtig?
1
ADC_ON:
2
in r16, ADCSRA
3
ori r16, (1<<ADEN)
4
out ADCSRA, r16
Lediglich das 'out' bekomme ich da nicht weg. Ich habe da im moment
keine Ahnung was es noch für einen Befehl dafür geben soll.
Grüße
Stephan
Hi
>Lediglich das 'out' bekomme ich da nicht weg. Ich habe da im moment>keine Ahnung was es noch für einen Befehl dafür geben soll.
IO-Register mit Adressen >= $60 werden wie RAM-Adressen mit lds/sts
statt in/out angesrochen. Kann man aber, wie schon gesagt auch durch ein
Macro erledigen:
.macro _out
.if @0<$60
out @0,@1
.else
sts @0,@1
.endif
.endmacro
Wird wie out benutzt:
_out ADCSRA, r16
Dazu gibt es auch eine AppNote von Atmel:
http://www.atmel.com/Images/doc2550.pdfhttp://www.atmel.com/Images/AVR001.zip
MfG Spess
Danke Spess,
das lese ich mir sofort durch. Habe den Code von oben eben getestet, was
ein Fehler gebracht hat.
Aber mit deiner Info kommt da schon Licht in sicht.
Eine eigene Frage?
Dieser Thread ist über 14 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.