Hallo zusammen,
Ich möchte gerne auf meinem STM8 den Timer 1 im PWM-Betrieb und den
Timer 4 im "normalen" Betrieb laufen lassen.
Timer 1 läuft ohne initialisieren von Timer 4 problemlos im PWM-Betrieb.
Möchte ich aber nun auf Timer 4 einen InterruptHandler programmieren, so
funktioniert weder Timer1 (PIN geht High und nicht wieder low) noch mein
InterruptHandler auf Timer 4. Im Debug lande ich entweder direkt nach
dem interruptEnable im NonHandledInterruptHandler() oder wenn ich diesen
auskommentiere komme ich einmal in die ISR von Timer4, jedoch "hängt"
sich das Programm dann am Ende der ISR auf.
Ich habe gefühlt schon alles probiert, mit dem folgenden Code komme ich
wenigstens in die ISR, aber das kann ja auch nicht die Lösung sein, da
die Pins auch nicht gesetzt werden...
it.c
1
INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler,23)
2
{
3
GPIO_WriteReverse(GPIOD,GPIO_PIN_3);
4
GPIO_WriteReverse(GPIOD,GPIO_PIN_4);
5
TIM4_ClearITPendingBit(TIM4_IT_UPDATE);
interrupt_vector.c
1
#include"stm8s_it.h"
2
3
typedefvoid@far(*interrupt_handler_t)(void);
4
5
structinterrupt_vector{
6
unsignedcharinterrupt_instruction;
7
interrupt_handler_tinterrupt_handler;
8
};
9
10
//@far @interrupt void NonHandledInterrupt (void)
11
//{
12
/* in order to detect unexpected events during development,
13
it is recommended to set a breakpoint on the following instruction
Wie oben schon erwähnt lande ich beim einkommentieren des
NonHandledInterrupts direkt nach dem IER in dessen ISR und komme da auch
nicht mehr raus.
Ich bin schon wirklich am verzweifeln, da weder das befolgen dieser
Anleitung
http://embedded-lab.com/blog/starting-stm8-microcontrollers/10/, noch
kopieren aus dem StdPeriphLib Example (wobei hier keine
Interrupt_vector.c existiert) zu einer Lösung führt.
Komischer Compiler. Naja egal.
Musst du halt selber lesen:
http://blog.mark-stevens.co.uk/?cat=17
Das Interruptsystem des STM8 ist im hoechsten Masze einfach
zu benutzen.
Deine _vectab[] ist fuers Popoechen.
Die // vor den Eintraegen verhindern mit Sicherheit, dass die
valide ist.
Das "Befolgen von Anleitungen" noch das "Kopieren von Beispielen"
ersetzt das Verstehen wie der Interruptmechanismus funktioniert.
Und ein Durchpermutieren durch Weglassen wird da auch nicht
zum Ziel fuehren.
Ich denke ich verstehe ganz gut, wie ein Interrupt funktioniert ;),
jedoch habe ich einfach nicht verstanden, wieso ich bei jedem IER direkt
in der NonHandledInterrupt-Funktion lande und habe dann mit Fehlersuche
halt mal alles probiert.
Letzendlich lags an einem GPIO, den ich als Floating-Input mit Interrupt
definiert habe, der mir ständig einen Interrupt ausgelöst hat (was mir
zwar nicht ganz eingeht, da nirgends am Board Signale anliegen).
Die Blogs habe ich auch schon gelesen, ansonsten hätte ich mich ja gar
nicht hier ans Forum gewandt, aber trotzdem danke für die Hilfe.
BS schrieb:> Letzendlich lags an einem GPIO, den ich als Floating-Input mit> Interrupt definiert habe
Ich habe den Fehler mal unterstrichen. Eingänge darf man nie floaten
lassen. Entweder legt man den Pegel mit der externen Beschaltung fest
oder man aktiviert einen internen Pullup/Pulldown oder man konfiguriert
sie als Ausgang.
Der zweite Fehler besteht darin, einen Interrupt zu aktivieren, für den
es keine ISR gibt.
Oh, und wenn man schon eine extra ISR für "non handled interrupt" hat,
dann sollte die auch etwas sinnvolles tun. Zwar kann sie eigentlich
nicht aufgerufen werden, wenn man sich an die Regel von eben hält. Aber
manche Leute brauchen halt Gürtel und Hosenträger...
BS schrieb:> Floating-Input mit Interrupt> definiert habe, der mir ständig einen Interrupt ausgelöst hat (was mir> zwar nicht ganz eingeht, da nirgends am Board Signale anliegen
Ist Dir nicht klar?
Ein offener, unbeschalteter, floatender Cmos Input, der unmotiviert
Zustände annimmt. Ach wie seltsam :-)))
Vielleicht im 50 bzw. 100 Hz Takt?
Oder im Khz Bereich, wenn Du Leuchtstoffröhren in der Nähe betreibst?
Wenn Du etwas als IRQ Quelle initialisierst, solltest Du im gleichen Zug
auch eine IRQ Behandlung dazu schreiben.
Du kannst auch Breakpoints auf alle nicht genutzten IRQ Einspungadressen
setzen, dann siehst Du sehr schnell wenn da etwas triggert das Du nicht
erwartet hast.
Nette Fehler sind auch IRQ Flags die man selber rücksetzen muss, wenn
man die IRQ je wieder verlassen will.
Die StdPeriphLib ist übrigens teilweise echt Mist.
Von Hinten durch die Brust ins Auge geschrieben und unterstützt auch
nicht alles was die HW kann.
Als 'how to' wenn das DB schwammig formuliert ist, aber ganz brauchbar.
Wenn Dir der Prg-Speicher ausgeht oder der Du performance Probleme hast,
ersetze mal die Wall of Text der StdPeriphLib Aufrufe durch direkte
Manipulation der Handvoll Register die Du eigentlich setzen willst.
Wirkt Wunder!
Axel S. schrieb:> Entweder legt man den Pegel mit der externen Beschaltung fest> oder man aktiviert einen internen Pullup/Pulldown oder man konfiguriert> sie als Ausgang.
Teils sind sie über einen externen PullUp beschalten, da hatte ich bei
einem nicht richtig aufgepasst und ein bisschen ohne Gedanken einfach
copy-paste benutzt. Trotz allem hätte ich die ISRs wohl auch im
Vornherein schon belegen sollen, das war ein bisschen dumm.
M. K. schrieb:> Wenn Dir der Prg-Speicher ausgeht oder der Du performance Probleme hast,> ersetze mal die Wall of Text der StdPeriphLib Aufrufe durch direkte> Manipulation der Handvoll Register die Du eigentlich setzen willst.> Wirkt Wunder!
Hatte ich anfangs so gemacht, dann bin aber über die StdPeriph
"gestolpert" & dachte mir, dass es dadurch übersichtlicher wird. Aber
werde wohl wieder darauf zurück fallen.
Danke euch!
BS schrieb:> Hatte ich anfangs so gemacht, dann bin aber über die StdPeriph> "gestolpert" & dachte mir, dass es dadurch übersichtlicher wird. Aber> werde wohl wieder darauf zurück fallen.
Da tut sich bei mir gleich die Frage auf, woher bekomme ich denn das
iostm8s003.h-file, sodass ich meine Register korrekt beschrieben kann?
Weil wenn ich die stm8s.h und alle anderen header der STDPeriphLib
trotzdem inkludieren muss macht das ja (vorallem speicherplatztechnisch)
eher weniger Sinn oder?
Ich nutze nur die mit dem Ref-Manual von ST übereinstimmenden
Definitionen meines Compilers (IAR) für meinen konkreten STM8, z.B.:
1
#include<iostm8s105s4.h>
Alles andere im Programm mache ich dann selbst direkt an der Hardware.
(also über die Register gemäß RefMan)
Solche include-Dateien gibt es meines Wissens bei der HAL auch.
BS schrieb:> BS schrieb:>> Hatte ich anfangs so gemacht, dann bin aber über die StdPeriph>> "gestolpert" & dachte mir, dass es dadurch übersichtlicher wird. Aber>> werde wohl wieder darauf zurück fallen.>> Da tut sich bei mir gleich die Frage auf, woher bekomme ich denn das> iostm8s003.h-file, sodass ich meine Register korrekt beschrieben kann?> Weil wenn ich die stm8s.h und alle anderen header der STDPeriphLib> trotzdem inkludieren muss macht das ja (vorallem speicherplatztechnisch)> eher weniger Sinn oder?
Dumme Frage antwort: JA muss man trotzdem alles inkludieren, die hätte
ich mir bei nur einem genaueren Blick auch sparen können, hab das nur
bei Marc Steven Blog anders gesehen (also auch eine andere "Methode" zum
ansprechen der Register), dieser hat aber anscheinend seine Header-Files
von IAR, ich programmiere aber mit STVD.
BS schrieb:> trotzdem alles inkludieren
auch wieder falsch...in der stm8s.h kann man die Benutzung der StdPeriph
auskommentieren und benötigt dann nur die stm8s.h, langsam wirds
peinlich, aber falls mal jemand hierauf stößt möchte ich natürlich keine
falschen Infos weitergeben.
> Ich denke ich verstehe ganz gut, wie ein Interrupt funktioniert ;)> struct interrupt_vector const _vectab[] = {> //{0x82, (interrupt_handler_t)_stext}, /* reset */> //{0x82, NonHandledInterrupt}, /* trap */> //{0x82, NonHandledInterrupt}, /* irq0 */> ...> //{0x82, NonHandledInterrupt}, /* irq22 */> {0x82, (interrupt_handler_t)TIM4_UPD_OVF_IRQHandler}, /* irq23 */> //{0x82, NonHandledInterrupt}, /* irq24 */
Du verstehst davon scheinbar gar nichts.
Bei deiner _vectab landet der TIM4_UPD_OVF_IRQHandler auf der
Position von Reset.
Da wo der TIM4_UPD_OVF_IRQHandler erwartet wird, steht
irgendwas. Aber nicht das, was da hingehoert.
> Letzendlich lags an einem GPIO, den ich als Floating-Input mit> Interrupt definiert habe
Wohl kaum.
Mit z.B. IAR kann man weak Definitionen benutzen.
Wenn dein Compiler das nicht kann, dann entsorge ihn.