feat(canfd): 切换 CANFD 接收为中断驱动和环形缓冲机制
- 将 CANFD 接收机制由轮询改为 FIFO0 的中断事件驱动处理 - 实现循环取空硬件 FIFO0,提高接收效率和响应速度 - 引入环形缓冲区缓存接收帧,支持多路通道多帧队列管理 - 置位解析任务标志位,实现接收数据的异步解析 - 增加接收中断统计,包括 FIFO 满和溢出计数 - 重构临界区代码,使用自定义函数保护中断状态 - 修改接收过滤器配置,支持按掩码匹配标准帧进入 FIFO0 - 使能 CAN FIFO0 多种中断标志,包括非空、满和溢出中断
This commit is contained in:
@@ -7,6 +7,24 @@
|
||||
#include "device/adc.h"
|
||||
#include "sys/systick.h"
|
||||
#include "sys/config.h"
|
||||
#include <math.h>
|
||||
|
||||
namespace {
|
||||
constexpr float kMinValidVdda = 2.7f;
|
||||
constexpr float kMaxValidVdda = 3.6f;
|
||||
constexpr float kMinValidTemperature = -40.0f;
|
||||
constexpr float kMaxValidTemperature = 125.0f;
|
||||
|
||||
static bool isValidAdcRaw(uint16_t raw)
|
||||
{
|
||||
return (raw > 0U) && (raw < static_cast<uint16_t>(CONFIG_ADC_MAX_VALUE));
|
||||
}
|
||||
|
||||
static bool isFiniteFloat(float value)
|
||||
{
|
||||
return isfinite(value) != 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
constexpr uint32_t kDmaPeriph = DMA0;
|
||||
@@ -53,6 +71,7 @@ void Adc::initDma()
|
||||
* @param[out] 无。
|
||||
* @retval 无返回值。
|
||||
* @note 按 `VIN_ADC / TEMP / VREFINT` 三通道顺序启用连续扫描与 DMA 采样。
|
||||
* 参考 GD32E508 文档要求,内部温度与 VREFINT 通道使用长采样时间,以满足 ts_temp 要求。
|
||||
*/
|
||||
void Adc::init()
|
||||
{
|
||||
@@ -70,11 +89,14 @@ void Adc::init()
|
||||
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);
|
||||
|
||||
/* 内部温度传感器和 VREFINT 使用长采样时间,确保满足文档要求。 */
|
||||
adc_regular_channel_config(CONFIG_ADC_INSTANCE, 0U, CONFIG_ADC_VIN_CHANNEL, ADC_SAMPLETIME_239POINT5);
|
||||
adc_regular_channel_config(CONFIG_ADC_INSTANCE, 1U, CONFIG_ADC_TEMP_CHANNEL, ADC_SAMPLETIME_239POINT5);
|
||||
adc_regular_channel_config(CONFIG_ADC_INSTANCE, 2U, CONFIG_ADC_VREFINT_CHANNEL, ADC_SAMPLETIME_239POINT5);
|
||||
|
||||
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_external_trigger_config(CONFIG_ADC_INSTANCE, ADC_REGULAR_CHANNEL, ENABLE);
|
||||
adc_dma_mode_enable(CONFIG_ADC_INSTANCE);
|
||||
|
||||
adc_tempsensor_vrefint_enable();
|
||||
@@ -83,6 +105,7 @@ void Adc::init()
|
||||
adc_enable(CONFIG_ADC_INSTANCE);
|
||||
SysTickTimer::delayMs(CONFIG_ADC_STABILIZE_DELAY_MS);
|
||||
adc_calibration_enable(CONFIG_ADC_INSTANCE);
|
||||
SysTickTimer::delayMs(CONFIG_ADC_STABILIZE_DELAY_MS);
|
||||
adc_software_trigger_enable(CONFIG_ADC_INSTANCE, ADC_REGULAR_CHANNEL);
|
||||
SysTickTimer::delayMs(1U);
|
||||
s_dmaReady = 1U;
|
||||
@@ -169,8 +192,14 @@ float Adc::calculateVinAdcVoltage(uint16_t vinRaw, float vdda)
|
||||
*/
|
||||
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);
|
||||
if(!isValidAdcRaw(vrefRaw)) return 0.0f;
|
||||
|
||||
const float vdda = (CONFIG_ADC_VREFINT_TYPICAL_VOLTAGE * CONFIG_ADC_MAX_VALUE) /
|
||||
static_cast<float>(vrefRaw);
|
||||
if(!isFiniteFloat(vdda) || vdda < kMinValidVdda || vdda > kMaxValidVdda) {
|
||||
return 0.0f;
|
||||
}
|
||||
return vdda;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,11 +208,22 @@ float Adc::calculateVdda(uint16_t vrefRaw)
|
||||
* @param[in] vdda 当前 ADC 供电电压。
|
||||
* @param[out] 无。
|
||||
* @retval float 返回换算得到的芯片温度,单位 ℃。
|
||||
* @note 按 GD32E508 文档推荐公式处理:
|
||||
* Temperature = (V25 - Vtemperature) / Avg_Slope + 25
|
||||
*/
|
||||
float Adc::calculateTemperature(uint16_t tempRaw, float vdda)
|
||||
{
|
||||
if(!isValidAdcRaw(tempRaw)) return 0.0f;
|
||||
if(!isFiniteFloat(vdda) || vdda < kMinValidVdda || vdda > kMaxValidVdda) return 0.0f;
|
||||
|
||||
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;
|
||||
const float temperature = ((CONFIG_ADC_TEMP_V25 - sensorVoltage) / CONFIG_ADC_TEMP_AVG_SLOPE) + 25.0f;
|
||||
if(!isFiniteFloat(temperature) ||
|
||||
temperature < kMinValidTemperature ||
|
||||
temperature > kMaxValidTemperature) {
|
||||
return 0.0f;
|
||||
}
|
||||
return temperature;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,4 +243,9 @@ void Adc::collectSample(Sample *sample)
|
||||
sample->vdda = calculateVdda(sample->vref_raw);
|
||||
sample->vin_adc_v = calculateVinAdcVoltage(sample->vin_raw, sample->vdda);
|
||||
sample->temperature = calculateTemperature(sample->temp_raw, sample->vdda);
|
||||
}
|
||||
sample->valid = (isValidAdcRaw(sample->temp_raw) &&
|
||||
isValidAdcRaw(sample->vref_raw) &&
|
||||
(sample->vdda >= kMinValidVdda) && (sample->vdda <= kMaxValidVdda) &&
|
||||
(sample->temperature >= kMinValidTemperature) &&
|
||||
(sample->temperature <= kMaxValidTemperature)) ? 1U : 0U;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user