Hallo, laut STM32 Reference Manual ist es möglich den externen Interrupt so zu konfigurieren, dass dieser bei steigender und fallender Flanke auslöst. Nur wie unterscheide ich in der ISR ob der Interrupt durch die steigende bzw. fallende Flanke ausgelöst wurde? Mein erster Lösungsansatz wäre: Ich überprüfe in der ISR ob der entsprechende Portpin auf Low oder High liegt. Wenn der Portpin auf High gezogen ist, dann war es eine steigende Flanke. Und wenn der Portpin auf Low gezogen ist, dann war es eine fallende Flanke. Kann das so funktionieren, oder gibt es vielleicht ein Register das diese Information beinhaltet? Kurz zum Hintergrund: Ich möchte einen Portpin überwachen und bei der fallenden Flanke einen Timer starten. Bei der steigenden Flanke soll der Timer wieder gestoppt werden und die gemessene Zeit ausgegeben werden. Also im Prinzip möchte ich die Zeit zwischen zwei Flanken messen.
Ich mach das genauso, wie du es vor hast. Eine andere Möglichkeit habe ich noch nicht gefunden. Gruß Lasse
STM32_Beginner schrieb: > Also im Prinzip möchte ich die Zeit zwischen zwei Flanken messen. Wozu man normalerweise keinen externen Interrupt verwendet, sondern Timer Capture. Ist dann taktgenau, während bei der ExtInt Variante die variable Latenzzeit mit eingeht.
Lasse S. schrieb: > Ich mach das genauso, wie du es vor hast. Eine andere Möglichkeit habe > ich noch nicht gefunden. Danke für den Hinweis, das ist schon mal gut zu wissen. Sollte ich das mit dem Capture & Compare nicht hinbekommen, dann werd' ich das so lösen. A. K. schrieb: > Wozu man normalerweise keinen externen Interrupt verwendet, sondern > Timer Capture. Ist dann taktgenau, während bei der ExtInt Variante die > variable Latenzzeit mit eingeht. So wie ich das im Reference Manual verstanden habe, kann ich den Timer Capture so konfigurieren, dass dieser bei der entsprechenden Flanke(z.B: steigende Flanke) den Counter Wert in ein Zusatzregister sichert. Wie ich damit die Periodendauer eines Signals messen kann ist mir klar, doch wie messe ich damit die Pulsbreite eines Signals?
Was mir gerade noch eingefallen ist: Ich konfiguriere den Timer Capture so, dass ich zuerst den Counterstand bei der fallenden Flanke bekomme. Und wenn ich diesen dann habe, programmiere ich den Timer Capture um, sodass ich den Counterstand bei der steigenden Flanke bekomme. Die Differenz der beiden Werte entspricht dann der Pulsbreite. Kann das funktionieren?
Genau so geht das. Der primäre Unterschied zur Version über ExtInt ist dabei, dass Latenz/Laufzeit des Interrupts nur noch in die erforderliche Mindestdauer des Pulses eingehen, nicht mehr in die Messgenauigkeit. Alternativ kannst du auch 2 Eingänge des gleichen Timers nutzen, auf verschiedene Flanken konfiguriert. Dann muss nur noch durch das den Puls beendende Capture-Event ein Interrupt ausgelöst werden.
A. K. schrieb: > Genau so geht das. Der primäre Unterschied zur Version über ExtInt ist > dabei, dass Latenz/Laufzeit des Interrupts nur noch in die erforderliche > Mindestdauer des Pulses eingehen, nicht mehr in die Messgenauigkeit. > > Alternativ kannst du auch 2 Eingänge des gleichen Timers nutzen, auf > verschiedene Flanken konfiguriert. Dann muss nur noch durch das den Puls > beendende Capture-Event ein Interrupt ausgelöst werden. Vielen Dank für die Hilfestellung & die Erklärung! Ich werd' mich gleich mal ransetzen und das ausprobieren. Danke!
Hi, ich hab mir heute die Capture & Compare Unit des STM32 angesehen. Ich hab mich dazu entschlossen den TIM2_CH2 (entspricht Portpin PA.1) als Capture Eingang zu verwenden. Dazu gleich eine Frage: Im Datenblatt steht, dass PA.1 auch als USART2_RTS dient. Da ich in meiner Software auch den USART2 verwende (also nur RX und TX), wollte ich fragen ob ich den Portpin PA.1 nun verwenden kann oder nicht? Meine Konfiguration von TIM2 sieht im Prinzip so aus: -) GPIOA clock enable -) configure PA.1 as input with pullup -) CC2 channel is configured as input, IC2 is mapped on TI2. -) capture is done on the rising edge -) no prescaler, capture is done each time an edge is detected on the capture input -) enable capture -) capture interrupt enable -) TIM2 interrupt enable(NVIC) -) TIM2 priority = 2 -) set TIM2 counter enable Das Problem ist, dass der uC nie in die ISR springt. Hab ich bei der TIM2 Konfiguration vielleicht etwas wichtiges übersehen, oder könnte es etwas mit dem Portpin PA.1 zu tun haben? Bei Bedarf poste ich auch gerne den Code der Initialisierungsroutine.
Der alternate function clock für den TIM2 wird natürlich auch aktiviert
Sowas hast Du drin?
1 | NVIC_InitTypeDef NVIC_InitStructure; |
2 | /* Enable the TIM2 global Interrupt */
|
3 | NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; |
4 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; |
5 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; |
6 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; |
7 | NVIC_Init(&NVIC_InitStructure); |
STM32_Beginner schrieb: > steht, dass PA.1 auch als USART2_RTS dient. Da ich in meiner Software > auch den USART2 verwende (also nur RX und TX), wollte ich fragen ob ich > den Portpin PA.1 nun verwenden kann oder nicht? Ja, RTS kann man da drauf mappen, muss man aber nicht. Aber vorsorglich Errata-Sheet lesen, ob da irgendwas drüber drin steht. > -) GPIOA clock enable Timer auch? > Bei Bedarf poste ich auch gerne den Code der Initialisierungsroutine. Mach ma.
Markus Müller schrieb: > NVIC_InitTypeDef NVIC_InitStructure; > /* Enable the TIM2 global Interrupt */ > NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; > NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; > NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; > NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; > NVIC_Init(&NVIC_InitStructure); Von der ST Library hab ich leider nicht soviel Ahnung, ich hab die bisher nicht genutzt. A. K. schrieb: > Ja, RTS kann man da drauf mappen, muss man aber nicht. Aber > vorsorglich Errata-Sheet lesen, ob da irgendwas drüber drin steht. Als ich gestern im Errata-Sheet gestöbert hab, ist mir nichts aufgefallen. Aber es war schon spät, ich werd mir das daher heute nochmal in Ruhe ansehen. A. K. schrieb: > Mach ma. Anbei mein Sourcecode zur Initialisierung von TIM2:
1 | RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; //GPIOA clock enable |
2 | |
3 | RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; //TIM2 clock enable |
4 | |
5 | GPIOA->CRL = GPIOA->CRL & ~(0x000000F0) | (0x00000080);//configure PA.1 as input with pullup/pulldown |
6 | |
7 | TIM2->CCMR1 |= TIM_CCMR1_CC2S_0; //IC2 is mapped on TI2 |
8 | TIM2->CCMR1 |= (TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_1); //program input capture filter; N = 8 |
9 | |
10 | TIM2->CCER |= TIM_CCER_CC2P; //capture is done on the rising edge |
11 | TIM2->CCMR1 &= ~(TIM_CCMR1_IC2PSC_0 | TIM_CCMR1_IC2PSC_1); //no prescaler, capture is done each time an edge is detected on the capture input. |
12 | |
13 | TIM2->CCER |= TIM_CCER_CC2E; //capture counter value |
14 | TIM2->DIER |= TIM_DIER_CC2IE; //capture interrupt enable |
15 | |
16 | NVIC->ISER[0] |= (1<<28); //TIM2 interrupt enable |
17 | NVIC->IP[28] = 0x20; //TIM2 interrupt priority = 2 |
18 | TIM2->CR1 |= TIM_CR1_CEN; //set TIM2 runbit |
Und hier noch die ISR:
1 | volatile uint8_t dummy = 0; |
2 | |
3 | void TIM2_IRQHandler(void){ |
4 | if (TIM2->SR & 0x00000004) { //TIM2 capture&compare interrupt? |
5 | dummy = 1; |
6 | }
|
7 | TIM2->SR &= ~(0x00000004); //clear interrupt flag |
8 | }
|
TIM2->ARR setzen. Beispielsweise auf 0xFFFF. Obacht, wenn man ARR schreibt, dann schreibt man in ein Pufferregister, das erst bei einem Update-Event wirklich greift. Es kann nötig sein, dieses Event manuell auszulösen (UG bit in the TIMx_EGR). "In upcounting mode, the counter counts from 0 to the auto-reload value (content of the TIMx_ARR register), then restarts from 0 and generates a counter overflow event." "The counter is blocked while the auto-reload value is null."
Dein Tipp war goldrichtig, jetzt funktioniert's! Besten Dank!
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.