
一、适用场景
适用场景:车轮/轴转速测量、里程计(里程计算路程)、风速/流量脉冲采集、马达 RPM 测量、测速表盘、测速触发与检测教学。
二、器材清单
测速传感器(光电开关模块)×1
编码盘×1
小车轮子×1
STM32 开发板(3.3V MCU)×1
若干杜邦线(公/母)×1组
稳定电源:5V/3.3V(最好是5v)
三、工作原理(要点)
原理:传感器在目标穿孔经过检测点时产生电平跳变(脉冲)。把脉冲的频率或脉冲间隔测量出来,按脉冲每转数与轮胎周长换算为线速度。
四、接线示意
GND→ GND
VCC→ 5V/3.3V电源
标准库
DO→ PC3
HAL库
DO→ PA3
五、示例代码
标准库
cpp
#include "stm32f10x.h"
#include "stdio.h"
#include "bsp_SysTick.h"
#include "adc_time.h"
#include "breathing.h"
#include "bsp_usart.h"
int cnt;
char oledshow[20] = {0};
void TIM4_Init()
{
NVIC_InitTypeDef nvic;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
TIM_DeInit(TIM4);
TIM_TimeBaseInitStructure.TIM_Period = (1000000-1);
TIM_TimeBaseInitStructure.TIM_Prescaler = (72-1);
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM4,TIM_FLAG_Update);
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
nvic.NVIC_IRQChannel=TIM4_IRQn;
nvic.NVIC_IRQChannelPreemptionPriority=0;
nvic.NVIC_IRQChannelSubPriority=0;
nvic.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic);
TIM_Cmd(TIM4,ENABLE);
}
void Exit_Init()
{
NVIC_InitTypeDef nvic;
GPIO_InitTypeDef PC;
EXTI_InitTypeDef exti;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
PC.GPIO_Pin = GPIO_Pin_3;
PC.GPIO_Mode = GPIO_Mode_IPU;
PC.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &PC);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource3);
exti.EXTI_Line = EXTI_Line3;
exti.EXTI_Mode = EXTI_Mode_Interrupt;
exti.EXTI_Trigger = EXTI_Trigger_Falling;
exti.EXTI_LineCmd = ENABLE;
EXTI_Init(&exti);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
nvic.NVIC_IRQChannel=EXTI3_IRQn;
nvic.NVIC_IRQChannelPreemptionPriority=1;
nvic.NVIC_IRQChannelSubPriority=1;
nvic.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic);
}
int main()
{
SysTick_Init();
Exit_Init();
TIM4_Init();
USART_Config();
while(1)
{
}
// return 0;
}
void TIM4_IRQHandler()
{
if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET)
{
sprintf((char *)oledshow,"speed:%d\n",cnt);
Usart_SendString(USART1,oledshow);
cnt=0;
// Usart_SendString(USART1,"speed:0\n");
TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
}
}
void EXTI3_IRQHandler()
{
if(EXTI_GetITStatus(EXTI_Line3)!=RESET)
{
if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) == 0)
{
cnt++;
// sprintf((char *)oledshow,"speed:%d\n",cnt);
// Usart_SendString(USART1,oledshow);
}
}
EXTI_ClearITPendingBit(EXTI_Line3);
}
HAL库



cpp
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM4_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim4);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief TIM4 Initialization Function
* @param None
* @retval None
*/
static void MX_TIM4_Init(void)
{
/* USER CODE BEGIN TIM4_Init 0 */
/* USER CODE END TIM4_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM4_Init 1 */
/* USER CODE END TIM4_Init 1 */
htim4.Instance = TIM4;
htim4.Init.Prescaler = 7199;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 9999;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM4_Init 2 */
/* USER CODE END TIM4_Init 2 */
}
/**
* @brief USART1 Initialization Function
* @param None
* @retval None
*/
static void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin : PA3 */
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI3_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(EXTI3_IRQn);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_3)
{
uint32_t now = HAL_GetTick(); // 毫秒滴答
if (now - _last_exti_tick < 10) return; // <50ms 内当抖动,忽略
_last_exti_tick = now;
cnt++;
sprintf((char *)show, "speed:%d\r\n", cnt);
HAL_UART_Transmit(&huart1,show,strlen(show),HAL_MAX_DELAY);
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM4) // 判断是否是 TIM4
{
cnt=0;
HAL_UART_Transmit(&huart1,"speed:0\r\n",strlen("speed:0\r\n"),HAL_MAX_DELAY);
}
}
六、讲解视频