国民MCU n32G435CBL7 ADC+DMA+滤波算法
·
ADC.C
#include "adc_aq.h"
#include "debug.h"
static uint16_t i;
volatile adc_regular_dma_t adc_regular_dma_state;
volatile adc_inject_irq_t adc_inject_irq_state;
volatile double opa_base_voltage;
volatile opa_correct_data temp_210_opa_correct;
volatile opa_correct_data temp_245_opa_correct;
volatile opa_correct_data ileak_opa_correct;
volatile opa_correct_data voltage_opa_correct;
volatile opa_correct_data current_opa_correct;
void adc_gpio_init(void)
{
/* GPIO configuration ------------------------------------------------------*/
GPIO_InitType GPIO_InitStructure;
GPIO_InitStruct(&GPIO_InitStructure);
/* Configure PA.01 (in1)as analog input -------------------------*/
GPIO_InitStructure.Pin = BASE_1_2_ADC_CH1_PIN |
ILEAK_ADC_CH2_PIN |
SOLDER_VOUT_CH3_PIN |
SOLDER_CURRENT_CH4_PIN |
CH_TEMP_ADC_CH5_PIN |
CH_TEMP_ADC_CH6_PIN_COM;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Analog;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
}
void adc_temperature_init(void)
{
ADC_InitType ADC_InitStructure;
DMA_InitType DMA_InitStructure;
NVIC_InitType NVIC_InitStructure;
/* RCC_ADCHCLK_DIV16*/
ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16);
RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSI, RCC_ADC1MCLK_DIV8); //selsect HSI as RCC ADC1M CLK Source
ADC_DeInit(ADC);
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.MultiChEn = ENABLE;
ADC_InitStructure.ContinueConvEn = ENABLE;
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE;
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = 1;
ADC_Init(ADC, &ADC_InitStructure);
/* ADC regular channel configuration */
// ADC_ConfigRegularChannel(ADC, BASE_1_2_ADC_CH, 1, ADC_SAMP_TIME_71CYCLES5);
ADC_ConfigRegularChannel(ADC, CH_TEMP_CH, 1, ADC_SAMP_TIME_71CYCLES5);
/* Enable ADC DMA */
ADC_EnableDMA(ADC, ENABLE);
/* DMA channel1 configuration ----------------------------------------------*/
DMA_DeInit(TEMP_ADC_DMA_CH);
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.PeriphAddr = (uint32_t)&ADC->DAT;
DMA_InitStructure.MemAddr = (uint32_t)&adc_regular_dma_state.adc_val[0];
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;
DMA_InitStructure.BufSize = CH_TEMP_DMA_LENGTH;
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;
DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE;
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.CircularMode = DMA_MODE_CIRCULAR;
DMA_InitStructure.Priority = DMA_PRIORITY_LOW;
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
DMA_Init(TEMP_ADC_DMA_CH, &DMA_InitStructure);
DMA_RequestRemap(DMA_REMAP_ADC1, DMA, TEMP_ADC_DMA_CH, ENABLE);
/* Enable DMA channel */
DMA_EnableChannel(TEMP_ADC_DMA_CH, DISABLE);
/*开启传输完成中断*/
DMA_ConfigInt(TEMP_ADC_DMA_CH, DMA_INT_TXC, ENABLE);
/*配置dma通道一传输完成中断*/
NVIC_InitStructure.NVIC_IRQChannel = TEMP_ADC_DMA_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PREEM_PRIO_DMA_CH_ADC;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_SUB_PRIO_DMA_CH_ADC;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Start ADC Software Conversion */
// ADC_EnableSoftwareStartConv(ADC, ENABLE);
// DMA_EnableChannel(TEMP_ADC_DMA_CH, ENABLE);
}
void adc_monitor_init(void)
{
// ADC_InitType ADC_InitStructure;
NVIC_InitType NVIC_InitStructure;
/* Set injected sequencer length */
ADC_ConfigInjectedSequencerLength(ADC, 3);
/* ADC1 injected channel Configuration */
// ADC_ConfigInjectedChannel(ADC, BASE_1_2_ADC_CH, 1, ADC_SAMP_TIME_71CYCLES5);
/* ADC1 injected channel Configuration */
ADC_ConfigInjectedChannel(ADC, ILEAK_ADC_CH, 1, ADC_SAMP_TIME_71CYCLES5);
/* ADC1 injected channel Configuration */
ADC_ConfigInjectedChannel(ADC, SOLDER_VOUT_CH, 2, ADC_SAMP_TIME_71CYCLES5);
/* ADC1 injected channel Configuration */
ADC_ConfigInjectedChannel(ADC, SOLDER_CURRENT_CH, 3, ADC_SAMP_TIME_71CYCLES5);
/* Enable automatic injected conversion start after regular one */
ADC_EnableAutoInjectedConv(ADC, DISABLE);
/* ADC1 injected external trigger configuration */
ADC_ConfigExternalTrigInjectedConv(ADC, ADC_EXT_TRIG_INJ_CONV_T1_CC4);
/* Enablethe ADCx injected channels conversion through external trigger*/
ADC_EnableExternalTrigInjectedConv(ADC, ENABLE);
/* Enable JEOC interrupt */
ADC_ConfigInt(ADC, ADC_INT_JENDC, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PREEM_PRIO_VOL_CUR_ADC;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_SUB_PRIO_VOL_CUR_ADC;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void adc_tim_drv_init(void)
{
TIM_TimeBaseInitType TIM_TimeBaseStructure;
OCInitType TIM_OCInitStructure;
RCC_EnableAPB2PeriphClk(RCC_VOL_CUR_ADC_DRV_TIM, ENABLE);
TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.Period = VOL_CUR_ADC_DRV_TIM_PRD;
TIM_TimeBaseStructure.Prescaler = 71; // 分频后 1M 基准
TIM_TimeBaseStructure.ClkDiv = TIM_CLK_DIV1;
TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP;
TIM_TimeBaseStructure.RepetCnt = 0;
TIM_InitTimeBase(VOL_CUR_ADC_DRV_TIM, &TIM_TimeBaseStructure);
/* Prescaler configuration */
TIM_ConfigPrescaler(VOL_CUR_ADC_DRV_TIM, 71, TIM_PSC_RELOAD_MODE_IMMEDIATE);
TIM_OCInitStructure.OcMode = TIM_OCMODE_PWM1;
TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
TIM_OCInitStructure.OutputNState = TIM_OUTPUT_NSTATE_ENABLE;
TIM_OCInitStructure.Pulse = VOL_CUR_ADC_DRV_TIM_OC;
TIM_OCInitStructure.OcPolarity = TIM_OC_POLARITY_LOW;
TIM_InitOc4(VOL_CUR_ADC_DRV_TIM, &TIM_OCInitStructure); // 注入通道
TIM_ConfigOc4Preload(VOL_CUR_ADC_DRV_TIM, TIM_OC_PRE_LOAD_ENABLE);
TIM_ConfigArPreload(VOL_CUR_ADC_DRV_TIM, ENABLE);
TIM_EnableCtrlPwmOutputs(VOL_CUR_ADC_DRV_TIM, ENABLE);
TIM_Enable(VOL_CUR_ADC_DRV_TIM, ENABLE);
}
void adc_enable_init(void)
{
/* Enable ADC */
ADC_Enable(ADC, ENABLE);
/* Check ADC Ready */
while(ADC_GetFlagStatusNew(ADC, ADC_FLAG_RDY) == RESET)
;
/* Start ADC1 calibration */
ADC_StartCalibration(ADC);
/* Check the end of ADC1 calibration */
while (ADC_GetCalibrationStatus(ADC))
;
}
void adc_monitor_base12_config(void)
{
ADC_EnableSoftwareStartConv(ADC, DISABLE);
DMA_EnableChannel(TEMP_ADC_DMA_CH, DISABLE);
ADC_ConfigRegularChannel(ADC, BASE_1_2_ADC_CH, 1, ADC_SAMP_TIME_71CYCLES5);
DMA_SetCurrDataCounter(TEMP_ADC_DMA_CH, CH_TEMP_DMA_LENGTH);
}
void adc_monitor_temp_config(void)
{
ADC_EnableSoftwareStartConv(ADC, DISABLE);
DMA_EnableChannel(TEMP_ADC_DMA_CH, DISABLE);
ADC_ConfigRegularChannel(ADC, CH_TEMP_CH, 1, ADC_SAMP_TIME_71CYCLES5);
DMA_SetCurrDataCounter(TEMP_ADC_DMA_CH, CH_TEMP_DMA_LENGTH);
}
void temp_base_gather_start(void)
{
DMA_EnableChannel(TEMP_ADC_DMA_CH, ENABLE);
ADC_EnableSoftwareStartConv(ADC, ENABLE);
}
void temp_base_gather_stop(void)
{
ADC_EnableSoftwareStartConv(ADC, DISABLE);
DMA_EnableChannel(TEMP_ADC_DMA_CH, DISABLE);
DMA_SetCurrDataCounter(TEMP_ADC_DMA_CH, CH_TEMP_DMA_LENGTH);
}
void vol_cur_gather_start(void)
{
adc_inject_irq_state.cnts = 0;
TIM_SetAutoReload(VOL_CUR_ADC_DRV_TIM, VOL_CUR_ADC_DRV_TIM_PRD);
TIM_EnableCtrlPwmOutputs(VOL_CUR_ADC_DRV_TIM, ENABLE);
}
void vol_cur_gather_stop(void)
{
TIM_EnableCtrlPwmOutputs(VOL_CUR_ADC_DRV_TIM, DISABLE);
}
void TEMP_ADC_DMA_IRQHandler(void)
{
if (DMA_GetIntStatus(DMA_INT_TXC5, DMA) != RESET)
{
temp_base_gather_stop();
DMA_ClrIntPendingBit(DMA_INT_TXC5, DMA);
adc_regular_dma_state.adc_sum = 0;
for(i = 0; i < CH_TEMP_DMA_LENGTH; i++){
adc_regular_dma_state.adc_sum = adc_regular_dma_state.adc_sum + adc_regular_dma_state.adc_val[i];
}
adc_regular_dma_state.adc_average = adc_regular_dma_state.adc_sum / CH_TEMP_DMA_LENGTH;
#if DEBUG_CMD_CTROL == 1 && DEBUG_ADC_REG_DMA == 1
if(ch_bsp_debug.adc_val_monitor_flag == 1){
sprintf(debug_string_int_0, "debug adc reg dma: ");
for(i = 0; i < CH_TEMP_DMA_LENGTH; i++){
if(ch_bsp_debug.adc_val_monitor_flag == 1){
sprintf( debug_string_int_1, "%4d ", adc_regular_dma_state.adc_val[i]);
strcat( debug_string_int_0, debug_string_int_1);
}
}
sprintf( debug_string_int_1, ",sum: %5.1f, avr: %4.3f\n",
adc_regular_dma_state.adc_sum, adc_regular_dma_state.adc_average);
strcat( debug_string_int_0, debug_string_int_1 );
log_info(debug_string_int_0);
}
#endif
}
}
void opa_base_vol_correct(void)
{
adc_monitor_base12_config();
temp_base_gather_start();
delay_ms(10);
if(adc_regular_dma_state.dma_working_flag == 0){
opa_base_voltage = adc_regular_dma_state.adc_average / 4096 * 2.50f;
sprintf(debug_string_out_0, "1.2V base voltage = %.3f %4.3f\n",
opa_base_voltage, adc_regular_dma_state.adc_average);
log_info(debug_string_out_0);
}else{
log_info("1.2V base voltage adc dma error\n");
}
adc_monitor_temp_config();
temp_base_gather_start();
delay_ms(10);
if(adc_inject_irq_state.irq_working_flag == 0){
}else{
}
}
ADC.H
#ifndef __ADC_AQ_H__
#define __ADC_AQ_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "n32g43x.h"
#include "debug.h"
#define BASE_1_2_ADC_CH1_PIN GPIO_PIN_0
#define BASE_1_2_ADC_PORT GPIOA
#define BASE_1_2_ADC_CH ADC_CH_1_PA0
#define ILEAK_ADC_CH2_PIN GPIO_PIN_1
#define ILEAK_ADC_PORT GPIOA
#define ILEAK_ADC_CH ADC_CH_2_PA1
#define SOLDER_VOUT_CH3_PIN GPIO_PIN_2
#define SOLDER_VOUT_PORT GPIOA
#define SOLDER_VOUT_CH ADC_CH_3_PA2
#define SOLDER_CURRENT_CH4_PIN GPIO_PIN_3
#define SOLDER_CURRENT_PORT GPIOA
#define SOLDER_CURRENT_CH ADC_CH_4_PA3
#define CH_TEMP_ADC_CH5_PIN GPIO_PIN_4
#define CH_TEMP_PORT GPIOA
#define CH_TEMP_CH ADC_CH_5_PA4
#define CH_TEMP_ADC_CH6_PIN_COM GPIO_PIN_5
#define CH_TEMP_PORT_COM GPIOA
#define CH_TEMP_COM_CH ADC_CH_6_PA5
// 电压电流读取,定时读取
#define VOL_CUR_ADC_DRV_TIM TIM1
#define RCC_VOL_CUR_ADC_DRV_TIM RCC_APB2_PERIPH_TIM1
#define VOL_CUR_ADC_DRV_TIM_PRD 1000 // 500us
#define VOL_CUR_ADC_DRV_TIM_OC 500 // OC output
#define VOL_CUR_DATA_LENGTH 20
#define VOL_CUR_ONCE_NUM 3
#define CH_TEMP_DMA_LENGTH 10
//#define SOLDER_VOUT_ADC ADC1
//#define SOLDER_VOL_CUR_IRQHandler ADC1_2_IRQHandler
#define DEFAULT_BASE_VOLTAGE 1.246f
#define DEFAULT_AVCC_VOLTAGE 3.30f
#define cal_default_voltage(ADC_VAL_IN) (ADC_VAL_IN * 3.30f / 4096)
#define CORRECT_TAB_LENGTH 10
typedef struct
{
uint16_t base_1_2_adc_val;
uint16_t ileak_adc_val;
uint16_t solder_vout_adc_val;
uint16_t solder_current_adc_val;
uint16_t ch_temp_adc_val;
uint16_t ch_temp_com_adc_val;
}adc_aq_fltr_val_t;
typedef struct{
uint8_t dma_working_flag;
uint8_t length;
uint16_t adc_val[CH_TEMP_DMA_LENGTH];
double adc_average, adc_sum;
} adc_regular_dma_t;
typedef struct{
uint8_t irq_working_flag;
uint8_t length;
uint8_t cnts;
uint16_t adc_val[VOL_CUR_ONCE_NUM][VOL_CUR_DATA_LENGTH];
} adc_inject_irq_t;
typedef struct{
uint8_t index;
uint8_t length;
double mv_tab[CORRECT_TAB_LENGTH];
double Vo_tab[CORRECT_TAB_LENGTH];
double k, b;
} opa_correct_data;
extern volatile adc_regular_dma_t adc_regular_dma_state;
extern volatile adc_inject_irq_t adc_inject_irq_state;
extern volatile uint8_t ADC_DMA_Transfer_Flag;
extern volatile double opa_base_voltage;
extern volatile opa_correct_data temp_210_opa_correct;
extern volatile opa_correct_data temp_245_opa_correct;
extern volatile opa_correct_data ileak_opa_correct;
extern volatile opa_correct_data voltage_opa_correct;
extern volatile opa_correct_data current_opa_correct;
void adc_gpio_init(void);
void adc_temperature_init(void);
void adc_tim_drv_init(void);
void adc_monitor_init(void);
void adc_enable_init(void);
void adc_monitor_base12_config(void);
void adc_monitor_temp_config(void);
void temp_base_gather_start(void);
void temp_base_gather_stop(void);
void vol_cur_gather_start(void);
void vol_cur_gather_stop(void);
void opa_base_vol_correct(void);
void opa_init(volatile opa_correct_data *correct_data, double k, double b);
void opa_correct_cal(volatile opa_correct_data *correct_data);
double adc_ret_vol(double adc_val);
double opa_vol_cal(volatile opa_correct_data *correct_data, double vol);
#ifdef __cplusplus
}
#endif
#endif
滤波:
#include "comm_filter.h"
/**
***********************************************************
* @brief qsort函数调用的回调函数,比较规则,降序排列
* @param *_a,对应数组元素
* @param *_b,对应数组元素
* @return 比较结果
***********************************************************
*/
static int32_t CmpCb(const void *_a, const void *_b)
{
uint16_t *a = (uint16_t *)_a;
uint16_t *b = (uint16_t *)_b;
int32_t val = 0;
if (*a > *b)
{
val = -1;
}
else if (*a < *b)
{
val = 1;
}
else
{
val = 0;
}
return val;
}
/**
***********************************************************
* @brief 算术平均滤波
* @param arr,数组首地址
* @param len,元素个数
* @return 平均运算结果
***********************************************************
*/
static uint16_t ArithAvgFltr(uint16_t *arr, uint32_t len)
{
uint32_t sum = 0, i;
for (i = 0; i < len; i++)
{
sum += arr[i];
}
return (uint16_t)(sum / len);
}
/**
***********************************************************
* @brief 中位值平均滤波
* @param arr,数组首地址
* @param len,元素个数,需要大于等于3个
* @return 平均运算结果
***********************************************************
*/
uint16_t MedianAvgFltr(uint16_t *arr, uint32_t len)
{
// qsort(arr, len, sizeof(uint16_t), CmpCb);
return ArithAvgFltr(&arr[1], len - 2);
}
void ADC_DMA_DAT_Filt(void)
{
}
更多推荐



所有评论(0)