Verbindung des Ultraschallsensors HC-SR04 mit STM32L

Ich versuche, diesen HC-SR4-Ultraschallsensor zu steuern, indem ich einfach eine LED einschalte, wenn ein Objekt näher als 100 cm erkannt wird. Ich verwende TIM2 für das Triggersignal (Pin PB10) und TIM4, um das Echosignal (Pin PB6) zu empfangen. und die LED ist mit Pin PB7 verbunden. Wenn ich den folgenden Code lade, schaltet sich die LED einfach ein, egal ob es ein Objekt gibt oder nicht, es ist nur EIN.

#include <stdio.h>
#include "stm32l1xx.h"                  // Keil::Device:Startup

        //Initialize the timers variables.
    volatile int timespan = 0;      // Total pulse width
    volatile int lastcounter = 0;   // Timer counter value of the last event
    volatile int newcounter = 0;    // Timer counter value of the current event
    volatile int overflow = 0;      // Count the number of overflows

    void SetHSI(void);           
    void Delay(int);
    void GPIO_config(void);
    void TIM2_Trigger(void);
    void TIM4_Init(void);
    void TIM4_Echo_Read(void);
    void LED (void);


        int main(void){

            SetHSI();
            GPIO_config();
            TIM2_Trigger();
            TIM4_Init();


          while(1){

             TIM4_Echo_Read();
             LED();

             Delay(100);
      }
   }

void Delay(int x){
    //input milliseconds, delay that number of milliseconds
    int a,b;
    for(a=0; a<x; a++){
        for(b=0; b<1000; b++){
        }
    }
}

  //set HSI as SystemCoreClock (HSE is not populated on STM32L-Discovery board)//

void SetHSI(void) {

// Turn on HSI (16MHz)
RCC->CR |= RCC_CR_HSION;
// Wait until HSI is ready
while( (RCC->CR & RCC_CR_HSIRDY) == 0);
// Select HSI as system clock
RCC->CFGR &= ~RCC_CFGR_SW_HSI;
RCC->CFGR |= RCC_CFGR_SW_HSI;
while( (RCC->CFGR & RCC_CFGR_SWS)!=RCC_CFGR_SWS_HSI ); // Wait till HSI
}

// Configure GPIO Port B
void GPIO_config(void){

    RCC->AHBRSTR |= RCC_AHBRSTR_GPIOBRST;   // Reset GPIOB clock 
    RCC->AHBRSTR &= ~RCC_AHBRSTR_GPIOBRST;  // Clear Reset 
    RCC->AHBENR |= RCC_AHBENR_GPIOBEN;      // Enable GPIOB clock 

    //PB6 Echo Pin
    GPIOB->MODER   &=   ~(0x03 << 12);    // Clear bit 12 & 13 Alternate function mode 
    GPIOB->MODER   |=   (0x02 << 12);    // set as Alternate function mode 
    GPIOB->OSPEEDR &=   ~(0x03<< 12);   // 40 MHz  speed 
    GPIOB->OSPEEDR |=   (0x03<< 12);    // 40 MHz  speed 
    GPIOB->PUPDR &=         ~(0X3<<12); // NO PULL-UP PULL-DOWN 
    GPIOB->OTYPER &=        ~(1<<6);    // PUSH-PULL 
    GPIOB->AFR[0] &= ~GPIO_AFRL_AFRL6;  // Clear pin 6 for alternate function
    GPIOB->AFR[0] |=        0x2 << (4*6);   // set PB pin 6 as AF2 (TIM4_CH1) 

//PB10 Pluse Generating Pin
    GPIOB->MODER   &=   ~(0x03 << (2*10));  // Clear bit 12 & 13 Alternate function mode 
    GPIOB->MODER   |=   0x02 << (2*10);     // set as Alternate function mode 
    GPIOB->OSPEEDR &=   ~(0x03<< (2*10));   // 40 MHz  speed 
    GPIOB->OSPEEDR |=   0x03<< (2*10);      // 40 MHz  speed 
    GPIOB->PUPDR &=         ~(1<<10);       // NO PULL-UP PULL-DOWN 
    GPIOB->OTYPER &=        ~(1<<10);       // PUSH-PULL 
    GPIOB->AFR[1] |=        0x1 << (4*2);   // set PB pin 10 as AF1 (TIM2_CH3) 

//PB7 LED ON/OFF
    GPIOB->MODER   |=   GPIO_MODER_MODER7_0;   // General purpose output mode
  GPIOB->OSPEEDR |=   GPIO_OSPEEDER_OSPEEDR7;  // Max High speed 50MHz


}

// CONFIGURE TIM2 FOR SENDING OUTPUT SIGNAL
void TIM2_Trigger(void){
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // ENABLE TIM2 CLOCK
    TIM2->PSC = 159;                    // SET APPROPRAIT PRESCALER TO SLOW DOWN THE CLOCK
    TIM2->ARR = 0XFFFF;         // SET MAX PULSE WIDTH OF 65536us FOR 16-BIT TIMER

    TIM2->CCMR2 |= TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; // 111: PWM mode 1 
    TIM2->CCMR2 |= TIM_CCMR2_OC3PE;         // CH3 Output Preload Enable
    TIM2->CR1 |= TIM_CR1_ARPE;              // Auto-reload Prelaod Enable
    TIM2->CCER |= TIM_CCER_CC3E;            // Enable Output for CH3
    TIM2->EGR |= TIM_EGR_UG;                // Force Update
    TIM2->SR &= ~TIM_SR_UIF;                // Clear the Update Flag
    TIM2->DIER |= TIM_DIER_UIE;             // Enable Interrupt on Update
    TIM2->CR1 &= ~TIM_CR1_DIR;              // Set upcounting counter direction
    TIM2->CCR3 &= ~(TIM_CCR3_CCR3);         // Clear CCR3 (Channel 3) 
    TIM2->CCR3 |= 0x1;                      // Load the register 
    TIM2->CR1 |= TIM_CR1_CEN;               // Enable the counter
}


// CONFIGURE TIM4 FOR RECEIVING INPUT SIGNAL
void TIM4_Init(void){
    RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;         // ENABLE TIM4 CLOCK
    TIM4->PSC = 15;                             // SET APPROPRAIT PRESCALER TO SLOW DOWN THE CLOCK
    TIM4->ARR = 0xFFFF;                         // SET MAX PULSE WIDTH OF 65536us FOR 16-BIT TIMER
    TIM4->CCMR1 &= ~TIM_CCMR1_CC1S;             // CLEAR CAPTURE/COMPARE REGISTER
    TIM4->CCMR1 |= 0X1;                         // SELECT CH1 INPUTE CAPTURE 
    TIM4->CCMR1 &= ~TIM_CCMR1_IC1F;             // DISABLE DIGITAL FILTERING
    TIM4->CCER |= (1<<1 | 1<<3);                // SELECT BOTH RISING AND FALLING EDGE DETECTION CC1P & CC1NP
    TIM4->CCMR1 &= ~(TIM_CCMR1_IC1PSC);         // INPUT PRESCALER 0 TO CAPTURE EACH VALID EDGE
    TIM4->DIER |= TIM_DIER_UIE;                 // UPDATE INTERRUPT ENABLE
    TIM4->CCER |= TIM_CCER_CC1E;                // ENABLE COUNTER CAPTURE
    TIM4->DIER |= TIM_DIER_CC1IE;               // ENABLE CH1 CAPTURE/COMPARE INTERRUPT
    TIM4->CR1 |= TIM_CR1_CEN;                   // Enable the counter
    NVIC_SetPriority(TIM4_IRQn, 1);             // SET PRIORITY TO 1
    NVIC_EnableIRQ(TIM4_IRQn);                  //ENABLE TIM4 INTERRUPT IN NVIC


}

void TIM4_Echo_Read(void){

    if ((TIM4->SR & TIM_SR_UIF) != 0){          // Check the update event flag
        overflow++;                             // if UIF = 1, increment overflow counter
        TIM4->SR &= ~TIM_SR_UIF;                // clear UIF
    }
    if ((TIM4->SR & TIM_SR_CC1IF) != 0){        // Check capture event flag 
    newcounter = TIM4->CCR1;                    // read capture value, store as newcounter
    timespan = (newcounter - lastcounter)+(65536 * overflow); // calculate the total pulse width
    lastcounter = newcounter;                   // save the value of newcounter as lastcounter to be used for the next cycle
    overflow = 0;                               // clear overflow counter
    }

}

void LED (void){

    int Distance;               // actual distance in cm
    Distance = (timespan / 58);

    if (Distance <= 100){

        GPIOB->BSRRL = (1<<7);
    }
        else {
        GPIOB->BSRRH = (1<<7);

        }   
    }

Hier sind die Ergebnisse, wenn ich den Debugger ausführe:

1/ Newcounter liest den CCR1-Wert. (z. B. 0X000000000001AD2E), timespan lädt den Wert der Gleichung und Distance lädt den Wert der Gleichung (timespan/58).

2/ Der Wert von Distance ist immer weit über 100, selbst wenn ein Objekt 50 cm entfernt ist. Generell spiegeln die Werte nicht den tatsächlichen Zustand wieder.

Ganz zu schweigen davon, dass die LED seltsamerweise die ganze Zeit eingeschaltet ist, obwohl die obigen Ergebnisse zu einer AUS-LED führen sollten.

Ich kann die mit dem Echo-Pin (PB6) verbundene LED blinken sehen, was meiner Meinung nach bedeutet, dass ein kontinuierliches Signal empfangen wird.

Gedanken?

PS Ich hätte float für Distance verwenden sollen, aber aufgrund eines Debugger-Problems habe ich es durch int ersetzt, bis ich die oben genannten Probleme gelöst habe.

Zusätzlich verwende ich einen Spannungsteiler (5 V -> 3 V) vom Echo-Pin zum Eingangspin PB6
Sie sagen nicht, wie Ihre LED angeschlossen ist, also wäre eine erste Vermutung, dass das Einschalten des Pins die LED einschaltet. Es könnte jedoch sein, dass Sie die Pins nicht richtig eingerichtet haben und ich würde [versuchen], die LED zu Beginn Ihres Codes auszuschalten, jedoch in einem einzigen Schritt, und sicherstellen, dass sie sich wirklich ausschaltet.
Ein weiterer Gedanke ist, dass Sie viel zu viele globale Variablen verwenden. Das Übergeben von Werten in und aus Funktionen macht die Dinge viel einfacher zu lesen.
@DiBosco Ich habe erwähnt, dass LED an PB7 angeschlossen ist (als Teil des Discovery-Entwicklungsboards). Außerdem habe ich in einem separaten Code versucht, die LED mit BSRRL (Set) & BSRRH (Reset) zu blinken, und es hat funktioniert. Am wichtigsten ist, dass die LED beim Ausführen des Debuggers nie aufleuchtet, selbst wenn der gesamte Zyklus abgeschlossen ist. Können Sie mir in Bezug auf die globale Variable ein Beispiel geben, wie ich das besser machen kann?
Mir zu sagen, dass die LED an PB7 angeschlossen ist, bedeutet jedoch nichts. Ich wusste nicht, ob es angeschlossen war, also schaltete sein Pin, der hoch war, es ein oder aus? Das war der springende Punkt. Richtet Ihr separater Code den GPIO auf genau die gleiche Weise ein? Hat das auch nicht funktioniert, wenn du es mit dem Debugger ausgeführt hast?
Es gibt viele, viele Artikel und Hinweise zur Vermeidung globaler Variablen. Eines von vielen, vielen Beispielen finden Sie hier: stackoverflow.com/questions/29348663/… Sobald Sie den Dreh raus haben, werden Sie nicht wissen, wie Sie jemals mit so vielen verwirrenden Globals fertig geworden sind.
@DiBosco ja, die gleiche Konfiguration hat funktioniert, nämlich: GPIOB->MODER |= GPIO_MODER_MODER7_0; GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7; und dann if (Distanz <= 100) {GPIOB->BSRRL = (1<<7); } Else { GPIOB->BSRRH = (1<<7);
Ein bisschen mehr über Globals. Ich war wirklich ein bisschen schroff zu dir, das tut mir leid. Es gibt keine schnelle und einfache Antwort, die Sie lesen und üben müssen, aber eine Möglichkeit, damit zu beginnen, besteht darin, Werte in und aus Funktionen zu übergeben. Selbst die Grundregel, nach der Sie sagen, dass ich nur Variablen verwenden werde, die an die Funktionen und Locals innerhalb dieser Funktion übergeben werden, wird Ihnen wirklich sehr helfen.
OK, funktioniert das also mit dieser sehr einfachen Software, die nur eine LED ein- und ausschaltet, mit dem Debugger? Ich versuche nur, genau herauszufinden, wo dieses Problem liegen könnte.
@DiBosco ja, es funktioniert, ich habe es mit dem Debugger versucht und es gab keine Probleme
OK, wenn Sie also eine Funktion in die lästige Software einfügen, die, bevor Sie in die Endlosschleife der Hauptleitung wechseln, dann die LEDs ein- und ausschaltet?
@DiBosco wenn es in die Endlosschleife geht und direkt nach der Ausführung von GPIOB->BSRRL = (1<<7); die LED schaltet sich ein. dann geht es in die Verzögerung, um das Blinken zu verursachen, das es direkt nach der Ausführung von GPIOB->BSRRH = (1<<7); ausschaltet. dann wieder eine kurze Verzögerung ... dann wiederholt es sich
OK, gut und vorausgesetzt, Sie haben das gerade in den nicht funktionierenden Code eingefügt, bedeutet dies, dass der LED-Steuerungsteil der Software richtig ist. Also, wenn Sie diese Testfunktion entfernen, das Programm laufen lassen und die LED-Funktion beim if (Distance <= 100) unterbrechen, was passiert, wenn Sie einen Einzelschritt durchlaufen? Sind Sie sich zu 100 % sicher, dass Distance das ist, was Sie Ihrer Meinung nach sein sollten?
@DiBosco Ich denke, hier gibt es eine Verwirrung. Ich sprach über den LED-Blinky-Test, als ich sagte, die LED schaltet sich ein. Wenn wir über den problematischen Code oben sprechen, schaltet sich die LED nie ein, weil der Distanzwert IMMER > 100 ist. Und es springt direkt zur 'else{'-Anweisung, die den LED-Pin zurücksetzt. Ich denke, das Problem besteht darin, unrealistische Werte bei 'Distance' zu erhalten? Beachten Sie, dass die Werte bis zu 800 cm und möglicherweise mehr erreichen können, da der Ultraschallsensor nur bis zu 400 cm erkennen kann. Es bringt mich wirklich um..
@DiBosco Die globalen Variablen dienen der Anbindung an die Interrupt-Service-Routine. Da dies nicht vom Hauptausführungsthread aufgerufen wird, sondern effektiv von der Hardware "aufgerufen" wird, ist es nicht möglich, Variablen an es zu übergeben oder einen Rückgabewert wie bei einer gewöhnlichen Unterroutine zu erhalten. Einige der Globals könnten lediglich statische Locals sein, aber ein C-Programm wie dieses wird sowieso flach kompiliert, also ist das kein großer Unterschied. Wenn jedoch diejenigen, die nur innerhalb eines einzigen Laufs des ISR verwendet werden, nicht als "flüchtig" gekennzeichnet werden, würde es möglich sein, so etwas wie newcounterin einem Register zu führen.
@Chris, es gibt keine Interrupt-Service-Routine. Es ist alles mit Umfragen erledigt.
@DiBosco - es scheint als Interrupt-Service-Routine konzipiert worden zu sein, und in der Antwort des Fragestellers unten ist es eine Interrupt-Service-Routine, aber Sie haben Recht, in der Version der Frage, in der es abgefragt wurde.

Antworten (1)

Ich möchte den aktualisierten Code teilen, der tatsächlich funktioniert (keine Bibliothek erforderlich):

#include <stdio.h>
#include "stm32l1xx.h"                  // Keil::Device:Startup

        //Initialize the timers variables.
    volatile int timespan = 0;                              // Total pulse width
    volatile int lastcounter = 0;                           // Timer counter value of the last event
    volatile int newcounter = 0;                            // Timer counter value of the current event
    volatile int overflow = 0;                              // Count the number of overflows


    void SysTick_Handler(void);
    void SetHSI(void);
    void LED_GPIO(void);    
    void TIM4_C1_Init(void);
    void TIM2_C3_Init(void);
    void TIM4_IRQHandler(void);
    void LED (void);

        void setSysTick(void){
    // ---------- SysTick timer (1ms) -------- //
    if (SysTick_Config(SystemCoreClock / 1000)) {
    while (1);  // Capture error
    }
}
    volatile uint32_t msTicks=0; //counts 1ms timeTicks 
    void SysTick_Handler(void) {
    msTicks++;
}

static void Delay(__IO uint32_t dlyTicks){ 
  uint32_t curTicks; 
    curTicks = msTicks;
    while ((msTicks - curTicks) < dlyTicks);
}

        int main(void){
          SysTick_Handler();
            setSysTick();
            SetHSI();                             
            LED_GPIO();

            TIM2_C3_Init();
            TIM4_C1_Init();
while(1){

    LED();

Delay(100);
    }
}

/*----------------------------------------------------------------------------
  set HSI as SystemCoreClock (HSE is not populated on STM32L-Discovery board)
 *----------------------------------------------------------------------------*/
void SetHSI(void) {

// Turn on HSI (16MHz)
RCC->CR |= RCC_CR_HSION;
// Wait until HSI is ready
while( (RCC->CR & RCC_CR_HSIRDY) == 0);
// Select HSI as system clock
RCC->CFGR &= ~RCC_CFGR_SW_HSI;
RCC->CFGR |= RCC_CFGR_SW_HSI;
while( (RCC->CFGR & RCC_CFGR_SWS)!=RCC_CFGR_SWS_HSI ); // Wait till HSI
}

// Configure GPIO Port B
void LED_GPIO(void){


    RCC->AHBENR |= RCC_AHBENR_GPIOBEN;        // Enable GPIOB clock 

//PB7 LED ON/OFF
    GPIOB->MODER   |=   GPIO_MODER_MODER7_0;     // General purpose output mode
  GPIOB->OSPEEDR |=   GPIO_OSPEEDER_OSPEEDR7;  // Max High speed 50MHz


}

// CONFIGURE TIM2 FOR SENDING OUTPUT SIGNAL
void TIM2_C3_Init(void){

    RCC->AHBENR |= RCC_AHBENR_GPIOBEN;        // Enable GPIOB clock 

//PB10 Pluse Generating Pin
    GPIOB->MODER   &=   ~(0x03 << (2*10));     // Clear bit 12 & 13 Alternate function mode 
    GPIOB->MODER   |=   0x02 << (2*10);                 // set as Alternate function mode 
    GPIOB->OSPEEDR &=   ~(0x03<< (2*10));           // 40 MHz  speed 
    GPIOB->OSPEEDR |=   0x03<< (2*10);              // 40 MHz  speed 
    GPIOB->PUPDR &=         ~(1<<10);                           // NO PULL-UP PULL-DOWN 
    GPIOB->OTYPER &=        ~(1<<10);                           // PUSH-PULL 
    GPIOB->AFR[1] |=        0x1 << (4*2);                   // set PB pin 10 as AF1 (TIM2_CH3)

    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;                 // ENABLE TIM2 CLOCK
    TIM2->PSC = 159;                                                        // SET APPROPRAIT PRESCALER TO SLOW DOWN THE CLOCK
    TIM2->ARR = 0XFFFF;                                                 // SET MAX PULSE WIDTH OF 65536us FOR 16-BIT TIMER
    TIM2->CR1 |= TIM_CR1_DIR;                                       // Set downcounting counter direction
    TIM2->CCMR2 &= ~(TIM_CCMR2_OC3M);                       // Clear OC3M (Channel 3)
  TIM2->CCMR2 |= TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2;
    TIM2->CCMR2 |= TIM_CCMR2_OC3PE;                         // CH3 Output Preload Enable
    TIM2->CR1 |= TIM_CR1_ARPE;                                  // Auto-reload Prelaod Enable
    TIM2->CCER |= TIM_CCER_CC3E;                                // Enable Output for CH3
    TIM2->EGR |= TIM_EGR_UG;                                        // Force Update
    TIM2->SR &= ~TIM_SR_UIF;                                        // Clear the Update Flag
    TIM2->DIER |= TIM_DIER_UIE;                                 // Enable Interrupt on Update
    TIM2->CCR3 &= ~(TIM_CCR3_CCR3);                     // Clear CCR3 (Channel 3) 
    TIM2->CCR3 |= 0x1;                                            // Load the register 
    TIM2->CR1 |= TIM_CR1_CEN;                           // Enable the counter
}


// CONFIGURE TIM4 FOR RECEIVING INPUT SIGNAL
void TIM4_C1_Init(void){
    RCC->AHBENR |= RCC_AHBENR_GPIOBEN;        // Enable GPIOB clock 
    GPIOB->MODER   &=   ~(0x03 << 12);     // Clear bit 12 & 13 Alternate function mode 
    GPIOB->MODER   |=   (0x02 << 12);               // set as Alternate function mode 
    GPIOB->OSPEEDR &=   ~(0x03<< 12);           // 40 MHz  speed 
    GPIOB->OSPEEDR |=   (0x03<< 12);                // 40 MHz  speed 
    GPIOB->PUPDR &=         ~(0X3<<12);                         // NO PULL-UP PULL-DOWN 
    GPIOB->OTYPER &=        ~(1<<6);                            // PUSH-PULL 
    GPIOB->AFR[0] &= ~GPIO_AFRL_AFRL6;  // Clear pin 6 for alternate function
    GPIOB->AFR[0] |=        0x2 << (4*6);                   // set PB pin 6 as AF2 (TIM4_CH1) 

    RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;                 // ENABLE TIM4 CLOCK
    TIM4->PSC = 15;                                     // SET APPROPRAIT PRESCALER TO SLOW DOWN THE CLOCK                                              
    TIM4->CCMR1 &= ~TIM_CCMR1_CC1S;                         // CLEAR CAPTURE/COMPARE REGISTER
    TIM4->CCMR1 |= 0X1;                                                 // SELECT CH1 INPUTE CAPTURE 
    TIM4->CCMR1 &= ~TIM_CCMR1_IC1F;                         // DISABLE DIGITAL FILTERING
    TIM4->CCER |= (1<<1 | 1<<3);                                // SELECT BOTH RISING AND FALLING EDGE DETECTION CC1P & CC1NP
    TIM4->CCMR1 &= ~(TIM_CCMR1_IC1PSC);                 // INPUT PRESCALER 0 TO CAPTURE EACH VALID EDGE
    TIM4->CCER |= TIM_CCER_CC1E;                                // ENABLE COUNTER CAPTURE
    TIM4->DIER |= TIM_DIER_CC1IE;                               // ENABLE CH1 CAPTURE/COMPARE INTERRUPT
    TIM4->DIER |= TIM_DIER_CC1DE;   
    TIM4->DIER |= TIM_DIER_UIE;                                 // UPDATE INTERRUPT ENABLE
    TIM4->CR1 &= ~TIM_CR1_DIR;                                      // Set downcounting counter direction
    TIM4->CR1 |= TIM_CR1_CEN;                                       // Enable the counter
    NVIC_SetPriority(TIM4_IRQn, 1);                         // SET PRIORITY TO 1
    NVIC_EnableIRQ(TIM4_IRQn);                                  //ENABLE TIM4 INTERRUPT IN NVIC


}

void TIM4_IRQHandler(void){

    if ((TIM4->SR & TIM_SR_UIF) != 0){                  // Check the update event flag
        overflow++;                                 // if UIF = 1, increment overflow counter
        TIM4->SR &= ~TIM_SR_UIF;                                    // clear UIF
    }
    if ((TIM4->SR & TIM_SR_CC1IF) != 0){                // Check capture event flag 
    newcounter = TIM4->CCR1;                                        // read capture value, store as newcounter
    timespan = (newcounter - lastcounter)+(65536 * overflow);   // calculate the total pulse width
    lastcounter = newcounter;                               // save the value of newcounter as lastcounter to be used for the next cycle
    overflow = 0;                                                       // clear overflow counter
    }

}

void LED (void){

    float Distance;                                             // actual distance in cm
    Distance = (timespan / 58.0);

    if (Distance > 0.0 && Distance <= 100.0){

        GPIOB->BSRRL = (1<<7);
    }
        else {
        GPIOB->BSRRH = (1<<7);

        }   
    }
Es lag also daran, int statt float zu verwenden?
@DiBosco Nicht genau, der Hauptgrund, warum es nicht funktionierte, war das Schreiben eines falschen Funktionsnamens beim Aktivieren des NVIC-Interrupts, sobald NVIC_SetPriority(TIM4_IRQn, 1); NVIC_EnableIRQ(TIM4_IRQn);der Funktionsname übereinstimmte, es funktionierte. Der Grund, warum ich das geändert habe, floatist int, dass STM32L1 keine FPU hat. floatIch habe jedoch versucht, es nach dem Schreiben anstelle von auszuführen int, und es hat tatsächlich funktioniert, aber mit einer etwas langsamen Reaktion, und der DistanceWert wurde beim Ausführen des Debuggers nicht so gut angezeigt. Daher intstattdessen verwendet