将 `sampler::init()` 方法改为构造函数 `sampler()`,并在其中完成 DMA 和 ADC 的初始化配置, 同时进行初始采样操作。 feat(CAN): 更新角度传感器类接口并修复拼写错误 将全局函数 `KHT7823_readAngle()` 替换为 `angle_sensor::readAngle()` 类成员函数调用, 统一命名风格并修正部分函数名中的拼写错误(如 KHT7823 -> KTH7823)。 refactor(Can): 移除冗余的 timeout 成员变量 在 `CAN_transmiter` 类中移除了未使用的 `timeout` 成员变量,减少资源占用。 refactor(Timer): 删除重复注释内容 清理 `Timer.cpp` 中关于定时器配置的重复注释信息,保留核心常量定义。 refactor(ADC): 修正头文件中函数声明 将 `adc.h` 中的 `init()` 函数声明更新为构造函数 `sampler()`,保持实现与声明一致。 refactor(ang_sensor): 将角度传感器相关功能封装为类 将原先分散的 C 风格函数封装进 `angle_sensor` 类中,提升代码结构清晰度和可维护性。 添加构造函数和读取角度的方法,并修正原有函数命名不一致问题。 refactor(main): 调整初始化顺序并移除多余包含 修改 `main.cpp` 中外设初始化顺序,移除对 `core_cm4.h` 的重复包含, 并将角度传感器和采样器通过类实例方式初始化。
256 lines
7.3 KiB
C++
256 lines
7.3 KiB
C++
#include "ang_sensor.h"
|
||
#include "gd32c10x_dma.h"
|
||
#include "gd32c10x_gpio.h"
|
||
#include "gd32c10x_spi.h"
|
||
#include <stdint.h>
|
||
|
||
#define SPI_CS_ENABLE() gpio_bit_reset(GPIOA, GPIO_PIN_15)
|
||
#define SPI_CS_DISABLE() gpio_bit_set(GPIOA, GPIO_PIN_15)
|
||
|
||
constexpr float ANGLE_FACTOR = 1.0f / 65536.0f * 360.0f;
|
||
constexpr u16 DEFAULT_COMMAND = 0x0000;
|
||
constexpr u16 FAULT_RECEIVE = 0xFFFF;
|
||
|
||
// DMA传输完成标志
|
||
volatile bool spi_dma_tx_complete = false;
|
||
volatile bool spi_dma_rx_complete = false;
|
||
|
||
/**
|
||
* @brief Send or read half word through SPI using polling method
|
||
*
|
||
* @param[in] spi_periph SPI peripheral
|
||
* @param[in] i_HalfWord data
|
||
*/
|
||
u16 spi_rw_half_word(u32 spi_periph, const u16 i_HalfWord) {
|
||
u32 timeout;
|
||
u16 received_data = FAULT_RECEIVE;
|
||
|
||
/* Wait until transmit buffer is empty */
|
||
timeout = 200;
|
||
while ((RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE)) && --timeout)
|
||
;
|
||
if (timeout == 0)
|
||
return FAULT_RECEIVE;
|
||
|
||
/* Clear RX buffer if not empty */
|
||
if (SET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE)) {
|
||
(void)spi_i2s_data_receive(spi_periph);
|
||
}
|
||
|
||
/* Send data */
|
||
spi_i2s_data_transmit(spi_periph, i_HalfWord);
|
||
|
||
/* Wait for response */
|
||
timeout = 200;
|
||
while ((RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE)) && --timeout)
|
||
;
|
||
if (timeout == 0)
|
||
return FAULT_RECEIVE;
|
||
|
||
/* Read received data */
|
||
received_data = spi_i2s_data_receive(spi_periph);
|
||
|
||
/* Wait until SPI is not busy */
|
||
timeout = 200;
|
||
while ((SET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TRANS)) && --timeout)
|
||
;
|
||
if (timeout == 0)
|
||
return FAULT_RECEIVE;
|
||
|
||
return received_data;
|
||
}
|
||
|
||
/**
|
||
* @brief SPI DMA initialization
|
||
*/
|
||
void spi_dma_init(void) {
|
||
dma_parameter_struct dma_init_struct;
|
||
|
||
// 使能DMA时钟
|
||
rcu_periph_clock_enable(RCU_DMA0);
|
||
|
||
// 初始化发送DMA通道
|
||
dma_deinit(DMA0, DMA_CH2);
|
||
dma_struct_para_init(&dma_init_struct);
|
||
dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
|
||
dma_init_struct.memory_addr = (uint32_t)0; // 实际地址将在传输时设置
|
||
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
|
||
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
|
||
dma_init_struct.number = 1;
|
||
dma_init_struct.periph_addr = (uint32_t)(&SPI_DATA(SPI0));
|
||
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
|
||
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
|
||
dma_init_struct.priority = DMA_PRIORITY_HIGH;
|
||
dma_init(DMA0, DMA_CH2, &dma_init_struct);
|
||
|
||
// 初始化接收DMA通道
|
||
dma_deinit(DMA0, DMA_CH1);
|
||
dma_struct_para_init(&dma_init_struct);
|
||
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
|
||
dma_init_struct.memory_addr = (uint32_t)0; // 实际地址将在传输时设置
|
||
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
|
||
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
|
||
dma_init_struct.number = 1;
|
||
dma_init_struct.periph_addr = (uint32_t)(&SPI_DATA(SPI0));
|
||
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
|
||
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
|
||
dma_init_struct.priority = DMA_PRIORITY_HIGH;
|
||
dma_init(DMA0, DMA_CH1, &dma_init_struct);
|
||
|
||
// 使能SPI的DMA发送和接收功能
|
||
spi_dma_enable(SPI0, SPI_DMA_TRANSMIT);
|
||
spi_dma_enable(SPI0, SPI_DMA_RECEIVE);
|
||
|
||
// 配置DMA中断
|
||
nvic_irq_enable(DMA0_Channel2_IRQn, 1, 1);
|
||
nvic_irq_enable(DMA0_Channel1_IRQn, 1, 1);
|
||
|
||
// 使能DMA传输完成中断
|
||
dma_interrupt_enable(DMA0, DMA_CH2, DMA_INT_FTF);
|
||
dma_interrupt_enable(DMA0, DMA_CH1, DMA_INT_FTF);
|
||
}
|
||
|
||
/**
|
||
* @brief Send or read half word through SPI using DMA
|
||
*
|
||
* @param[in] spi_periph SPI peripheral
|
||
* @param[in] tx_data Data to transmit
|
||
* @param[out] rx_data Pointer to store received data
|
||
* @return 0 if success, -1 if error
|
||
*/
|
||
int spi_rw_half_word_dma(uint32_t spi_periph, uint16_t tx_data,
|
||
uint16_t *rx_data) {
|
||
// 重置完成标志
|
||
spi_dma_tx_complete = false;
|
||
spi_dma_rx_complete = false;
|
||
|
||
// 配置发送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_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);
|
||
|
||
// 等待传输完成,超时时间为1000个循环
|
||
uint32_t timeout = 1000;
|
||
while ((!spi_dma_tx_complete || !spi_dma_rx_complete) && --timeout) {
|
||
// 空循环等待DMA传输完成
|
||
}
|
||
|
||
// 检查是否超时
|
||
if (timeout == 0) {
|
||
// 禁用DMA通道
|
||
dma_channel_disable(DMA0, DMA_CH2);
|
||
dma_channel_disable(DMA0, DMA_CH1);
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief DMA0_Channel2中断处理函数
|
||
* @param 无
|
||
*/
|
||
extern "C" void DMA0_Channel2_IRQHandler(void) {
|
||
if (dma_interrupt_flag_get(DMA0, DMA_CH2, DMA_INT_FLAG_FTF)) {
|
||
dma_interrupt_flag_clear(DMA0, DMA_CH2, DMA_INT_FLAG_FTF);
|
||
spi_dma_tx_complete = true;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief DMA0_Channel1中断处理函数
|
||
* @param 无
|
||
*/
|
||
extern "C" void DMA0_Channel1_IRQHandler(void) {
|
||
if (dma_interrupt_flag_get(DMA0, DMA_CH1, DMA_INT_FLAG_FTF)) {
|
||
dma_interrupt_flag_clear(DMA0, DMA_CH1, DMA_INT_FLAG_FTF);
|
||
spi_dma_rx_complete = true;
|
||
}
|
||
}
|
||
/**
|
||
* @brief 角度传感器初始化
|
||
* @param 无
|
||
*/
|
||
void KTH7823_gpio_init(void) {
|
||
rcu_periph_clock_enable(RCU_GPIOA);
|
||
rcu_periph_clock_enable(RCU_GPIOB);
|
||
rcu_periph_clock_enable(RCU_SPI0);
|
||
rcu_periph_clock_enable(RCU_AF);
|
||
/* 关闭 JTAG,仅保留 SWD(释放 PA15、PB3、PB4) */
|
||
gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP, ENABLE);
|
||
|
||
/* -------- SPI0 全 remap:PB3/4/5 + PA15 -------- */
|
||
gpio_pin_remap_config(GPIO_SPI0_REMAP, ENABLE);
|
||
/* PA15 → NSS, 推挽输出 */
|
||
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_15);
|
||
/* PB3 → SCK, PB5 → MOSI, 推挽输出 */
|
||
gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ,
|
||
GPIO_PIN_3 | GPIO_PIN_5);
|
||
/* PB4 → MISO, 浮空输入 */
|
||
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ,
|
||
GPIO_PIN_4 | GPIO_PIN_10 | GPIO_PIN_11);
|
||
}
|
||
|
||
/**
|
||
* @brief SPI 初始化
|
||
*
|
||
* @details Configures SPI hardware and initializes necessary settings
|
||
*/
|
||
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_init_str.device_mode = SPI_MASTER;
|
||
spi_init_str.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
|
||
spi_init_str.frame_size = SPI_FRAMESIZE_16BIT;
|
||
spi_init_str.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE;
|
||
spi_init_str.nss = SPI_NSS_SOFT;
|
||
spi_init_str.endian = SPI_ENDIAN_MSB;
|
||
|
||
spi_init_str.prescale = 24; /* 5MHz @ 120MHz */
|
||
spi_init(SPI0, &spi_init_str);
|
||
spi_nss_output_enable(SPI0);
|
||
spi_nssp_mode_enable(SPI0);
|
||
spi_enable(SPI0);
|
||
}
|
||
|
||
/**
|
||
* @brief KTH7823 初始化
|
||
*/
|
||
void angle_sensor::KTH7823_init(void) {
|
||
KTH7823_gpio_init(); // GPIO初始化
|
||
KTH7823_spi_init(); // SPI初始化
|
||
spi_dma_init(); // DMA初始化
|
||
}
|
||
/**
|
||
* @brief 角度传感器构造函数
|
||
*/
|
||
angle_sensor::angle_sensor(void) { KTH7823_init(); }
|
||
|
||
/**
|
||
* @brief 读取传感器数据
|
||
* @return 传感器数据
|
||
*/
|
||
float angle_sensor::readAngle(void) {
|
||
u16 u16data = FAULT_RECEIVE;
|
||
|
||
SPI_CS_ENABLE();
|
||
// 使用DMA发送命令并接收数据
|
||
if (spi_rw_half_word_dma(SPI0, DEFAULT_COMMAND, &u16data) == 0) {
|
||
SPI_CS_DISABLE();
|
||
return u16data * ANGLE_FACTOR;
|
||
} else {
|
||
SPI_CS_DISABLE();
|
||
// 处理读取错误
|
||
printf("Error reading angle from sensor.\n");
|
||
return FAULT_RECEIVE; // 错误返回
|
||
}
|
||
} |