#include "drv_adc.h" #include "stdlib.h" #include "string.h" #include "gd32f4xx.h" #include "gd32f4xx_adc.h" #include "gd32f4xx_dma.h" #include "rtthread.h" /* 自定义宏,方便修改通道和引脚 */ uint16_t buff[2] = {0}; float curadc[ADC_CHANNEL_NUM]; void adc_gpio_config(void) { /* 启用GPIOA时钟 */ rcu_periph_clock_enable(RCU_GPIOC); /* 启用ADC0时钟 */ rcu_periph_clock_enable(RCU_ADC1); /* 配置ADC引脚为模拟输入模式 */ gpio_mode_set(ADC_GPIO_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, VOLTAGE_ADC_PIN); gpio_mode_set(ADC_GPIO_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, CURRENT_ADC_PIN); } void adc_config(void) { /* ########## ADC 基础配置 ########## */ // 复位ADC配置(可选,但建议初始化时做一次) adc_deinit(); // 配置数据对齐方式为右对齐 adc_data_alignment_config(TEST, ADC_DATAALIGN_RIGHT); // 配置ADC分辨率:12位 adc_resolution_config(TEST, ADC_RESOLUTION_12B); /* ########## 设置转换通道序列 ########## */ // 配置规则序列的长度:2个通道 // adc_channel_length_config(TEST, ADC_INSERTED_CHANNEL, 2); adc_channel_length_config(TEST, ADC_ROUTINE_CHANNEL, ADC_CHANNEL_NUM); // 配置规则序列:序号0是电压通道,序号1是电流通道 adc_routine_channel_config(TEST, 0, VOLTAGE_ADC_CHANNEL, ADC_SAMPLETIME_480); adc_routine_channel_config(TEST, 1, CURRENT_ADC_CHANNEL, ADC_SAMPLETIME_480); // adc_inserted_channel_config(TEST, 0, CURRENT_ADC_CHANNEL,ADC_SAMPLETIME_480);//电流 // adc_inserted_channel_config(TEST, 1, VOLTAGE_ADC_CHANNEL,ADC_SAMPLETIME_480);//电压 // 打开扫描模式 adc_special_function_config(TEST, ADC_SCAN_MODE, ENABLE); // 禁止连续模式 -> 单次转换模式 adc_special_function_config(TEST, ADC_CONTINUOUS_MODE, DISABLE); // DMA adc_dma_request_after_last_enable(ADC0); adc_dma_mode_enable(ADC0); /* ########## 其他设置 ########## */ // 使能外部触发:这里使用软件触发,所以先禁用硬件触发 adc_external_trigger_config(TEST, ADC_ROUTINE_CHANNEL, DISABLE); // adc_external_trigger_config(TEST, ADC_INSERTED_CHANNEL, DISABLE); // 开启ADC adc_enable(TEST); // 等待ADC稳定 rt_thread_mdelay(100); // 执行ADC自校准 adc_calibration_enable(TEST); adc_clock_config(ADC_ADCCK_PCLK2_DIV4); adc_software_trigger_enable(TEST, ADC_ROUTINE_CHANNEL); } static void DMA_config() { uint32_t dmax = DMA1; uint32_t dmax_rcu = RCU_DMA1; uint32_t dmax_ch = DMA_CH0; uint32_t damx_sub = DMA_SUBPERI0; uint32_t dmax_dirction = DMA_PERIPH_TO_MEMORY; uint32_t dmax_src = (uint32_t)(&ADC_RDATA(ADC1)); uint32_t dmax_src_inc = DMA_PERIPH_INCREASE_DISABLE; uint32_t dmax_src_width = DMA_PERIPH_WIDTH_16BIT; uint32_t dmax_src_len = 2; uint32_t dmax_dst = (uint32_t)(buff); uint32_t dmax_dst_inc = DMA_MEMORY_INCREASE_ENABLE; /**************** DMA p2m *******************/ // 时钟 rcu_periph_clock_enable(dmax_rcu); // 重置dma dma_deinit(dmax, dmax_ch); //////// dma 配置 dma_single_data_parameter_struct dsdps; dma_single_data_para_struct_init(&dsdps); // 方向 dsdps.direction = DMA_PERIPH_TO_MEMORY; // 内存: dst dsdps.memory0_addr = dmax_dst; dsdps.memory_inc = dmax_dst_inc; // 外设: src dsdps.periph_addr = dmax_src; dsdps.periph_inc = dmax_src_inc; // 数据长度 dsdps.number = dmax_src_len; // dst数据宽度 dsdps.periph_memory_width = dmax_src_width; // 传输优先级 dsdps.priority = DMA_PRIORITY_ULTRA_HIGH; dma_single_data_mode_init(dmax, dmax_ch, &dsdps); //////// 配置 dma 子连接 dma_channel_subperipheral_select(dmax, dmax_ch, damx_sub); dma_circulation_enable(dmax, dmax_ch); // 默认开启接收 dma_flag_clear(dmax, dmax_ch, DMA_FLAG_FTF); dma_channel_enable(dmax, dmax_ch); } // adc采集 float ptz_adc1_collect_task() { // static float adc1_v[LB_TIMES]; // static float curadc1_out; // static uint8_t adc1_num = 0; // int j,k; // float tem; // float curadc1; // uint16_t value_V = 0; uint16_t value = buff[0]; curadc[0] = (float)buff[0] / 4096.0 * 3.3; curadc[1] = (float)buff[1] / 4096.0 * 3.3; //软件触发使能 // adc_software_trigger_enable(TEST, ADC_ROUTINE_CHANNEL); // adc_software_trigger_enable(TEST, ADC_INSERTED_CHANNEL); // while(adc_flag_get(TEST, ADC_FLAG_EOC) == RESET); // 等待转换结束 // value_V = adc_routine_data_read(TEST); // 读取规则组数据寄存器 // value_V = adc_inserted_data_read(TEST, VOLTAGE_ADC_CHANNEL); // 读取规则组数据寄存器 // ... 后面的中位值平均滤波处理保持不变 ... // *11,硬件需要 // adc1_v[adc1_num] = (float)value_V / 4096.0 * 3.3; // 间接测量,11倍分压/放大 // ... // adc1_num++; // if(adc1_num >= LB_TIMES) // { // adc1_num = 0; // for(j = 0; j < LB_TIMES-1; j++)//采样值由小到大排列 // { // for(k = 0; k < LB_TIMES-j-1; k++) // { // if(adc1_v[k] > adc1_v[k+1]) // { // tem = adc1_v[k]; // adc1_v[k] = adc1_v[k+1]; // adc1_v[k+1] = tem; // } // } // } // for(uint8_t i = 1; i < LB_TIMES - 1; i++) // { // curadc1 = curadc1 + adc1_v[i]; // } // curadc1 = curadc1 /((float)(LB_TIMES - 2));//去掉一个最大值和一个最小值求平均值 // // g_ptz.Voltage = curadc1; // memset(adc1_v, 0, sizeof(adc1_v));//adc1_v 快速清零 // curadc1_out = curadc1; // } // return curadc1_out; } // //电流采集 // float ptz_Current_collect_adc1_task() // { // static float adc1_i[LB_TIMES]; // static float curadc0_out; // static uint8_t adc0_num; // int j,k; // float tem; // float curadc0; // uint16_t value_I; // adc_software_trigger_enable(TEST,ADC_ROUTINE_CHANNEL); // // adc_software_trigger_enable(TEST,ADC_INSERTED_CHANNEL); // // while(adc_flag_get(TEST, ADC_FLAG_EOC) == RESET); // 等待转换结束 // value_I = adc_routine_data_read(TEST); // 读取规则组数据寄存器 // // value_I = adc_inserted_data_read(TEST, CURRENT_ADC_CHANNEL); // 读取规则组数据寄存器 // adc1_i[adc0_num] = (((float)value_I / 4096.0 * 3.3)-3.3/2) / 0.132;//(float)value_I;// // adc0_num ++; // if(adc0_num >= LB_TIMES) // { // adc0_num = 0; // for(j = 0; j < LB_TIMES-1; j++)//采样值由小到大排列 // { // for(k = 0; k < LB_TIMES-j-1; k++) // { // if(adc1_i[k] > adc1_i[k+1]) // { // tem = adc1_i[k]; // adc1_i[k] = adc1_i[k+1]; // adc1_i[k+1] = tem; // } // } // } // for(uint8_t i = 1; i < LB_TIMES - 1; i++) // { // curadc0 = curadc0 + adc1_i[i]; // } // curadc0 = curadc0 /((float)(LB_TIMES - 2));//去掉一个最大值和一个最小值求平均值 // memset(adc1_i, 0, sizeof(adc1_i)); // curadc0_out = curadc0; // } // return curadc0_out; // } void init_data_collect_module(void) { adc_gpio_config(); adc_config(); DMA_config(); }