正大建设集团股份有限公司网站,wordpress 下载页,淮南网名,3合一网站怎么做GD32/STM32ADC采样及滤波
本文主要讨论代码层面的ADC采集及程序滤波。
ADC注意事项
ADC的参考电压为单片机的VDDA电压。
ADC单采
采用单路采集#xff0c;然后通过DMA去ADC_RDATA(ADC0)读取数据。以下为GD32例程。
/*!\brief configure the GPIO peripheral\param[…GD32/STM32ADC采样及滤波
本文主要讨论代码层面的ADC采集及程序滤波。
ADC注意事项
ADC的参考电压为单片机的VDDA电压。
ADC单采
采用单路采集然后通过DMA去ADC_RDATA(ADC0)读取数据。以下为GD32例程。
/*!\brief configure the GPIO peripheral\param[in] none\param[out] none\retval none
*/
void gpio_config(void)
{/* config the GPIO as analog mode */gpio_init(ADC_GPIO_PORT, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, ADC_GPIO_PIN);
}/*!\brief configure the DMA peripheral\param[in] none\param[out] none\retval none
*/
void dma_config(void)
{/* ADC_DMA_channel configuration */dma_parameter_struct dma_data_parameter;/* ADC DMA_channel configuration */dma_deinit(DMA0, DMA_CH0);/* initialize DMA single data mode */dma_data_parameter.periph_addr (uint32_t)(ADC_RDATA(ADC0));dma_data_parameter.periph_inc DMA_PERIPH_INCREASE_DISABLE;dma_data_parameter.memory_addr (uint32_t)(adc_value);dma_data_parameter.memory_inc DMA_MEMORY_INCREASE_DISABLE;dma_data_parameter.periph_width DMA_PERIPHERAL_WIDTH_16BIT;dma_data_parameter.memory_width DMA_MEMORY_WIDTH_16BIT; dma_data_parameter.direction DMA_PERIPHERAL_TO_MEMORY;dma_data_parameter.number 1;dma_data_parameter.priority DMA_PRIORITY_HIGH;dma_init(DMA0, DMA_CH0, dma_data_parameter);dma_circulation_enable(DMA0, DMA_CH0);/* enable DMA channel */dma_channel_enable(DMA0, DMA_CH0);
}/*!\brief configure the ADC peripheral\param[in] none\param[out] none\retval none
*/
void adc_config(void)
{/* reset ADC */adc_deinit(ADC0);/* ADC mode config */adc_mode_config(ADC_MODE_FREE);/* ADC contineous function enable */adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);/* ADC scan mode disable */adc_special_function_config(ADC0, ADC_SCAN_MODE, DISABLE);/* ADC data alignment config */adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);/* ADC channel length config */adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 1);/* ADC regular channel config */adc_regular_channel_config(ADC0, 0, BOARD_ADC_CHANNEL, ADC_SAMPLETIME_55POINT5);/* ADC trigger config */adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE);adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);/* enable ADC interface */adc_enable(ADC0);delay_1ms(1);/* ADC calibration and reset calibration */adc_calibration_enable(ADC0);/* ADC DMA function enable */adc_dma_mode_enable(ADC0);/* ADC software trigger enable */adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
}
ADC多路采集DMA
采用多路采集然后通过DMA去ADC_RDATA(ADC0)读取数据。以下为GD32例程。
/***********************************************************************
*brief :ADC初始化
*param :None
*return:None
***********************************************************************/
void ADC_Init(void)
{/* config the GPIO as analog mode */gpio_init(ADC_CHL1_PORT, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, ADC_CHL1_PIN);gpio_init(ADC_CHL2_PORT, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, ADC_CHL2_PIN);gpio_init(ADC_CHL3_PORT, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, ADC_CHL3_PIN);gpio_init(ADC_CHL4_PORT, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, ADC_CHL4_PIN);gpio_init(ADC_CHL5_PORT, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, ADC_CHL5_PIN);gpio_init(ADC_CHL6_PORT, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, ADC_CHL6_PIN);gpio_init(ADC_CHL7_PORT, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, ADC_CHL7_PIN);gpio_init(ADC_CHL8_PORT, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, ADC_CHL8_PIN);gpio_init(ADC_CHL9_PORT, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, ADC_CHL9_PIN);gpio_init(ADC_CHL10_PORT, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, ADC_CHL10_PIN);gpio_init(ADC_CHL11_PORT, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, ADC_CHL11_PIN);gpio_init(ADC_CHL12_PORT, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, ADC_CHL12_PIN);gpio_init(ADC_CHL13_PORT, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, ADC_CHL13_PIN);gpio_init(ADC_CHL14_PORT, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, ADC_CHL14_PIN);gpio_init(ADC_CHL15_PORT, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, ADC_CHL15_PIN);/* enable ADC clock */rcu_periph_clock_enable(RCU_ADC0);/* config ADC clock */rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV6); //12MHz;/* reset ADC */adc_deinit(ADC0);/* ADC mode config */adc_mode_config(ADC_MODE_FREE);/* ADC contineous function enable */adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);/* ADC scan mode disable */adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);/* ADC data alignment config */adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);/* ADC channel length config */adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, ADC_MAX_NUM);adc_tempsensor_vrefint_enable(); // 开启温度传感器/* ADC regular channel config */adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_0, ADC_SAMPLETIME_41POINT5); adc_regular_channel_config(ADC0, 1, ADC_CHANNEL_1, ADC_SAMPLETIME_41POINT5); adc_regular_channel_config(ADC0, 2, ADC_CHANNEL_2, ADC_SAMPLETIME_41POINT5); adc_regular_channel_config(ADC0, 3, ADC_CHANNEL_3, ADC_SAMPLETIME_41POINT5); adc_regular_channel_config(ADC0, 4, ADC_CHANNEL_5, ADC_SAMPLETIME_41POINT5); adc_regular_channel_config(ADC0, 5, ADC_CHANNEL_6, ADC_SAMPLETIME_41POINT5); adc_regular_channel_config(ADC0, 6, ADC_CHANNEL_7, ADC_SAMPLETIME_41POINT5); adc_regular_channel_config(ADC0, 7, ADC_CHANNEL_8, ADC_SAMPLETIME_41POINT5); adc_regular_channel_config(ADC0, 8, ADC_CHANNEL_9, ADC_SAMPLETIME_41POINT5); adc_regular_channel_config(ADC0, 9, ADC_CHANNEL_10, ADC_SAMPLETIME_41POINT5); adc_regular_channel_config(ADC0, 10, ADC_CHANNEL_11, ADC_SAMPLETIME_41POINT5); adc_regular_channel_config(ADC0, 11, ADC_CHANNEL_12, ADC_SAMPLETIME_41POINT5);adc_regular_channel_config(ADC0, 12, ADC_CHANNEL_13, ADC_SAMPLETIME_41POINT5);adc_regular_channel_config(ADC0, 13, ADC_CHANNEL_14, ADC_SAMPLETIME_41POINT5); adc_regular_channel_config(ADC0, 14, ADC_CHANNEL_15, ADC_SAMPLETIME_41POINT5); adc_regular_channel_config(ADC0, 15, ADC_CHANNEL_16, ADC_SAMPLETIME_41POINT5);/* ADC trigger config */adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE);adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);/* enable ADC interface */adc_enable(ADC0);
// delay_1ms(1);/* ADC calibration and reset calibration */adc_calibration_enable(ADC0);/* ADC DMA function enable */adc_dma_mode_enable(ADC0);/* ADC software trigger enable */adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
}
/***********************************************************************
*brief :DMA初始化
*param :ADC传送
*return:None
***********************************************************************/
void DMA_Init(void)
{/* enable DMA0 clock */rcu_periph_clock_enable(RCU_DMA0);/* ADC_DMA_channel configuration */dma_parameter_struct dma_data_parameter;/* ADC DMA_channel configuration */dma_deinit(DMA0, DMA_CH0);/* initialize DMA single data mode */dma_data_parameter.periph_addr (uint32_t)(ADC_RDATA(ADC0));dma_data_parameter.periph_inc DMA_PERIPH_INCREASE_DISABLE;dma_data_parameter.memory_addr (uint32_t)(adc_memory[0]);dma_data_parameter.memory_inc DMA_MEMORY_INCREASE_ENABLE;dma_data_parameter.periph_width DMA_PERIPHERAL_WIDTH_16BIT;dma_data_parameter.memory_width DMA_MEMORY_WIDTH_16BIT; dma_data_parameter.direction DMA_PERIPHERAL_TO_MEMORY;dma_data_parameter.number ADC_MAX_NUM;dma_data_parameter.priority DMA_PRIORITY_HIGH;dma_init(DMA0, DMA_CH0, dma_data_parameter);dma_circulation_enable(DMA0, DMA_CH0);/* enable DMA channel */dma_channel_enable(DMA0, DMA_CH0);
}去极值求平均值滤波
采用一个数组采样10次去掉一个最大值一个最小值剩下八个求平均值。
#include stdio.h
#include stdlib.hint main() {// 定义数组和变量int arr[10];int i, j, temp;float avg;// 获取 10 个样本值printf(Enter 10 sample values:\n);for (i 0; i 10; i) {scanf(%d, arr[i]);}// 排序数组for (i 0; i 10; i) {for (j i 1; j 10; j) {if (arr[i] arr[j]) {// 交换 arr[i] 和 arr[j]temp arr[i];arr[i] arr[j];arr[j] temp;}}}// 去掉最大值和最小值for (i 1; i 9; i) {avg arr[i];}// 计算平均值avg / 8;// 打印去极值后的平均值printf(Average of the remaining 8 values: %.2f\n, avg);return 0;
}滑动求平均值滤波
一组数据采用10位数组队列式进队和出队然后求平均值得到最终的值。
#include stdio.h
#include stdlib.h#define ARRAY_SIZE 10int main() {// 定义队列数组和变量int queue[ARRAY_SIZE];int head 0;int tail 0;int count 0;float avg;// 获取 10 个样本值printf(Enter 10 sample values:\n);for (int i 0; i ARRAY_SIZE; i) {scanf(%d, queue[tail]);tail (tail 1) % ARRAY_SIZE;count;}// 滑动求平均值while (count 0) {// 计算平均值avg 0;for (int i 0; i count; i) {avg queue[head];head (head 1) % ARRAY_SIZE;}avg / count;// 打印平均值printf(Average: %.2f\n, avg);// 出队count--;}return 0;
}振幅平均滤波法
#include stdio.h
#include stdlib.h// 定义滑动窗口大小
#define WINDOW_SIZE 5int main() {// 定义输入信号和滤波器参数int input_signal[] {1, 3, 5, 10, 15, 20, 25, 30, 25, 20, 15, 10, 5, 3, 1};int threshold 10;int window[WINDOW_SIZE];int head 0;int tail 0;int count 0;float avg;// 循环处理输入信号for (int i 0; i sizeof(input_signal) / sizeof(int); i) {// 限制幅度int limited_value input_signal[i];if (limited_value threshold) {limited_value threshold;}// 滑动窗口进队window[tail] limited_value;tail (tail 1) % WINDOW_SIZE;if (count WINDOW_SIZE) {count;}// 计算平均值avg 0;for (int j 0; j count; j) {avg window[head];head (head 1) % WINDOW_SIZE;}avg / count;// 打印滤波后的信号printf(Filtered signal: %.2f\n, avg);}return 0;
}总结
大家可以取其精华然后结合具体进行应用。