Hallo, ich stehe vor folgendem Problem. Ich möchte gerne Impulse zählen. Die Anforderungen sind hier wie folgt: Es gibt 6 Kanäle auf denen Impulse mit 5µs länge ankommen. Die Frequenz variiert von 0Hz – 65kHz Momentan nutze ich den Interrupt on Change (IOC) des PIC16F18346 und frage hier bei jedem Interrupt mit dem IOCCFX Flag ab welcher Pin den Interrupt ausgelöst hat. Leider scheint mir das sehr ungenau zu sein, wahrscheinlich gibt es hier Probleme wenn zwei Pins zur gleichen Zeit einen Impuls erfassen. Hat jemand eventuell einen Tip wie man das genauer / besser hinbekommen kann. Danke im vorraus.
Miki schrieb: > Leider scheint mir das sehr ungenau zu sein, wahrscheinlich gibt es hier > Probleme wenn zwei Pins zur gleichen Zeit einen Impuls erfassen. Musst du alle Kanäle gleichzeitig erfassen? Grundsätzlich solltest du dich etwas mit Zeitmessung beschäftigen. Hier gibt es zwei unterschiedliche Ansätze: Tormethode und Periodenmethode. Periodenmethode vermisst bei lagsamen Frequenzen die Periodendauer. Die Tormethode zählt ankommende Pulse in einem definierten Zeitfenster, sinnvoll bei hoher Frequenz. Bei deinem Frequenzbereich 0(!)-65kHz musst du beide Varianten anwenden und diese auch dynamisch umschalten können. Das ist nicht so einfach wie es klingt. Wenn du alle Kanäle nacheinander vermessen könntest wäre das schon sehr sinnvoll. Dir ist klar, dass egal welches Verfahren du benutzt, mindestens 20s vergehen bei 0,1Hz bevor du ein Ergebnis hast? Irgendwo musst du auch Abstriche machen, denn der von dir geforderte Dynamikumfang liegt bei unendlich...
Ingo Less schrieb: > Grundsätzlich solltest du > dich etwas mit Zeitmessung beschäftigen. Hier gibt es zwei > unterschiedliche Ansätze: Tormethode und Periodenmethode. Er braucht nicht die Frequenz sondern nur die Anzahl. Miki schrieb: > Momentan nutze ich den Interrupt on Change (IOC) des PIC16F18346 und > frage hier bei jedem Interrupt mit dem IOCCFX Flag ab welcher Pin den > Interrupt ausgelöst hat. Du mußt den alten Wert zwischenspeichern und mit dem neuen Wert vergleichen. Daran kann man die Änderung der Pins und ihre Flanke feststellen. Der PIC sollte das doch locker schaffen. temp = (alter_wert ^ neuer_wert) & neuer_wert; In temp stehen die Änderungen mit positiver Flanke.
Zu Z80-Zeiten haette man 2 CTCs an die CPU gehaengt und waere fertig.
Miki schrieb: > Ich möchte gerne Impulse zählen. Die Anforderungen sind hier wie folgt: > Es gibt 6 Kanäle auf denen Impulse mit 5µs länge ankommen. > Die Frequenz variiert von 0Hz – 65kHz Nimm ein kleines FPGA (z.B. Lattice MachXO, gibts ab 2.50€, handlötbares Gehäuse) und implementiere dort Deine 6 Zähler mit einer Dir genehmen Bitbreite und einem Mechanismus zum Auslesen. Das wird bis in dem MHz-Bereich zuverlässig funktionieren. fchk
Miki schrieb: > Leider scheint mir das sehr ungenau zu sein Wie stellst du das fest? > Probleme wenn zwei Pins zur gleichen Zeit einen Impuls erfassen. Hast du da evtl. ein Problem beim Zurücksetzen der Flags? Setzt du im Interrupt vielleicht einfach alle Bits auf einmal zurück? Zeig doch mal den entsprechenden Code.
m.n. schrieb: > Er braucht nicht die Frequenz sondern nur die Anzahl. Oh ja sorry, hatte mich durch die Frequenz ablenken lassen... Larry schrieb: > Bei knapp 16 us wird das mit dem locker wohl nichts. Nein, dass ist eigentlich nicht vernünftig um zu setzen denke ich. Frank K. schrieb: > Nimm ein kleines FPGA (z.B. Lattice MachXO, gibts ab 2.50€, handlötbares > Gehäuse) und implementiere dort Deine 6 Zähler mit einer Dir genehmen > Bitbreite und einem Mechanismus zum Auslesen. Das wird bis in dem > MHz-Bereich zuverlässig funktionieren. Halte ich auch für die beste Lösung. Oder diskret mit nem Zählergrab und Latches (sofern dern Zähler die nicht intern hat) die Zählerstände nacheinander auslesen...
Hat dein PIC Timer? Im Normalfall kann der Flanken zählen, und damit sollte man deinen Fall abdecken können. Der kann dir auch einen Interrupt geben, wenn du eine gewisse Zahl überschreitest, oder du liest ihn zyklisch. Das externe Signal kommt an den Takteingang des Timers. Ich habe das schon für einen Geigerzähler verwendet, beispielsweise. Der Vorteil liegt darin, dass die CPU nicht belastet wird.
Blumpf schrieb: > Das externe Signal kommt an den Takteingang des Timers. Er hat 6 Signale zu zählen, nichtmal ein STM32F4 hat 6 Eingänge für externe Zählsignale, ich halte es für unwahrscheinlich, das ein 8-Bitter sowas an Board hat...
Ingo Less schrieb: > nichtmal ein STM32F4 hat 6 Eingänge für > externe Zählsignale, Oh doch. Timer 1, 2, 3, 4, 5, 8, 9 und 12 sind zusammen 8. Beim PIC könnte man auch eine Kombination von Hardwarezählern und flankengetriggerten Interrupts verwenden. W.S. programmiert das sicher auch in Assembler ;-)
Ingo Less schrieb: > Blumpf schrieb: >> Das externe Signal kommt an den Takteingang des Timers. > Er hat 6 Signale zu zählen, nichtmal ein STM32F4 hat 6 Eingänge für > externe Zählsignale, ich halte es für unwahrscheinlich, das ein 8-Bitter > sowas an Board hat... Hmm, guter Einwand. Ganz furchtbar schlecht siehts aber nicht aus. Immerhin hat der PIC 4 Takteingänge für Timer, und damit sind schon 4 von 6 automatisch gezählt. Bleiben 2 übrig. Je nach Zählrate wäre das über Interrupts umsetzbar, oder man muss Logik dazubauen. Beispiel: http://www.ti.com/lit/ds/symlink/sn74lv8154.pdf Den würde man parallel auslesen. Eventuell ließe sich sicher was mit seriellem Interface auftreiben. Leider ist die Auswahl bei diskreter Logik nicht so toll, und ich konnte in 5 Minuten nichts finden. Im Notfall könnte man einfach einen zweiten PIC als Counter verwenden und die über UART verbinden. Ich würde zählen immer einem Peripheriebaustein oder Logik überlassen, weil bei externen Ereignissen dann die Zählinterrupts das Verhalten der Software unverhershbar werden lassen. Wird schwierig, das zu testen.
Ingo Less schrieb: > Bei deinem Frequenzbereich 0(!)-65kHz Ich korrigiere auf 1-65kHz Lothar M. schrieb: > Hast du da evtl. ein Problem beim Zurücksetzen der Flags? > Setzt du im Interrupt vielleicht einfach alle Bits auf einmal zurück? > > Zeig doch mal den entsprechenden Code. OK das werde ich mal probieren, mein code sieht bisher so aus:
1 | void IOC_ISR (void) |
2 | {
|
3 | if(IOCCF0) counter0++; |
4 | if(IOCCF1) counter1++; |
5 | if(IOCCF2) counter2++; |
6 | if(IOCCF3) counter3++; |
7 | if(IOCCF4) counter4++; |
8 | if(IOCCF5) counter5++; |
9 | }
|
Blumpf schrieb: > Hat dein PIC Timer? > > Im Normalfall kann der Flanken zählen, und damit sollte man deinen Fall > abdecken können. > Der kann dir auch einen Interrupt geben, wenn du eine gewisse Zahl > überschreitest, oder du liest ihn zyklisch. Ja aber leider keine 6 Zähleingänge
der fpga vorschlag ist gut, aber ich denke beim to reicht es weder zu dieser noch zur nutzung der hw resourcen des pic's. immer wieder die selben typen, ... zu keinen eigenen lsg. fähig, bestenfalls halbe fragen und viel hoffen, dass andere was können. mt
:
Bearbeitet durch User
Apollo M. schrieb: > der fpga vorschlag ist gut Wenn man den oben erwähnten STM32F4 nimmt, hat man auch genug Zählereingänge per Hardware. Was aber überhaupt nicht klar ist, wo die Daten verwendet werden sollen. Es müßte ja noch irgendeine (Vor-)verarbeitung oder Ausgabe stattfinden. Da dürfte es unter Umständen eng werden. Miki schrieb: >> Bei deinem Frequenzbereich 0(!)-65kHz > > Ich korrigiere auf 1-65kHz Du mußt garnicht korrigieren; 0 Hz ist für jeden Zähler die optimale Eingangsfrequenz ;-)
Apollo M. schrieb: > der fpga vorschlag ist gut, aber ich denke beim to reicht es weder zu > dieser noch zur nutzung der hw resourcen des pic's. > > immer wieder die selben typen, ... zu keinen eigenen lsg. fähig, > bestenfalls halbe fragen und viel hoffen, dass andere was können. > > mt Bezüglich der FPGA Lösung gebe ich dir volkommen recht, wäre bestimmt super aber mangels Kentnisse werde ich das nicht umgesetzt kriegen. Bezüglich der Nutzung der PIC Pherepherie kann ich dir leider kein Recht geben, das klappt bestimmt. Aber da selbst ein solcher Spezialist (wie du es anscheinend bist) spontan keine Lösung parat hatte denke ich das auch nicht ganz so trivial ist. Sonst höttest du diese bestimmt direkt gepostet statt irgendwelcher umproduktiver Kommentare..... Zurück zum Thema,momentan denke ich das die Lösung mit externen Zählern (SN74LV8154) mangels FPGA,CPLD Kentnisse die beste sein wird.
Miki schrieb: > momentan denke ich das die Lösung mit externen Zählern > (SN74LV8154) mangels FPGA,CPLD Kentnisse die beste sein wird. Wenn schon eine Lösung mit mehreren Bauteilen, warum dann nicht wie schon vorgeschlagen einfach 2 PICs? Die 18346 haben doch 3 Counter (Timer1/3/5)? Die Kommunikation ist bestimmt auch nicht schwieriger.
:
Bearbeitet durch User
Wenn der kürzeste Impuls 5µs lang ist, dann sollte es reichen 8Bit eines Ports alle 4µs zu Sampeln. Wenn man die entsprechende Interruptroutine mit der höchsten Priorität in den RAM legt bleiben bei einem Stm32F103 und 72MHz noch 288 Takte übrig. Ungetestet könnte das in C so aussehen:
1 | uint8_t utmp=0; |
2 | volatile uint32_t carr[8]; |
3 | |
4 | void cntloop() |
5 | {
|
6 | uint8_t u=GPIOA->IDR & 0xff; |
7 | uint8_t ug=(u^utmp)&u; |
8 | utmp=u; |
9 | for (int n=0; n<8; n++) |
10 | {
|
11 | if (ug&(0x01<<n)) |
12 | carr[n]++; |
13 | }
|
14 | }
|
Das wird übersetzt zu:
1 | 4B0B ldr r3, =0x10000048 <utmp> |
2 | 480C ldr r0, =0x10000024 <carr> |
3 | 781C ldrb r4, [r3] |
4 | F04F4590 mov.w r5, #0x48000000 |
5 | 692B ldr r3, [r5, #16] |
6 | 4621 mov r1, r4 |
7 | B2DC uxtb r4, r3 |
8 | EA240101 bic.w r1, r4, r1 |
9 | 2300 movs r3, #0 |
10 | FA41F203 asr.w r2, r1, r3 |
11 | 07D2 lsls r2, r2, #31 |
12 | D504 bpl 0x0800046C |
13 | F8502023 ldr.w r2, [r0, r3, lsl #2] |
14 | 3201 adds r2, #1 |
15 | F8402023 str.w r2, [r0, r3, lsl #2] |
16 | 3301 adds r3, #1 |
17 | 2B08 cmp r3, #8 |
18 | D1F3 bne 0x0800045A |
19 | E7EC b 0x0800044E |
cntloop() ist natürlich die Interruptroutine des schnellen Timers. Bevor ich hier nach anderen Lösungen suchen würde wäre das einen Versuch Wert. Selbst wenn nur noch 10% Zeit für was anderes übrig bleiben, reicht das sicher für die Weiterverarbeitung der Zählerstände. Darüber wissen wir aber noch nichts.
temp schrieb: > Bevor ich hier nach anderen Lösungen suchen würde wäre das einen Versuch > Wert. Ob Stm32 statt PIC16 nicht schon unter (ganz) andere Lösungen fällt?
:
Bearbeitet durch User
Miki schrieb: > Zurück zum Thema,momentan denke ich das die Lösung mit externen Zählern > (SN74LV8154) mangels FPGA,CPLD Kentnisse die beste sein wird. Dann zeichne Dir einen Schaltplan, bei dem Dein 20-pol. µC 3 x Zähler ICs mit 8 Bit Datenbus ausliest. Das wird sicherlich spontan zu einer Änderung Deines Planes führen. Zudem neigen 16 Bit Zähler bei 65 kHz Eingangsfrequenz zu Überläufen im Sekundenabstand. Wohin mit diesen Ausgängen, die bei Überlauf auch nur einen kurzen Impuls liefern? Wenn schon ext. Bausteine verwendet werden sollen, dann eher Zähler >= 32 Bit im 8-pol. Gehäuse per IIC-Bus auszulesen. Mag sein, daß es so etwas fertig gibt, andernfalls könnte ein passender µC dies erledigen.
Miki schrieb: > Hat jemand eventuell einen Tip wie man das genauer / besser hinbekommen > kann. Ich würde das als kleine Fingerübung zur Frühstückspause etwa so machen wie im Anhang. Für 6 Stück 32 Bit Zähler und das entsprechende Schattenregister brauche ich 384 Flipflops, dazu kommen noch knapp 20 für den Rest, sodass ein MachXO2 mit 640 Flipflops im 48-Pin QFN 7x7mm Gehäuse locker ausreicht: https://www.latticesemi.com/en/Products/FPGAandCPLD/MachXO2 Und wenn ich ein wenig Gehinschmalz und 5..10 extra Codezeilen reinstecke pass das auch in ein FPGA mit nur 256 Flipflops. Damit kostet der Spaß dann knapp 3€ bei Einzelstückzahlen. Miki schrieb: > Bezüglich der FPGA Lösung gebe ich dir volkommen recht, wäre bestimmt > super aber mangels Kentnisse werde ich das nicht umgesetzt kriegen. Ist ein nettes Thema und die Einarbeit lohnt sich... ;-) Ich setze solche Zähler bewusst niemals(!) zurück, denn solches Zurücksetzen bringt garantiert irgendwann Pulsverluste. Überläufe können bei einem 32-Bit-Zähler einfach in der Software abgefangen werden. Die treten bei 65kHz am Eingang sowieso nur alle 18 Stunden auf. Man könnte die Zählerbreite auch auf "nur" 24 Bits festlegen, dann hat man schlimmstenfalls alle 4 Minuten einen Überlauf. Mindestens so oft müssten dann die Zähler ausgelesen werden, dass man keinen Überlauf "verschlampt". Aber vermutlich passiert das Auslesen eh' viel öfter, sodass auch 16-Bit-Zähler reichen und das Design von vorn herein ins kleinste FPGA passt.
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Ich setze solche Zähler bewusst niemals(!) zurück, denn solches > Zurücksetzen bringt garantiert irgendwann Pulsverluste. Überläufe können > bei einem 32-Bit-Zähler einfach in der Software abgefangen werden. Geht immer, wenn garantiert ist, dass nur ein Überlauf stattgefunden hat. Dann kann man das im Code herausrechnen. Wenn das Ergebnis neu-alt <0 ist, hat ein Überlauf stattgefunden. Ich wüsste adhoc gar nicht, wie man anders garantieren soll, dass keine Impulse verloren gehen.
Auf einem 16LF1509 braucht eine "for fun" geschriebene Interruptroutine < 10 us um 6 16 bit Zaehler zu bedienen. Dazu kaeme dann noch die Interruptlatenz. Sollte also gehen.
P.S. Und ca. 5 us mehr fuer pflegeleichtere 32 bit Zaehler. Das ganze bei 20 MHz Takt.
Larry schrieb: > Auf einem 16LF1509 braucht eine "for fun" geschriebene Interruptroutine > < 10 us um 6 16 bit Zaehler zu bedienen. > > Dazu kaeme dann noch die Interruptlatenz. > > Sollte also gehen. Wenn du 6 aysnchrone 65kHz-Signale zählen wilst, kannst du entweder 6 individuelle Interrupts einrichten, dann reden wir von 384% maximaler CPU-Auslastung (wenn du mal 65kHzx10µsx6Kanäle nimmst). Oder du tastest alle Signale in einer ISR (timergesteuert) ab, dann musst du aber mindestens mit der doppelten Frequenz abtasten, um alles zu erwischen. Macht 130kHz. Geht also auch nicht. Wenn die Signale synchron zum Timertakt sind, dann gehts. Wie man das hibekommen will, weiß ich nicht. Eventuell mit Flipflops.
Blumpf schrieb: > Oder du tastest alle Signale in einer ISR (timergesteuert) ab, dann > musst du aber mindestens mit der doppelten Frequenz abtasten, um alles > zu erwischen. Macht 130kHz. Geht also auch nicht. Wenn man "nur" den aktuellen Pinzustand auswertet, dann muss man spürbar schneller als mit 5µs abtasten, denn so lange dauert ein Impuls, wie schon Miki schrieb: >>> auf denen Impulse mit 5µs länge ankommen. Oder man macht es mit dem vorgeschlagenen X µs-Interrupt und den Flipflops der IOCCFX Flags, die ja diese Flanke speichern, bis sie wieder zurückgesetzt werden. In diesem Fall darf X dann fast 15ns (1/65kHz) werden und bei 125ns kürzester Befehlszykluszeit kann der PIC16F18346 ja immerhin grob überschlagen 120 Maschinenbefehle ausführen. Damit sollte das doch hinzubekommen sein.
:
Bearbeitet durch Moderator
Es geht noch anders. Ich werte nur die aus, und setze nur die zurueck, wenn der Interrupt "feuert". Falls also waehrend der Bearbeitung noch welche dazu kommen: Kein Problem. Die landen dann einfach im naechsten Durchlauf. Halt 10 us spaeter.
??? schrieb: > 15 ns ??? Oh, kleiner Typo, bin offenbar zu oft in diesen Zeitbereichen unterwegs. Ja, FPGA sind schon toll... ;-) > 15 ns ??? 1/65kHz sind latürnich 15µs.
:
Bearbeitet durch Moderator
Ich habe folgendes mal auf einem Bluepill-Board probiert.
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <stm32f10x.h> |
4 | |
5 | uint8_t utmp=0; |
6 | volatile uint32_t carr[8]; |
7 | |
8 | __attribute__ ((long_call, optimize("O3"), section (".fast"))) |
9 | void TIM2_IRQHandler(void) |
10 | {
|
11 | GPIOC->BSRR=GPIO_BSRR_BS13; |
12 | TIM2->SR=0; //|=TIM_SR_UIF; |
13 | |
14 | uint8_t u=GPIOA->IDR & 0xff; |
15 | uint8_t ug=(u^utmp)&u; |
16 | utmp=u; |
17 | |
18 | for (int n=0; n<8; n++) |
19 | {
|
20 | if ((ug&(0x01<<n))!=0) |
21 | carr[n]++; |
22 | }
|
23 | GPIOC->BRR=GPIO_BRR_BR13; |
24 | }
|
25 | |
26 | void main(void) |
27 | {
|
28 | RCC->APB1ENR|=RCC_APB1ENR_TIM2EN; |
29 | RCC->APB2ENR|=RCC_APB2ENR_IOPCEN; |
30 | RCC->APB2ENR|=RCC_APB2ENR_IOPAEN; |
31 | GPIOC->CRH |= GPIO_CRH_MODE13_0 | GPIO_CRH_MODE13_1; |
32 | GPIOC->CRH &= ~(GPIO_CRH_CNF13_0 | GPIO_CRH_CNF13_1); |
33 | GPIOC->BRR=GPIO_BRR_BR13; |
34 | |
35 | TIM2->ARR=72*2; |
36 | |
37 | TIM2->DIER=TIM_DIER_UIE; |
38 | TIM2->CR1=TIM_CR1_CEN; |
39 | |
40 | NVIC_EnableIRQ(TIM2_IRQn); |
41 | |
42 | while (1) |
43 | ;
|
44 | }
|
Damit wird mit 500kHz gesampelt und der Interrupt braucht ca. 1µs. Im schlimmsten Fall (alle 8 Counter muessen incrementiert werden) sind es ca. 1,3µs. Also bleibt noch genügend Zeit für was anderes übrig. Wenn es ein Einzelstück werden soll, ist es extrem preiswert.
Andere Herangehensweise: Wenn die Pulse recht genau sind, dann koennte man damit auch einen Kondensator laden und in Abstaenden dessen Spannung mit einem ADC messen, hat der besagte PIC doch bestimt.
Mark W. schrieb: > Wenn die Pulse recht genau sind, dann koennte man damit auch einen > Kondensator laden und in Abstaenden dessen Spannung mit einem ADC > messen, hat der besagte PIC doch bestimt. Da fallen mir aber auf Anhieb einige Pferdefüße und Haken an der Sache ein... temp schrieb: > Ich habe folgendes mal auf einem Bluepill-Board probiert. Nett. Hat schon Vorteile, so ein 32-Bit µC. > Im schlimmsten Fall (alle 8 Counter muessen incrementiert werden) sind > es ca. 1,3µs. Kannst du mal ausprobieren, ob es was bringt, wenn du selber die Schleife ausrollst?
1 | if (ug&0x01) carr[0]++; |
2 | if (ug&0x02) carr[1]++; |
3 | if (ug&0x04) carr[2]++; |
4 | if (ug&0x08) carr[3]++; |
5 | if (ug&0x10) carr[4]++; |
6 | if (ug&0x20) carr[5]++; |
7 | if (ug&0x40) carr[6]++; |
8 | if (ug&0x80) carr[7]++; |
Oder hat das der Compiler eh' schon gemacht?
Lothar M. schrieb: > Kannst du mal ausprobieren, ob es was bringt, wenn du selber die > Schleife ausrollst? Das habe ich gemacht, allerdings ohne sichtbare Änderungen. Den erzeugten Code habe ich aber nicht verglichen. Hier noch 2 Screenshots vom Oszi. Der eine wenn keine Zähler incrementiert werden müssen und alternativ alle 8 müssen eins weiterrücken.
temp schrieb: > Das habe ich gemacht, allerdings ohne sichtbare Änderungen. Im Vergleich zu was? Sowohl deine verschliffene Variante wie auch die ausgerollte jeweils 1µs bei keinem und 1,4µs bei allen Zählern?
Lothar M. schrieb: > Sowohl deine verschliffene Variante wie auch die ausgerollte jeweils 1µs > bei keinem und 1,4µs bei allen Zählern? Ja genau. Hier mal ein Stück aus dem Dissassembler beim Debuggen meiner Version mit der for-Schleife, die am Ende keine mehr ist: Hier mit "if ((ug&(0x01<<n))==0)" um das Weiterzählen zu erzwingen.
1 | for (int n=0; n<8; n++) |
2 | {
|
3 | if ((ug&(0x01<<n))==0) |
4 | D403 bmi 0x2000002E |
5 | --- main.c -- 75 ------------------------------------------- |
6 | carr[n]++; |
7 | 491D ldr r1, =0x200000A4 <carr> |
8 | 680A ldr r2, [r1] |
9 | 3201 adds r2, #1 |
10 | 600A str r2, [r1] |
11 | --- main.c -- 74 ------------------------------------------- |
12 | if ((ug&(0x01<<n))==0) |
13 | 0799 lsls r1, r3, #30 |
14 | D403 bmi 0x2000003A |
15 | --- main.c -- 75 ------------------------------------------- |
16 | carr[n]++; |
17 | 491A ldr r1, =0x200000A4 <carr> |
18 | 684A ldr r2, [r1, #4] |
19 | 3201 adds r2, #1 |
20 | 604A str r2, [r1, #4] |
21 | --- main.c -- 74 ------------------------------------------- |
22 | if ((ug&(0x01<<n))==0) |
23 | 075A lsls r2, r3, #29 |
24 | D403 bmi 0x20000046 |
25 | --- main.c -- 75 ------------------------------------------- |
26 | carr[n]++; |
27 | 4917 ldr r1, =0x200000A4 <carr> |
28 | 688A ldr r2, [r1, #8] |
29 | 3201 adds r2, #1 |
30 | 608A str r2, [r1, #8] |
31 | --- main.c -- 74 ------------------------------------------- |
32 | if ((ug&(0x01<<n))==0) |
33 | 071C lsls r4, r3, #28 |
34 | D403 bmi 0x20000052 |
35 | --- main.c -- 75 ------------------------------------------- |
36 | carr[n]++; |
37 | 4914 ldr r1, =0x200000A4 <carr> |
38 | 68CA ldr r2, [r1, #12] |
39 | 3201 adds r2, #1 |
40 | 60CA str r2, [r1, #12] |
41 | --- main.c -- 74 ------------------------------------------- |
42 | if ((ug&(0x01<<n))==0) |
43 | 06D8 lsls r0, r3, #27 |
44 | D403 bmi 0x2000005E |
45 | --- main.c -- 75 ------------------------------------------- |
46 | carr[n]++; |
47 | 4911 ldr r1, =0x200000A4 <carr> |
48 | 690A ldr r2, [r1, #16] |
49 | 3201 adds r2, #1 |
50 | 610A str r2, [r1, #16] |
51 | --- main.c -- 74 ------------------------------------------- |
52 | if ((ug&(0x01<<n))==0) |
53 | 0699 lsls r1, r3, #26 |
54 | D403 bmi 0x2000006A |
55 | --- main.c -- 75 ------------------------------------------- |
56 | carr[n]++; |
57 | 490E ldr r1, =0x200000A4 <carr> |
58 | 694A ldr r2, [r1, #20] |
59 | 3201 adds r2, #1 |
60 | 614A str r2, [r1, #20] |
61 | --- main.c -- 74 ------------------------------------------- |
62 | if ((ug&(0x01<<n))==0) |
63 | 065A lsls r2, r3, #25 |
64 | D403 bmi 0x20000076 |
65 | --- main.c -- 75 ------------------------------------------- |
66 | carr[n]++; |
67 | 490B ldr r1, =0x200000A4 <carr> |
68 | 698A ldr r2, [r1, #24] |
69 | 3201 adds r2, #1 |
70 | 618A str r2, [r1, #24] |
71 | --- main.c -- 74 ------------------------------------------- |
72 | if ((ug&(0x01<<n))==0) |
73 | 09DB lsrs r3, r3, #7 |
74 | D103 bne 0x20000082 |
75 | --- main.c -- 75 ------------------------------------------- |
76 | carr[n]++; |
77 | 4A08 ldr r2, =0x200000A4 <carr> |
78 | 69D3 ldr r3, [r2, #28] |
79 | 3301 adds r3, #1 |
80 | 61D3 str r3, [r2, #28] |
81 | --- main.c -- 76 ------------------------------------------- |
82 | }
|
83 | GPIOC->BRR=GPIO_BRR_BR13; |
84 | F44F5200 mov.w r2, #0x2000 |
85 | 4B02 ldr r3, =0x40011000 |
86 | --- main.c -- 79 ------------------------------------------- |
87 | }
|
88 | BC10 pop {r4} |
89 | --- main.c -- 78 ------------------------------------------- |
90 | GPIOC->BRR=GPIO_BRR_BR13; |
91 | 615A str r2, [r3, #20] |
92 | --- main.c -- 79 ------------------------------------------- |
93 | }
|
Wenn wir jetzt schon bei 32-Bitter angelangt sind und der TE ohnehin mit PIC arbeitet, kann er das Problem auch gleich mit einem PIC32MZxxxxx erschlagen. Der hat genügend Timer, jeder mit externen Takt befeuerbar, jeder einen eigenen Interrupt. Die Interruptroutinen brauchen da nur mehr je einen Zähler inkrementieren, Int-Flag rücksetzen und am Ende der Messung stehen ein paar Multiplikationen und Additionen an......
Chris B. schrieb: > Wenn wir jetzt schon bei 32-Bitter angelangt sind und der TE ohnehin mit > PIC arbeitet, kann er das Problem auch gleich mit einem PIC32MZxxxxx > erschlagen. Mein Beispiel ist in reinem C und sollte auch auf einem PIC32 laufen. Ich kann aber nur für die Controller sprechen die ich kenne. PIC32 gehört nicht dazu und wird es auch nicht mehr. Trotzdem ist es hin und wieder besser man hat eine Lösung die eventuell etwas mehr Zeit braucht, dafür aber in engen Grenzen komplett vorhersehbar abläuft unabhängig von den Pegeln an den Eingängen. Nach dem selben Muster wäre es möglich kurze digitale Filter mit zu berechnen. Sicher nicht in diesem Beispiel wegen der min. Zeit von 5µs. Trotzdem, das mit einem einzelnen Timer und einem einzigen Interrupt abzuhandeln ist ohne Aufwand auf die verschiedensten Controller portierbar. Besser jedenfalls als wenn man extrem an den Hardwareblöcken hängt. Ich würde mir dafür jedenfalls nicht 6 Interrupt-Routinen ans Bein heften.
temp schrieb: > Besser jedenfalls als wenn man extrem an den Hardwareblöcken > hängt. > Ich würde mir dafür jedenfalls nicht 6 Interrupt-Routinen ans Bein > heften. Hardwareblöcke sind doch gerade dazu da, bestimmte Dinge nicht in Software machen zu müssen. Bräuchte man sonst uC? Wieso 6 IR-Routinen? (Eine reicht doch, um regelmäßig alle Hardware-Counter auszulesen, bzw. deren evtl. automatisch zwischengespeicherten Werte)
Volker S. schrieb: > Hardwareblöcke sind doch gerade dazu da, bestimmte Dinge nicht in > Software machen zu müssen. Bräuchte man sonst uC? Verwendet meine Lösung denn keine Hardwarblöcke? Chris B. schrieb: > Der hat genügend Timer, jeder mit externen Takt befeuerbar, jeder einen > eigenen Interrupt. > Wieso 6 IR-Routinen? (Eine reicht doch, um regelmäßig alle > Hardware-Counter auszulesen, bzw. deren evtl. automatisch > zwischengespeicherten Werte) Ich habe auf den Post von Chris B. geantwortet und nicht auf deine Vorstellungen. Das schöne daran ist, dass es jeder machen kann wie er will und es sicher viele Lösungsansätze gibt. Ich habe ein Beispiel probiert und gepostet und ob es dir gefällt oder nicht ist mir Wumpe. Jeder der will, kann seine Lösung hier rein stellen, aber bitte kein Geschwafel sondern am konkreten Beispiel. Ich werde jedenfalls nicht danach suchen, bei welche PICs es möglich ist 6 separate Timer mit jeweils externem Eingang zu verwenden.
temp schrieb: > Volker S. schrieb: >> Hardwareblöcke sind doch gerade dazu da, bestimmte Dinge nicht in >> Software machen zu müssen. Bräuchte man sonst uC? > Verwendet meine Lösung denn keine Hardwarblöcke? Wenn ich einen Zähler brauche, dann schau ich gewöhnlich zuerst mal ob da schon einer da ist, den ich nur konfigurieren muss und der dann die Aufgabe unabhängig vom Programm übernehmen kann. temp schrieb: > Ich habe auf den Post von Chris B. geantwortet > ... > Ich werde jedenfalls nicht danach suchen, bei welche PICs es möglich ist > 6 separate Timer mit jeweils externem Eingang zu verwenden. Ich auch nicht, aber ich hatte den Eindruck Chris B. hätte einen konkreten vorgeschlagen. Der TE hat vermutlich eh schon das Weite gesucht, damit ihm nicht der Kopf platzt ob der zu vielen guten Lösungsmöglichkeiten ;-) Ich hätte eben erst noch auf Rückmeldung gewartet bevor ich so ganz konkrete Beispiele gebe um eine bestimmte Lösung aufzudrängen. Bringt ja nix.
Wenn ich bei meiner ISR auch spaeter eintrudelnde IOC beruecksichtige, komme ich bei 6 16 bit Zaehlern in der ISR auf max. 12.2 us (plus Latenz zum Aufruf). Und die duerfen asynchron kommen wie sie wollen, weil sie ja im IOCAF-Register gelatcht und nur bei Zaehlung zurueckgesetzt werden. Das globale IOCIF wird auch nur geloescht, wenn in der ISR keine neuen IOCs dazu gekommen sind. Wo ist also das Problem?
temp schrieb: > Ich würde mir dafür jedenfalls nicht 6 Interrupt-Routinen ans Bein > heften. Um bei Deinem F103 zu bleiben, reichen zwei ISRs, die jeweils eine Gruppe von Capture-Interrupts bedienen. An PA0-PA3 liegen die vier Capture-Eingänge von TIM2 und an PA6+PA7 zwei von TIM3. Jeder dieser Eingänge kann einen Interrupt auslösen, wobei die Eingangsflanke und eine leichte Filterung separat eingestellt werden können. Daß der µC für diese Aufgabe schnell genug ist, hattest Du ja schon gezeigt. Der Vorteil gegenüber einem Polling mit 500 kHz ist jedoch, daß bei niedrigen Impulsfrequenzen die Interruptlast nur sehr gering ist. Wer neugierig ist, kann nebenbei auch noch die Frequenz messen ;-) Wenn man einen F103 in einem größeren Gehäuse verwendet, kann man wie oben beim F4xx angedeutet alles per Hardware zählen. Dazu wird von den betreffenden Timer TIMx_CH1 verwendet und im "External Clock Mode 1" betrieben.
m.n. schrieb: > Um bei Deinem F103 zu bleiben, reichen zwei ISRs, die jeweils eine > Gruppe von Capture-Interrupts bedienen. > An PA0-PA3 liegen die vier Capture-Eingänge von TIM2 und an PA6+PA7 zwei > von TIM3. Jeder dieser Eingänge kann einen Interrupt auslösen, wobei die > Eingangsflanke und eine leichte Filterung separat eingestellt werden > können. Und das soll besser sein? Hast du auch mal den Fall bedacht, dass an einer oder mehrerer der Leitungen anstelle des Nutzsignals ein besseres Rauschen anliegt? Das kann die Interruptlast dann so weit treiben das überhaupt nichts mehr geht. Das trifft aber auf alle Varianten zu die mit Flankeninterrupts arbeiten und aus meiner Sicht aus diesem Grund ungeeignet sind. m.n. schrieb: > Der Vorteil gegenüber einem Polling mit 500 kHz ist jedoch, daß > bei niedrigen Impulsfrequenzen die Interruptlast nur sehr gering ist. Ja, mir tut es auch immer weh wenn ich zusehen muss wie sich so ein µC mit Interrupts quält die noch dazu vorhersehbar sind in Zeit und Länge. Das ist schon eine schwere Microcontrollerrechtsverletzung und muss unbedingt unterbunden werden. Koste es was es wolle und wenn ich dafür einen 144pin Controller brauche anstelle eines mit 32 oder 48 Beinen spielt das überhaupt keine Rolle. m.n. schrieb: > Wenn man einen F103 in einem größeren Gehäuse verwendet, kann man wie > oben beim F4xx angedeutet alles per Hardware zählen. Dazu wird von den > betreffenden Timer TIMx_CH1 verwendet und im "External Clock Mode 1" > betrieben. Und das ist nur deshalb besser nur weil du dich besser fühlst? Nenn mal einen Typ bei dem 6 Timer mit externem Zählereingang vorhanden sind.
temp schrieb: > Nenn mal > einen Typ bei dem 6 Timer mit externem Zählereingang vorhanden sind Hat Cris B. doch schon längst getan. Da wären sogar 8 drin:
Volker S. schrieb: > Hat Cris B. doch schon längst getan. Da wären sogar 8 drin: Chris B. schrieb: > Wenn wir jetzt schon bei 32-Bitter angelangt sind und der TE ohnehin mit > PIC arbeitet, kann er das Problem auch gleich mit einem PIC32MZxxxxx > erschlagen. PIC32MZxxxxx ist eine ganze Serie und kein einzelner Typ. Noch dazu in einer komplett anderen Leistungs- und Preisklasse. Den preiswertesten davon gibt es bei Mouser für ca. 8.50€ incl. MwSt. Für den Preis gibt es 5 komplette Bluepill Boards.
@temp Sag mal, hast Du schlecht geschlafen? Da Du den F103 ins Spiel gebracht hattest, dachte ich, Du würdest Dich damit auskennen. Das war wohl ein Irrtum. Die TIMx_CHx-Eingänge kann man derart filtern lassen, daß selbst der oben genannte 5 µs Impuls als Störung unterdrückt wird. Dein konstruiertes "Rauschen" läßt daher garkeine ISR anspringen.
m.n. schrieb: > Sag mal, hast Du schlecht geschlafen? > Da Du den F103 ins Spiel gebracht hattest, dachte ich, Du würdest Dich > damit auskennen. Das war wohl ein Irrtum. Am Ende der Argumentationskette bleiben wie immer nur noch Beleidigungen übrig... Damit bin ich raus.
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.