Initial commit: CCU621_M firmware project with BLE debug link support.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,303 @@
|
||||
#include "gd32h7xx.h"
|
||||
#include "adc_temp.h"
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "usart.h"
|
||||
#include "sys_drv_init.h"
|
||||
#include "gd32h7xx_dma.h"
|
||||
/* 忙等待延时函数 */
|
||||
static void delay_ms(uint32_t ms)
|
||||
{
|
||||
/* 使用固定的时钟频率 600MHz 来计算延时,避免 SystemCoreClock 未初始化的问题 */
|
||||
for(volatile uint32_t i = 0; i < (600000000 / 4000) * ms; i++)
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
}
|
||||
/* ADC2 DMA连续采样缓冲:DMA中断只负责“完成标记”,数据处理放在 get_adc_data()。 */
|
||||
#define ADC_TEMP_DMA_PERIPH DMA1
|
||||
#define ADC_TEMP_DMA_CH DMA_CH0
|
||||
#define ADC_TEMP_DMA_IRQN DMA1_Channel0_IRQn
|
||||
#define ADC_TEMP_DMA_SAMPLE_CNT (16U)
|
||||
|
||||
static __IO uint32_t g_adc_dma_buf[ADC_TEMP_DMA_SAMPLE_CNT];
|
||||
static volatile uint32_t g_adc_dma_frame_cnt;
|
||||
|
||||
__IO uint32_t adc_value[4];
|
||||
|
||||
void init_adc(void)
|
||||
{
|
||||
dma_single_data_parameter_struct dma_init_struct;
|
||||
|
||||
/* GPIO时钟使能 */
|
||||
rcu_periph_clock_enable(RCU_GPIOC);
|
||||
/* ADC时钟使能 */
|
||||
rcu_periph_clock_enable(RCU_ADC2);
|
||||
/* DMA时钟使能 */
|
||||
rcu_periph_clock_enable(RCU_DMA1);
|
||||
/* GPIO参数配置*/
|
||||
gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_2);
|
||||
/* ADC初始化 -- 根据数据手册,ADC2_IN0--PC2端子仅能使用ADC2第0个通道 */
|
||||
adc_deinit(ADC2);
|
||||
/* ADC时钟配置 */
|
||||
adc_clock_config(ADC2, ADC_CLK_SYNC_HCLK_DIV6);
|
||||
/* 单通道连续转换 + DMA */
|
||||
adc_special_function_config(ADC2, ADC_SCAN_MODE, DISABLE);
|
||||
adc_special_function_config(ADC2, ADC_CONTINUOUS_MODE, ENABLE);
|
||||
/* 转换结果(12/14位)存放在 32 位寄存器的低 16 位中 */
|
||||
adc_data_alignment_config(ADC2, ADC_DATAALIGN_RIGHT);
|
||||
/* ADC 通道配置(规则通道组,单通道) */
|
||||
adc_channel_length_config(ADC2, ADC_REGULAR_CHANNEL, 1);
|
||||
/* 配置规则通道序列,决定 ADC 在转换时,对 PC2 引脚电压进行采样的时间长度*/
|
||||
adc_regular_channel_config(ADC2, 0, ADC_CHANNEL_0, 240);
|
||||
/* 禁用外部触发*/
|
||||
adc_external_trigger_config(ADC2, ADC_REGULAR_CHANNEL, EXTERNAL_TRIGGER_DISABLE);
|
||||
|
||||
/* DMA配置:ADC2 regular data -> g_adc_dma_buf[] (循环) */
|
||||
dma_deinit(ADC_TEMP_DMA_PERIPH, ADC_TEMP_DMA_CH);
|
||||
dma_single_data_para_struct_init(&dma_init_struct);
|
||||
dma_init_struct.request = DMA_REQUEST_ADC2;
|
||||
dma_init_struct.periph_addr = (uint32_t)&ADC_RDATA(ADC2);
|
||||
dma_init_struct.periph_inc = DMA_MEMORY_INCREASE_DISABLE;
|
||||
dma_init_struct.memory0_addr = (uint32_t)g_adc_dma_buf;
|
||||
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
|
||||
dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_32BIT;
|
||||
dma_init_struct.circular_mode = DMA_CIRCULAR_MODE_ENABLE;
|
||||
dma_init_struct.direction = DMA_PERIPH_TO_MEMORY;
|
||||
dma_init_struct.priority = DMA_PRIORITY_HIGH;
|
||||
dma_init_struct.number = ADC_TEMP_DMA_SAMPLE_CNT;
|
||||
dma_single_data_mode_init(ADC_TEMP_DMA_PERIPH, ADC_TEMP_DMA_CH, &dma_init_struct);
|
||||
dma_interrupt_enable(ADC_TEMP_DMA_PERIPH, ADC_TEMP_DMA_CH, DMA_INT_HTF);
|
||||
dma_interrupt_enable(ADC_TEMP_DMA_PERIPH, ADC_TEMP_DMA_CH, DMA_INT_FTF);
|
||||
nvic_irq_enable(ADC_TEMP_DMA_IRQN, 6U, 0U);
|
||||
/* 使能 ADC2 模块 */
|
||||
adc_enable(ADC2);
|
||||
/* wait for ADC stability */
|
||||
delay_ms(1);
|
||||
/* 配置校准模式,偏移量校准,用于纠正 ADC 自身的零点误差 */
|
||||
adc_calibration_mode_config(ADC2, ADC_CALIBRATION_OFFSET);
|
||||
/* 配置校准次数 */
|
||||
adc_calibration_number(ADC2, ADC_CALIBRATION_NUM1);
|
||||
/*执行校准 */
|
||||
adc_calibration_enable(ADC2);
|
||||
|
||||
/* 启动DMA与ADC连续转换 */
|
||||
memset((void *)g_adc_dma_buf, 0, sizeof(g_adc_dma_buf));
|
||||
g_adc_dma_frame_cnt = 0U;
|
||||
dma_channel_enable(ADC_TEMP_DMA_PERIPH, ADC_TEMP_DMA_CH);
|
||||
adc_dma_mode_enable(ADC2);
|
||||
adc_dma_request_after_last_enable(ADC2);
|
||||
adc_software_trigger_enable(ADC2, ADC_REGULAR_CHANNEL);
|
||||
}
|
||||
|
||||
|
||||
uint32_t adc_channel_sample(uint8_t channel)
|
||||
{
|
||||
uint32_t timeout = 1000000U;
|
||||
/* 重新配置规则通道 */
|
||||
adc_regular_channel_config(ADC2, 0U, channel, 240);
|
||||
/* 软件触发转换 */
|
||||
adc_software_trigger_enable(ADC2, ADC_REGULAR_CHANNEL);
|
||||
/* 等待转换结束 */
|
||||
while(!adc_flag_get(ADC2, ADC_FLAG_EOC)){
|
||||
if (timeout-- == 0U) {
|
||||
return 0U;
|
||||
}
|
||||
}
|
||||
/* 清除标志 */
|
||||
adc_flag_clear(ADC2, ADC_FLAG_EOC);
|
||||
/* 读取结果并返回 */
|
||||
return (adc_regular_data_read(ADC2));
|
||||
}
|
||||
|
||||
void DMA1_Channel0_IRQHandler(void)
|
||||
{
|
||||
if (SET == dma_interrupt_flag_get(ADC_TEMP_DMA_PERIPH, ADC_TEMP_DMA_CH, DMA_INT_FLAG_HTF)) {
|
||||
dma_interrupt_flag_clear(ADC_TEMP_DMA_PERIPH, ADC_TEMP_DMA_CH, DMA_INT_FLAG_HTF);
|
||||
g_adc_dma_frame_cnt++;
|
||||
}
|
||||
|
||||
if (SET == dma_interrupt_flag_get(ADC_TEMP_DMA_PERIPH, ADC_TEMP_DMA_CH, DMA_INT_FLAG_FTF)) {
|
||||
dma_interrupt_flag_clear(ADC_TEMP_DMA_PERIPH, ADC_TEMP_DMA_CH, DMA_INT_FLAG_FTF);
|
||||
g_adc_dma_frame_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
void select_temp_channel(uint8_t flag_set)
|
||||
{
|
||||
//温度采集选通,
|
||||
/*
|
||||
OUT8、OUT7设置为高电平,A枪正温度
|
||||
OUT8设置为高电平,OUT7设置为低电平,A枪负温度
|
||||
OUT8设置为低电平,OUT7设置为高电平,B枪正温度
|
||||
OUT8、OUT7设置为低电平,B枪负温度
|
||||
*/
|
||||
if(flag_set == 0)
|
||||
{
|
||||
TEMP_MULT_CTRA(1);
|
||||
TEMP_MULT_CTRB(1);
|
||||
TEMP_MULT_CTRC(1);
|
||||
}
|
||||
else if(flag_set == 1)
|
||||
{
|
||||
TEMP_MULT_CTRA(0);
|
||||
TEMP_MULT_CTRB(1);
|
||||
TEMP_MULT_CTRC(1);
|
||||
}
|
||||
else if(flag_set == 2)
|
||||
{
|
||||
TEMP_MULT_CTRA(1);
|
||||
TEMP_MULT_CTRB(0);
|
||||
TEMP_MULT_CTRC(1);
|
||||
}
|
||||
else if(flag_set == 3)
|
||||
{
|
||||
TEMP_MULT_CTRA(0);
|
||||
TEMP_MULT_CTRB(0);
|
||||
TEMP_MULT_CTRC(1);
|
||||
}
|
||||
else if(flag_set == 4)
|
||||
{
|
||||
TEMP_MULT_CTRA(1);
|
||||
TEMP_MULT_CTRB(1);
|
||||
TEMP_MULT_CTRC(0);
|
||||
}
|
||||
else if(flag_set == 5)
|
||||
{
|
||||
TEMP_MULT_CTRA(0);
|
||||
TEMP_MULT_CTRB(1);
|
||||
TEMP_MULT_CTRC(0);
|
||||
}
|
||||
else if(flag_set == 6)
|
||||
{
|
||||
TEMP_MULT_CTRA(1);
|
||||
TEMP_MULT_CTRB(0);
|
||||
TEMP_MULT_CTRC(0);
|
||||
}
|
||||
else if(flag_set == 7)
|
||||
{
|
||||
TEMP_MULT_CTRA(0);
|
||||
TEMP_MULT_CTRB(0);
|
||||
TEMP_MULT_CTRC(0);
|
||||
}
|
||||
}
|
||||
double double_Vol_to_resistance(double vol)
|
||||
{
|
||||
double ret = 0;
|
||||
//BL1117-50CX输出+5V_Tem,可通过测量VOL_Vin2校准+5V_Tem,Rt=3kΩ*Vo/(+5V_Tem-Vo)
|
||||
|
||||
ret = (3000 * vol) / (5.04 - vol);
|
||||
|
||||
return ret / 1000.0;
|
||||
}
|
||||
|
||||
double PT1000_Vol_To_Temperature(double vol)
|
||||
{
|
||||
// 定义PT1000常数
|
||||
double R;
|
||||
const double R0 = 1000.0; // 0°C时的电阻值
|
||||
const double A = 3.9083e-3; // IEC751系数
|
||||
const double B = -5.775e-7;
|
||||
const double C = -4.183e-12; // 负温度区系数
|
||||
|
||||
// 计算电阻值(kΩ单位)
|
||||
R = double_Vol_to_resistance(vol);
|
||||
|
||||
/* 校准系数(保持kΩ单位) */
|
||||
if (R > 1.219)
|
||||
{
|
||||
R = R * 1.01778; // 高温区补偿
|
||||
}
|
||||
else if (R > 1)
|
||||
{
|
||||
R = R * 1.00395; // 常温区补偿
|
||||
}
|
||||
else
|
||||
{
|
||||
R = R * 0.98884; // 低温区补偿
|
||||
}
|
||||
|
||||
// 转换为Ω单位
|
||||
double R_ohm = R * 1000.0;
|
||||
|
||||
// 计算温度
|
||||
if (R_ohm >= R0)
|
||||
{
|
||||
// 正温度区使用二次方程
|
||||
double discriminant = A * A - 4 * B * (1 - R_ohm / R0);
|
||||
return (-A + sqrt(discriminant)) / (2 * B);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 负温度区使用牛顿迭代法
|
||||
const int max_iter = 100; // 最大迭代次数
|
||||
const double tol = 1e-6; // 收敛误差
|
||||
double T = -50.0; // 初始温度估计值
|
||||
|
||||
for (int i = 0; i < max_iter; i++)
|
||||
{
|
||||
double T2 = T * T;
|
||||
double T3 = T2 * T;
|
||||
|
||||
// Callendar-Van Dusen方程
|
||||
double f = R0 * (1 + A * T + B * T2 + C * (T - 100) * T3) - R_ohm;
|
||||
|
||||
// 检查是否收敛
|
||||
if (fabs(f) < tol)
|
||||
{
|
||||
return T;
|
||||
}
|
||||
|
||||
// 导数计算
|
||||
double df = R0 * (A + 2 * B * T + C * (4 * T3 - 300 * T2));
|
||||
|
||||
// 避免除零错误
|
||||
if (fabs(df) < 1e-10)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// 牛顿迭代法更新
|
||||
T -= f / df;
|
||||
}
|
||||
|
||||
// 返回收敛值
|
||||
return T;
|
||||
}
|
||||
}
|
||||
uint32_t get_adc_data(void)
|
||||
{
|
||||
uint64_t sum = 0U;
|
||||
uint32_t i;
|
||||
|
||||
/* 仅处理DMA中断已写入的采样数据,不触发硬件采样。 */
|
||||
for (i = 0U; i < ADC_TEMP_DMA_SAMPLE_CNT; i++)
|
||||
{
|
||||
sum += g_adc_dma_buf[i];
|
||||
// printf("data = %d\n", g_adc_dma_buf[i]);
|
||||
}
|
||||
|
||||
return (uint32_t)(sum / ADC_TEMP_DMA_SAMPLE_CNT);
|
||||
|
||||
}
|
||||
uint32_t adc_readval(void)
|
||||
{
|
||||
float ret, temp_data = 0.0f;
|
||||
|
||||
ret = (get_adc_data() * 3.0f) / 4095.0f;
|
||||
|
||||
temp_data = PT1000_Vol_To_Temperature(ret);
|
||||
|
||||
return temp_data;
|
||||
|
||||
}
|
||||
void adc_test(uint8_t i)
|
||||
{
|
||||
float val_value;
|
||||
(void)i;
|
||||
delay_ms(1000);
|
||||
adc_value[0] = adc_channel_sample(ADC_CHANNEL_0);
|
||||
val_value = (adc_value[0] * 3.0f) / 4095.0f;
|
||||
(void)val_value;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user