/********************************************************************************************************* * 模块名称:ADC.c * 摘 要:内部ADC应用,采用12bit。 * 当前版本:1.0.0 * 作 者:anycrying * 完成日期:2024年04月06日 * 内 容: * 注 意: ********************************************************************************************************** * 取代版本: * 作 者: * 完成日期: * 修改内容: * 修改文件: *********************************************************************************************************/ /********************************************************************************************************* * 包含头文件 *********************************************************************************************************/ #include #include "ADC.h" #include "gd32e230x_conf.h" #include "SysTick.h" #include "Timer.h" /********************************************************************************************************* * 宏定义 *********************************************************************************************************/ /********************************************************************************************************* * 枚举结构体 *********************************************************************************************************/ /********************************************************************************************************* * 内部变量定义 *********************************************************************************************************/ bool adc_data_ok_flag = false; uint8_t adc_sample_n;//采样次数 uint16_t adc_original_value[ADC_CH_N]={0};//存放各通道原始值 uint16_t adc_calc_value[ADC_Avg_N][ADC_CH_N];//各通道中间过程计算值 uint32_t adc_Avg_value[ADC_CH_N];//存放各通道平均值 extern uint16_t adc_data_zero[ADC_CH_N]; /********************************************************************************************************* * 内部函数声明 *********************************************************************************************************/ /********************************************************************************************************* * 函数名称:Init_ADC * 函数功能:初始化ADC模块 * 输入参数:void * 输出参数:void * 返 回 值:void * 创建日期:2024年04月06日 * 注 意: *********************************************************************************************************/ void Init_ADC(void) { adc_sample_n = 0; ConfigADCGPIO(); } /********************************************************************************************************* * 函数名称:ConfigADCGPIO * 函数功能:配置ADC的GPIO ,ADC通道3和4用于串口通信,所以扩展用了ADC通道9和10 * 输入参数:void * 输出参数:void * 返 回 值:void * 创建日期:2024年04月06日 * 注 意: *********************************************************************************************************/ void ConfigADCGPIO(void) { //使能RCU相关时钟 rcu_periph_clock_enable(ADC_0_5_RCU);//使能GPIOA的时钟 rcu_periph_clock_enable(ADC_67_RCU);//使能GPIOB的时钟 //使能ADC时钟 rcu_periph_clock_enable(RCU_ADC); //使能DMA的时钟 rcu_periph_clock_enable(RCU_DMA); //配置ADC时钟 rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6); //设置GPIO为ADC接口 gpio_mode_set(ADC_0_5_IO, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ADC_ch0|ADC_ch1|ADC_ch2|ADC_ch3|ADC_ch4|ADC_ch5);//ADC通道3和4用于串口通信,所以扩展用了ADC通道9和10 gpio_mode_set(ADC_67_IO, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ADC_ch6|ADC_ch7); //复位ADC外设 adc_deinit(); //配置DMA ADC_dma_config(); //内部ADC配置 adc_special_function_config(ADC_SCAN_MODE,ENABLE);//配置ADC扫描转换模式 adc_special_function_config(ADC_CONTINUOUS_MODE,ENABLE);//配置ADC连续转换模式 adc_external_trigger_source_config(ADC_REGULAR_CHANNEL,ADC_EXTTRIG_REGULAR_NONE);//配置ADC外部触发是软件触发 adc_data_alignment_config(ADC_DATAALIGN_RIGHT);//配置ADC数据对齐方式是右对齐 adc_resolution_config(ADC_RESOLUTION_12B);//配置ADC为12位 adc_channel_length_config(ADC_REGULAR_CHANNEL, ADC_CH_N);//配置ADC规则通道组成或注入通道组的长度,因为用到8个通道,所以是8 adc_regular_channel_config(0U, ADC_CHANNEL_0, ADC_SAMPLETIME_55POINT5);//配置ADC通道组 adc_regular_channel_config(1U, ADC_CHANNEL_1, ADC_SAMPLETIME_55POINT5); adc_regular_channel_config(2U, ADC_CHANNEL_4, ADC_SAMPLETIME_55POINT5); adc_regular_channel_config(3U, ADC_CHANNEL_5, ADC_SAMPLETIME_55POINT5); adc_regular_channel_config(4U, ADC_CHANNEL_6, ADC_SAMPLETIME_55POINT5); adc_regular_channel_config(5U, ADC_CHANNEL_7, ADC_SAMPLETIME_55POINT5); adc_regular_channel_config(6U, ADC_CHANNEL_8, ADC_SAMPLETIME_55POINT5); adc_regular_channel_config(7U, ADC_CHANNEL_9, ADC_SAMPLETIME_55POINT5); adc_enable();//使能 adc_enable();//使能 //delay_ms(2); adc_calibration_enable();//校准复位 adc_dma_mode_enable();//使能DMA adc_software_trigger_enable(ADC_REGULAR_CHANNEL);//软件触发 adc_software_trigger_enable(ADC_REGULAR_CHANNEL); //dma_interrupt_enable(DMA_CH0,DMA_INT_FTF); } /********************************************************************************************************* * 函数名称:ADC_dma_config * 函数功能:配置ADC采用DMA方式 * 输入参数:void * 输出参数:void * 返 回 值:void * 创建日期:2024年04月06日 * 注 意: *********************************************************************************************************/ void ADC_dma_config(void) { //通道参数配置 dma_parameter_struct dma_data_parameter; //使能ADC时钟 rcu_periph_clock_enable(RCU_ADC); //使能DMA的时钟 rcu_periph_clock_enable(RCU_DMA); //复位DMA通道 dma_deinit(DMA_CH0); //初始化DMA为单数据模式 dma_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA);//设置DMA外设地址,也是DMA数据传输的源地址,ADC单次采样转换结束后,会将数据存入ADC_RDATA地址中 dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;//设置DMA数据传输的源地址自增算法取消,ADC每次转换后数据存入地址不变 dma_data_parameter.memory_addr = (uint32_t)(adc_original_value);//设置DMA存储器地址,也是DMA数据传输的目标地址 dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;//设置DMA数据传输目标地址自增算法使能,因为DMA每个周期需要传送八个数据,所以在一个周期内,目标地址要自增 dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;//设置DMA从外设中读出数据的位数,因为ADC转换后的数值是12位,用16位数值表示,所以这里设置为1字 dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT; //设置DMA存入存储器的数据位数 dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY;//设置DMA的数据传输方向 dma_data_parameter.number = ADC_CH_N;//设置DMA一个周期要传输的数据个数,用了8个通道的ADC,所以在一个周期内要传输8个数据 dma_data_parameter.priority = DMA_PRIORITY_HIGH;//设置DMA数据传输高优先级 dma_circulation_enable(DMA_CH0);//DMA循环模式使能,这样DMA在传输8个数据后,存储地址复位,自动开启下一轮传输 dma_init(DMA_CH0, &dma_data_parameter);//初始化DMA dma_memory_to_memory_disable(DMA_CH0);//这里用不上,所以存储器到存储器DMA传输取消 dma_channel_enable(DMA_CH0);//使能DMA通道 } /********************************************************************************************************* * 函数名称:DC_I_calfunction * 函数功能:直流电流计算公式函数 * 输入参数:uint16_t 电流的ADC值 * 输出参数:uint32_t 浮点电流值(mA) * 返 回 值:uint32_t 浮点电流值(mA) * 创建日期:2024年04月06日 * 注 意:12位ADC转换公式:实际电压值V = (ADC参考电压Vref * 采样数值N) / 2^12 * 电流传感器转换公式:实际电流值I(A) = 实际电压值V / 灵敏度参数(V/A) * 实际计算时,让小数变成整数,最终结果扩大1000倍 *********************************************************************************************************/ uint32_t DC_I_calfunction(uint16_t da) { uint32_t temp_i = 0; uint32_t temp_v = 0; if(da > 0) { temp_v = da; temp_v *= ADC_Vref; temp_v *= 1000; temp_v = temp_v >> 12;//temp_v /= ADC_Fulscale; temp_v /= A_gain; temp_i = temp_v / I_sens; temp_i /= 10;//去掉第3位小数 temp_i *= 10; return temp_i; } else { return 0; } } /********************************************************************************************************* * 函数名称:read_adc_val * 函数功能:读取ADC各通道的数据,并将原始值存储到缓冲区,采样ADC_Avg_N次后才计算均值 * 输入参数:void * 输出参数:void * 返 回 值:void * 创建日期:2024年04月06日 * 注 意: *********************************************************************************************************/ void read_adc_val(void) { int8_t i = 0; if(adc_sample_n < ADC_Avg_N) { for(i = 0;i < ADC_CH_N ;i++) { adc_Avg_value[i] += adc_original_value[i]; } adc_sample_n++; } else { adc_sample_n = 0; for(i = 0;i < ADC_CH_N ;i++) { adc_Avg_value[i] = adc_Avg_value[i] / ADC_Avg_N; if(adc_Avg_value[i] > adc_data_zero[i]) { adc_Avg_value[i] -= adc_data_zero[i]; } else { adc_Avg_value[i] = 0; } } adc_data_ok_flag = true; } }