这篇文章主要介绍了STM32F429如何使用定时器多路HC-SR04超声波输入捕获,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
介绍
STMF429IGT开发板,通过定时器2接入2路超声波模块。使用Timer2的输入捕获功能来实现。超声波模块使用HC-SR04模组。
关于hc-sr04的工作原理这里不再介绍,请自行百度。废话不多说,直接上代码:
Timer2 GPIO配置代码:
TIM_HandleTypeDef TIM2_Handler; //定时器2句柄
//timer2 gpio配置
void Timer2_Cap_Init(u32 arr,u16 psc)
{
//GPIO³õʼ»¯
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_TIM2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**TIM2 GPIO Configuration
PA5 ------> TIM2_CH1
PB3 ------> TIM2_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* TIM2 interrupt Init */
HAL_NVIC_SetPriority(TIM2_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
//TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_IC_InitTypeDef sConfigIC = {0};
TIM2_Handler.Instance = TIM2;
TIM2_Handler.Init.Prescaler = psc;
TIM2_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;
TIM2_Handler.Init.Period = arr;
TIM2_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
//下面几句不能开启,开启后输入捕获异常
//HAL_TIM_Base_Init(&TIM2_Handler);
//sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
//HAL_TIM_ConfigClockSource(&TIM2_Handler, &sClockSourceConfig);
if (HAL_TIM_IC_Init(&TIM2_Handler) != HAL_OK)
{
//Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&TIM2_Handler, &sMasterConfig) != HAL_OK)
{
//Error_Handler();
}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; //配置为上升沿检测
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
//配置ch2
if (HAL_TIM_IC_ConfigChannel(&TIM2_Handler, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
{
//Error_Handler();
}
//配置ch3
if (HAL_TIM_IC_ConfigChannel(&TIM2_Handler, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
{
//Error_Handler();
}
HAL_TIM_IC_Start_IT(&TIM2_Handler,TIM_CHANNEL_2); //开启ch3输入捕获
HAL_TIM_IC_Start_IT(&TIM2_Handler,TIM_CHANNEL_1); //开启ch2输入捕获
__HAL_TIM_ENABLE_IT(&TIM2_Handler,TIM_IT_UPDATE); //使能更新中断
}
输入捕获数值的获取:
//TIM2CHx_CAPTURE_STA记录捕获状态
//[7]:0,没有捕获 1,成功捕获
//[6]:0,还没捕获到低电平 1.捕获到低电平
//[5:0]:捕获低电平溢出次数
u8 TIM2CH1_CAPTURE_STA=0; //输入捕获状态
u32 TIM2CH1_CAPTURE_VAL; //输入捕获值(TIM2/TIM5是32位)
u32 TIM2CH1_count = 0;
u8 TIM2CH2_CAPTURE_STA=0; //输入捕获状态
u32 TIM2CH2_CAPTURE_VAL; //输入捕获值(TIM2/TIM5是32位)
u32 TIM2CH2_count = 0;
//timer2中断服务程序
void TIM2_IRQHandler(void)
{
HAL_TIM_IRQHandler(&TIM2_Handler);
}
//定时器更新中断处理回调函数,该函数在HAL_TIM_IRQHandler()中被调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//更新中断发生时执行
{
if(htim->Instance ==TIM2)
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
if((TIM2CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
{
if(TIM2CH1_CAPTURE_STA&0X40)//捕获到一次高电平
{
if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长,导致溢出了
{
TIM2CH1_CAPTURE_STA|=0X80; //标记完成一次捕获
TIM2CH1_CAPTURE_VAL=0XFFFFFFFF;
}
else
{
TIM2CH1_CAPTURE_STA++;
}
}
}
}
else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
if((TIM2CH2_CAPTURE_STA&0X80)==0)
{
if(TIM2CH2_CAPTURE_STA&0X40)
{
if((TIM2CH2_CAPTURE_STA&0X3F)==0X3F)
{
TIM2CH2_CAPTURE_STA|=0X80;
TIM2CH2_CAPTURE_VAL=0XFFFFFFFF;
}
else
{
TIM2CH2_CAPTURE_STA++;
}
}
}
}
}
}
//定时器输入捕获回调函数,会在HAL_TIM_IRQHandler()中被调用
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获中断发生时执行
{
if(htim->Instance ==TIM2)
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
//printf("TIM_CHANNEL_1\n");
if((TIM2CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
{
if(TIM2CH1_CAPTURE_STA&0X40) //捕获到一个下降沿
{
TIM2CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
TIM2CH1_CAPTURE_VAL=HAL_TIM_ReadCapturedValue(&TIM2_Handler,TIM_CHANNEL_1) - TIM2CH1_count;//获取当前捕获值
TIM_RESET_CAPTUREPOLARITY(&TIM2_Handler,TIM_CHANNEL_1); //清除原配置
//配置上升沿捕获
TIM_SET_CAPTUREPOLARITY(&TIM2_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);
}
else //还未开始捕获,第一次捕获到上升沿
{
TIM2CH1_CAPTURE_STA=0; //清零
TIM2CH1_CAPTURE_VAL=0;
TIM2CH1_count = 0;
TIM2CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿
//记录第一次捕获值
TIM2CH1_count = HAL_TIM_ReadCapturedValue(&TIM2_Handler,TIM_CHANNEL_1);
TIM_RESET_CAPTUREPOLARITY(&TIM2_Handler,TIM_CHANNEL_1); //清除原配置
//设置为下降沿捕获
TIM_SET_CAPTUREPOLARITY(&TIM2_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//
}
}
}
else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
//printf("TIM_CHANNEL_2\n");
if((TIM2CH2_CAPTURE_STA&0X80)==0)
{
if(TIM2CH2_CAPTURE_STA&0X40)
{
TIM2CH2_CAPTURE_STA|=0X80;
TIM2CH2_CAPTURE_VAL=HAL_TIM_ReadCapturedValue(&TIM2_Handler,TIM_CHANNEL_2)- TIM2CH2_count;
TIM_RESET_CAPTUREPOLARITY(&TIM2_Handler,TIM_CHANNEL_2);
TIM_SET_CAPTUREPOLARITY(&TIM2_Handler,TIM_CHANNEL_2,TIM_ICPOLARITY_RISING);//
}
else
{
TIM2CH2_CAPTURE_STA=0;
TIM2CH2_CAPTURE_VAL=0;
TIM2CH2_count = 0;
TIM2CH2_CAPTURE_STA|=0X40;
TIM2CH2_count = HAL_TIM_ReadCapturedValue(&TIM2_Handler,TIM_CHANNEL_2);
TIM_RESET_CAPTUREPOLARITY(&TIM2_Handler,TIM_CHANNEL_2);
TIM_SET_CAPTUREPOLARITY(&TIM2_Handler,TIM_CHANNEL_2,TIM_ICPOLARITY_FALLING);//
}
}
}
}
}
HC_sr04 trig信号触发,gpio配置,使用PC0来做触发引脚:
//使用PC0触发信号
void FFIntell_hcsr04_trig_gpio_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
/*Configure GPIO pin : PC0 */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);
}
调用,在初始化timer2 gpio初始化后,发送trig信号后,直接获取数据即可
//发送trig信号
void FFIntell_hcsr04_trig()
{
__HAL_TIM_ENABLE(&TIM2_Handler);//使能定时器
PCout(0) = 1;
delay_us(20); //20us延时
PCout(0) = 0;
}
//获取距离数据
int FFIntell_hcsr04_get_data(void)
{
//ch2获取到了数据
if(TIM2CH1_CAPTURE_STA&0X80)
{
dist_info.ch2_distance = TIM2CH1_CAPTURE_VAL *0.058; //计算距离
TIM2CH1_CAPTURE_STA=0; //清状态
}
if(TIM2CH2_CAPTURE_STA&0X80)
{
dist_info.ch3_distance = TIM2CH2_CAPTURE_VAL*0.058;
TIM2CH2_CAPTURE_STA=0;
}
__HAL_TIM_DISABLE(&TIM2_Handler); //关闭定时器
__HAL_TIM_SET_COUNTER(&TIM2_Handler, 0); //计数清零
return 0;
}
通过上述配置可以很方便的扩展到4路输入捕获。
感谢你能够认真阅读完这篇文章,希望小编分享的“STM32F429如何使用定时器多路HC-SR04超声波输入捕获”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/ffintell/blog/3216371