Hallo,
Ich bin neu hier und Anfänger.
Ich habe zwei LED wechselnd zum Blinken gebracht mit dem Attiny 85,
mit folgendem Code in C
1
/*
2
* GccApplication25.c
3
*
4
* Created: 14.01.2015 22:24:28
5
* Author: mb_win 7
6
*/
7
8
9
#include<avr/io.h>
10
11
#define F_CPU 8000000UL //Taktfrequenz 8MHz
12
13
#include<avr/io.h>
14
#include<util/delay.h>
15
16
intmain(void){
17
DDRB|=(1<<PB0);// damit ist dann PB0 ein Ausgang
18
DDRB|=(1<<PB1);// damit ist dann PB1 ein Ausgang
19
20
while(1){
21
PORTB|=(1<<PB0);//PB0 im PORTB setzen
22
_delay_ms(250);//250ms warten
23
24
PORTB&=~(1<<PB0);//PB0 im PORTB löschen
25
_delay_ms(250);//250ms warten
26
27
PORTB|=(1<<PB1);//PB0 im PORTB setzen
28
_delay_ms(500);//500ms warten
29
30
PORTB&=~(1<<PB1);//PB0 im PORTB löschen
31
_delay_ms(500);//500ms warten
32
}
33
return0;
34
}
funktioniert wunderbar die zwei LED blinken abwechselnd.
Jetzt mein Problem. Ich habe keine Lösung wie ich die zwei LED
unabhängig blinken lassen kann. Wie kann ich zB. zwei Schleifen parallel
ablaufen lassen oder eine andere Lösung , mit unabhängigen,definierten
und genauen Blinkzeiten. Ich habe keine Idee und brauche Hilfe für einen
Lösungsansatz für den C-Code.
vielen Dank
Holger
Sieh dir mal die ziemlich gute Erklärung von einem Forumsmitglied zum
Ansatz der Protothreads an:
http://stefanfrings.de/avr_io/protosockets.html
Der "Trick" dahinter sind state machines, die mittels switch/case gelöst
werden. Je nach Anforderung und von dir investiertem Aufwand kannst du
dabei den Controller auch zwischen seinen Tasks schlafen legen.
Am besten wird es sein, wenn du möglichst vergißt, daß es eine Anweisung
"delay" oder "delay_ms" gibt. Stattdessen lies dich mal in das Thema
TIMER ein. Damit kannst du viele unabhängige Sachen gleichzeitig machen,
die sich dann auch nicht in die Quere kommen.
Im Forum findest du unzählige Beiträge zum Thema Timer.
Was brauchst du da für Erklärungen?
Du stehst da und beobachtest eine Uhr. Jedesmal wenn du den
Sekundenzeiger ticken hörst, streckst du sowohl in der linken als auch
in der rechten Hand einen Finger aus. Wenn du danach
* an der rechten Hand 3 ausgestreckte Finger siehst, schaltest du Lampe
1 um und ziehst die Finger der rechten Hand wieder ein
* an der linken Hand 4 ausgestreckte Finger siehst, schaltest du Lampe 2
um und ziehst die Finger der linken Hand wieder ein
Fazit: Lampe 1 wird alle 3 Sekunden umgeschaltet, Lampe 2 wird alle 4
Sekunden umgeschaltet.
Der Trick besteht darin, die 'Wartzeit' für das Umschalten von Lampe 1
bzw. Lampe 2 nicht als unteilbare Zeit zu sehen, sondern auf einen
gemeinsame kleinste Einheit runterzubrechen (hier: 1 Sekunde) und dann
einfach entsprechende Vielfache dieses gemeinsamen kleinsten Einheit
abzuzählen, wann die nächste Umschaltung fällig ist. Dieses Abzählen
kann aber für alle Lampen reihum nacheinander erfolgen. Bei jedem Tick
werden die Zähler aller Lampen um 1 erhöht.
Klar soweit?
Und jetzt studierst du den Code um die besprochenen Einzelteile im
Programm wieder zu finden.
LostInMusic schrieb:> int i = 0, k = 0;>> while(1){> i++; if (i==25) {i = 0; PB0_toggle;}> k++; if (k==53) {k = 0; PB1_toggle;}>> _delay_ms(10); // 10 ms warten> }>> return 0;Holger Weiß schrieb:> Ich bitte um eine kurze Erklärung zu diesem Code von LostInMusic.> vielen Dank
- i und k starten mit 0
- eine While-Schleife (Endlos)
- i wird erhöht, dann wird geprüft, ob i=25 ist
- wenn ja, wird i wieder auf 0 gesetzt und der Ausgangspin (PB0)
getoggelt
- das gleiche mit k
- anschließend wird 10ms gewartet
- dann wird ein neuer Schleifendurchlauf begonnen.
Hier auch wieder das delay. Wenn du den gleichen Code statt in eine
while-Schleife in eine Timer-ISR steckst, die aller 10ms aufgerufen
wird, hast du das gleiche Ergebnis, ohne daß sich der µC die ganze Zeit
mit Warten und Nichtstun beschäftigt. So wie hier kannst du nebenher
keine anderen Sachen machen (Tasten abfragen, Display ansteuern usw.)
Mit der Timer-Version kannst du es.
>So wie hier kannst du nebenher keine anderen Sachen machen
Und warum soll das nicht gehen? Hier wird doch auch schon das Blinken
der LED 2 nebenher zum Blinken der LED 1 gemacht (oder je nach
Betrachtungsweise andersrum)? Nach demselben Schema kannst Du zusätzlich
auch noch eine Taste parallel abfragen oder sonstwas veranstalten. Die
Regeln für jede "Veranstaltung" lauten halt, dass sie im 10
ms-Zeitraster stattfindet und selbst immer schnellstmöglich die
Kontrolle wieder an die main-Schleife zurückzugeben hat. Außer dem
delay_ms(10) darf es also nirgendwo sonst irgendwelche Delays geben.
Kooperatives Multitasking nennt sich der Spaß.
>Mit der Timer-Version kannst du es.
Mit einem Timer kann man das auch realisieren, und der Vorteil dieser
Variante ist der genaue Zeittakt. Ansonsten gibt es keinen
prinzipiellen Unterschied.
LostInMusic schrieb:>>Mit der Timer-Version kannst du es.>> Mit einem Timer kann man das auch realisieren, und der Vorteil dieser> Variante ist der genaue Zeittakt. Ansonsten gibt es keinen> prinzipiellen Unterschied.
Ich weiss, du hast das nicht so gemeint.
Aber einen prinzipiellen Unterschied gibt es: Mit einem Timer umzugehen
muss man erst mal lernen. Und genau da liegt das Problem: man kann nicht
alles auf einmal lernen.
Von daher würde ich es so bewerten: zur Zeit ist für den TO die delay
Lösung durchaus in Ordnung. Aber im Hinterkopf behalten, dass es
andere/bessere Lösungsansätze gibt, die dann interessant werden, wenn er
über mehr Wissen verfügt.
LostInMusic schrieb:> Und warum soll das nicht gehen?
So lange wie du das gesamte Programm, also alles was der µC machen
soll, in dieser einen Schleife machst, geht das. Aber was ist
beispielsweise mit Displayansteuerung, der Bedienung einer oder mehrerer
Schnittstellen (UART, CAN, Ethernet) oder Berechnungen, also alles was
Zeit braucht, geht das in die Hose. Denn alle Zeit, die nicht zum
Toggeln der beiden LEDs benötigt wird, frißt der µC mit dem delay
komplett auf.
Wenn du allerdings wirklich nur paar LEDs toggeln willst, kannst du das
gerne mit dem delay machen. Dann darfst du aber für später keine
Erweiterungen des Programms vorhaben...
So jetzt TO nochmal, den code von LostInMusic habe ich schon verstanden,
habe ihn aber nicht zum laufen gebracht ( bin bald verzweifelt und
wollte auch nicht dumm fragen). Ich habe herausgefunden das die Zeilen
i++; if (i==25) {i = 0; PB0_toggle;}
k++; if (k==53) {k = 0; PB1_toggle;}
mit den Attiny 85 nicht funktionieren, PB0_toggle geht so nicht. Ich
habe folgende Zeilen dafür geschrieben
i++; if (i==20) {i = 0; PORTB ^= (1<<PB0); } // zustandswechsel PB0
k++; if (k==10) {k = 0; PORTB ^= (1<<PB1); } // zustandswechsel PB1
und es funktioniert. Für den Anfang bin ich da schon ein bisschen Stolz
auf mich. Aber genaue vorbestimmte definierte Zeiten bekomme ich damit
nicht hin. Die dely Lösung, kooperatives Multitasking (war gut um etwas
zulernen. Heute Abend werde ich mit dem Timer weitermachen, ich verfüge
ja jetzt schon über mehr Wissen :-). Wenn ich am verzweifeln bin melde
ich mich wieder. Vielen Dank der Thread hat mich etwas weiter gebracht.
Für grundlegende praktische Tipps zum Timer für den Anfang wäre ich
dankbar.
Grüße Holger
der attiny 85 nimmt den Code fehlerfrei an aber es blinkt wie erwartet
nichts. Ich will hier niemanden zu sehr für mich beanspruchen. Für einen
Tipp würde ich mich freuen.
Holger
Fast. Du musst nur noch das Enable-Bit für Deinen Timer-Interrupt setzen
(TOIE0 im Register TIMSK).
>sei(); // enable timer interrupt
"enable all interrupts" triffts eher. sei bewirkt die globale
Interruptfreigabe, d. h. es lässt alle (aktivierten) Interrupts zu. Das
Gegenstück ist cli() - dies verbietet dem µC die Ausführung von
Interrupts (aber nicht das Vormerken etwaiger Interruptereignisse in den
zugehörigen Flags, um die Interrupts später behandeln zu können).
Manchmal ist es zum Schutz gewisser sensibler Codeteile nötig, alle
Interruptaktivitäten kurzzeitig zu sperren. Das erreicht man mit dann
mit "cli - [Code] - sei".
>PB0_toggle geht so nicht
Natürlich nicht, war doch nur ein Fantasiename zur Benennung der
Funktionalität.
Antwort:
Ja klar.
Einfach mal ein bischen nach unten scrollen.
Nein, nicht bis zum Eingabefeld. Ein bischen weiter oben. Grosse
Überschrift "Formatierungen"
Habe es jetzt geschafft eine LED blinkt im Takt 8MHz /256 /1024 /30
also mit 1,01725260421 /s. Kann man einen genauen Sekundentakt
programmieren und kann man mehrere Timer laufen lassen? Bitte einen
Tipp.
Kann man beim Timer auch einen Interrupt bei einen bestimmten
Zählerstand
zB. bei 200 auslösen oder geht der Interrupt nur beim Überlauf?
Fragen über Fragen.
Holger
>...Interrupt bei einen bestimmten Zählerstand zB. bei 200 auslösen
Ja! Die schlauen Entwickler von Atmel haben Deinen Wunsch vorausgesehen
;-) und dazu bestimmte Timer mit dem CTC Mode (Clear Timer on Compare
Match) ausgestattet.
- CTC Mode aktivieren.
- OCR0A auf gewünschten Wert setzen.
- Interrupt "Timer/Counter0 Compare Match" aktivieren.
- ISR(TIM0_OVF_vect) durch ISR(TIM0_COMPA_vect) ersetzen.
Der Timer0-Overflow-Interrupt ist dann überflüssig.
Für Details wie immer Datenblatt konsultieren.
Noch eine spezielle Frage zum Timer mit dem CTC Mode. Kann man
verschiedene
Interrupt Routinen über einen Timer ansprechen. zB bei Zählerstand 150
die Routine A und bei Zählerstand 230 die Routine B.
In einer Interrupt Routine des Timers die nächste ISR festzulegen also
beim nächsten Interrupt eine andere ISR auszuführen.
Kann man in der Hauptroutine auch Timer mit ISR festlegen die dann nur
einmal ausgeführt werden oder auch verschachtelt sind oder gehen die
Timer nit ISR nur global.
Meine Fragen deshalb weil die Anzahl der Timer je nach Chip begrenzt
ist.
Für praktische Tipps bin sich dankbar.
Grüsse Holger
Hilfe ich bin am Verzweifeln. Habe einen CTC Timer im Attiny 13
aktiviert.( Danke LostInMusic war sehr hilfreich für mich als Anfänger )
Mit der von mir berechneten Zeit funktioniert etwas nicht.
Nach meiner Berechnung sollte bei 9 MHz die ISR bei k=200 den Ausgang
umschalten in Sekundentakt. Um einen genauen Sekundentakt an der LED
einzustellen muss k=164 sein.(gemessen mit einen Zähler). Warum ist das
so?
Habe ich mich verrechnet, arbeitet der Attiny nicht mit 9MHz ( nach
meinen Berechnungen müsste er dann wesentlich unter 9Mhz arbeiten) ,
oder liegt es am C Code ( wird hier etwas verzögert).
In den Fuses ist INTRCOSC_9MHZ6_14CK_64MS eingestellt.( arbeitet er bei
9,6 MHz ? , ergibt aber bei meinen Berechnungen auch keinen Sinn)
Danke
> Habe ich mich verrechnet?
Ja hast du. Der R/C Oszillator hat 9,6Mhz und standardmäßig wird das
wegen der CLKDIV8 Fuse nochmal durch 8 geteilt, also 1,2Mhz.
Da du den Timer mit Prescaler 8 verwendest, ist die Taktfrequenz des
Timers 150kHz. Wenn du ihn bis 224 zählen lässt, tritt bei jedem 224.
Takt ein Interrupt auf. Also alle 2.493333 ms.
In der IRQ Routine teilst du die Frequenz nochmal durch 164, das ergibt
dann eine Umschaltung der LED alle 0.2449 Sekunden. Also fast 2 Hz.
Dein Kommentar bezüglichb Division durch 225 ist falsch. Wenn der Zähler
nur bis 224 zählt, dann musst du in der Berechnung auch durch 224
teilen. Die 0 erfordert keinen Takt, denn auf null wird der Zähler ja
bereits bei erreichen des Höchstwertes zurück gesetzt. Gleiches gilt
auch für deine Software-Zählung bis 164.
Wo hast du die 5000 her?
Habe es jetzt am Attiny 85 mit 8 MHz versucht:
- berechnet bei OCR0A = 199 : k = 200 und
- eingestellt bei OCR0A = 199 , k=148 um den Sekundentakt zu erhalten.
Was ist hier los ?????
Sorry, ich habe mich mit den 224 / 225 vertan. Der Zähler springt doch
erst einen Takt nach Erreichen des maximalen Wertes auf 0 um.
Aber damit ist dein Problem noch nicht geklärt.
> Was ist hier los ?????> // 9000000/8/225 entspricht 500 HZ
Nein, das entspricht 5000 Hz. Bei Dir läuft er jedoch anscheinend weder
mit 500 noch mit 5000 Hz.
Du solltest erstmal prüfen, ob der µC überhaupt mit der erwarteten
Taktrat läuft:
1
main() {
2
DDRB|=2;
3
while (1) {
4
PORTB^=2;
5
_delay_ms(1000);
6
PORTB^=2;
7
_delay_ms(1000);
8
}
9
}
So müsste die LED im Sekundentak an und aus gehen, also mit 0,5 Hz. Wenn
nicht, prüfe die CLKDIV8 Fuse. Wenn es dann immer noch nicht klappt,
hast du eventuell den Abblock Kondensator vergessen oder versehentlich
den Watchdog aktiviert.
Mach das erstmal, dann sehen wir weiter.
Als nächstes würde ich die Zählung in der ISR weglassen, damit der
LED-Ausgang anzeigt, wie hoch die Interrupt-Rate ist. Mess die mal mit
einem Frequenzzähler oder Oszilloskop nach. Falls du keins hast,
verbinde den Ausgang über einen 100k Ohm Widerstand mit der Soundkarte
und nimm den Ton auf. Dann kannst du mit einer Audio-Software (z.B.
Audacity) die Frequenz ermitteln.
Die CLKDIV8 Fuse ist raus. Beide arbeiteten nicht mit nochmal durch 8
geteilt. Die 5000 um einen definierten Zählwert ohne Komma im ms Bereich
zu erhalten um dann in der IRQ Routine mit ganzen Zahlen zu arbeiten.
5000 für einen Takt von 0,2 ms ( bei 1000 wäre es eine ms ,geht aber
nicht weil der der Zähler nur bis 255 geht.
!!!!! Ich glaube ich habe den Fehler gefunden, die IRQ Routine arbeitet
ja mit der Frequenz vom Chip und nicht mit Prescaler 8. Ich habe alles
zusammengeschmissen. !!! böser Fehler. Ich muss neu rechnen. Mal sehen
ob
es möglich ist genau einen Sekundentakt auszurechnen.
Beim Attiny 85 mit _delay_ms(1000) und #define F_CPU 8000000UL sind es
gemessen mit den Oszilloskop 993 ms. Ich müsste es mal mit einen
externen Quarz versuchen, mal sehen ob ich das schaffe. Ich werde es
versuchen.
Ist etwas besonderes beim Attiny mit externen Quarz zu beachten? Ein
Tipp wäre hilfreich.
Danke
Vorschlag:
- als Taktquelle den "Calibrated Internal Oscillator" wählen (8 MHz)
- CLKDIV8-Fuse enablen
- T/C0 im CTC-Mode mit Prescaler 64
- OCRA0 auf 125 setzen
Dann wird der Compare-Match-Interrupt mit 125 Hz aufgerufen (8000000 Hz/
8 64 125 = 125 Hz). Das ist ein ganz brauchbarer Wert.
In der ISR teilst Du die 125 Hz dann per Software auf 1 Hz runter:
1
k++;
2
if(k==125)k=0;
3
if(k==0)LEDFlash;// LED kurz aufblitzen lassen
Damit wird die LED fortwährend im Sekundentakt aufblitzen.
Um eine LED im Sekundentakt blinken (statt blitzen) zu lassen, musst
Du sie im Takt von 2 Hz togglen. 2 Hz lässt sich leider nicht erzeugen,
weil Du das k==125 natürlich nicht in k==62.5 ändern kannst
(mathematisch: 2 ist kein ganzzahliger Teiler von 125). Eine mögliche
Lösung:
Nein der Fehler war ich habe mit Prescaler 8 gerechnet und CS02 gesetzt
also Prescaler 256 programmiert. *Da kann nur Unsinn rauskommen.*
Noch mal zu Berechnung Attiny 8 Mhz, Prescaler 8 und OCR0A = 199 , also
aller 0,2 ms wird die IRQ Routine angwurfen. Um auf 1 Sekunde zu kommen
muß die ISR 5000 mal angefurfen werden. Die Zeit die die ISR verbraucht
spielt keine Rolle weil der Zähler unabhängig läuft.
Gemessen mit Oszilloskop sind es 994 ms das entspricht dem
_delay_ms(1000) gemessen 993 ms. *Ist die Differenz zur ganzen Sekunde
die Toleranz in der Frequenz ? oder habe ich noch einen Fehler?*
Gemessen mit einen alten RFT Zähler 994,19 ms bei 18 C°. Ich habe den
Attiny mit den Lötkolben eingheizt, da geht die Zeit gleich auf 989 ms
runter. Bei Wärme läuft der Attiny deutlich schneller.
Da ich erst seit seit 3 Tagen mich mit diesen Sachen beschäftige bin ich
schon stolz auf mich. Aber auch ein Lob an das Forum. Hier kamen einige
Denkanstöße. Alleine hätte ich vielleicht aufgegeben.
richtiger Code
Ich muss noch mal nerven zum Sonntag. Noch eine spezielle Frage zum
Timer mit dem CTC Mode.
Kann man verschiedene Interrupt Routinen über einen Timer ansprechen.
zB bei Zählerstand 150 die Routine A und bei Zählerstand 230 die
Routine B.
In einer Interrupt Routine des Timers die nächste ISR festzulegen also
beim nächsten Interrupt eine andere ISR auszuführen.
Kann man in der Hauptroutine auch Timer mit ISR festlegen die dann nur
einmal ausgeführt werden oder auch verschachtelt sind oder gehen die
Timer mit ISR nur global.
Meine Fragen deshalb weil die Anzahl der Timer je nach Chip begrenzt
ist.
Für praktische Tipps bin sich dankbar.
Grüsse Holger
Holger Weiß schrieb:> Kann man verschiedene Interrupt Routinen über einen Timer ansprechen.> zB bei Zählerstand 150 die Routine A und bei Zählerstand 230 die> Routine B.
nein, aber du kannst den Interrupt schneller kommen lassen und dann
mittels eines Zählers in der Interruptroutine verschiedene Aktionen
machen
Ein 8-Bit Timer und ein 16-Bit Timer kann doch unabhänig und
gleichzeitig laufen (oder?) und unterschiedliche ISR aufrufen oder sehe
ich das falsch ? oder ist nur eine ISR für Timer zugelassen die von
allen Timern aufgerufen wird ?
Holger Weiß schrieb:> Ein 8-Bit Timer und ein 16-Bit Timer kann doch unabhänig und> gleichzeitig laufen (oder?) und unterschiedliche ISR aufrufen
ja, pro Timer gibt es einen Satz Interuptroutinen, die Liste findet sich
im Datenblatt
Danke. Ist noch jemand am Computer? Ich werde morgen Abend mal einen
externen Quarz an den Attiny 13 oder 85 anschließen. Die Ungenauigkeit
in der Frequenz möchte ich abstellen und mit den genialen RFT Zähler
genaue Zeiten messsen bis auf die halbe_Femtosekunde :~) genau.
Meine Frage: Ich bin bei den Fuses nicht so sicher. 2 Attiny und einen
Atmega 32 habe ich schon unbrauchbar genacht mit Fuses. 1 oder 2 Tipps
für den exteren Quarz und den Fuses wären gut, weil heute Sontag ist.
Grüße Holger
>2 Attiny und einen Atmega 32 habe ich schon unbrauchbar genacht mit Fuses.
Dann bau mal mit dem nächsten µC einen Taktgenerator, mit f = irgendwas
zwischen 20 und 200 kHz. Falls sich die falsche Fuse-Einstellung bei
Deinen verunglückten Exemplaren auf die Taktquelle bezieht, kannst Du
sie mit einem externen Takt nämlich leicht "wiederbeleben".
Gute Nacht.
Holger Weiß schrieb:> Ich werde morgen Abend mal einen> externen Quarz an den Attiny 13 oder 85 anschließen.
Beim Tiny13 wird dir das kaum gelingen. Der kann keine Quarze
oszillieren lassen. Ein auch nur ganz flüchtiger Blick in's Datenblatt
hätte diesen Fakt auch für dich offenbart...
Wenn du beim Tiny13 einen Quarztakt haben willst, mußt du einen externen
Quarzoszillator benutzen.
> Meine Frage: Ich bin bei den Fuses nicht so sicher. 2 Attiny und einen> Atmega 32 habe ich schon unbrauchbar genacht mit Fuses.
Auch das hätte durch intensive Lektüre der Datenblätter vermieden werden
können.
Nimm' einfach mal zu Kenntnis: Wer lesen kann, ist klar im Vorteil.
Holger Weiß schrieb:> Ich bin bei den Fuses nicht so sicher. 2 Attiny und einen> Atmega 32 habe ich schon unbrauchbar genacht mit Fuses.
Im AVR-Studio ist die Auswahl der Fuses doch narrensicher.
Von RSTDISBL und DWEN Finger weg!
Dann hilft nur noch ein STK500 zum Wiederbeleben.
naja ich bin kein Narr, deshalb nicht sicher genug. habe doch etwas
falsches verstellt. Die Verstellen sind jetzt in der runden Ablage.
M
it dem Attiny 85 und externen Quarz sollte es funktionieren. Ich muss
mich nur noch schlau machen wie der Quarz angebaut wird und welche Fuses
ich setze. Damit ich mit den Timern weiter experimentieren kann.
Hat jemand eine interessante Anregung für einen Versuch oder eine
Aufgabe für mich zu dem Timern Attiny 85.
Holger
c-hater schrieb:> Nimm' einfach mal zu Kenntnis: Wer lesen kann, ist klar im Vorteil.
Genau. Dann hättest Du diesen Satz des TO vielleicht besser deuten
können:
Holger Weiß schrieb:> Da ich erst seit seit 3 Tagen mich mit diesen Sachen beschäftige bin ich> schon stolz auf mich. Aber auch ein Lob an das Forum. Hier kamen einige> Denkanstöße. Alleine hätte ich vielleicht aufgegeben.
SCNR
Eine Frage zum Timer. Ich habe herausgefunden, dass bei dem Code C jeder
Chip eigene Bezeichnungen für die Timer hat.
zB. attiny 85
TIMSK = (1 << TOIE0); // bei attiny 85
und bei attiny 13
TIMSK0 = (1 << TOIE0); // bei attiny 13
bei der Anpassung das Codes an den Atmega 32 scheitere ich. Stehen die
Programmbezeichnungen im Datenblatt? Bitte eine kurze Erklärung für
einen Anfänger.
Warning 1 'TIM0_COMPA_vect' appears to be a misspelled signal handler
[enabled by default]
Error 2 'TCCR0A' undeclared (first use in this function)
Message 3 each undeclared identifier is reported only once for each
function ............
Error 4 'TCCR0B' undeclared (first use in this function)
Error 5 'OCR0A' undeclared (first use in this function)
Error 6 'OCIE0A' undeclared (first use in this function)
hier der Code für Attiny 85 der funktioniert, den ich auf den Atmega32
senden will, da kommen die oben genanten Fehlermeldungen.
Holger Weiß schrieb:> bei der Anpassung das Codes an den Atmega 32 scheitere ich. Stehen die> Programmbezeichnungen im Datenblatt?
Ja.
> Warning 1 'TIM0_COMPA_vect' appears to be a misspelled signal handler> [enabled by default]
TIM0_COMP_vect, es gibt hier keine Unterscheidung A<->B.
> Error 2 'TCCR0A' undeclared (first use in this function)
TCCR0, aus demselben Grund.
> Error 4 'TCCR0B' undeclared (first use in this function)
dito.
> Error 5 'OCR0A' undeclared (first use in this function)
OCR0
> Error 6 'OCIE0A' undeclared (first use in this function)
OCIE0
Sämtliche Bezeichnungen findest Du im Datenblatt.
Du musst auch ein wenig aufpassen: Ab und zu "wandern" bestimmte Bits je
nach Atmega in verschiedene Register, z.B. bei den WGM-Bits. Hier
solltest Du immer erst ins Datenblatt schauen, auch wenn eine Zuweisung
erstmal augenscheinlich bei einer Portierung auf einen anderen ATmega
durch den Compiler geht. Deshalb hast Du noch keine Sicherheit, ob das
gesetzte Bit tatsächlich in dem benutzten Register tatsächlich steckt.
Holger Weiß schrieb:> Die Verstellen sind jetzt in der runden Ablage.
Nicht so voreilig.
Solange RSTDISBL und DWEN nicht verstellt sind, lassen sie sich mit
einem 2. ATtiny als Taktgeber wiederbeleben.
eine Fehlermeldung kam noch
So funktioniert es:
TIM0_COMP_vect musste noch TIMER0 COMP werden. beim Atmega32
ganz böse Fallen für den Anfang.
Beim Attiny 13: TIMSK0 |= (1<<OCIE0A) und TIM0_COMPA_vect
beim Attiny 85: TIMSK |= (1<<OCIE0A) und TIM0_COMPA_vect
beim Atmega 32: TIMSK |= (1<<OCIE0) und TIMER0_COMP_vect
Das kann ja noch kompliziert werden. Jetzt blinkt die LED in
Sekundentakt am Atmega 32.
Gibt es eine Zusammenstellung für die gebräuchlichen Chips und häufigen
Codes oder hilft hier nur das Datenblatt.
Bei der Zeitmessung der LED´s mit den Zähler konnte ich feststellen das
der Takt stark von der VVC abhängt, aber der Takt beim Atmega32 exakt
konstant gehalten wird, während bei de Attiny´s Schwankungen im Takt
auftraten.
Schwankung Attiny in der Konstanz um eine Millisekunde.
Schwankung Atmega 32 in der Konstanz nur um 0,03 Millisekunden.
falls das jemanden interessiert.
Ist es richtig wenn ich aller (0,2ms) 200 Zählertakte die ISR aufrufen
will OCR0A = 199 einzugeben da erst bei 200 die ISR angeht?
Holger Weiß schrieb:> Beim Attiny 13: TIMSK0 |= (1<<OCIE0A) und TIM0_COMPA_vect>> beim Attiny 85: TIMSK |= (1<<OCIE0A) und TIM0_COMPA_vect>> beim Atmega 32: TIMSK |= (1<<OCIE0) und TIMER0_COMP_vect
Mit Hilfe des Preprocessors kannst Du den Source einheitlich halten:
1
#if defined (__AVR_ATtiny87__)
2
TIMSK0|=(1<<OCIE0A);
3
#if defined (__AVR_ATtiny85__)
4
TIMSK|=(1<<OCIE0A);
5
#if defined (__AVR_ATmega32__)
6
TIMSK|=(1<<OCIE0);
7
#endif
Die ISR-Vektoren kann Du µC-spezifisch schreiben als:
1
#if defined (__AVR_ATtiny87__)
2
#define T0_COMP_vect TIM0_COMPA_vect
3
#if defined (__AVR_ATtiny85__)
4
#define T0_COMP_vect TIM0_COMPA_vect
5
#if defined (__AVR_ATmega32__)
6
#define T0_COMP_vect TIMER0_COMP_vect
7
#endif
Dann:
1
ISR(T0_COMP_vect)
2
{
3
....
4
}
Mit der Zeit wirst Du dann auf die Idee kommen, solche Konstrukte für
eigene "Bibliotheken" zu verwenden, um einen möglichst portablen Code zu
erhalten.
> Gibt es eine Zusammenstellung für die gebräuchlichen Chips und häufigen> Codes oder hilft hier nur das Datenblatt.
Datenblatt.
> Ist es richtig wenn ich aller (0,2ms) 200 Zählertakte die ISR aufrufen> will OCR0A = 199 einzugeben da erst bei 200 die ISR angeht?
Schaue hier: AVR-GCC-Tutorial/Die Timer und Zähler des AVR
External Crystal/Ceramic Resonator Einstellung:
Fuse Einstellung : EXTRCOSC_8MHZ_12MHZ_18CK_64MS ist richtig für den
externen Quarz 8 MHz an dem Atmega32 ?
Was sagen die 18CK und 64MS aus?
JA war richtig. super mit externen Quarz. Der Takt ist absolut genau
8MHz
Die LED blinkt absolut konstant mit 999,986 ms. Wenn ich den Quarz mit
dem Lötkolben einheize verändert sich die Zeit nur minimal auf 999,984
ms. Es ist schon erstaunlich was alles so in dem Chip steckt.
Habe jetzt meinen alten RFT Zähler G2001.500 angemacht und die Zeit
gemessen : 999,994 ms. Ein Spitzenwert. So habe ich mir das
vorgestellt.
Ich führe ja schon Selbstgespräche.
Hat jemand eine interessante Anregung für einen Versuch oder eine
Aufgabe für mich zu den Timern Attiny 85 oder Amega32 so zur Übung für
einen Anfänger.
Holger
Wie wäre es mit einer Lichtschranke ?
Da hätte man eine wenig Optoelektronik, auf dem Mµ Pinchange Interrupt
bzw. steigende\fallende Flanke mit ISR, EEprom bzw. ein Anzeigeelement
um die Zeiten auszugeben, ein wenig Logik, ein wenig Physik ...
Holger Weiß schrieb:> Hat jemand eine interessante Anregung für einen Versuch oder eine> Aufgabe für mich zu den Timern Attiny 85 oder Amega32 so zur Übung für> einen Anfänger.
Auf meiner Tiny-Projektliste steht noch ein "Briefkastenmelder". LED
hinter das Namensschild, wenn Klappe geöffnet wird (Reed Schalter) LED
an. Automatisch zurücksetzen, wenn die große Klappe zur Entnahme der
Briefe geöffnet wird.
Mal so als Idee. Ansonsten Google mal nach attiny Projekten.
Gruß Max
Ich werde mal einen Zeitmesser für die Belichtungszeiten meiner analogen
Kameras bauen, mit einer Anzeige an den Atmega32. Bisher habe ich die
Zeiten mit dem Zähler gemessen. Mal sehen hoffentlich ist das nicht zu
kompliziert für den Anfang.
Interessant wäre auch die Daten aus dem Analog-Digital-Umsetzer auf
einer SD Karte zu loggen mit einer txt Datei die man in Exel einlesen
kann.
Ist das möglich mit einen Atmega32 wie kann man eine SD Karte einbinden.
Ist das sehr kompliziert und welche Hardware brauche ich dazu.
Die Aufzeichnung soll ohne PC funktionieren.
Holger
Holger Weiß schrieb:> Ich werde mal einen Zeitmesser für die Belichtungszeiten meiner> analogen> Kameras bauen, mit einer Anzeige an den Atmega32. Bisher habe ich die> Zeiten mit dem Zähler gemessen. Mal sehen hoffentlich ist das nicht zu> kompliziert für den Anfang.>> Interessant wäre auch die Daten aus dem Analog-Digital-Umsetzer auf> einer SD Karte zu loggen mit einer txt Datei die man in Exel einlesen> kann.> Ist das möglich mit einen Atmega32 wie kann man eine SD Karte einbinden.> Ist das sehr kompliziert und welche Hardware brauche ich dazu.> Die Aufzeichnung soll ohne PC funktionieren.>> Holger
Als Hardware brauchst du eigentlich nur paar Widerstände und einen
SD-Karten-Leser. Schau doch mal bei Ulrich Radig vorbei:
http://www.ulrichradig.de/
und dann auf "AVR" gehen, dann auf "MMC/SD". Dort ist alles beschrieben.
Holger Weiß schrieb:> Interessant wäre auch die Daten aus dem Analog-Digital-Umsetzer auf> einer SD Karte zu loggen mit einer txt Datei die man in Exel einlesen> kann.
Sehr spannendes Vorhaben, es gibt ja nur (gefühlt) 20.000 Lösungen für
AVR-Datenlogger bisher...
Ich würde dir eher empfehlen, dir eine der bestehenden Lösungen zu
greifen und zu versuchen, sie bis zur letzten Zeile zu verstehen,
inklusive aller dort benutzten "Copy&Paste-Importe".
Da lernst du sehr viel mehr als mit noch viel mehr Copy&Paste und
sinnlosem Rumgefrage in 1000 Jahren lernen kannst...
c-hater schrieb:> Sehr spannendes Vorhaben, es gibt ja nur (gefühlt) 20.000 Lösungen für> AVR-Datenlogger bisher...
Du vergißt wiedermal, daß er noch vor 4 Tagen das hier geschrieben hat.
Holger Weiß schrieb:> Ich bin neu hier und Anfänger.> Ich habe zwei LED wechselnd zum Blinken gebracht mit dem Attiny 85,
Und vor paar Minuten hat er danach gefragt:
Holger Weiß schrieb:> Hat jemand eine interessante Anregung für einen Versuch oder eine> Aufgabe für mich zu den Timern Attiny 85 oder Amega32 so zur Übung für> einen Anfänger.
Mußt du da wirklich wieder einen deiner arroganten Kommentare ablassen?
Er will lernen und braucht was als Übung.
npn schrieb:> Du vergißt wiedermal, daß er noch vor 4 Tagen das hier geschrieben hat.
Nein, das hab' ich nicht vergessen.
> Er will lernen und braucht was als Übung.
Genau das ist, was ich meine. Copy&Paste übt und lehrt garnix und
erzeugt so auch keinerlei Kompetenz, um was wirklich eigenes machen zu
können.
Ja das ist schon richtig, c-hater. nur Copy&Paste lernt nichts.
Mir geht es nicht um Copy&Paste. Das kenne ich aus meinem Beruf. Ohne
grundlegendes Verständnis und Copy&Paste wird das Ergebnis nur
schlechter Gut Entwickeltes wird an einer anderen Stelle oder bei
punktuellen Anpassungen ohne Verständnis nur schlechter und fehlerhaft.
Aber ich brauche schon einen Anfang und ich will das Rad nicht neu
erfinden. Wenn ich etwas schon Erfundenes nehme zum üben, für mich
anpasse und damit Prinzip verstehe, komme ich ein ganzes Stück weiter.
Die eine oder andere Frage taucht halt mal auf beim experimentieren und
ein paar Denkanstöße und Hinweise für den Anfang sind schon sehr
hilfreich. Die eine oder andre eigene kleine sinnvolle Anwendung will
ich dann schon mal eigenständig entwickeln können.
Holger
Hi
...und ich will das Rad nicht neu erfinden.
Dieser Spruch kotzt mich langsam an. Es ist der, den alle benutzen, die
nichts wirklich lernen wollen. Um zu wirklich zu lernen muss man ein
paar Räder neu erfinden.
MfG Spess
Holger Weiß schrieb:> Ich bin erstaunt, den Erfinder von Rädern hier anzutreffen.
Och... davon gibt es sogar mehrere ;-)
Aber manchmal ist es nicht verkehrt, das Rad neu zu erfinden. Auch Räder
können immer noch verbessert werden.
Holger Weiß schrieb:> Wie kann man aus dem c Code die Anzahl der verbrauchten Takte ableiten?
Indem man sich vom Compiler ein Assembler Listing erzeugen lässt und
dann für die Instruktionen Takte zählt.
Holger Weiß schrieb:> Ich bin erstaunt, den Erfinder von Rädern hier anzutreffen.
Wer Radmacher werden will, kommt nicht umhin mit einfachen Rädern sein
Handwerk erst mal zu lernen. Selbst wenn sich die dazu benutzte Technik
seit 3000 Jahren nicht wesentlich verändert hat.
Peter Dannegger schrieb:> Karl Heinz schrieb:>> Selbst wenn sich die dazu benutzte Technik>> seit 3000 Jahren nicht wesentlich verändert hat.>> Solange gibt es schon 3D-Drucker?
Klar, Schnitzeisen und ein Stück Holz.
Holger Weiß schrieb:> Wie kann man aus dem c Code die Anzahl der verbrauchten Takte ableiten?Karl Heinz schrieb:> Compiler ein Assembler Listing erzeugen lässt und> dann für die Instruktionen Takte zählt.
ist das nicht was für langweilige Winterabende?
ich setze einen Port am Anfang, am Ende wieder zurück und sehe die Zeit
auf dem Oszi, wieviel Takte das sind sehe ich ja an Zeit / Taktzeit
(=1/F_CPU)
Joachim B. schrieb:> ich setze einen Port am Anfang, am Ende wieder zurück und sehe die Zeit> auf dem Oszi, wieviel Takte das sind sehe ich ja an Zeit / Taktzeit> (=1/F_CPU)
Ich setze im Simulator 2 Brechpunkte und lasse mir die Zeit oder Zyklen
dafür anzeigen.
Joachim B. schrieb:> Holger Weiß schrieb:>> Wie kann man aus dem c Code die Anzahl der verbrauchten Takte ableiten?>> Karl Heinz schrieb:>> Compiler ein Assembler Listing erzeugen lässt und>> dann für die Instruktionen Takte zählt.>> ist das nicht was für langweilige Winterabende?
Natürlich.
Aber wenn mir das nächste mal an einem Winterabend langweilig ist,
strick ich mir erst mal ein Oszi :-)
(Wir ham ja nix ghabt, nachm Krieg. Was hamma denn ghabt? Nix hamma
ghabt!=
Mit Rädern kann man auch strickeln und häkeln. Wieder etwas gelernt! Ich
muss nur noch etwas üben.
Einen Oszi habe ich, ist ein guter Tipp.
Peter Dannegger schrieb:> Ich setze im Simulator 2 Brechpunkte und lasse mir die Zeit oder Zyklen> dafür anzeigen.
auch ein guter Tipp.
Ich werde mal testen ob bei den beiden Varianten die Zeiten gleich sind.
Danke Holger.
Peter Dannegger schrieb:> Ich setze im Simulator 2 Brechpunkte und lasse mir die Zeit oder Zyklen> dafür anzeigen.
Ja, und du fällst grandios auf die Schnauze, wenn du einen anderen
Compiler benutzt oder auch nur eine ander Version desselben Compilers
oder auch nur denselben Compiler mit anderen Optionen...
Für mich ist Programmieren etwas deterministisches. Ein
deterministisches Zeitverhalten gehört da ganz selbstverständlich dazu,
jedenfalls überall dort, wo es relevant ist, also eigentlich immer dann,
wenn man eine Hardware auch nur annähernd bis an ihre Leistungsgrenze
ausnutzen will (oder muss).
Alles andere ist Nasenpopelei. Das geht dann auch in C. Allerdings kann
man dann auch einfach die wirklich komfortablen echten Hochsprachen
dafür verwenden, dann gibt es keinen Grund mehr, sich mit der kruden
Syntax und den vielen eingebauten Sprachfallen von C rumzuschlagen...
Ich habe es mit dem Simulator getestet, aber nur mit 1 MHz. Da mußte ich
umrechnen zum Takt 8 MHz . Wo kann man im Simulator die Taktfrequenz
einstellen?
Im Ergebnis Timer blink LED
Gemessen mit OSZI 1000 ms
im Simulator mit Brechpunkt 1000 ms
also gleich.
c-hater schrieb:> Ja, und du fällst grandios auf die Schnauze, wenn du einen anderen> Compiler benutzt
Heißt das verschiedene Compiler unterschiedlich übersetzen.
Welche echten Hochsprachen, für dem Atmega 32 sind empfehlenswert.
Holger
Hallo Holger,
die folgenden beiden sind am meisten bekannt. Beide sind kommerziell,
sie haben jeweils auch Demo-Versionen, die eingeschränkt sind.
Ich habe aber selber mit beiden noch nicht gearbeitet, kann also keine
weiteren Aussagen dazu treffen.
http://www.mikroe.com/mikropascal/avr/http://www.e-lab.de/AVRco/
Daneben gibt es noch LunaAVR, macht auch keinen schlechten Eindruck und
wird ständig weiterentwickelt.
http://avr.myluna.de/doku.php
Ich denke, da hast du erstmal was zum Lesen und Testen...
mfg
Hallo Holger,
Holger Weiß schrieb:> Jetzt mein Problem. Ich habe keine Lösung wie ich die zwei LED> unabhängig blinken lassen kann. Wie kann ich zB. zwei Schleifen parallel> ablaufen lassen oder eine andere Lösung , mit unabhängigen,definierten> und genauen Blinkzeiten. Ich habe keine Idee und brauche Hilfe für einen> Lösungsansatz für den C-Code.
Bei einem Prozessorkern kann es keine echte parallele Verarbeitung
geben. Das ist auch in "großen" Betriebssystemen nicht anders. Die
angeblich parallele Verarbeitung wird in Wirklichkeit durch kleine
Prozessorzeitscheiben realisiert, die ein Scheduler sequentiell den
laufbereiten Prozessen/Threads zuteilt. Das nennt sich dann präemptives
Multitasking. Dafür gibt es auch einfache Bibliotheken für
AVR-Controller.
Ebenso ist die Anzahl der Timer begrenzt. Man kann aber beliebig viele
Softwaretimer mit nur einem einzigen Hardwaretimer simulieren. Dazu
führt man eine Liste aller Softwaretimer und deren Rückrufroutinen, am
besten sortiert nach der anstehenden Triggersequenz.
Joachim B. schrieb:> Holger Weiß schrieb:>> Wie kann man aus dem c Code die Anzahl der verbrauchten Takte ableiten?>> Karl Heinz schrieb:>> Compiler ein Assembler Listing erzeugen lässt und>> dann für die Instruktionen Takte zählt.
Diesen Rat solltest Du als Anfänger auf jeden Fall befolgen, du wirst
dabei viel Nützliches lernen.
Holger Weiß schrieb:> Welche echten Hochsprachen, für dem Atmega 32 sind empfehlenswert.
Hochsprachen sind Geschmackssache. Manche würden auch zum Beispiel C++
(von Arduino benutzt) nicht als Hochsprache bezeichnen. Pass auf, dass
Deine Frage nicht einen der berüchtigten Sprachkriege auslöst :)
LG, Sebastian
Peter Dannegger schrieb:
> Ich setze im Simulator 2 Brechpunkte und lasse mir die Zeit oder Zyklen> dafür anzeigen.
Ich finde keine Einstellmöglichkeit vom Takt im Simulator. Ich habe in
den Fuses des Simulators 8 MHZ eingestellt.
Es wird immer der Simulator mit 1 MHZ ausgeführt und die Fuses auf 1 MHZ
zurückgestellt.
Die Empfehlung Erst, wenn er dann mal läuft kannst du im Menü unter
"Debug" --> "AVR-Simulator-Options" den Typ und die Taktfrequenz
einstellen.....
Das finde ich im AVR Studio 6.2 nicht ???
Holger Weiß schrieb:> Die Empfehlung Erst, wenn er dann mal läuft kannst du im Menü unter> "Debug" --> "AVR-Simulator-Options" den Typ und die Taktfrequenz> einstellen.....>> Das finde ich im AVR Studio 6.2 nicht ???
Wenn der Simulator läuft, kannst du im Fenster Processor View die
Taktfrequenz einstellen. Also dort, wo auch der Cycle Counter und Stop
Watch in der Tabelle angezeigt wird. Da ist auch der Eintrag Frequency
vorhanden. Standardmäßig steht dort 1MHz. Ein Klick auf die Zahl und du
kannst beispielsweise 16MHz einstellen. Enter und das war's...
npn schrieb:> Holger Weiß schrieb:>> Die Empfehlung Erst, wenn er dann mal läuft kannst du im Menü unter>> "Debug" --> "AVR-Simulator-Options" den Typ und die Taktfrequenz>> einstellen.....>>>> Das finde ich im AVR Studio 6.2 nicht ???>> Wenn der Simulator läuft, kannst du im Fenster Processor View die> Taktfrequenz einstellen. Also dort, wo auch der Cycle Counter und Stop> Watch in der Tabelle angezeigt wird. Da ist auch der Eintrag Frequency> vorhanden. Standardmäßig steht dort 1MHz. Ein Klick auf die Zahl und du> kannst beispielsweise 16MHz einstellen. Enter und das war's...
Funktioniert's denn jetzt?
Hallo pnp,
Ja so funktioniert es exakt.
npn schrieb:> Daneben gibt es noch LunaAVR, macht auch keinen schlechten Eindruck und> wird ständig weiterentwickelt.> http://avr.myluna.de/doku.php
Ich habe heute mal mit LunaAVR den Compare Match Timer mit blink 1s
programmiert. Nach einigen Schwierigkeiten hat es funktioniert.
Hier das Beispiel.
1
avr.device=atmega32//Controller-Typ festlegen
2
avr.clock=8000000//Dem Compiler mitteilen mit welcher Taktrate der Controller läuft
Ist ähnlich Pascal meiner Meinung. Mit Pascal hatte ich mal vor 30
Jahren zu tun, danach bis jetzt nur Windows. Ich muss erstmal wieder
reinkommen in die Materie. Das Forum hier war sehr hilfreich.
Holger