Servus Leute,
Erst mal zu meinem Vorhaben: Und zwar möchte ich ein PWM-Sinus erzeugen.
Bzw. immer nur die positive Halbwelle abwechseln auf 2 PWM-Ausgängen des
ATTiny13.
Jetzt hab mich mich ein wenig eingelesen und gelernt, dass es am
sinnvollsten ist ein paar Werte in den EEPROM zu schreiben und anhand
derer den Sinus zu generieren. Die Methode gefällt mir auch, nur mangelt
es mir an Programmierkunst, da ich leider noch nicht allzulange dabei
bin und mit EEPROM noch nie etwas gearbeitet habe. Desweiteren bin ich
recht froh C zu verstehen und auch ein wenig schreiben zu können,
allerdings beherrsche ich Assembler sicher nicht!
D.h. ich möchte mein kleines Projekt in C schreiben, auch wenn viele
sagen, dass der Tiny13 mit Assembler und sonst nix programmiert gehört.
Und nun zu meiner Frage:
Wie schreibe ich in den EEPROM rein und wie kann ich die Werte auch
wieder auslesen?
EEPROM: Sieh dir mal die Beschreibung des Tiny13 an - unter Memories
stehen Codebeispiele in ASM und C, wie man das macht.
C und Tiny13: da wirst du u.U. sehr schnell in Speicherplatznot kommen -
512 Codeworde sind schnell voll geschrieben. Man kann zwar durch
geschickte Codieren in C einiges rausholen, aber dazu muß man sich den
ASM-Output des Compilers ansehen - was aber auch eine gute Methode ist,
den Assembler zu lernen...
ah ja das im datenblatt habe ich soeben auch gefunden gehabt, nur hilft
mich dar gerade nicht zuu viel. Gibts da nicht auch irgendiwe so ein
Tutorial wie das AVR-GCC-Tutorial? Da würde meinem Verständnist stark
helfen!
Zu Assembler: Grundsätzlich will ich das schon noch lernen, aber jetzt
erstal uss ich C richtig lernen und beherrschen. Und da der Tiny13 nicht
mehr als dieses geteilet Sinussignal erzeugen soll, hab ich kein problem
mit mangeldem Speicher denke ich.
Hi, ich hatte sowas mal für einen Tiny25 gebastelt, allerdings die Werte
nicht im EEPROM (Quelltext anbei).
Würde ich nur heute anders machen, bastel dir einfach einen Schwingkreis
(LC) mit der gewünschten Resonanzfrequenz, den du mit einer einfachen
PWM der gewünschten Frequenz pulst.
Grade mal versucht auf einem Tiny13 zu kompilieren:
1. TIMSK heisst dort TIMSK0
2. Sind es zu viele Werte für den Speicher.
(Nur die Hälfte der Sinuswerte nehmen und spiegeln!)
Idee zum EEPROM:
1
OCR0A=eeprom_read_byte(counter);
Setzt vorraus das die Sinuswerte ab 0x00h im EEPROM liegen, allerdings
ist dieser NICHT schnell genug um die Daten in der ISR zu liefern!
gast wrote:
> ah ja das im datenblatt habe ich soeben auch gefunden gehabt, nur hilft> mich dar gerade nicht zuu viel. Gibts da nicht auch irgendiwe so ein> Tutorial wie das AVR-GCC-Tutorial? Da würde meinem Verständnist stark> helfen!
Zu dem Thema EEPROM schreiben/lesen gibt es - zumindest aus
Softwaresicht - nicht mehr zu sagen, als im Datenblatt steht, aber du
kannst ja hier mal gucken:
http://www.mikrocontroller.net/articles/Speicher#EEPROM> Zu Assembler: Grundsätzlich will ich das schon noch lernen, aber jetzt> erstal uss ich C richtig lernen und beherrschen. Und da der Tiny13 nicht> mehr als dieses geteilet Sinussignal erzeugen soll, hab ich kein problem> mit mangeldem Speicher denke ich.
Du wirst dich wundern, wie schnell der Tiny13 voll ist...
Uhu Uhuhu wrote:
> Du wirst dich wundern, wie schnell der Tiny13 voll ist...
Ohne jetzt einen Glaubenskrieg (ASM vs. C) anzuzetteln, aber das Problem
ist diesmal wirklich das DATA Segment und da wirst du nix mit ASM dran
optimieren können, 64 Byte bleiben 64 Byte und da bekomme zumindest ich
nur 64 Byte rein^^
PS: Nach Anpassung mit Spiegelung in C:
Program: 234 bytes (22.9% Full)
(.text + .data + .bootloader)
Data: 41 bytes (64.1% Full)
(.data + .bss + .noinit)
Tim T. wrote:
> Uhu Uhuhu wrote:>> Du wirst dich wundern, wie schnell der Tiny13 voll ist...>> Ohne jetzt einen Glaubenskrieg (ASM vs. C) anzuzetteln,
Nimms nicht tragisch, war nicht böse gemeint...
Hey super Danke euch.
Den Code von Tim T. finde ich Spitze! Danke!
Zur Arraylänge kann ich sagen, dass die sich vierteln lässt, da ich ja
mit sin(0) -> sin(90) -> sin(0) schon wieder ne halbwelle habe.
Die Idee mit dem EEProm hatte ich nur um eben den Flash zu entlasten,
aber wenn das passt, dann ists mir so auch lieber.
Zu meinem Verständis hätte ich aber doch noch ein paar kleine Fragen:
(auch wenn ich den EEPROM in diesem Projekt dann also doch nicht nutzen
werde will ich doch etwas über ihn lernen...)
-Ihr sag der EEPROM sei zu langsam. Ist denn der Flash schneller, oder
wird das Array automatisch in den SRAM abgelegt?
- Wie schnell ist denn der EEPROM überhaupt?
-Und allgemein zum EEPROM. Den muss ich ja nicht bei jedem programmstart
neu schreiben bzw. würde das ja auch keine entlastung für den
Flash-Speicher sein. Also wie bekäme ich das Array in den EEPROM? Muss
ich da erst ne Software drauflasen, mit der ich über RS232 o.ä. in den
EEPROM reinschreibe und dann neu Flashen mit der Software die das dann
nutzt oder wie ginge sowas in meinem Fall?
EEPROM: Lesen geht recht flott, aber das Schreiben braucht lange - wie
beim Flash auch.
Die AVRs sind Harvard-Maschinen - die können keinen Code aus RAM oder
EEPROM ausführen. http://de.wikipedia.org/wiki/Harvard-Architektur
gast wrote:
>Zur Arraylänge kann ich sagen, dass die sich vierteln lässt, da ich ja>mit sin(0) -> sin(90) -> sin(0) schon wieder ne halbwelle habe.
Klar, das kann man mit ner Viertelperiode machen, wird nur wieder etwas
aufwändiger.
>Die Idee mit dem EEProm hatte ich nur um eben den Flash zu entlasten,>aber wenn das passt, dann ists mir so auch lieber.
Da das Programm sonst nur 2 Byte im Data Segment belegt, bleiben dir 62
Byte. Im EEPROM hingegen hast du volle 64 Byte, lohnt also ansich nicht.
>Ihr sag der EEPROM sei zu langsam. Ist denn der Flash schneller, oder>wird das Array automatisch in den SRAM abgelegt?
Ja der Flash ist schneller und nein, es wird vorher nicht ins SRAM
kopiert.
>Wie schnell ist denn der EEPROM überhaupt?
Der Zugriff dauert afaik 4 Takte, aufs Flash 2 Takte. Demnach halb so
schnell. Sollte aber solange du mit CPU-Takt/8 die PWM benutzt gehen,
sonst könnte es bei großen OCR0A Werten (z.B. 254) Probleme geben da vom
Compare(254) bis zum Update (255) der OCR0A noch keinen neuen Wert hat.
Ergo ist meine Aussage oben, das der EEPROM nicht schnell genug für die
Verwendung in der ISR ist, zumindest beim reinen Lesezugriff, als
relativ zu betrachten^^
>Und allgemein zum EEPROM. Den muss ich ja nicht bei jedem programmstart>neu schreiben bzw. würde das ja auch keine entlastung für den>Flash-Speicher sein. Also wie bekäme ich das Array in den EEPROM? Muss>ich da erst ne Software drauflasen, mit der ich über RS232 o.ä. in den>EEPROM reinschreibe und dann neu Flashen mit der Software die das dann>nutzt oder wie ginge sowas in meinem Fall?
Nein, es wäre in der Tat nicht so sinnig den bei jedem Programmstart neu
zu schreiben. Für das Beschreiben des EEPROMS kannst du im AVR Studio
unter View -> Memory -> EEPROM die Bytes von Hand setzen und dann beim
Beschreiben "Use Current Simulator EEPROM" auswählen. Oder du erstellst
ein EEPROM.hex File das du reinschreibst. Oder du bastelst ein Programm
was mal eben das Sinustabellen Array ins EEPROM schreibt und löschst den
EEPROM dann nicht mehr, bzw. liest den EEPROM aus und schreibst ihn in
ein Hexfile.
Ansonsten zum lernen:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#EEPROM
und
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Speicher#EEPROM_2
Uhu Uhuhu wrote:
>Die AVRs sind Harvard-Maschinen - die können keinen Code aus RAM oder>EEPROM ausführen. http://de.wikipedia.org/wiki/Harvard-Architektur
Stimmt, ist aber für die Fragestellung nicht ganz passend, natürlich
kann man DATEN aus jeder Datenquelle verarbeiten, nur das PROGRAMM muss
im Flash stehen. Wo das Array mit den Werten steht ist egal.
Im Datenblatt vom ATTiny bin ich glaube ich auch ein stück schlauer
geworden. Die daten werden wohl erst aus den EEPROM in ein Register im
SRAM gespeichert und könnn von dort aus verarbeitet werden. Jetzt
dämerts auch was man mir vor eingen Jahren mal über Mikrocontroller
erzählt hatte. (Damals konnte ich mit glück einen Transistor als
Schalter Verwenden)
Aber nochmal zurück zum Code von Tim T. Kann das sein, dass das keine
saubere Sinuswelle ergibt? wenn ich das so richtig sehe, dann wird dort
der Falsche interrupt verwendet. Nämlich der "Timer/Counter Compare
Match A"-Interrupt. Dies dürfte meiner Meinung nach zu einer Kurve wie
dem in folgendem Beitrag führen:
Beitrag "Re: PWM-Sinus"
Wenn man stattdessen den "Timer/Counter Overflow"-Interrupt verwendet,
werden die gleichmäßig breit ausgerechneten Abschnitte der Sinuskurve
auch gleichmäßig breit wiedergegeben.
Oder liege ich da falsch?
gast wrote:
> Viel Text.
Der Quelltext benutzt die Fast PWM Variante, in der Einstellung das der
Ausgang bei 0x00 auf 1 und beim Match auf 0 gesetzt wird, der Zähler
zählt allerdings IMMER bis 0xFF, absolut unabhänig welcher Interrupt
ausgelöst wird. Der Wert von ORC0A die On-Tastzeit an. Die PWM Periode
geht immer von 0x00 bis 0xFF und läuft mit einer Frequenz von
F_CPU/(Vorteiler*256), bei 8MHz und einem Vorteiler von 8 etwa
3906,25Hz. Und da ich hintereinander die 78 Werte ausgebe, jeder braucht
eine PWM-Periode, teilt sich dabei diese Frequenz nochmals durch 78 und
ich komme auf etwa 50,08 Hz.
Der Timer Compare Match A wird ausgelöst wenn Zähler = OCR0A.
Der Timer Overflow wird ausgelöst wenn Zähler = 0xFF.
Auswirkungen auf das Zählerverhalten haben diese Interrupts nicht.
Wenn man wie du es vorschlägst den Overflow Interrupt benutzt, kommt
dieser immer nach der gleichen Zeit beim überlauf von 0xFF nach 0x00,
nur ist das ansich schon zu spät um ORC0A noch vor dem nächsten
Durchlauf zu ändern (die komplette ISR muss vorher durchlaufen werden),
da der Wert von OCR0A intern schon bei BOTTOM (0x00) übernommen wird.
Bei meiner Variante wird der nächste 0RC0A Wert schon beim Compare
geschrieben, man hat somit mehr Zeit (höchster Wert der Sinustabelle war
glaubich 254). Somit hat man (256-254)*Vorteiler -> 16 Takte Zeit bis
der Wert aus dem ORC0A intern übernommen wird.
Achso ja... Ok hast mich überredet. Ich hab aus irgendeinem Grund
gedanklich bei jedem Komparematch den Counter gelöscht, was aber
irgendwie keinen Sinn gibt. Naja Fehler passieren.
Aber danke für deine ausführliche Antwort.
Dass und wann OCR0A übernommen wird wusste ich gar nicht.
Tim T. schreib:
>>Program: 234 bytes (22.9% Full)>(.text + .data + .bootloader)>>Data: 41 bytes (64.1% Full)>(.data + .bss + .noinit)
Wie kommst du zu diesen Angaben? ich benutze WinAVR und war der festen
Überzeugung das hast das schon mal angezeitg aber ich weiß einfach nicht
wie?!
gast wrote:
>Achso ja... Ok hast mich überredet. Ich hab aus irgendeinem Grund>gedanklich bei jedem Komparematch den Counter gelöscht, was aber>irgendwie keinen Sinn gibt. Naja Fehler passieren.>Aber danke für deine ausführliche Antwort.
Kein Akt, hatte selber als ich das Programm gebastelt hab den Denkfehler
mit dem Timer Overflow gemacht.
>Dass und wann OCR0A übernommen wird wusste ich gar nicht.http://www.atmel.com/dyn/resources/prod_documents/doc8126.pdf
Seite 73 in der Tabellenspalte "Update of OCRx at"
Komischerweise übernimmt der Tiny13 das OCRx laut der Tabelle im
Datenblatt schon beim erreichen von TOP (0xFF) in Mode 3.
Der Tiny25 in Mode 3 allerdings erst bei BOTTOM (0x00):
http://www.atmel.com/dyn/resources/prod_documents/doc2586.pdf
Seite 82.
Kurzer Vergleich mit 5 Weiteren Datenblättern ergab das alle bei BOTTOM
aktualisieren, demnach geh ich von einem Druckfehler im Datenblatt des
Tiny13 aus...
> Wie kommst du zu diesen Angaben? ich benutze WinAVR und war der festen> Überzeugung das hast das schon mal angezeitg aber ich weiß einfach nicht> wie?!AVR Studio -> View -> Toolbars -> Build Output (Haken davor machen)
Wenn da ein Haken ist, einfach auf Build im Unteren Fenster gehen, nach
dem Build stehen die Infos dann da.
> AVR Studio -> View -> Toolbars -> Build Output (Haken davor machen)> Wenn da ein Haken ist, einfach auf Build im Unteren Fenster gehen, nach> dem Build stehen die Infos dann da.
Der Haken ist gesetzt und unter build steht bei mir nur
Build started 6.1.2009 at 09:34:22
avr-gcc -mmcu=attiny13 -Wall -gdwarf-2 -DF_CPU=4000000 -Os
-fsigned-char -Wp,-M,-MP,-MT,test.o,-MF,dep/test.o.d -c ../test.c
avr-gcc -mmcu=attiny13 test.o -o test.elf
avr-objcopy -O ihex -R .eeprom test.elf test.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load"
--change-section-lma .eeprom=0 -O ihex test.elf test.eep
c:\Programme\AVR\WinAVR\bin\avr-objcopy.exe: --change-section-lma
.eeprom=0x00000000 never used
Build succeeded with 0 Warnings...
Da werde ich wohl noch Google nach unbekannt durchforsten müssen...
Trotzdem aber vielen vielen Dank.
gast wrote:
> Da werde ich wohl noch Google nach unbekannt durchforsten müssen...> Trotzdem aber vielen vielen Dank.
Naja, ganz so schlimm ist es ja nicht:
Beitrag "AVR Memory Usage ausgeben lassen"
Ansonsten mal in dein Makefile ob dort
## Build
all: $(TARGET) xxx.hex xxx.eep xxx.lss size
und
size: ${TARGET}
@echo
@avr-size -C --mcu=${MCU} ${TARGET}
drin steht.
wahrscheinlich mach ichs falsch aber es funktioniert bei mir nicht.
Warum auch immer.
Wenn ich das makefile Exportiere und da dann diese Zeilen einfüge (die
1. zwei sind schon vorhanden, die unteren nicht), dann noch das Exterene
Makefile verwenden und Compilieren. Und schon gibt er mir ne
Fehlermeldung:
Makefile:69: *** missing separator. Stop.
Das ist die Zeiel: @echo
Suche ich allerdings irgendwoanders das Standardmakefile (gefunden in
...\WinAVR\sample\ ) dann passiert nix und nutze kein externes Makefile,
dann passiert nix.
Ärgert mich jetz langsam!