STM32学习-37-[定时器]超声波测距实验

HC-SR04模块

image

HC-SR04模块的使用方法

image

image

使用的时候
想Trlg引脚写入一个大于10us的高电平
声波发生器就会发送声波
发送声波完成后Echo就会输出高电平
知道接收到回声完成后回到低电平

搭建电路

image

梳理思路

image

主要测量Echo引脚发出的脉冲宽度
使用一个通道捕获上升沿
一个捕获下降沿
分别获得快照后
就能会的高电平的持续事件

image

Trig启动测量发出一个大于10us的脉冲
声波发出Echo发出高电平从发从结束到接收结束
接收捕获记录CNT快照推算出时间
image

初始化时基单元

image
输入到计数器的频率决定了精度
自动重装寄存器决定了量程

image
按如图所示进行配置

初始化输入捕获

image

image

image

编程

image
向定时器CNT写值

image
清楚标志位

image
获取寄存器的状态

image
计算结果

#include "stm32f10x.h"

void App_USART1_Init(void);
void App_HCRS04_Init(void);

int main(void)
{
	App_USART1_Init();
	App_HCRS04_Init();

	while(1)
	{
		// 向CNT写0
		TIM_SetCounter(TIM1, 0);

		// 清除CC1和CC2的标志位
		TIM_ClearFlag(TIM1, TIM_FLAG_CC1);
		TIM_ClearFlag(TIM1, TIM_FLAG_CC2);

		// 开启定时器
		TIM_Cmd(TIM1, ENABLE);

		// 向Trig写入10us的脉冲
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
		DelayUs(10);	// 这个是自己实现的函数
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);

		// 等待测量完成
		while(TIM_GetFlagStatus(TIM1, TIM_FLAG_CC1) == RESET);
		while(TIM_GetFlagStatus(TIM1, TIM_FLAG_CC2) == RESET);

		// 关闭定时器
		TIM_Cmd(TIM1, DISABLE);

		// 读取CCR1的值
		uint16 t ccr1 = TIM GetCapture1(TIM1);
		// 读取CCR2的值
		uint16_t ccr2 = TIM_GetCapture2(TIM1);
		// 计算距离 =(ccr2-ccr1)*分辨率*声速÷2
		float distance = (ccr2 - ccr1) * 1.0e-6f * 340.0f / 2;
		// 打印结果
		My_USART_Printf(USART1, "%.4f\n", distance * 100);
		// 延迟
		Delay(100) ;
	}
}

void App_USART1_Init(void){
	// 1.初始化IO引脚
	RCC_APB2PeriphCLockCmd(RCC_APB2Periph_GPIOA, ENABLE);	// 先启动时钟

	GPIO_InitTypeDef GPIO_InitStruct;	// 定义初始化结构体
	// Tx PA9 复用输出推挽
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;	// 设置配置的引脚编号
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; // 模式
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; // 最大速度
	GPIO_Init(GPIOA.&GPIO_InitStruct);
	
	// Rx PA10 输入浮空 输入上拉
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; // 模式
	GPIO_Init(GPIOA, &GPIO_InitStruct); 

	// 2.初始化USART1模块
	RCC_APB2PriphClockCmd(RCC_APB2Periph_USART1, ENABLE);	// 启动UASRT1模块的时钟
 
	// 对串口进行初始化
	USART_InitTypeDef USART_InitStruct;
 
	USART_InitStruct.USART_BaudRate = 115200;	// 设置波特率
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	// 不使用硬件流控
	USART_InitStruct.USART_Mode = USART_Tx | USART_Rx;	// 设置收发方向
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;	// 设置数据位数
	USART_InitStruct.USART_StopBits = USART_StopBits_1;	// 设置停止位
	USART_InitStruct.USART_Parity = USART_Parity_No;	// 设置校验位
 
	// 调用初始化函数
	USART_Init(USART1, &USART_InitStruct);
 
	// 启用USART模块 闭合总开关
	USART_Cmd(USART1, ENABLE);
}

void App_HCRS04_Init(void){
	// 初始化时基单元
	// 开启定时器1的时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM1, ENABLE);
 
	// 配置时基单元的参数
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	TIM_TimeBaseInitStruct.TIM_Period = 65535;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_RepertitionCounter = 0;
 
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct); 

	// 初始化输入捕获
	RCC_APB2PeriphCLockCmd(RCC_APB2Periph_GPIOA, ENABLE);	// 先启动时钟

	GPIO_InitTypeDef GPIO_InitStruct;	// 定义初始化结构体
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;	// 设置配置的引脚编号
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD; // 模式
	GPIO_Init(GPIOA.&GPIO_InitStruct);

	// 初始化输入捕获的通道1
	TIM_ICInitTypeDef TIM_ICInitStruct;
	TIM ICInitStruct.TIM Channel = TIM_Channel_1;
	TIM ICInitStruct.TIM ICFilter = 0;	// 不使用滤波器
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;	// 捕获哪个边沿
	TIM ICInitStruct.TIM ICPrescaler = TIM_ICPSC_DIV1;	// 设置分频系数
	TIM ICInitStruct.TIM ICSelection = TIM_ICSelection_DirectTI;	// 选择来源,直接
	TIM_ICInit(TIM1, &TIM_ICInitStruct);

	// 初始化输入捕获的通道2
	TIM_ICInitTypeDef TIM_ICInitStruct;
	TIM ICInitStruct.TIM Channel = TIM_Channel_2;
	TIM ICInitStruct.TIM ICFilter = 0;	// 不使用滤波器
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Falling;	// 捕获哪个边沿
	TIM ICInitStruct.TIM ICPrescaler = TIM_ICPSC_DIV1;	// 设置分频系数
	TIM ICInitStruct.TIM ICSelection = TIM_ICSelection_IndirectTI;	// 选择来源,直接
	TIM_ICInit(TIM1, &TIM_ICInitStruct);

	// 初始化Trig引脚
	RCC_APB2PeriphCLockCmd(RCC_APB2Periph_GPIOA, ENABLE);	// 先启动时钟
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;	// 设置配置的引脚编号
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT_PP; // 模式
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz; // 最大速度
	GPIO_Init(GPIOA.&GPIO_InitStruct);
}
posted @ 2026-09-03 09:58  灵垚克府  阅读(5)  评论(0)    收藏  举报