Servus! Mit dem STM32 bin ich noch recht neu. Hab' schon ein bisschen was gemacht (PWM, I2C), bin aber noch recht unsicher. Jetzt müsste ich folgendes implementieren, weiss aber noch nicht so recht, wie ich da ran gehen soll: An einem Pin eines STM32F303xE liegt eine Spannung an, die von nahe 0V auf +3.3V steigt, wenn die Netzspannung ausfällt. Wenn die Spannung also über einen bestimmten Wert steigt, möchte ich einen Interrupt aufrufen, um wichtige Daten zu speichern. Das muss natürlich alles recht schnell gehen. Im Reference-Manual bin ich auf das Comparator-Modul gestoßen (mit DAC oder interene Referenz). Ist das die richtige Richtung? Kann mir jemand einen Schubser (Möglichst einfacher Beispielcode z.B.) geben? Vielen Dank, Markus
Markus G. schrieb: > Im Reference-Manual bin ich auf das Comparator-Modul gestoßen (mit DAC > oder interene Referenz). Ist das die richtige Richtung? Kann mir jemand > einen Schubser (Möglichst einfacher Beispielcode z.B.) geben? Wenn die Spannung wirklich von nahe 0 auf 3,3V steigt, dann reicht dir ein einfacher Externer Interrupt (EXTI genannt). Der wird bei fallender oder steigender Spannung am Pin ausgelöst. Geeignet ist dazu beim STM32 jeder Pin. Google einfach mal nach EXTI. Die Schaltschwelle ist die eines Schmitt-Triggers und steht im Datenblatt des jeweiligen STM32. Nur wenn du andere Schaltschwellen hast / diese nicht zur Charakteristik eines Schmitt Triggers (ST) passen, dann würde ich den Komparator oder sogar das ADC Modul verwenden.
RM0316 Zumindest die F0, F1, F2, F3, F4 haben einen Analog Watchdog. Der ist genau für Deine Aufgabenstellung gebaut. - Du lässt einen der vielen ADCs frei laufen. - Sobald sich das zu überwachende Analogsignal außerhalb des vorgegebenen Toleranzbandes befindet, wird die ISR angesprungen. Für robuste Systeme ist das Ding ist Pflicht, genau wie WWDG / IWDG. - Aktuelles Beispiel: - EEPROM Emulation im Flash (selbstverständlich mit Backup, Checksumme, etc...) - Schreibzugriff auf Flash wird blockiert, sobald Versorgungsspannungproblem erkannt wird. - D.h. vorne zieht einer ohne Warnung den 24V-Stecker, die Baugruppe erkennt das innerhalb von wenigen Mikrosekunden - bis die 5V/3V3 Zwischenkreise entladen sind, ist die Peripherie in einem sicheren Zustand.
Markus G. schrieb: > Das muss natürlich alles recht schnell > gehen. Du solltest mal Deine Vorstellung von "schnell" gründlich überdenken. Netzspannung (50Hz = 1/20ms) ist aber sowas von schnarchlahm. Es reicht also dicke, alle langsamen 10ms einen Timerinterrupt aufzusetzen, der den AD-Wandler startet und dann das Ergebnis mit der gewünschten Schwelle vergleicht. Schnell ist für einen MC etwa <1µs. P.S.: Willst Du den Ausfall einzelner Perioden feststellen, führe die 50Hz ungesiebt auf den ADC, messe alle 1ms und bilde das gleitende Maximum über 20ms.
:
Bearbeitet durch User
Wozu sollte er einen Interrupt bemühen wenn das ganze via Analog Watchdog ohne einen einzigen CPU-Takt passiert...? Analog Watchdog, siehe obere Antwort. Das Ding funktioniert (mit etwas mühsamer Konfiguration) sogar mit X-fachem Oversampling.
Ggf. koennte auch der Komparatore in manchen Familien helfen...
Servus Marcus! > RM0316 Danke, bin am Lesen :) > Zumindest die F0, F1, F2, F3, F4 haben einen Analog Watchdog. > Der ist genau für Deine Aufgabenstellung gebaut. Ja, da hast Du mich überzeugt. > - Sobald sich das zu überwachende Analogsignal außerhalb des > vorgegebenen Toleranzbandes befindet, wird die ISR angesprungen. Hmmm, was ist denn "die" ISR? Die zum "ADCn global interrupt" bzw. ADC1_2? Oder muss ich einen konfigurieren? Die Verwendung von HAL_ADC_AnalogWDGConfig ist fast klar, aber ein paar Fragen hab' ich doch noch: - Kann ich den analog wd gleichzeitig mit der AD-Messung konfigurieren? Also zB. ADC holt Daten per DMA + watchdog zusammen? Oder soll ich das doch "manuell" machen, wenn die Daten eh schon gesamplet werden...? - Welcher IRQ wird ausgelöst (s.o.)? Ich hab' leider auch nirgends Beispielcode gefunden :( Schon mal vielen Dank für die Hilfe! Dass der analog wd das Richtige für mich ist bin ich fast sicher, an der Implementierung hapert's noch ;) cu Markus
Hat sich erledigt :) War wie vermutet - so geht's:
1 | ADC_AnalogWDGConfTypeDef analogWDGConfig = |
2 | {
|
3 | .WatchdogNumber = ADC_ANALOGWATCHDOG_1, |
4 | .WatchdogMode = ADC_ANALOGWATCHDOG_SINGLE_REG, // watch only one channel |
5 | .Channel = 1, |
6 | .ITMode = ENABLE, |
7 | .HighThreshold = (uint32_t)( 1.65 * 4095/3.3 +0.5), // 1.65V |
8 | .LowThreshold = 0 |
9 | };
|
10 | |
11 | HAL_NVIC_SetPriority( ADC1_2_IRQn, 10, 0); |
12 | HAL_NVIC_EnableIRQ( ADC1_2_IRQn ); |
Aufgerufen wird dann
1 | ADC1_2_IRQHandler
|
, z.B.
1 | void ADC1_2_IRQHandler(void) |
2 | {
|
3 | OS_EnterInterrupt(); |
4 | HAL_NVIC_ClearPendingIRQ( ADC1_2_IRQn ); |
5 | LedOn( LED_RED ); |
6 | OS_LeaveInterrupt(); |
7 | }
|
Eine Frage habe ich aber doch noch: Warum wird der IRQ-Handler immer wieder aufgerufen, auch wenn die Spannung wieder sinkt? Was hab' ich da falsch gemacht?
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.