Files
car_stm32f103vet6/Core/Bsp/bsp_hall.c
wangbeihong 65478d9f02 feat: 集成循迹与超声波驱动并优化控制任务节拍
- 新增 HC-SR04 驱动与测距接口(bsp_sr04)

- 增加循迹状态读取与输出,完善任务内日志

- 调整 CarCtrl 闭环更新周期,匹配霍尔测速周期,降低抖动

- 同步更新 CubeMX/CMake 生成配置与相关引脚定义
2026-04-14 21:59:49 +08:00

150 lines
4.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "bsp_hall.h"
#include "bsp_sr04.h"
/* 霍尔传感器数据结构体定义描述 */
static hall_sensor_t sensors[MOTOR_COUNT];
/**
* @brief 霍尔引脚初始化 (本驱动依赖 CubeMX 预设的 GPIO_EXTI 模式)
*/
void hall_init(void)
{
for(int i = 0; i < MOTOR_COUNT; i++) {
sensors[i].pulse_count = 0;
sensors[i].speed_rpm = 0.0f;
}
}
/**
* @brief HAL 层 GPIO 外部中断回调函数实现
* @note 此函数重写了 HAL 库中的 __weak 定义
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
hall_pulse_callback(GPIO_Pin);
}
/**
* @brief 外部中断回调函数中的统计处理
*/
void hall_pulse_callback(uint16_t GPIO_Pin)
{
/* 只负责计数,不再在中断中进行浮点运算和日志打印 */
if (GPIO_Pin == M_I_1_Pin) {
sensors[MOTOR_1].pulse_count++;
} else if (GPIO_Pin == M_I_2_Pin) {
sensors[MOTOR_2].pulse_count++;
} else if (GPIO_Pin == M_I_3_Pin) {
sensors[MOTOR_3].pulse_count++;
} else if (GPIO_Pin == M_I_4_Pin) {
sensors[MOTOR_4].pulse_count++;
}
}
// /**
// * @brief 获取霍尔传感器脉冲计数
// */
// uint32_t hall_get_count(motor_id_t motor_id)
// {
// if (motor_id < MOTOR_COUNT) {
// return sensors[motor_id].pulse_count;
// }
// return 0;
// }
/**
* @brief 获取当前实时转速 (RPM)
*/
float hall_get_speed(motor_id_t motor_id)
{
if (motor_id < MOTOR_COUNT) {
return sensors[motor_id].speed_rpm;
}
return 0.0f;
}
// /**
// * @brief 重置霍尔传感器计数值
// */
// void hall_reset_count(motor_id_t motor_id)
// {
// if (motor_id < MOTOR_COUNT) {
// sensors[motor_id].pulse_count = 0;
// }
// }
/**
* @brief 计算并更新转速 (供应用层在定时任务中调用)
* @param motor_id 电机 ID
* @param interval_ms 两次调用之间的时间间隔 (ms)
* @return float 计算出的 RPM
*/
float hall_update_speed(motor_id_t motor_id, uint32_t interval_ms)
{
if (motor_id >= MOTOR_COUNT || interval_ms == 0) return 0.0f;
/* 获取当前增量并重置计数 */
uint32_t current_pulses = sensors[motor_id].pulse_count;
sensors[motor_id].pulse_count = 0;
/* PPR = 330. RPM = (增量脉冲 / 间隔ms) * 60000ms / PPR */
sensors[motor_id].speed_rpm = ((float)current_pulses / (float)interval_ms) * 60000.0f / 330.0f;
// /* 应用层打印日志 */
// log_i("Motor[%d] Real-time: %.2f RPM (pulses: %d)", motor_id + 1, sensors[motor_id].speed_rpm, current_pulses);
return sensors[motor_id].speed_rpm;
}
// /**
// * @brief 计算转速 (由于只有一根线,仅支持根据脉冲频率计算速度)
// */
// float hall_calculate_speed(motor_id_t motor_id, uint32_t interval_ms)
// {
// if (motor_id >= MOTOR_COUNT || interval_ms == 0) return 0.0f;
//
// /* 获取当前脉冲数 */
// uint32_t current_count = sensors[motor_id].pulse_count;
//
// /*
// * 计算 RPM (转每分钟)
// * 公式: (脉冲增量 / 采样时间ms) * 1000ms * 60s / PPR
// * 注意:由于此处没有传入上一次的 count我们假设 interval_ms 是相对于 count=0 开始的,
// * 或者你可以在调用前手动 reset。这里先实现基础频率转换为 RPM 的逻辑。
// * 假设 PPR (每圈脉冲数) 暂定为 11 (常见磁平衡霍尔) * 30 (减速比) = 330
// */
// const float PPR = 330.0f;
// sensors[motor_id].speed_rpm = ((float)current_count / interval_ms) * 60000.0f / PPR;
//
// /* 输出日志:电机编号 + 转速 */
// // log_i("Motor[%d] speed: %.2f RPM", motor_id + 1, sensors[motor_id].speed_rpm);
//
// /* 计算完后为了下一次增量计算,通常需要重置计数,或者记录旧值。这里保持框架。 */
//
// return sensors[motor_id].speed_rpm;
// }
/* USER CODE BEGIN Header_speed_get */
/**
* @brief Function implementing the timerTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_speed_get */
void speed_get(void *argument) {
/* USER CODE BEGIN speed_get */
/* Infinite loop */
for (;;) {
/* 在每 100ms 执行一次的任务中 */
for (int i = 0; i < MOTOR_COUNT; i++) {
hall_update_speed(i, 100);
}
osDelay(100); // 100ms
}
/* USER CODE END speed_get */
}