PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Interrupts fur Anfanger



Arexx-Henk
08.03.2005, 22:10
Hallo Robotiker,

Ich habe immer schwierigkeiten wenn's um Interrupts geht.
Dann mahl ist dies und dann mahl ist dass wieder nicht in ordnung und lauft nichts.

Ich hab timer/counter0 benutzt um die grune Led jede Sekunde ein und aus zu schalten. Da gibts zwei programme in eine Datei.

Dass 1e Teil benutzt die timer/counter0 'overflow' Fahne und dass 2e Teil benutzt die timer/counter0 Interrupt. Beide machen die Led ein und aus.

Hab viel kommentar im Program beigeschrieben.

Hoffne mahl dass jemand etwas daraus lernen kann.

Gruss

Henk

Banzai
09.03.2005, 08:45
Hallo Leutz,

der Code oben ist mir völlig fremd (und ich dachte, ich kann C).
Mein größtes Problem ist, das bei z.B. ASURO.C manche Dinge irgendwie nirgends definiert werden und von Datenblättern bzw. Schaltplänen habe ich soviel Ahnung, wie ein Hund vom eierlegen.

Meine Frage ist, wie man eine Funktion im ASURO aktivieren/ programmieren/ irgendwiereinbringen kann, die einen 'Tick'-Wert in millisekunden zurückliefert, seit der Robbie eingeschaltet wurde. Da die Register, so vermute ich mal, keine 64Bit-Superlong sind, wäre der Wert vielleicht ein 2-Byte int(?). Wäre schön, so eine Funktion in die asuro.c mit zu übernehmen und vielleicht hat jemand in diesem Forum sich darüber schon Gedanken gemacht und diese Interrupt-Beispiel scheint ja irgendwie damit zu tun zu haben.

Greets


Banzai

Weja
09.03.2005, 15:36
Siehe auch :
https://www.roboternetz.de/phpBB2/viewtopic.php?t=7571
erweiterte ASURO Bibliothek.
Weja

Arexx-Henk
09.03.2005, 18:09
Hallo Banzai (und andere die's nicht verstehen)



der Code oben ist mir völlig fremd (und ich dachte, ich kann C).


na ja, dass ist auch ein bisschen Schade...
aber dass kann ich mich vorstellen.

z.B. 'abracadabra, sim sala bim...'

========================================
TCCR2 &= ~ ( (1<<CS22) | ( 1<<CS21) | (1<<CS20) )

TCCR2 ist ein register im Atmega8L chip, ein Timer/counter2 control register.
========================================
CS22 ist nicht anderes als 2 (wieso denn?)

in test.c steht irgendwo #include "asuro.h"
dass heisst an dieser stelle sollte mann eigentlich die Datei asuro.h zwischenfugen, aber da wird die test.c Datei so gross und unubersichtlich und es ist einfacher um hier asuro.c zu includen statt complet zu kopieren.

aber, aber...

in asuro.h steht auch wieder #include <avr/io.h>, #include <avr/interrupt.h> und #include <avr/signal.h>

ai, ai....und wass sehe ich irgendwo in avr/io.h? nah,
#elif defined (__AVR_ATmega8__)
# include <avr/iom8.h>

und wenn wir in <avr/iom8.h> gucken, dort steht irgendwo
#define CS22 2
#define CS21 1
#define CS20 0

so fur CS22 kann man auch '2' lesen

ich hab nicht gesagt dasses einfach ist

<avr/iom8.h> ist die datei C:\WinAVR\avr\include\avr\iom8.h, ja, ja

========================================
TCCR2 &= ~ ( (1<<CS22) | ( 1<<CS21) | (1<<CS20) )

anders geschrieben
TCCR2 &= ~ ( (1<<2) | ( 1<<1) | (1<<0) )

aufmerkung zwischendurch: binair heist so wass wie 'bitweis'.

1<<2 heist, die 1 wird zweimahl nach links geschoben, oder
binair: aus 0000 0001 wird 0000 0100
oder
hex: aus 0x01 wird 0x04

anders geschrieben
TCCR2 &= ~ ( (0x04) | (0x02) | (0x01) )

die '|' damit is ODER gemeint

(0x04) oder (0x02) oder (0x01) ist dass gleiche wie
binair: 0000 0100 = hex: 0x04
binair: 0000 0010 = hex: 0x02
binair: 0000 0001 = hex: 0x01
------------------------------ oder, oder, macht zusammen
binair: 0000 0111 = hex: 0x07

seuche, seuche...

========================================
TCCR2 &= ~ ( (1<<CS22) | ( 1<<CS21) | (1<<CS20) )
ist gleich wie
TCCR2 &= ~ ( 0x07 )

'~' heisst 'invertiere mahl'

so ~( 0x07 ) ist gleich
~ (binair: 0000 0111) = (binair: 1111 1000) = hex: 0xF8

========================================
TCCR2 &= ~ ( (1<<CS22) | ( 1<<CS21) | (1<<CS20) )
ist gleich wie
TCCR2 &= 0xF8
ist gleich wie
TCCR2 = TCCR2 & 0xF8
ist gleich wie
TCCR2 = TCCR2 UND 0xF8

anders gesagt

binair: 0110 0011 = TCCR2, mit ein beispiel inhalt, VOR der anderung
binair: 1111 1000 = hex: 0xF8
----------------------------- jetzt ein UND function bitweise durchfuhren
binair: 0110 1000 = hex: 0x68 = resultat dass wieder zuruck geschrieben wird nach TCCR2

jetzt kan mann sehen dass die rechter 3 bits in TCCR2 jetzt '0' sind unabhagig wass vorher in die rechter 3 bits von TCCR2 war
und dass die linker 5 bits in TCCR2 sich NICHT geanderd haben

so, sosososo,

========================================
TCCR2 &= ~ ( (1<<CS22) | ( 1<<CS21) | (1<<CS20) )
ist nicht anderes als mache die 3 rechter bits in TCCR2 mahl alle drei '0' und lass die ubrigen bits ungeandert.

Bis soweit diese Sendung,

ich wunsche ihnen einen gute nacht

gruss,

Henkes

Arexx-Henk
09.03.2005, 20:04
kleine fehler...

:Haue ai, auwah!

binair: 0110 0011 = TCCR2, mit ein beispiel inhalt, VOR der anderung
binair: 1111 1000 = hex: 0xF8
----------------------------- jetzt ein UND function bitweise durchfuhren
binair: 0110 1000 = hex: 0x68 = resultat dass wieder zuruck geschrieben wird nach TCCR2 IST FALSCH

binair: 0110 0000 = hex: 0x60 = resultat dass wieder zuruck geschrieben wird nach TCCR2 IST GUT

gruss

Henk

Grave80
14.03.2005, 19:45
hi,
versuch heute schon den ganzen tag die motoren mittels C anzusprechen ohne asuro.h einzubinden
bekomm das einfach nicht hin ,
wie macht ihr das???
könntet ihr da vielleicht ein Codeschnipsel posten, wie gesagt aber ohen einbindung der asuro.h

müsste dann irgendwie so ähnlich aussehen:

DDRB |= (1 << PB1) | (1 << PB2);
PORTB |= (1 << PB5);
PORTD |= (1 << PD5);
OCR1A = 0xFF;
OCR1B = 0xFF;

mfg der Grave

Arexx-Henk
14.03.2005, 22:12
Hallo Grave80

ich hab mahl was zusammen gebastelt.



//NICHT VERGESSEN DIE asuro.c DATEI LEER ZU MACHEN!

//denn die MAKEFILE will asuro.c auch compilieren, und
//weil 'asuro.h' nicht 'included' ist entstehen compilerfehler
//wenn 'asuro.c' leer ist gibts kein fehler und daurt das flashen mahl ganz kurz!

#include <avr/io.h>

int main(void){

//linker motor forwarts/ruckwarts signalen als ausgang schalten
DDRD|=(1<<PD5)|(1<<PD4);

//linker motor forwarts/ruckwarts signalen hoch schalten (inaktief)
PORTD|=(1<<PD5)|(1<<PD4);

//rechter motor forwarts/ruckwarts signalen als ausgang schalten
DDRB|=(1<<PB5)|(1<<PB4);

//rechter motor forwarts/ruckwarts signalen hoch schalten (inactief)
PORTB|=(1<<PB5)|(1<<PB4);

//geschwindigkeits kontrol beider motoren als ausgang schalten
DDRB|=(1<<PB2)|(1<<PB1);

//timer/counter1 prescaler faktor 64 einstellen (nur fur die deutlichkeit bit fur bit programmiert)
TCCR1B&=~(1<<CS12); //CS12 niedrich
TCCR1B|= (1<<CS11); //CS11 hoch
TCCR1B|= (1<<CS10); //CS10 hoch

//ausgang OC1A hoch/niedrich schalten (wie die ausgang auf timer1 reagieren soll)
TCCR1A|=(1<<COM1A1)|(1<<COM1A0);

//ausgang OC1B hoch/niedrich schalten (wie die ausgang auf timer1 reagieren soll)
TCCR1A|=(1<<COM1B1)|(1<<COM1B0);

//timer1 mode 5 selektieren (nur fur die deutlichkeit bit fur bit programmiert)
TCCR1B&=~(1<<WGM13); //WGM13 niedrich
TCCR1B|= (1<<WGM12); //WGM12 hoch
TCCR1A&=~(1<<WGM11); //WGM11 niedrich
TCCR1A|= (1<<WGM10); //WGM10 hoch

//linker motor forwarts
PORTD&=~(1<<PD4);

//rechter motor forwarts
PORTB&=~(1<<PB4);

//linker moter ungefahr ein drittel von maximale geschwindigkeit (0x00 = full speed, 0xFE = am langsahmsten)
OCR1A=0xA0;

//rechter motor ungefahr ein drittel von maximale geschwindigkeit (0x00 = full speed, 0xFE = am langsahmsten)
OCR1B=0xA0;

//UND LOS GEHT'S!!!

//warte hier
while(1);

//verlasse die function (wird niemahl ausgefurt, sonst kompilierer warnung)
return 0;

}


/*

Einige bemerkungen:

- allein bits hoch programmieren ist ganz gefahrlich weil mann nicht da von ausgehen sollte
dass bits die niedrich sein sollten dass schon vorher sind!
Mann weiss nie wie das boot-programm die bits hinterlasst.
Hat mich schon mache stunde gekostet!

- timer1 kent 15 verschiedene modes (mode 5 is gewahlt)

mode 5 lass timer1 hochzahlen von 0 bis 255 und wieder zurck zahlen nach 0 und wieder hoch zahlen, usw.

mode 5:

COM1A0/COM1A1 beide hoch heisst: (OC1A = linker motor geschwindigkeits reglung)
- wenn timer1 hoch zahlt und gleich OCR1A ist wird ausgang OC1A hoch
- wenn timer1 zuruck zahlt und gleich OCR1A ist wird ausgang OC1A niedrich

COM1B0/COM1B1 beide hoch heisst: (OC1B = rechter motor geschwindigkeits reglung)
- wenn timer1 hoch zahlt und gleich OCR1B ist wird ausgang OC1B hoch
- wenn timer1 zuruck zahlt und gleich OCR1B ist wird ausgang OC1B niedrich

Wie hoher die OC1A/OC1B wert je kurzer ist die ausgang OC1A/OC1B hoch und lauft die motor langsamer

Die prescaler ist auf 64 gewahlt dass macht die taktfrequenz vom timer1 gleich:
8MHz (externen oszillator) geteilt durch 64 macht 488Hz aber weil die timer1 hochzahl und zuruck zahlt
bleiben 488Hz/2 = 244Hz ubrich, dass ist die frequenz womit die IC1A/OC1B pinnen pulsieren.


PORTD PD5 PD4
hoch hoch = linker motor beide anschliessungen hochohmig/unterbrochen
hoch niedrich = linker motor vorwarts
niedrich hoch = linker motor zuruckwarts
niedrich niedrich = linker motor beide anschliessungen mit plus verbunden

PORTB PB5 PB4
hoch hoch = rechter motor beide anschliessungen hochohmig/unterbrochen
hoch niedrich = rechter motor vorwarts
niedrich hoch = rechter motor zuruckwarts
niedrich niedrich = rechter motor beide anschliessungen mit plus verbunden


gruss

Arexx-Henk


*/


gruss

Henk

UlliC
15.03.2005, 19:01
//linker motor forwarts/ruckwarts signalen als ausgang schalten
DDRD|=(1<<PD5)|(1<<PD4);


Hallo Henk,

ich gehe mal davon aus, daß PD5 = 5 ist etc.

Ist
DDRD|=0x30;
dann nicht kürzer und übersichtlicher ?
Wo ist der Vorteil bei der Bitschieberei ?
Gruß
Ulli

Arexx-Henk
15.03.2005, 19:55
Hallo UlliC

Da hast Du recht.

DDRD|=(1<<PD5)|(1<<PD4);
ist gleich wie
DDRD|=0x30;


ich gehe mal davon aus, daß PD5 = 5 ist etc.
in die 'included' Datei avr/io.h wird Datei iom8.h angerufen und darin steht zum Beispiel:
#define PD5 5
io.h und iom8.h sind die Dateien:
C:\WinAVR\Avr\include\avr\io.h
C:\WinAVR\Avr\include\avr\iom8.h


Dass ganze Program kann mann auch so schreiben:

DDRB = 0x33;
PORTB = 0x20;
DDRD = 0x30;
PORTD = 0x20;
TCCR1A = 0xF1;
TCCR1B = 0x0D;
OCR1A = 0xA0;
OCR1B = 0xA0;

Aber hier werden alle 8 bits pro byte geschrieben.
Da sollte mann sich genau bedenken wie die ubrige bits (die nicht fur
die Motorsteurung benotigt sind) zu schalten sind so dass keine unerwunsten effekte auftreten.


Wo ist der Vorteil bei der Bitschieberei ?
Dass Vorteil ist dass mann nur die bits zur sache andert und die ubrige bits nicht andert.

Die schreibeweise (1<<PD5) wird in Atmega datasheets genutzt und die Asuro entwickler haben dass so ubernommen.
Deshalb hab ich dass beispiel auch so geschrieben und alles etwas ausfuhrig notiert, nur zum besseren verstandnis.

Persohnlich finde ich die schreibweise (1<<PD5) ein bischen unschon und unubersichtlich, wenn mann ein bichen die bits kent ist DDRD|=0x20 besser zu lesen als DDRD|=(1<<PD5), aber vielleicht ist dass gesmacksache und sollte mann sich daran gewohnen.

gruss

Henk

UlliC
15.03.2005, 20:40
Dass Vorteil ist dass mann nur die bits zur sache andert und die ubrige bits nicht andert.

Hallo Henk,

danke für die guten Erklärungen.
Allerding: Mit der zusammengesetzten Zuweisung |= (bitweises ODER) werden doch immer nur die gesetzten Bits des rechten Operanden dem linken zugewiesen und der linke ansonsten nicht beeinflußt, oder ?

Ich glaube jetzt werde ich mir auch mal so einen Asuro zulegen....
Vielleicht krieg ich ihn ja zum Balancieren.

MfG
Ulli

Arexx-Henk
15.03.2005, 21:36
Hallo Ulli


Mit der zusammengesetzten Zuweisung |= (bitweises ODER) werden doch immer nur die gesetzten Bits des rechten Operanden dem linken zugewiesen und der linke ansonsten nicht beeinflußt, oder ?

Richtig!

beispiel1:
DDRD|=0x22
ist gleich wie
DDRD = DDRD | 0x22
ist gleich wie
DDRD = DDRD oder 0x22


0000 1111 (DDRD = 0x0F)
0010 0010 (|= 0x22) (oder 0x22)
------------
0010 1111 (DDRD = 0x2F)

mit |= macht jeden einzelne '1' bit (von 0x22)
aus ein '0' bit von DDRD ein '1' bit <== das ubereinstimmende bit wird '1'
aus ein '1' bit von DDRD ein '1' bit (bleibt '1')

beispiel2:
DDRD&=~0x22 ('~' heisst invertiert/umgekehrt)
ist gleich wie
DDRD = DDRD & ~0x22
ist gleich wie
DDRD = DDRD & 0xDD
ist gleich wie
DDRD = DDRD und 0xDD

0000 1111 (DDRD = 0x0F)
1101 1101 (&= ~0x22) (&=0xDD)
------------
0000 1101 (DDRD = 0x0D)

mit &= ~ macht jeden einzelne '1' bit (von 0x22)
aus ein '0' bit von DDRD ein '0' bit (bleibt '0')
aus ein '1' bit von DDRD ein '0' bit <== das ubereinstimmende bit wird '0'

|= macht einzelne bit(s) '1'
&= ~ macht einzelne bit(s) '0'


gruss

Henk

UlliC
15.03.2005, 22:19
Hi Henk,

das sieht klasse aus.
Vielleicht solltest Du das mal zusammenfassen und hier im Forum einen Artikel über AVR-C schreiben.

Gruß
Ulli