feat: 添加GD32E508 DCU应用工程的初始结构

- 新增完整的CMSIS解决方案配置,包含AC6/GCC/IAR/CLANG编译器支持
- 添加项目配置文件,定义了设备层、系统层、应用层的模块结构
- 配置ARM::CMSIS和GigaDevice::GD32E50x_DFP软件包依赖
- 创建多层代码架构:应用入口(main)、系统层(sys)、设备层(device)
- 实现任务管理系统,包含任务调度器和任务执行器分离设计
- 集成ADC、CANFD、定时器、串口、温度采样等核心功能模块
- 添加详细的README文档说明项目结构和代码组织方式
- 配置AC6链接脚本和运行时环境文件
- 设置Git忽略规则以排除编译产物和临时文件
This commit is contained in:
cbb
2026-05-10 17:28:14 +08:00
commit 4b8b47bc9b
116 changed files with 36659 additions and 0 deletions
+126
View File
@@ -0,0 +1,126 @@
/**
* @file ADC.cpp
* @brief ADC 采样模块实现。
*/
#include "main.h"
#include "device/adc.h"
#include "sys/systick.h"
#include "sys/config.h"
namespace {
constexpr uint32_t kDmaPeriph = DMA0;
constexpr dma_channel_enum kDmaChannel = DMA_CH0;
constexpr uint32_t kChannelCount = 3U;
constexpr uint32_t kVinGpio = GPIOA;
constexpr uint32_t kVinPin = GPIO_PIN_6;
volatile uint16_t s_dmaBuffer[kChannelCount] = {0U, 0U, 0U};
volatile uint8_t s_dmaReady = 0U;
} // namespace
void Adc::initDma()
{
dma_parameter_struct dma_initpara{};
rcu_periph_clock_enable(RCU_DMA0);
dma_deinit(kDmaPeriph, kDmaChannel);
dma_struct_para_init(&dma_initpara);
dma_initpara.periph_addr = (uint32_t)(&ADC_RDATA(CONFIG_ADC_INSTANCE));
dma_initpara.memory_addr = (uint32_t)s_dmaBuffer;
dma_initpara.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_initpara.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
dma_initpara.memory_width = DMA_MEMORY_WIDTH_16BIT;
dma_initpara.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_initpara.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_initpara.number = kChannelCount;
dma_initpara.priority = DMA_PRIORITY_HIGH;
dma_init(kDmaPeriph, kDmaChannel, &dma_initpara);
dma_circulation_enable(kDmaPeriph, kDmaChannel);
dma_channel_enable(kDmaPeriph, kDmaChannel);
}
void Adc::init()
{
rcu_periph_clock_enable(RCU_ADC0);
rcu_periph_clock_enable(RCU_GPIOA);
rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV8);
/* 原理图:PA6 -> VIN_ADC,为外部电源分压检测输入 */
gpio_init(kVinGpio, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, kVinPin);
initDma();
adc_deinit(CONFIG_ADC_INSTANCE);
adc_mode_config(ADC_MODE_FREE);
adc_special_function_config(CONFIG_ADC_INSTANCE, ADC_SCAN_MODE, ENABLE);
adc_special_function_config(CONFIG_ADC_INSTANCE, ADC_CONTINUOUS_MODE, ENABLE);
adc_data_alignment_config(CONFIG_ADC_INSTANCE, ADC_DATAALIGN_RIGHT);
adc_channel_length_config(CONFIG_ADC_INSTANCE, ADC_REGULAR_CHANNEL, kChannelCount);
adc_regular_channel_config(CONFIG_ADC_INSTANCE, 0U, CONFIG_ADC_VIN_CHANNEL, CONFIG_ADC_SAMPLE_TIME);
adc_regular_channel_config(CONFIG_ADC_INSTANCE, 1U, CONFIG_ADC_TEMP_CHANNEL, CONFIG_ADC_SAMPLE_TIME);
adc_regular_channel_config(CONFIG_ADC_INSTANCE, 2U, CONFIG_ADC_VREFINT_CHANNEL, CONFIG_ADC_SAMPLE_TIME);
adc_external_trigger_source_config(CONFIG_ADC_INSTANCE, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE);
adc_external_trigger_config(CONFIG_ADC_INSTANCE, ADC_REGULAR_CHANNEL, DISABLE);
adc_dma_mode_enable(CONFIG_ADC_INSTANCE);
adc_tempsensor_vrefint_enable();
SysTickTimer::delayMs(CONFIG_ADC_STABILIZE_DELAY_MS);
adc_enable(CONFIG_ADC_INSTANCE);
SysTickTimer::delayMs(CONFIG_ADC_STABILIZE_DELAY_MS);
adc_calibration_enable(CONFIG_ADC_INSTANCE);
adc_software_trigger_enable(CONFIG_ADC_INSTANCE, ADC_REGULAR_CHANNEL);
SysTickTimer::delayMs(1U);
s_dmaReady = 1U;
}
bool Adc::dmaReady()
{
return s_dmaReady != 0U;
}
const uint16_t *Adc::dmaBuffer()
{
return (const uint16_t *)s_dmaBuffer;
}
uint16_t Adc::readRaw(uint8_t channel)
{
if(channel == CONFIG_ADC_VIN_CHANNEL) return s_dmaBuffer[0];
if(channel == CONFIG_ADC_TEMP_CHANNEL) return s_dmaBuffer[1];
if(channel == CONFIG_ADC_VREFINT_CHANNEL) return s_dmaBuffer[2];
return 0U;
}
uint16_t Adc::readVinRaw() { return readRaw(CONFIG_ADC_VIN_CHANNEL); }
uint16_t Adc::readVrefRaw() { return readRaw(CONFIG_ADC_VREFINT_CHANNEL); }
uint16_t Adc::readTempRaw() { return readRaw(CONFIG_ADC_TEMP_CHANNEL); }
float Adc::calculateVinAdcVoltage(uint16_t vinRaw, float vdda)
{
return (static_cast<float>(vinRaw) * vdda) / CONFIG_ADC_MAX_VALUE;
}
float Adc::calculateVdda(uint16_t vrefRaw)
{
if(vrefRaw == 0U) return CONFIG_ADC_DEFAULT_VDDA;
return (CONFIG_ADC_VREFINT_TYPICAL_VOLTAGE * CONFIG_ADC_MAX_VALUE) / static_cast<float>(vrefRaw);
}
float Adc::calculateTemperature(uint16_t tempRaw, float vdda)
{
const float sensorVoltage = (static_cast<float>(tempRaw) * vdda) / CONFIG_ADC_MAX_VALUE;
return ((CONFIG_ADC_TEMP_V25 - sensorVoltage) / CONFIG_ADC_TEMP_AVG_SLOPE) + 25.0f;
}
void Adc::collectSample(Sample *sample)
{
if(sample == nullptr) return;
sample->vin_raw = readVinRaw();
sample->temp_raw = readTempRaw();
sample->vref_raw = readVrefRaw();
sample->vdda = calculateVdda(sample->vref_raw);
sample->vin_adc_v = calculateVinAdcVoltage(sample->vin_raw, sample->vdda);
sample->temperature = calculateTemperature(sample->temp_raw, sample->vdda);
}