Files
car_stm32f103vet6/Core/Bsp/bsp_hall.c
wangbeihong 1cc8327f13 特性:实现电机控制与霍尔传感器功能
新增电机板级支持包:基于 AT8236-MS 驱动芯片,实现了对 4 个直流电机的 PWM 控制。
实现霍尔传感器功能:用于速度测量和脉冲计数。
更新 GPIO 初始化:为霍尔传感器添加了外部中断(EXTI)配置。
修改系统时钟配置:改用高速外部时钟(HSE)并调整了锁相环(PLL)设置。
更改定时器配置:将时基生成从 TIM8 改为 TIM4。
增强 FreeRTOS 任务:实现从霍尔传感器周期性读取并更新速度数据。
更新项目配置:以反映外设使用情况和优先级的变更。
2026-04-03 20:24:55 +08:00

135 lines
4.0 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"
/* 霍尔传感器数据结构体定义描述 */
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 重置霍尔传感器计数值
// */
// 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 */
}