Moin an alle Ich habe problem mit dieser interrupt routine angeschlossen ist ein ad-wandler bei gültigen wert (/drdy) springe ich in der int4 interrupt erzeuge 24 clk und schaue auf den daten pin ob high oder low und schreibe das in "gewicht" rein. als kontrolle setze ich "port G ." Der Port wird richtig gesetzt ,aber die variable bekommt nur 1 mit. Mit eine datenanalyser getestet. habe sonst mit keil gearbeitet und denke das irgendwas mit der syntax oder deklarierung nicht stimmt. Wem gerade dazu was einfällt .. volatile long gewicht; volatile unsigned char b_temp,i; volatile long gewicht_res; SIGNAL(SIG_INTERRUPT4) { EIMSK &= ~(1<<INT4); // INT4 sperren PORTG=0; PORTG=255; PORTG=0; PORTG=255; PORTG=0; PORTG=255; int4_counter++; // läuft wunderbar gewicht=0; b_temp = 0; for(i=0;i<24;i++) { gewicht=gewicht<<1; SETPIN(CLK_AD); SETPIN(CLK_AD);// zeitverzögerung SETPIN(CLK_AD); SETPIN(CLK_AD); SETPIN(CLK_AD); SETPIN(CLK_AD); SETPIN(CLK_AD); SETPIN(CLK_AD); CLRPIN(CLK_AD); CLRPIN(CLK_AD); CLRPIN(CLK_AD); CLRPIN(CLK_AD); if(PINE&(1<<PE4)) { gewicht=gewicht|1; // klappt nicht PORTG=255; // klappt auch wunderbar b_temp++; // klappt auch nicht ergebniss immer 24 } else { PORTG=0; // klappt auch wunderbar } } gewicht_res=gewicht; EIMSK |= (1<<INT4); // INT4 freigeben } in der main schleife wird gewicht_res ausgegeben.
Um 24 Clckimpulse zu generieren solltest Du den Pin abwechselnd ein und ausschalten. Also SETPIN(CLK_AD); CLRPIN(CLK_AD); SETPIN(CLK_AD); CLRPIN(CLK_AD); . . .
Hallo dort ist eine schleife for(i=0;i<24,i++) das doppelte ist nur fürs timming
Und warum schreibst Du achtmal hintereinander SetPin ??? Einmal reicht doch...
wegen dem timming jedes SETPIN braucht ein µs ,sonst wird alles zu schnell
Vielleicht ist deine Abfrage zu schnell und Du liest immer nur '1' ein ?
nein ,der PORTG wird bei 1 auf 255 und bei 0 auf 0 gesetzt, angeschlossen habe ich ein logik analysator
Vielleicht liegt das Problem in main und der Ausgabe von gewicht_res ?
Hallo Ich habe jetzt in der interrupt routine nur ein bit gesetzt alles ander in der main schleife. das klappt wunderbar. Variablen in der Interrupt routine werden irgen wie nicht verarbeitet, Speicher ?
Juppo Nini schrieb: > Variablen in der Interrupt routine werden irgen wie nicht verarbeitet, > Speicher ? Die Variable i ist in der ISR nicht lokal deklariert !
die ist wie die anderen global läft auch die long werte laufen nicht
Bei der Kontrolle/Anzeige im Hauptprogramm musst du beachten, dass du gewicht atomar lesen musst, d.h. mit gesperrtem INT4. Wenn du das nicht machst, können dir die Zeilen gewicht = 0; und gewicht <<= 1; Fheler vorgaukeln. Näheres siehe Interrupt. Ansonsten: > angeschlossen habe ich ein logik analysator Mehrspurig? Bei 1-4 Spuren würde mich ein LA-Diagramm von dem folgenden Code interessieren. Je nach Speicherkapazität deines LA triggern auf PORTG.7 (viel Speicher), PORTG.1 (weniger Speicher) oder PORTG.0 (ganz wenig Speicher) und dabei PINE.4 messen. Kannst du das aufnehmen?
1 | // PORTG.7 = Anzeige wann sich das Programm im Interrupt befindet
|
2 | #define DEBUG_START_INT4() do { PORTG |= (1<<7); } while (0)
|
3 | #define DEBUG_ENDE__INT4() do { PORTG &= ~(1<<7); } while (0)
|
4 | |
5 | // PORTG.0 = Anzeige wann das Programm PINE.4 auswertet
|
6 | #define DEBUG_EVAL_PINE4_START() do { PORTG |= (1<<0); } while (0)
|
7 | #define DEBUG_EVAL_PINE4_ENDE() do { PORTG &= ~(1<<0); } while (0)
|
8 | |
9 | // PORTG.1 = Anzeige wann das Programm in der for-Schleife ist
|
10 | #define DEBUG_FOR_START() do { PORTG |= (1<<1); } while (0)
|
11 | #define DEBUG_FOR_ENDE() do { PORTG &= ~(1<<1); } while (0)
|
12 | |
13 | // PINE.4 = zu pollendes Disgitalsignal
|
14 | |
15 | // Ausgelagert für bessere Übersicht in der Interruptroutine
|
16 | #define WARTE() do { \
|
17 | SETPIN(CLK_AD); \
|
18 | SETPIN(CLK_AD); \
|
19 | SETPIN(CLK_AD); \
|
20 | SETPIN(CLK_AD); \
|
21 | SETPIN(CLK_AD); \
|
22 | SETPIN(CLK_AD); \
|
23 | SETPIN(CLK_AD); \
|
24 | SETPIN(CLK_AD); \
|
25 | CLRPIN(CLK_AD); \
|
26 | CLRPIN(CLK_AD); \
|
27 | CLRPIN(CLK_AD); \
|
28 | CLRPIN(CLK_AD); \
|
29 | } while (0)
|
30 | |
31 | volatile long gewicht; |
32 | volatile long gewicht_res; |
33 | volatile unsigned char b_temp; |
34 | |
35 | SIGNAL(SIG_INTERRUPT4) |
36 | {
|
37 | EIMSK &= ~(1<<INT4); // INT4 sperren |
38 | DEBUG_START_INT4(); |
39 | int4_counter++; // läuft wunderbar <=== DATENTYP? |
40 | gewicht = 0; |
41 | b_temp = 0; |
42 | for ( unsigned char i = 0; i < 24; i++ ) |
43 | {
|
44 | unsigned char pine4; |
45 | DEBUG_FOR_START(); |
46 | gewicht <<= 1; |
47 | WARTE(); |
48 | DEBUG_EVAL_PINE4_START(); |
49 | pine4 = PINE & (1<<PE4); |
50 | DEBUG_EVAL_PINE4_ENDE(); |
51 | if ( pine4 != 0 ) |
52 | {
|
53 | gewicht |= 1; |
54 | b_temp++; |
55 | }
|
56 | DEBUG_FOR_ENDE(); |
57 | }
|
58 | gewicht_res = gewicht; |
59 | DEBUG_ENDE__INT4(); |
60 | EIMSK |= (1<<INT4); // INT4 freigeben |
61 | }
|
Wie sieht die Hardwareschaltung an PINE.4 aus?
Der Anmerkung von Sven sollte man unbedingt nach gehen. Dazu müsste man
auch die Definitionen von SETPIN und CLRPIN sehen.
> angeschlossen ist ein ad-wandler
Ist ein Datenblatt oder Link zum Datenblatt bekannt?
Mehrspurig gemessen habe ich ,wie geschrieben wird der Port gesetzt oder halt nicht. Interuppt sperren und öffnen mache ich EIMSK &= ~(1<<INT4); // INT4 sperren EIMSK |= (1<<INT4); // INT4 freigeben Angeschlossen ist ein ADS1231 Die Datenleitung gibt ein /DRDY Signal aus Anschliesend müssen 24 Clock angelegt werden und der gleiche Port PORT E pin 4 bringt die daten. also: interrupt INT4 (Port E,4) wartet auf fallende Flanke dann interrupt sperren dann (for to do ) 24 Clock anlegen(zum AD1231) und den PORT E 4 in long variable einlesen interuppt 4 freigeben jetzt habe ich: in der Interuppt routine int4 wird ein bit gesetzt dann funktion mit dem clock anlegen und daten lesen und int 4 variable zurücksetzen das klappt wunderbar. wenn ich aber die einlese funktion direkt in der interrupt routine mache sind die daten wieder falsch. Wie schon geschrieben habe ich ein ATMEGA 2561 mit AVR Studio wie muss die long variable deklariert sein und wo? wie geschrieben wird bei der if PE4 gesetzt ein HardwarePort G gesetzt und ist auch mit dem Logikanalyser zu sehen. gruß juppo
Deine SCLK stimmt nicht, wenn man sich die Anforderungen aus dem Datenblatt betrachtet.
1 | // Min. 100ns Delay für t_sclk erforderlich
|
2 | // 1. Ansatz: grobes 1 µs Delay aus der acr-libc
|
3 | // Gefahr: 24*2*1µs = 50 µs > t_conv
|
4 | // t_conv typ. 12,5 oder 100ms => Gefahr besteht nicht
|
5 | #define TSCLK() _delay_us(1)
|
6 | |
7 | // Ausgelagert für bessere Übersicht in der Interruptroutine
|
8 | //
|
9 | #define SCLK_ERZEUGEN() do { \
|
10 | SETPIN(CLK_AD); \
|
11 | TSCLK(); \
|
12 | CLRPIN(CLK_AD); \
|
13 | TSCLK(); \
|
14 | } while (0)
|
15 | |
16 | volatile long gewicht; |
17 | volatile long gewicht_res; |
18 | |
19 | SIGNAL(SIG_INTERRUPT4) |
20 | {
|
21 | EIMSK &= ~(1<<INT4); |
22 | gewicht = 0; |
23 | for ( unsigned char bit = 0; bit < 24; bit++ ) |
24 | {
|
25 | gewicht <<= 1; // MSB first |
26 | SCLK_ERZEUGEN(); |
27 | if ( PINE & (1<<PE4) ) gewicht |= 1; |
28 | }
|
29 | gewicht_res = gewicht; |
30 | EIMSK |= (1<<INT4); |
31 | }
|
Wie triggert dein INT4? Ich würde auf fallende Flanke von /DRDY auslösen lassen.
Hallo Mit dem CLK habe ich rumgespielt bis zur vergasung Bei der if ( PINE & (1<<PE4) ) gewicht |= 1; werden nur 1 reingeschrieben. aber PORT setzen klappt wunderbar IST DAS RICHTIG volatile long gewicht; volatile long gewicht_res; SIGNAL(SIG_INTERRUPT4) { EIMSK &= ~(1<<INT4); gewicht = 0; for ( unsigned char bit = 0; bit < 24; bit++ ) { gewicht <<= 1; // MSB first SCLK_ERZEUGEN(); if ( PINE & (1<<PE4) ) gewicht |= 1; Hier werden nur 1 reingeschrieben. } gewicht_res = gewicht; EIMSK |= (1<<INT4); }
> EIMSK |= (1<<INT4); // INT4 wieder enablen
Da würde ich vorher zur Sicherheit das Interruptflag löschen. Oder - um
die Sache genauer zu untersuchen - eine Debugmöglichkeit einbauen, die
zeigt, ob das Flag wider den gewollten Programmablauf gesetzt ist.
> if ( PINE & (1<<PE4) ) gewicht |= 1; Hier werden nur 1 reingeschrieben.
Das niederwertigste Bit wird auf 1 gesetzt, wenn ein 1 Bit am PINE.4
anliegt. Da zuvor gewicht mit gewicht <<= 1; um eine Stelle nach links
geschoben wurde steht eine 0 an der Bitposition und die bleibt auch für
diese Bitleserunde dort, wenn an PINE.4 ein 0 Bit anliegt.
Du hast doch mit dem LA ein super Debugtool... Kann dein LA keine
Diagramme speichern? Wenn doch: Zeig doch mal welche /DRDY Leitung
PINE.4 Leitung und SCLK/CLK_AD Leitung. Das Diagramm kann man dann mit
dem Diagramm im Datenblatt vergleichen. Und mit dem LA umgehst du die
noch unbeantwortete Falle "Wie verlässlich ist die Anzeige der Variablen
gewicht?".
> Da würde ich vorher zur Sicherheit das Interruptflag löschen.
1 | EIFR |= (1<<INTF4); // INTF4 löschen durch Schreiben einer 1 |
2 | EIMSK |= (1<<INT4); // INT4 wieder enablen |
Helfer schrieb: >> Da würde ich vorher zur Sicherheit das Interruptflag löschen. > >
1 | > EIFR |= (1<<INTF4); // INTF4 löschen durch Schreiben einer 1 |
2 | >
|
NEIN! http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_intbits
1 | EIFR = (1<<INTF4); |
Selbst, falls es hier egal sein sollte (keine weiteren Interruptflags können gesetzt sein in EIFR), bitte nicht erst falsch angewöhnen.
Klappt auch nicht. Besten Dank für eure Hilfe . Ich komme erst mal klar ,eventuell in einem biergarten und schweinzhaxen fällt uns was ein. Gruß juppo
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.