- HAL库
- STM32F103C8T6主控芯片
- HC-SR04超声波测距模块
参考文章,十分感谢原作者
手把手教你,通过HAL库实现STM32的超声波测距–以SR-04为例
工程源码
基本配置
- 配置sys
- 配置RCC
- 配置USART 用来串口输出,注意波特率
- 配置时钟,将超声波测距模块的ECHO引脚设置为PB11,通道4,计数值和模式如下
- 配置时钟
代码编写
- time.c 在
/* USER CODE BEGIN 1 */
处编写,防止重新配置芯片的时候覆盖写好的代码
/* USER CODE BEGIN 1 */
//溢出回调函数和捕获回调函�?
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if((TIM2CH2_CAPTURE_STA & 0x80)==0) // 还未捕获成功
{
if(TIM2CH2_CAPTURE_STA & 0x40) // 捕获到一个下降沿
{
if((TIM2CH2_CAPTURE_STA & 0x3F) == 0x3F) // 高电平的时间太长�?
{
TIM2CH2_CAPTURE_STA |= 0X80; // 标记为成功捕获一�?
TIM2CH2_CAPTURE_VAL = 0XFFFF;
}
else
TIM2CH2_CAPTURE_STA ++; // 否则标记溢出数加�?
}
}
}
// 捕获中断发生时执�?
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if((TIM2CH2_CAPTURE_STA & 0X80) == 0) //还未捕获成功
{
if(TIM2CH2_CAPTURE_STA & 0X40) // 成功率捕获到�?个下降沿
{
TIM2CH2_CAPTURE_STA |= 0X80; // 标记成功,捕获到�?次高电平完成
TIM2CH2_CAPTURE_VAL = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_4); // 捕获当前设置�?
TIM_RESET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_4); // 清除原来设置的�??
TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_4,TIM_ICPOLARITY_RISING); // 捕获到下降沿之后,将捕获到复位为上升�?
}
else // 捕获到一个上升沿
{
TIM2CH2_CAPTURE_STA = 0;
TIM2CH2_CAPTURE_VAL = 0;
TIM2CH2_CAPTURE_STA |= 0X40;
__HAL_TIM_DISABLE(&htim2);
__HAL_TIM_SET_COUNTER(&htim2,0);
TIM_RESET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_4);
TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_4,TIM_ICPOLARITY_FALLING);
__HAL_TIM_ENABLE(&htim2);
}
}
}
/* USER CODE END 1 */
2 . 给TRIG引脚一个不小于10us的高电平,然后重新置为低电平,原理如下
gpio.c
/* USER CODE BEGIN 2 */
// 模拟TRIG引脚,先输入高电平,持续40us之后复位
void CHL_capture(void)
{
uint32_t i;
HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET);
for(i=0;i<72*15;i++)
__NOP();
HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET);
}
/* USER CODE END 2 */
- main.c
1、串口打印函数
/* USER CODE BEGIN 0 */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYOE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYOE
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/* USER CODE END 0 */
2、定义变量
/* USER CODE BEGIN 1 */
float len = 0;
uint32_t time = 0;
extern uint8_t TIM2CH2_CAPTURE_STA; // 输入捕获状�??
extern uint16_t TIM2CH2_CAPTURE_VAL; //输入捕获�?
/* USER CODE END 1 */
3、启动定时器
/* USER CODE BEGIN 2 */
printf("status----");
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_4);
__HAL_TIM_ENABLE_IT(&htim2,TIM_IT_UPDATE);
/* USER CODE END 2 */
4、while函数
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(1000);
CHL_capture();
if(TIM2CH2_CAPTURE_STA & 0X80)
{
time = TIM2CH2_CAPTURE_STA & 0X3f;
time *= 65536;
time += TIM2CH2_CAPTURE_VAL;
len = time * 342.62*100/2000000;
TIM2CH2_CAPTURE_STA = 0;
}
printf("length: %f cm\r\n",len);
}
可能遇到的问题
1、len一直为0,检查代码是否编写错误,接线是否正确
2、不能输出float
4、len有输出,但是一直不变,将vcc引脚的接到5v而不是3.3v
5、串口打印没有输出原因可能有两个
- main.c或者tim.c中没有包含头文件#include <stdio.h>
- RXD和TXD接线接反