高精度Σ-ΔADC数字抽取滤波器设计与优化

需积分: 48 34 下载量 28 浏览量 更新于2024-09-06 1 收藏 1.18MB PDF 举报
“高精度_ADC中的数字抽取滤波器设计.pdf” 在高精度Σ-Δ模数转换器(Σ-ΔADC)中,数字抽取滤波器是至关重要的组成部分,其设计直接影响到转换器的性能。该文介绍了一个适用于高精度Σ-ΔADC的数字抽取滤波器的设计方案,该滤波器采用0.35微米的半导体工艺制造,工作电压为5V。滤波器的结构采用了多级设计,主要包括级联的梳状滤波器、补偿滤波器和窄带有限冲击响应半带滤波器。 梳状滤波器主要负责去除高频噪声,其特点是具有多个相等间隔的传输零点,能够有效地降低特定频率的噪声。补偿滤波器则用于改善系统的整体频率响应,确保滤波效果的线性和稳定性。最后,窄带有限冲击响应半带滤波器则专注于在特定频率范围内提供精确的信号选择和衰减,以提高信噪比。 在设计过程中,通过优化各级滤波器的结构、阶数和系数,实现了电路面积的最小化和功耗的降低。所设计的数字抽取滤波器在21.77kHz的通带频率下,波纹系数控制在±0.01dB,这表明滤波器的频率响应非常平坦。同时,滤波器在阻带的增益衰减达到120dB,这意味着它可以有效地抑制不必要的高频噪声。 在实际应用中,这个数字抽取滤波器用于处理128倍过采样、二阶Σ-Δ调制器的输出码流,结果表明其信噪失真比高达102.8dB,这一数值反映了滤波器的极高信号处理能力。此外,该滤波器的功耗仅为49mW,占用的面积约为0.6mm×1.9mm,这些特性都满足了高精度模数转换器对于低功耗和小型化的需求。 关键词涵盖了Σ-ΔADC技术、模数转换器的核心——调制器、降采样过程以及数字滤波器的设计与实现。文章的发表表明了在提升ADC性能和效率方面的最新进展,对于理解和改进高性能ADC系统的设计者来说,提供了宝贵的理论和技术参考。 总结来说,该设计展示了数字抽取滤波器在高精度Σ-ΔADC中的关键作用,包括噪声消除、信号恢复和能效优化。通过精心的结构优化,成功地在有限的空间和功率预算内实现了卓越的信号处理性能,这对于现代电子设备中对高精度模拟信号数字化的需求具有重要意义。
2023-05-15 上传

解析代码extern __IO uint16_t ADC1_Value; extern __IO uint16_t ADC2_Value; ADC_HandleTypeDef hadc1; ADC_HandleTypeDef hadc2; void MX_ADC1_Init(void){ ADC_ChannelConfTypeDef sConfig; hadc1.Instance = ADC1; hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; hadc1.Init.ContinuousConvMode = DISABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 1; if (HAL_ADC_Init(&hadc1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } sConfig.Channel = ADC_CHANNEL_4; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }} void MX_ADC2_Init(void){ ADC_ChannelConfTypeDef sConfig; hadc2.Instance = ADC2; hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE; hadc2.Init.ContinuousConvMode = DISABLE; hadc2.Init.DiscontinuousConvMode = DISABLE; hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc2.Init.NbrOfConversion = 1; if (HAL_ADC_Init(&hadc2) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } sConfig.Channel = ADC_CHANNEL_5; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }} void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle){ GPIO_InitTypeDef GPIO_InitStruct; if(adcHandle->Instance==ADC1) { __HAL_RCC_ADC1_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_NVIC_SetPriority(ADC1_2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(ADC1_2_IRQn); } else if(adcHandle->Instance==ADC2) { __HAL_RCC_ADC2_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_NVIC_SetPriority(ADC1_2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(ADC1_2_IRQn); }} void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle){ if(adcHandle->Instance==ADC1) { __HAL_RCC_ADC1_CLK_DISABLE(); HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4); } else if(adcHandle->Instance==ADC2) { __HAL_RCC_ADC2_CLK_DISABLE(); HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5); }} void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadcx){ if(hadcx==&hadc1){ ADC1_Value=HAL_ADC_GetValue(hadcx);} if(hadcx==&hadc2){ ADC2_Value=HAL_ADC_GetValue(hadcx);}}

2023-06-07 上传

#include "bflb_adc.h" #include "bflb_mtimer.h" #include "board.h" struct bflb_device_s adc; #define TEST_ADC_CHANNELS 2 #define TEST_COUNT 10 struct bflb_adc_channel_s chan[] = { { .pos_chan = ADC_CHANNEL_2, .neg_chan = ADC_CHANNEL_GND }, { .pos_chan = ADC_CHANNEL_GND, .neg_chan = ADC_CHANNEL_3 }, }; int main(void) { board_init(); board_adc_gpio_init(); adc = bflb_device_get_by_name("adc"); / adc clock = XCLK / 2 / 32 */ struct bflb_adc_config_s cfg; cfg.clk_div = ADC_CLK_DIV_32; cfg.scan_conv_mode = true; cfg.continuous_conv_mode = false; cfg.differential_mode = true; cfg.resolution = ADC_RESOLUTION_16B; cfg.vref = ADC_VREF_3P2V; bflb_adc_init(adc, &cfg); bflb_adc_channel_config(adc, chan, TEST_ADC_CHANNELS); for (uint32_t i = 0; i < TEST_COUNT; i++) { bflb_adc_start_conversion(adc); while (bflb_adc_get_count(adc) < TEST_ADC_CHANNELS) { bflb_mtimer_delay_ms(1); } for (size_t j = 0; j < TEST_ADC_CHANNELS; j++) { struct bflb_adc_result_s result; uint32_t raw_data = bflb_adc_read_raw(adc); printf("raw data:%08x\r\n", raw_data); bflb_adc_parse_result(adc, &raw_data, &result, 1); printf("pos chan %d,neg chan %d,%d mv \r\n", result.pos_chan, result.neg_chan, result.millivolt); } bflb_adc_stop_conversion(adc); bflb_mtimer_delay_ms(100); } while (1) { } }根据以上代码对bl618程序的编写对以下stm32中代码#include "stm32f10x.h" #include "delay.h" #include "FSR.h" #include "usart.h" #include "adc.h" #define PRESS_MIN 20 #define PRESS_MAX 6000 #define VOLTAGE_MIN 150 #define VOLTAGE_MAX 3300 u8 state = 0; u16 val = 0; u16 value_AD = 0; long PRESS_AO = 0; int VOLTAGE_AO = 0; long map(long x, long in_min, long in_max, long out_min, long out_max); int main(void) { delay_init(); NVIC_Configuration(); uart_init(9600); Adc_Init(); delay_ms(1000); printf("Test start\r\n"); while(1) { value_AD = Get_Adc_Average(1,10); VOLTAGE_AO = map(value_AD, 0, 4095, 0, 3300); if(VOLTAGE_AO < VOLTAGE_MIN) { PRESS_AO = 0; } else if(VOLTAGE_AO > VOLTAGE_MAX) { PRESS_AO = PRESS_MAX; } else { PRESS_AO = map(VOLTAGE_AO, VOLTAGE_MIN, VOLTAGE_MAX, PRESS_MIN, PRESS_MAX); } printf("ADÖµ = %d,µçѹ = %d mv,ѹÁ¦ = %ld g\r\n",value_AD,VOLTAGE_AO,PRESS_AO); delay_ms(500); } } long map(long x, long in_min, long in_max, long out_min, long out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; }移植到bl618进行改写

2023-05-12 上传