HC-SR4超声波传感器与STM32L1的接口
我试图控制这个HC-SR4超声波传感器,当检测到一个距离1米远的物体时,只需在一个LED上。 我使用TIM2作为触发信号(引脚PB10),使用TIM4接收回波信号(引脚PB6)。LED连接至引脚PB7。 当我加载下面的代码时,LED只会亮起,无论是否有对象,它都会亮起 知道我哪里出错了吗HC-SR4超声波传感器与STM32L1的接口,c,embedded,stm32,stm32ldiscovery,C,Embedded,Stm32,Stm32ldiscovery,我试图控制这个HC-SR4超声波传感器,当检测到一个距离1米远的物体时,只需在一个LED上。 我使用TIM2作为触发信号(引脚PB10),使用TIM4接收回波信号(引脚PB6)。LED连接至引脚PB7。 当我加载下面的代码时,LED只会亮起,无论是否有对象,它都会亮起 知道我哪里出错了吗 #include <stdio.h> #include "stm32l1xx.h" // Keil::Device:Startup // switch fro
#include <stdio.h>
#include "stm32l1xx.h" // Keil::Device:Startup
// switch from HSE to HSI clock 16MHz
void HSI_config(){
RCC->CR |= RCC_CR_HSION; // Turn On HSI oscillator
RCC->CFGR |= RCC_CFGR_SW; // Select HSI clock
RCC->CFGR |= RCC_CFGR_SWS_HSI;
RCC->CR |= RCC_CR_HSIRDY; // wait for HSI stabilize
}
// Configure GPIO Port B
void GPIO_config(){
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 << (2*6)); // Clear bit 12 & 13 Alternate function mode
GPIOB->MODER |= 0x02 << (2*6); // set as Alternate function mode
GPIOB->OSPEEDR &= ~(0x03<< (2*6)); // 40 MHz speed
GPIOB->OSPEEDR |= 0x03<< (2*6); // 40 MHz speed
GPIOB->PUPDR &= ~(1<<6); // NO PULL-UP PULL-DOWN
GPIOB->OTYPER &= ~(1<<6); // PUSH-PULL
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 TIM4 FOR RECEIVING INPUT SIGNAL
void TIM4_Enable(){
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->CCER |= TIM_CCER_CC1E; // ENABLE COUNTER CAPTURE
TIM4->DIER |= TIM_DIER_CC1IE; // ENABLE CH1 CAPTURE/COMPARE INTERRUPT
NVIC_SetPriority(TIM4_IRQn, 1); // SET PRIORITY TO 1
NVIC_EnableIRQ(TIM4_IRQn); //ENABLE TIM4 INTERRUPT IN NVIC
}
// CONFIGURE TIM2 FOR SENDING OUTPUT SIGNAL
void TIM2_Enable(){
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // ENABLE TIM2 CLOCK
TIM2->PSC = 15; // 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 downcounting counter direction
TIM2->CR1 |= TIM_CR1_CEN; // Enable Counter
}
//Initialize the float variables.
volatile uint8_t timespan = 0; // Total pulse width
volatile uint8_t lastcounter = 0; // Timer counter value of the last event
volatile uint8_t newcounter = 0; // Timer counter value of the current event
volatile uint8_t overflow = 0; // Count the number of overflows
volatile uint8_t PulseEnd = 0; // Declare end of pulse
void Echo_TIM4_IRQHandler(){
if ((TIM4->SR & TIM_SR_UIF) != 0){ // Check the update even flag
overflow = overflow + 1; // 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
PulseEnd = 1;
}
}
void setSysTick(void){
// ---------- SysTick timer (1ms) -------- //
if (SysTick_Config(SystemCoreClock / 1000)) {
// Capture error
while (1){};
}
}
volatile uint32_t msTicks; //counts 1ms timeTicks
void SysTick_Handler(void) {
msTicks++;
}
static void Delay(__IO uint32_t dlyTicks){
uint32_t curTicks = msTicks;
while ((msTicks - curTicks) < dlyTicks);
}
int main(void){
float Distance = 0.0f; // actual distance in cm
int Pulsesent = 0;
HSI_config();
setSysTick();
GPIO_config();
TIM4_Enable();
Echo_TIM4_IRQHandler();
while(1){
if (Pulsesent == 0) {
(Pulsesent = 1);
TIM2_Enable();
}
if(Pulsesent && PulseEnd){
Pulsesent = 0;
if(overflow == 1){
timespan = 0;
}
else {
Distance = (timespan / 58) ;
}
Delay(1);
}
if (Distance <= 100){
GPIOB->BSRRL = (1<<7);
}
else {
GPIOB->BSRRL = (0<<7);
}
}
}
#包括
#包括“stm32l1x.h”//Keil::设备:启动
//从HSE切换到HSI时钟16MHz
无效HSI_配置(){
RCC->CR |=RCC_CR_HSION;//打开HSI振荡器
RCC->CFGR |=RCC_CFGR_SW;//选择HSI时钟
RCC->CFGR |=RCC_CFGR_SWS_HSI;
RCC->CR |=RCC_CR_HSIRDY;//等待HSI稳定
}
//配置GPIO端口B
无效GPIO_配置(){
RCC->AHBRSTR |=RCC_AHBRSTR_GPIOBRST;//重置GPIOB时钟
RCC->AHBRSTR&=~RCC\u AHBRSTR\u GPIOBRST;//清除重置
RCC->AHBENR |=RCC_AHBENR_GPIOBEN;//启用GPIOB时钟
//PB6回音针
GPIOB->MODER&=~(0x03 MODER |=0x02 OSPEEDR&=~(0x03OSPEEDR |=0x03PUPDR&=~(1ARR=0XFFFF;//为16位计时器设置65536us的最大脉冲宽度
TIM4->CCMR1&=~TIM\u CCMR1\u CC1S;//清除捕获/比较寄存器
TIM4->CCMR1 |=0X1;//选择CH1输入捕获
TIM4->CCMR1&=~TIM\u CCMR1\u IC1F;//禁用数字滤波
TIM4->CCER |=(1APB1ENR |=RCC_APB1ENR| u TIM2EN;//启用TIM2时钟
TIM2->PSC=15;//设置适当的预分频器以降低时钟速度
TIM2->ARR=0XFFFF;//设置16位定时器的最大脉冲宽度为65536us
TIM2->CCMR2 |=TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2;//111:PWM模式1
TIM2->CCMR2 |=TIM_CCMR2_OC3PE;//CH3输出预加载启用
TIM2->CR1 |=TIM_CR1_ARPE;//自动重新加载预加载启用
TIM2->CCER |=TIM_CCER_CC3E;//为CH3启用输出
TIM2->EGR |=TIM_EGR_UG;//强制更新
TIM2->SR&=~TIM\u SR\u UIF;//清除更新标志
TIM2->DIER |=TIM_DIER_UIE;//在更新时启用中断
TIM2->CR1 |=TIM_CR1_DIR;//设置下行计数计数器方向
TIM2->CR1 |=TIM_CR1_CEN;//启用计数器
}
//初始化浮点变量。
易失性uint8\u t timespan=0;//总脉冲宽度
volatile uint8\u t lastcounter=0;//上次事件的计时器计数器值
volatile uint8\u t newcounter=0;//当前事件的计时器计数器值
volatile uint8\u t overflow=0;//计算溢出的数量
volatile uint8\u t PulseEnd=0;//声明脉冲结束
void Echo_TIM4_IRQHandler(){
如果((TIM4->SR&TIM_SR_UIF)!=0){//请检查更新偶数标志
溢出=溢出+1;//如果UIF=1,则递增溢出计数器
TIM4->SR&=~TIM\U SR\U UIF;//清除UIF
}
如果((TIM4->SR&TIM_SR_CC1IF)!=0){//检查捕获事件标志
newcounter=TIM4->CCR1;//读取捕获值,存储为newcounter
timespan=(newcounter-lastcounter)+(65536*溢出);//计算总脉冲宽度
lastcounter=newcounter;//将newcounter的值另存为lastcounter以用于下一个周期
溢出=0;//清除溢出计数器
脉冲数=1;
}
}
void设置系统键(void){
//------系统时钟(1ms)--//
if(系统时钟配置(系统时钟/1000)){
//捕获错误
而(一){};;
}
}
volatile uint32\u t msTicks;//计算1ms时间刻度
void SysTick_处理器(void){
msTicks++;
}
静态无效延迟(uu IO uint32_t dlyTicks){
uint32_t curTicks=msTicks;
而((msTicks-curTicks) 如果(距离BSRRL=(1你的代码是多么混乱,不仅仅是你的布局,“逻辑”你对全局变量的使用似乎完全是foobar。我认为你必须花一些精力来整理你的代码设计,从一位经验丰富的嵌入式软件工程师那里获得建议。想想:这是一个很小的代码,你无法让它工作,所以用你目前的开发方法,你怎么能得到一些呢复杂的工作-你需要改变你的方法
与您看到的症状直接相关的代码中至少有一个问题是,在main()中,您的全局变量PulseEnd
被设置为副作用
您直接调用TIM4中断处理程序-为什么?可能是为了初始化全局变量?不要这样做!-并且永远不会重置此代码中的任何地方
那么首先
#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);
}
}