Estoy tratando de controlar este sensor ultrasónico HC-SR4 simplemente ENCENDIENDO un LED cuando se detecta un objeto cercano a 100 cm. Estoy usando TIM2 para la señal de activación (Pin PB10), y TIM4 para recibir la señal de Echo (Pin PB6). y el LED está conectado al Pin PB7. cuando cargo el código a continuación, el LED simplemente se enciende, ya sea que haya un objeto o no, simplemente está ENCENDIDO.
#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);
}
}
Estos son los resultados cuando ejecuto el depurador:
1 / Newcounter lee el valor CCR1. (por ejemplo, 0X000000000001AD2E), el intervalo de tiempo carga el valor de la ecuación, y la Carga de distancia el valor de la ecuación (intervalo de tiempo / 58).
2 / El valor de Distancia siempre es mucho mayor que 100, incluso si hay un objeto a 50 cm de distancia. En general, los valores no reflejan la condición real.
Sin mencionar que el LED está de forma extraña ENCENDIDO todo el tiempo, aunque los resultados anteriores deberían resultar en un LED APAGADO.
Puedo ver el LED conectado al pin Echo (PB6) parpadeando, lo que creo que significa que se está recibiendo una señal continua.
¿Pensamientos?
P.S Debería haber usado float para Distancia, sin embargo, debido al problema del depurador, lo reemplacé con int, hasta que resolví los problemas mencionados anteriormente.