Nein, das hast du falsch verstanden. Ich rede über das ATMEL_Atmega328P-PU Dokument von der Hauptseite. Angesprochene seite ist die 130. Dort wird es OCRnx statt C genannt.
Nein, das hast du falsch verstanden. Ich rede über das ATMEL_Atmega328P-PU Dokument von der Hauptseite. Angesprochene seite ist die 130. Dort wird es OCRnx statt C genannt.
ick find dit irgendwie netauf Seite 130 sind Diagramme und die Rede von OCR-1, OCR+1 usw
hier der Link
http://www.atmel.com/Images/Atmel-82..._datasheet.pdf
Achtung wenn du die Includedatei des µC öffnest dann siehst du das dort an einigen Stellen MOMERY MAPPED steht diese Adressen sind nur mit LDS/STS zu erreichen.
aber vielleicht hilft der Code ein wenig weiter
Code:rcall mode2_T0_init rcall prescaler_T0_on start: rjmp start mode2_T0_init:;CTC_MODE OCRx update sofort oder im INT sbi ddrd,6 ;output aktivieren wenn Toggeln am PIND6=OCR0A erwünscht ldi temp0,$80 ;Toggeln oder Clr/Set aktiv muss OCR0A-Register beachtet werden um out OCR0A,temp0 ;____--- oder _------ zu erreichen ;mit OCRyx wird die Frequenz festgelegt des Rechtecksignales lds temp0,TIMSK0 ori temp0,(0<<OCIE0B||0<<OCIE0A|0<<TOIE0) ;INTs aktivieren sts TIMSK0,temp0 ldi temp0,(0<<COM0B1|0<<COM0B0|0<<COM0A1|1<<COM0A0|1<<WGM01|0<<WGM00) ;zum Toggeln COMyx Einstellungen beachten!!!!!!!!! out TCCR0A,temp0 ; ldi temp0,(0<<FOC0A|0<<FOC0B|0<<WGM02) out TCCR0B,temp0 ret prescaler_T0_on: in temp0,TCCR0B ori temp0,(0<<CS02|0<<CS01|1<<CS00) ;schmeißt den counter out TCCR0B,temp0 sei ret OC0A_int: in temp0,OCR0A out OCR0A,temp0 reti
Danke für dein Beispiel.
In deinem Beispiel steht, das du mit OCR0A die Frequenz einstellst. In konnte mir nicht vorstellen wie du ein _------ Signal mit einem Festen Wert erzeugen möchtest. In der Doku habe ich dazu folgenden Satz gefunden:
Zur Erklärung, der TOP Value ist der Wert an dem Der Vergleich zwischen OCR0A und TCNT statt findet und der Wert wieder auf 0 gesetzt wird. Bedeutet ich setze in der ISR einfach einen neuen Wert bei OCR0A ein?If the interrupt is enabled, the interrupt handler routine can be used for updating the TOP value
Wieso nimmst du eigentlich den ORI befehl?
Quelle: http://www.atmel.no/webdoc/avrassemb...er.wb_ORI.htmlPerforms the logical OR between the contents of register Rd and a constant and places the result in the destination register Rd.
Übriegens, dein Link führt auf die Doku, die ich weiter oben meinte.
> Zur Erklärung, der TOP Value ist der Wert an dem Der Vergleich zwischen OCR0A und TCNT statt findet und der Wert wieder auf 0 gesetzt wird. Bedeutet ich setze in der ISR einfach einen > neuen Wert bei OCR0A ein?
jep so siehts aus. Aber solltest du den Mode ändern denn guck in die Tabelle welches Register als Vergleich herangezogen wird. Der Quellcode ist nur für den CTC-Modus (Autoreload) heißt, wenn OCR0A geändert wird, änderst du nur die Frequenz nicht aber das ON/OFF Verhältniss. Dafür müsstest du die FAST-PWM nutzen.
> Wieso nimmst du eigentlich den ORI befehl?
Der OR-Befehl bezieht sich direkt auf 2 Register die geodert werden, bei dem ORI-Befehl wird eine Konstante mit dem Register geodert. Der Klimzug mit dem ORI-Befehl habe ich nur deshalb gemacht wenn man den Timer noch andersweitig nutzt oder verändern will also kompatibel bleiben möchte.
> Übriegens, dein Link führt auf die Doku, die ich weiter oben meinte.
Check
Gruß avr_racer
Also erste Überlegungen:
Timer 0 kann mit einem Prescale von 1028 eine maximal Zeit von 13,15 mS erreichen bis zum Überllaufen
Timer 1 schafft eine Zeit von 3,36s
Meine Idee ist also, den Timer 0 auf einen Prescale von 8 einzustellen, dann ist die Laufzeit zum Overflow 102us. Das Vergleichs Register OCRA0 , stelle ich dann auf 0x64(100);
In der Routine des Vergleichs Vergleichs Interrupts, muss ich dann prüfen ob der Pegel High oder Low war und wie häufig es Überlaufe gab.
Nur mal als Idee.Code:ISR_Compare: inc r16 ; Zähle Überläufe sbic PORTB, 0 ; Prüfe ob Ausgang LOW jmp Pegel_Low sbis PORTB, 1 ; Überprüfe ob Ausgang High jmp Pegel_High ; Wenn nicht setze Ihn High reti Pegel_Low: cpi r16, 0x05 ; Überprüfe ob Wert 5; brne reti ldi r16,0x00 cbi PORTB,0 reti Pegel_High: cpi r16, 0x01 ; Überprüfe ob Wert 1; brne reti ldi r16,0x00 sbi PORTB,0 reti
Timer 1 würde ich als ICP fahren und damit die Messwert Laufzeit erfassen.
> Timer 0 kann mit einem Prescale von 1028 eine maximal Zeit von 13,15 mS erreichen bis zum Überllaufen
> Timer 1 schafft eine Zeit von 3,36s
ACHTUNG der Teiler ist max 1024 und bits max. 255bits machen 13,05...ms !!!!!! in längster Ausführung
> Meine Idee ist also, den Timer 0 auf einen Prescale von 8 einzustellen, dann ist die Laufzeit zum Overflow 102us. Das Vergleichs Register OCRA0 , stelle ich dann auf 0x64(100);
jo 8 ist gut und wenn du OCR0A mit 250 ($FA) beschreibts hast du alle 100µs eine OC0A Interrupt der ausgelöst wird und könntest diesen nutzen.
Warum auf 100? denn wird doch alle 40µs einer OVFL ausgelöst oder verstehe ich das jetzt falsch?
Du hast natürlich recht, ich war bei einem anderen Wert in Gedanken.
Ich habe jetzt einen Anfang gemacht und möchte das mit dem USART verbinden, allerdings klappt das nicht so wie ich das möchte.
Die Low Time ist jetzt auf 10ms eingestellt, wie könnte ich das erweitern auf 100ms mit einem 8 Bit Timer?
Es wäre lieb wenn Ihr einmal drüber schaut:
In der Doku steht:Code:.def temp = r16 .def value = r17 .def timer0 = r20 .def timer1_low = r21 .def timer1_high = r22 /* BEGINN DES HAUPTPROGRAMMES*/ Reset: ldi temp, HIGH(RAMEND) ; Stackpointer out SPH, temp ldi temp, LOW(RAMEND) out SPL, temp ldi temp, ( (1<<PD2) | (1<<PD3) ) ; Interrupt Pins auf Eingang, der Rest bleibt als Ausgang out DDRD, temp ldi temp, 0xFF ; PORTB wird als Ausgang gesetzt out DDRB, temp ldi temp, 0x00 out PORTD, temp ; Alle Pins auf 0 setzen (Die beiden Eingänge bekommen keinen Pull-Up) UART_Reset: ldi temp, HIGH(UBRR_VAL) sts UBRR0H, temp ldi temp, LOW(UBRR_VAL) sts UBRR0L, temp ldi temp, ( (1<<UMSEL00) | (1<<UCSZ01) | (1<<UCSZ00) ) ; synchron mit 8 Bit. sts UCSR0C, temp ldi temp, (1<<TXEN0) sts UCSR0B, temp Timer0_Reset: ldi temp, (1<<CS01) ; setze Vorteiler auf 8 out TCCR0B, temp ldi temp, (1<<COM0A1) ; der Ausgang wird immer beim Oberflow out TCCR0A, temp ; immer auf LOW gesetzt ldi temp, 0xFA ; 250 Schritte entsprechen genau 100us out OCR0A, temp ldi temp, (1<<OCIE0A) ; aktiviere Compare-Overflow Interrupt sts TIMSK0, temp Timer1_Reset: ldi temp, (1<<ICES1) sts TIMSK1, temp Loop: jmp Loop isUDRclear: ldi temp, UCSR0A sbis temp, 5 ; Überprüfe ob das UDR Register LEER ist !!! Hier ist der Fehler :" Invalid number" rjmp isUDRclear ; Wenn nicht bleibt in einer Schleife bis es so ist. sts UDR0, value ret nop Result_Output: mov value, timer1_low ; Timerwert auf den USART geben rcall isUDRclear mov value, timer1_high ; Timerwert auf den USART geben rcall isUDRclear rcall sync_0 jmp Loop Sound_On: cbi PORTD, 6 reti nop TIM0_COM: /*Die Pegel auf LOW setzen brauch nicht implementiert werden, da das von der HArdware gemacht wird*/ inc timer0 cpi timer0, 0x64 ; Damit wird der High Timer auf 10ms festgelegt. breq Sound_On reti nop TIM1_CAP: /*Hardware speichert Werte im RAM*/ ldi timer1_low, TCNT1L ldi timer1_high, TCNT1H reti nop
Wenn das so eingetippt wird, ist das UCSR0A Register nicht in der Range.Code:in r16, UCSRnA sbrs r16, UDREn
Ich muss mir noch etwas einfallen lassen, wie ich die Ausgabe zum PC mache, ohne das interrupt zu verlängern und ohne es im Main Loop die ganze Zeit ausgeben zu lassen
Liebe Grüße
Lesezeichen