feat(CAN): 实现多节点CAN总线通信与节点ID管理功能

- 添加CAN调试宏定义,支持条件编译调试信息输出
- 实现节点ID相关功能,包括构建CAN ID、消息过滤、获取/设置节点ID
- 支持Flash存储节点ID,提供加载和保存功能
- 实现节点ID设置和查询命令处理
- 更新CANFD发送函数使用节点ID构建发送ID
- 添加消息过滤逻辑,只处理目标节点的消息
- 重构DMA中断服务程序,优化数据传输处理
- 替换printf为调试宏,便于生产环境控制调试输出
This commit is contained in:
cbb
2026-03-15 02:38:50 +08:00
parent 2b93a4537c
commit 9f56ab394e
10 changed files with 751 additions and 461 deletions
+39 -33
View File
@@ -11,12 +11,19 @@
#include <cstring>
#include <stdint.h>
// ANG_SENS 调试宏定义
#if ANG_SENS_DEBUG
#define ANG_SENS_DEBUG_PRINT(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define ANG_SENS_DEBUG_PRINT(fmt, ...) ((void)0)
#endif
#define ANG_SPI_CS_ENABLE() gpio_bit_reset(GPIOA, GPIO_PIN_15)
#define ANG_SPI_CS_DISABLE() gpio_bit_set(GPIOA, GPIO_PIN_15)
#define DRV_SPI_CS_ENABLE() gpio_bit_reset(GPIOB, GPIO_PIN_14)
#define DRV_SPI_CS_DISABLE() gpio_bit_set(GPIOB, GPIO_PIN_14)
// DMA传输完成标志
// DMA 传输完成标志
volatile bool spi_dma_tx_complete = false;
volatile bool spi_dma_rx_complete = false;
@@ -24,7 +31,7 @@ angle_sensor KTH7823; // 角度传感器初始化
extern FlashEEPROM flashEEP;
extern EncoderAngleKalman Angle_kalman;
extern EncoderVelocityKalman Vel_kalman;
extern CAN_transmiter CAN0_transmiter; // CAN初始化
extern CAN_transmiter CAN0_transmiter; // CAN 初始化
/**
* @brief SPI DMA initialization
@@ -32,10 +39,10 @@ extern CAN_transmiter CAN0_transmiter; // CAN初始化
void spi_dma_init(void) {
dma_parameter_struct dma_init_struct;
// 使能DMA时钟
// 使能 DMA 时钟
rcu_periph_clock_enable(RCU_DMA0);
// 初始化发送DMA通道
// 初始化发送 DMA 通道
dma_deinit(DMA0, DMA_CH2);
dma_struct_para_init(&dma_init_struct);
dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
@@ -49,7 +56,7 @@ void spi_dma_init(void) {
dma_init_struct.priority = DMA_PRIORITY_HIGH;
dma_init(DMA0, DMA_CH2, &dma_init_struct);
// 初始化接收DMA通道
// 初始化接收 DMA 通道
dma_deinit(DMA0, DMA_CH1);
dma_struct_para_init(&dma_init_struct);
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
@@ -63,15 +70,15 @@ void spi_dma_init(void) {
dma_init_struct.priority = DMA_PRIORITY_HIGH;
dma_init(DMA0, DMA_CH1, &dma_init_struct);
// 使能SPI的DMA发送和接收功能
// 使能 SPI 的 DMA 发送和接收功能
spi_dma_enable(SPI0, SPI_DMA_TRANSMIT);
spi_dma_enable(SPI0, SPI_DMA_RECEIVE);
// 配置DMA中断
// 配置 DMA 中断
nvic_irq_enable(DMA0_Channel2_IRQn, 0, 1);
nvic_irq_enable(DMA0_Channel1_IRQn, 0, 1);
// 使能DMA传输完成中断
// 使能 DMA 传输完成中断
dma_interrupt_enable(DMA0, DMA_CH2, DMA_INT_FTF);
dma_interrupt_enable(DMA0, DMA_CH1, DMA_INT_FTF);
}
@@ -90,30 +97,30 @@ int spi_rw_half_word_dma(uint32_t spi_periph, uint16_t tx_data,
spi_dma_tx_complete = false;
spi_dma_rx_complete = false;
// 配置发送DMA
// 配置发送 DMA
dma_channel_disable(DMA0, DMA_CH2);
dma_memory_address_config(DMA0, DMA_CH2, (uint32_t)&tx_data);
dma_transfer_number_config(DMA0, DMA_CH2, 1);
dma_channel_enable(DMA0, DMA_CH2);
// 配置接收DMA
// 配置接收 DMA
dma_channel_disable(DMA0, DMA_CH1);
dma_memory_address_config(DMA0, DMA_CH1, (uint32_t)rx_data);
dma_transfer_number_config(DMA0, DMA_CH1, 1);
dma_channel_enable(DMA0, DMA_CH1);
// 等待传输完成,超时时间为100个循环
// 等待传输完成,超时时间为 100 个循环
uint32_t timeout = 100;
while ((!spi_dma_tx_complete || !spi_dma_rx_complete) && --timeout) {
// 空循环等待DMA传输完成
// 空循环等待 DMA 传输完成
}
// 检查是否超时
if (timeout == 0) {
// 禁用DMA通道
// 禁用 DMA 通道
dma_channel_disable(DMA0, DMA_CH2);
dma_channel_disable(DMA0, DMA_CH1);
printf("SPI DMA transfer timeout\r\n");
ANG_SENS_DEBUG_PRINT("SPI DMA transfer timeout\r\n");
return -1;
}
@@ -121,7 +128,7 @@ int spi_rw_half_word_dma(uint32_t spi_periph, uint16_t tx_data,
}
/**
* @brief DMA0_Channel2中断处理函数
* @brief DMA0_Channel2 中断处理函数
* @param 无
*/
extern "C" void DMA0_Channel2_IRQHandler(void) {
@@ -132,7 +139,7 @@ extern "C" void DMA0_Channel2_IRQHandler(void) {
}
/**
* @brief DMA0_Channel1中断处理函数
* @brief DMA0_Channel1 中断处理函数
* @param 无
*/
extern "C" void DMA0_Channel1_IRQHandler(void) {
@@ -174,7 +181,7 @@ void KTH7823_spi_init(void) {
spi_parameter_struct spi_init_str;
spi_struct_para_init(&spi_init_str);
/* SPI参数:16bit, 主机, 全双工, CPOL=1 CPHA=1, MSB first */
/* SPI 参数:16bit, 主机,全双工,CPOL=1 CPHA=1, MSB first */
spi_init_str.device_mode = SPI_MASTER;
spi_init_str.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
spi_init_str.frame_size = SPI_FRAMESIZE_16BIT;
@@ -194,16 +201,16 @@ void KTH7823_spi_init(void) {
* @return 0:初始化成功 1:初始化失败
*/
u8 angle_sensor::init(void) {
KTH7823_gpio_init(); // GPIO初始化
KTH7823_spi_init(); // SPI初始化
spi_dma_init(); // DMA初始化
KTH7823_gpio_init(); // GPIO 初始化
KTH7823_spi_init(); // SPI 初始化
spi_dma_init(); // DMA 初始化
return 0;
}
/**
* @ 角度传感器类 设置当前角度
* @param angle 输出级角度值
* @return 0成功/1失败
* @return 0 成功/1 失败
*/
u8 angle_sensor::angle_set(float angle) {
m_cumulativeAngle = angle * REDUCTION_RATIO;
@@ -230,10 +237,9 @@ inline float angle_sensor::read_sensorAngle(void) {
return angle_deg;
}
// 仅在调试模式下输出错误,避免发布版本中的I/O开销
// 仅在调试模式下输出错误,避免发布版本中的 I/O 开销
if (result != 0) {
// 使用更高效的串口输出替代printf(如果可用)
printf("Error reading angle from sensor.\n");
ANG_SENS_DEBUG_PRINT("Error reading angle from sensor.\n");
}
return (float)FAULT_RECEIVE;
@@ -255,13 +261,13 @@ float angle_sensor::update(void) {
// 计算角度变化
float delta = current_angle_deg - m_lastAngle;
// 处理角度绕回情况(0度和360度之间的跳变)
// 如果变化超过300度,说明发生了绕回
// 处理角度绕回情况(0 度和 360 度之间的跳变)
// 如果变化超过 300 度,说明发生了绕回
if (delta > ANGLE_WRAP_THRESHOLD) {
// 从接近360度绕回到接近0度
// 从接近 360 度绕回到接近 0 度
delta -= ANGLE_WRAP_VALUE;
} else if (delta < -ANGLE_WRAP_THRESHOLD) {
// 从接近0度绕到接近360度
// 从接近 0 度绕到接近 360 度
delta += ANGLE_WRAP_VALUE;
}
@@ -271,7 +277,7 @@ float angle_sensor::update(void) {
}
/**
* @brief 获取累积角度值(输出级)
* @brief 获取累积角度值 (输出级)
* @return 累积角度值
*/
float angle_sensor::getAngle(void) const {
@@ -279,15 +285,15 @@ float angle_sensor::getAngle(void) const {
}
/**
* @brief 获取累积角度值(原始级)
* @brief 获取累积角度值 (原始级)
* @return 累积角度值
*/
float angle_sensor::getRawAngle(void) const { return m_cumulativeAngle; }
/**
* @brief 获取角度值(原始级)
* @return 角度值(原始级)
* @brief 获取角度值 (原始级)
* @return 角度值 (原始级)
*/
float angle_sensor::getcurrent_sensorangle(void) const{
return current_angle_deg;
}
}