Files
FilmForge/Src/ntc.c
T

92 lines
3.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "ntc.h"
#include "gd32f4xx_adc.h"
#include "gd32f4xx_rcu.h"
#include "gd32f4xx_gpio.h"
#include "board_config.h"
#include <math.h>
/**
* @brief 配置 NTC 引脚(PC5 模拟输入)与 ADC0 常规通道。
*/
static void ntc_gpio_adc_config(void) {
/* 使能 GPIOC 与 ADC0 时钟 */
rcu_periph_clock_enable(NTC_GPIO_RCU);
rcu_periph_clock_enable(NTC_ADC_RCU);
/* PC5 模拟输入模式 */
gpio_mode_set(NTC_GPIO_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, NTC_GPIO_PIN);
/* ADC0 独立模式,常规通道软件触发、单次转换、右对齐 */
adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);
adc_special_function_config(NTC_ADC, ADC_CONTINUOUS_MODE, DISABLE);
adc_special_function_config(NTC_ADC, ADC_INSERTED_CHANNEL, DISABLE);
adc_external_trigger_config(NTC_ADC, ADC_ROUTINE_CHANNEL, EXTERNAL_TRIGGER_DISABLE);
adc_data_alignment_config(NTC_ADC, ADC_DATAALIGN_RIGHT);
adc_channel_length_config(NTC_ADC, ADC_ROUTINE_CHANNEL, 1U);
adc_routine_channel_config(NTC_ADC, 0U, NTC_ADC_CHANNEL, NTC_SAMPLETIME);
adc_enable(NTC_ADC);
adc_calibration_enable(NTC_ADC);
}
void ntc_init(void) {
ntc_gpio_adc_config();
}
/**
* @brief 触发一次转换并读取 12bit 原始值。
*/
static uint16_t ntc_read_raw_once(void) {
adc_flag_clear(NTC_ADC, ADC_FLAG_EOC);
adc_software_trigger_enable(NTC_ADC, ADC_ROUTINE_CHANNEL);
/* 等待转换完成(EOC) */
while (SET != adc_flag_get(NTC_ADC, ADC_FLAG_EOC)) {}
return (uint16_t)adc_routine_data_read(NTC_ADC);
}
float ntc_read_temperature(void) {
uint16_t samples[NTC_SAMPLE_COUNT];
uint32_t sum = 0U;
/* 采集 NTC_SAMPLE_COUNT 个样本 */
for (uint8_t i = 0; i < NTC_SAMPLE_COUNT; i++) {
samples[i] = ntc_read_raw_once();
}
/* 插入排序(16 元素,开销可忽略),为修剪均值做准备 */
for (uint8_t i = 1; i < NTC_SAMPLE_COUNT; i++) {
uint16_t key = samples[i];
int8_t j = (int8_t)(i - 1);
while (j >= 0 && samples[j] > key) {
samples[j + 1] = samples[j];
j--;
}
samples[j + 1] = key;
}
/* 修剪均值:去掉每端 NTC_TRIM_COUNT 个极值(野值/毛刺)后取平均 */
for (uint8_t i = NTC_TRIM_COUNT; i < (NTC_SAMPLE_COUNT - NTC_TRIM_COUNT); i++) {
sum += samples[i];
}
float adc_val = (float)sum / (float)(NTC_SAMPLE_COUNT - 2U * NTC_TRIM_COUNT);
/* 分压点电压:上拉 R_PULL 在 VREF 侧,NTC 接 GND 侧 */
float voltage = adc_val * NTC_VREF / NTC_ADC_MAX;
/* 开路/短路判定:电压贴近电源轨说明 NTC 支路没有形成分压通路 */
if (voltage >= 0.97f * NTC_VREF) {
return -273.15f; /* 开路(PC5 被上拉拉满,NTC 未连通) */
}
if (voltage <= 0.03f * NTC_VREF) {
return -274.15f; /* 短路(PC5 被拉到 GND) */
}
/* 反解 NTC 阻值:V = VREF * R / (R_PULL + R) => R = R_PULL * V / (VREF - V) */
float r_ntc = NTC_R_PULL * voltage / (NTC_VREF - voltage);
/* B 值公式:1/T = 1/T25 + ln(R/R25)/B */
float t_k = 1.0f / (1.0f / NTC_T25 + logf(r_ntc / NTC_R25) / (float)NTC_B_VALUE);
return t_k - 273.15f;
}