角度传感器改使用DMA
This commit is contained in:
@@ -733,9 +733,6 @@ void DMA0_Channel4_IRQHandler(void) {
|
|||||||
i++) {
|
i++) {
|
||||||
CAN0_transmiter.receive_message.rx_data[i] = can_rx_buffer[i];
|
CAN0_transmiter.receive_message.rx_data[i] = can_rx_buffer[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 接收标志位置1
|
|
||||||
CAN0_transmiter.can0_receive_flag = SET;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -747,8 +744,5 @@ void DMA0_Channel5_IRQHandler(void) {
|
|||||||
if (dma_interrupt_flag_get(DMA0, DMA_CH5, DMA_INT_FLAG_FTF)) {
|
if (dma_interrupt_flag_get(DMA0, DMA_CH5, DMA_INT_FLAG_FTF)) {
|
||||||
// 清除DMA传输完成中断标志
|
// 清除DMA传输完成中断标志
|
||||||
dma_interrupt_flag_clear(DMA0, DMA_CH5, DMA_INT_FLAG_G);
|
dma_interrupt_flag_clear(DMA0, DMA_CH5, DMA_INT_FLAG_G);
|
||||||
|
|
||||||
// 发送完成标志位置1
|
|
||||||
CAN0_transmiter.can0_send_flag = RESET;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+176
-41
@@ -1,57 +1,184 @@
|
|||||||
#include "ang_sensor.h"
|
#include "ang_sensor.h"
|
||||||
|
#include "gd32c10x_dma.h"
|
||||||
#include "gd32c10x_gpio.h"
|
#include "gd32c10x_gpio.h"
|
||||||
#include "gd32c10x_spi.h"
|
#include "gd32c10x_spi.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
#define SPI_CS_ENABLE() gpio_bit_reset(GPIOA, GPIO_PIN_15)
|
#define SPI_CS_ENABLE() gpio_bit_reset(GPIOA, GPIO_PIN_15)
|
||||||
#define SPI_CS_DISABLE() gpio_bit_set(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 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
|
* @brief Send or read half word through SPI using polling method
|
||||||
*
|
*
|
||||||
* @param[in] spi_periph SPI peripheral
|
* @param[in] spi_periph SPI peripheral
|
||||||
* @param[in] i_HalfWord data
|
* @param[in] i_HalfWord data
|
||||||
*/
|
*/
|
||||||
uint16_t spi_rw_half_word(uint32_t spi_periph, const uint16_t i_HalfWord) {
|
u16 spi_rw_half_word(u32 spi_periph, const u16 i_HalfWord) {
|
||||||
uint32_t to;
|
u32 timeout;
|
||||||
uint16_t data = 0xFFFF;
|
u16 received_data = FAULT_RECEIVE;
|
||||||
bool ok = true;
|
|
||||||
|
|
||||||
/* ---------- Send data ---------- */
|
/* Wait until transmit buffer is empty */
|
||||||
to = 200;
|
timeout = 200;
|
||||||
while ((RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE)) && --to)
|
while ((RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE)) && --timeout)
|
||||||
;
|
;
|
||||||
if (to == 0)
|
if (timeout == 0)
|
||||||
ok = false;
|
return FAULT_RECEIVE;
|
||||||
|
|
||||||
if (ok) {
|
/* Clear RX buffer if not empty */
|
||||||
if (RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE)) {
|
if (SET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE)) {
|
||||||
(void)spi_i2s_data_receive(spi_periph); /* throw Dummy */
|
(void)spi_i2s_data_receive(spi_periph);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Send data */
|
||||||
spi_i2s_data_transmit(spi_periph, i_HalfWord);
|
spi_i2s_data_transmit(spi_periph, i_HalfWord);
|
||||||
/* wait rx succ*/
|
|
||||||
to = 200;
|
/* Wait for response */
|
||||||
while ((RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE)) && --to)
|
timeout = 200;
|
||||||
|
while ((RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE)) && --timeout)
|
||||||
;
|
;
|
||||||
if (to == 0)
|
if (timeout == 0)
|
||||||
ok = false;
|
return FAULT_RECEIVE;
|
||||||
else
|
|
||||||
data = spi_i2s_data_receive(spi_periph); /* throw Dummy */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------- wait bsu idle ---------- */
|
/* Read received data */
|
||||||
if (ok) {
|
received_data = spi_i2s_data_receive(spi_periph);
|
||||||
to = 200;
|
|
||||||
while ((SET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TRANS)) &&
|
/* Wait until SPI is not busy */
|
||||||
SET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE) && --to)
|
timeout = 200;
|
||||||
|
while ((SET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TRANS)) && --timeout)
|
||||||
;
|
;
|
||||||
if (to == 0)
|
if (timeout == 0)
|
||||||
ok = false;
|
return FAULT_RECEIVE;
|
||||||
|
|
||||||
|
return received_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ok ? data : 0xFFFF;
|
/**
|
||||||
|
* @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 KHT7823_gpio_init(void) {
|
void KHT7823_gpio_init(void) {
|
||||||
rcu_periph_clock_enable(RCU_GPIOA);
|
rcu_periph_clock_enable(RCU_GPIOA);
|
||||||
rcu_periph_clock_enable(RCU_GPIOB);
|
rcu_periph_clock_enable(RCU_GPIOB);
|
||||||
@@ -71,8 +198,9 @@ void KHT7823_gpio_init(void) {
|
|||||||
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ,
|
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ,
|
||||||
GPIO_PIN_4 | GPIO_PIN_10 | GPIO_PIN_11);
|
GPIO_PIN_4 | GPIO_PIN_10 | GPIO_PIN_11);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize SPI module
|
* @brief SPI 初始化
|
||||||
*
|
*
|
||||||
* @details Configures SPI hardware and initializes necessary settings
|
* @details Configures SPI hardware and initializes necessary settings
|
||||||
*/
|
*/
|
||||||
@@ -95,21 +223,28 @@ void KHT7823_spi_init(void) {
|
|||||||
spi_enable(SPI0);
|
spi_enable(SPI0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief KHT7823 初始化
|
||||||
|
*/
|
||||||
void KHT7823_init(void) {
|
void KHT7823_init(void) {
|
||||||
KHT7823_gpio_init();
|
KHT7823_gpio_init(); // GPIO初始化
|
||||||
KHT7823_spi_init();
|
KHT7823_spi_init(); // SPI初始化
|
||||||
|
spi_dma_init(); // DMA初始化
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 读取传感器数据
|
||||||
|
* @return 传感器数据
|
||||||
|
*/
|
||||||
float KHT7823_readAngle() {
|
float KHT7823_readAngle() {
|
||||||
u16 u16Command = 0x0000; // 读取角度命令
|
|
||||||
|
|
||||||
float ang = 0;
|
|
||||||
SPI_CS_ENABLE();
|
SPI_CS_ENABLE();
|
||||||
// 发送命令1,同时接收回答1
|
// 使用DMA发送命令并接收数据
|
||||||
u16 u16data = spi_rw_half_word(SPI0, u16Command);
|
u16 u16data;
|
||||||
|
if (spi_rw_half_word_dma(SPI0, DEFAULT_COMMAND, &u16data) == 0) {
|
||||||
SPI_CS_DISABLE();
|
SPI_CS_DISABLE();
|
||||||
|
return u16data * ANGLE_FACTOR;
|
||||||
ang = u16data * ANGLE_FACTOR;
|
} else {
|
||||||
|
SPI_CS_DISABLE();
|
||||||
return ang;
|
return FAULT_RECEIVE; // 错误返回
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,8 @@ extern "C" {
|
|||||||
void KHT7823_init(void);
|
void KHT7823_init(void);
|
||||||
u16 spi_rw_half_word(u32 spi_periph, const u16 i_HalfWord);
|
u16 spi_rw_half_word(u32 spi_periph, const u16 i_HalfWord);
|
||||||
float KHT7823_readAngle(void);
|
float KHT7823_readAngle(void);
|
||||||
|
int spi_rw_half_word_dma(uint32_t spi_periph, uint16_t tx_data, uint16_t* rx_data);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+4
-6
@@ -17,17 +17,15 @@ int main(void) {
|
|||||||
systick_config(); // 系统时钟初始化
|
systick_config(); // 系统时钟初始化
|
||||||
USART0_init(); // 调试串口初始化
|
USART0_init(); // 调试串口初始化
|
||||||
User_timer_init(); // Timer初始化
|
User_timer_init(); // Timer初始化
|
||||||
sampler.init(); // 采样器初始化
|
sampler.init(); // ADC采样器初始化
|
||||||
|
KHT7823_init(); // 角度传感器初始化
|
||||||
driver_init(); // 电机驱动初始化
|
driver_init(); // 电机驱动初始化
|
||||||
|
|
||||||
KHT7823_init();
|
|
||||||
|
|
||||||
watchdog_init(5000);
|
watchdog_init(5000);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
/* clear the FWDGT reset flag */
|
|
||||||
// delay_1ms(100);
|
// delay_1ms(100);
|
||||||
fwdgt_counter_reload();
|
fwdgt_counter_reload(); // 看门狗复位
|
||||||
CAN0_transmiter.communication_check();
|
CAN0_transmiter.communication_check(); // CAN通信
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user