STM32F373使用SDADC结合DMA采样电压,采样周期5120Hz(<16.6ksps),采集的数据偏大且波动大,大家来看看什么情况

2019-07-21 02:13发布

使用SDADC1的差分输入模式。VREFSD+采用片内1.22V做参考电压,在VREFSD+和VREFSD-之间以1uF+10nF相连,VREFSD-接GND。
配置DMA,一次采样1024个点;定时器TIM19触发。基本情况就是这些。
下面通过测量直流0.5V说明问题:
应该测得的数据为(0.5/1.22)*2^16=26859,实测为下图所示

这。。。。。。。。。。误差太大,而且波动也太剧烈了,根本不能做后续工作啊,怎么搞?

代码基本为库文件中所提供的例子,如下所示
》》》》》》注释部分略多,请自动忽略》》》》》》
希望大神帮忙解决疑惑啊!
[mw_shl_code=c,true]uint32_t SDADC1_Config(void) { SDADC_AINStructTypeDef SDADC_AINStructure; GPIO_InitTypeDef GPIO_InitStructure; DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; uint32_t SDADCTimeout = 0; /* Enable DMA2 clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE); /* ECG_SDADC APB2 interface clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SDADC1 ,ENABLE);//| RCC_APB2Periph_SDADC2, ENABLE); /* PWR APB1 interface clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); /* Enable ECG_SDADC analog interface */ PWR_SDADCAnalogCmd(PWR_SDADCAnalog_1, ENABLE); // PWR_SDADCAnalogCmd(PWR_SDADCAnalog_2, ENABLE); // PWR_SDADCAnalogCmd(PWR_SDADCAnalog_3, ENABLE); /* Set the SDADC divider: The SDADC should run @6MHz */ /* If Sysclk is 72MHz, SDADC divider should be 12 */ RCC_SDADCCLKConfig(RCC_SDADCCLK_SYSCLK_Div12); /* GPIOE Peripheral clock enable */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE);// | RCC_AHBPeriph_GPIOB, ENABLE);//8-20注释,发现错误,将GPIOA改为GPIOB,只要2路ADC的话,GPIOB也没用了 /* ECG_SDADC channel pin configuration: PE8,PE9,PE11,PE12*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 ;//| GPIO_Pin_11 | GPIO_Pin_12;// | GPIO_Pin_13 | GPIO_Pin_14;//8-20注释 GPIO_Init(GPIOE, &GPIO_InitStructure); // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;//8-20注释 // GPIO_Init(GPIOB, &GPIO_InitStructure); DMA_StructInit(&DMA_InitStructure); /* Config the DMA2 channel 3 */ DMA_DeInit(DMA2_Channel3); DMA2_MEM_LEN=length; DMA_InitStructure.DMA_PeripheralBaseAddr = SDADC1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)InjectedConvData; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = DMA2_MEM_LEN; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA2_Channel3, &DMA_InitStructure); /* Enable DMA2 Channel3 Transfer half and Complete interrupt */ DMA_ITConfig(DMA2_Channel3, DMA_IT_TC, ENABLE); /* Enable DMA2 Channel3 */ DMA_Cmd(DMA2_Channel3, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); SDADC_DeInit(SDADC1); // SDADC_DeInit(SDADC2); /* Select External reference: The reference voltage selection is available only in SDADC1 and therefore to select the VREF for SDADC2/SDADC3, SDADC1 clock must be already enabled */ SDADC_VREFSelect(POT_SDADC_VREF); /* Insert delay equal to ~10 ms (4 ms required) */ delay_ms(5); /* ENABLE ECGSDADC */ SDADC_Cmd(SDADC1, ENABLE); // SDADC_Cmd(SDADC2, ENABLE); /* Enter initialization mode */ SDADC_InitModeCmd(SDADC1, ENABLE); // SDADC_InitModeCmd(SDADC2, ENABLE); SDADCTimeout = SDADC_INIT_TIMEOUT; /* wait for INITRDY flag to be set */ while((SDADC_GetFlagStatus(SDADC1, SDADC_FLAG_INITRDY) == RESET) && (--SDADCTimeout != 0)); if(SDADCTimeout == 0) { /* INITRDY flag can not set */ return 1; } // SDADCTimeout = SDADC_INIT_TIMEOUT; // /* wait for INITRDY flag to be set */ // while((SDADC_GetFlagStatus(SDADC2, SDADC_FLAG_INITRDY) == RESET) && (--SDADCTimeout != 0)); // if(SDADCTimeout == 0) // { // /* INITRDY flag can not set */ // return 1; // } SDADC_AINStructure.SDADC_InputMode = SDADC_InputMode_Diff; SDADC_AINStructure.SDADC_Gain = POT_SDADC_GAIN; SDADC_AINStructure.SDADC_CommonMode = SDADC_CommonMode_VSSA; SDADC_AINStructure.SDADC_Offset = 0; SDADC_AINInit(SDADC1, SDADC_Conf_0, &SDADC_AINStructure); // SDADC_AINInit(SDADC2, SDADC_Conf_0, &SDADC_AINStructure); /* select ECG_SDADC channel to use conf0 */ SDADC_ChannelConfig(SDADC1, SDADC_Channel_8, SDADC_Conf_0); // SDADC_ChannelConfig(SDADC2, SDADC_Channel_4, SDADC_Conf_0); /* select SDADC Channel */ SDADC_InjectedChannelSelect(SDADC1, SDADC_Channel_8 ); // SDADC_InjectedChannelSelect(SDADC2, SDADC_Channel_4 ); /* 3、4路SDADC configuration */ // SDADC_AINInit(SDADC1, SDADC_Conf_1, &SDADC_AINStructure);//8-20注释 // SDADC_AINInit(SDADC2, SDADC_Conf_1, &SDADC_AINStructure); // SDADC_ChannelConfig(SDADC1, SDADC_Channel_6, SDADC_Conf_1); // SDADC_ChannelConfig(SDADC2, SDADC_Channel_2, SDADC_Conf_1); /* Select the SDADC injected channel */ // SDADC1->JCHGR |= (uint32_t) (SDADC_Channel_6 & 0x0000FFFF);//8-20注释 // SDADC2->JCHGR |= (uint32_t) (SDADC_Channel_2 & 0x0000FFFF); // SDADC_InjectedContinuousModeCmd(SDADC1,ENABLE); // SDADC_InjectedContinuousModeCmd(SDADC2,ENABLE); // /* Select an external trigger */ SDADC_ExternalTrigInjectedConvConfig(SDADC1, SDADC_ExternalTrigInjecConv_T19_CC2); /* Select rising edge */ SDADC_ExternalTrigInjectedConvEdgeConfig(SDADC1, SDADC_ExternalTrigInjecConvEdge_Rising); /*JSYNC: Launch a injected conversion synchronously with SDADC1 0: Do not launch injected conversion synchronously with SDADC1 1: Launch an injected conversion in this SDADC at the same moment that an injected conversion is launched in SDADC1 This bit can be modified only when INITRDY=1 (SDADC_ISR) or ADON=0 (SDADC_CR2).*/ // SDADC_InjectedSynchroSDADC1(SDADC2,ENABLE); /* Enable DMA transfer for injected conversions */ SDADC_DMAConfig(SDADC1, SDADC_DMATransfer_Injected, ENABLE); // SDADC_FastConversionCmd(SDADC1,ENABLE); // SDADC_FastConversionCmd(SDADC2,ENABLE); // /* configure calibration to be performed on conf0 */ // SDADC_CalibrationSequenceConfig(SDADC1, SDADC_CalibrationSequence_1); // /* configure calibration to be performed on conf0 */ // SDADC_CalibrationSequenceConfig(SDADC2, SDADC_CalibrationSequence_1); /* Exit initialization mode */ SDADC_InitModeCmd(SDADC1, DISABLE); // SDADC_InitModeCmd(SDADC2, DISABLE); ///////////////////////////校准///////////////////////////////////// // /* configure calibration to be performed on conf0 */ // SDADC_CalibrationSequenceConfig(SDADC1, SDADC_CalibrationSequence_2); SDADC_CalibrationSequenceConfig(SDADC1, SDADC_CalibrationSequence_1); /* start ECG_SDADC Calibration */ SDADC_StartCalibration(SDADC1); /* Set calibration timeout: 5.12 ms at 6 MHz in a single calibration sequence */ SDADCTimeout = SDADC_CAL_TIMEOUT; /* wait for ECG_SDADC Calibration process to end */ while(SDADC_GetFlagStatus(SDADC1, SDADC_FLAG_EOCAL) == RESET && (--SDADCTimeout != 0)); if(SDADCTimeout == 0) { /* EOCAL flag can not set */ return 2; } // SDADC_SoftwareStartInjectedConv(SDADC1); // ////////////////////////////校准//////////////////////////////////// //// /* configure calibration to be performed on conf0 */ //// SDADC_CalibrationSequenceConfig(SDADC2, SDADC_CalibrationSequence_2); // /* start ECG_SDADC Calibration */ // SDADC_StartCalibration(SDADC2); // /* Set calibration timeout: 5.12 ms at 6 MHz in a single calibration sequence */ // SDADCTimeout = SDADC_CAL_TIMEOUT; // /* wait for ECG_SDADC Calibration process to end */ // while(SDADC_GetFlagStatus(SDADC2, SDADC_FLAG_EOCAL) == RESET && (--SDADCTimeout != 0)); // if(SDADCTimeout == 0) // { // /* EOCAL flag can not set */ // return 2; // } return 0; } /** * @brief Configure timer TIM3: It is used as trigger for SDADC conversion * @param None * @retval None */ void TIM19_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; /* Enable TIM19 clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM19, ENABLE); TIM_DeInit(TIM19); TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Period = SystemCoreClock/100/SAMPLING_FREQ-1; //自动装载值72M/SAMPLING_FREQ,相当于得到定时器的频率为SAMPLING_FREQ TIM_TimeBaseStructure.TIM_Prescaler = 99; //预分频CK_CNT=fCK_PSC/(0+1) TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0; TIM_TimeBaseInit(TIM19, &TIM_TimeBaseStructure); /* Channel2 Configuration in PWM mode */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; TIM_OCInitStructure.TIM_Pulse = SystemCoreClock/100/SAMPLING_FREQ/2; //保证从0向上计数时,在TIM_Period/2处产生一个上升沿,保证在定时器频率下,每个周期触发SDADC一次,触发频率为SAMPLING_FREQ TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;; TIM_OC2Init(TIM19, &TIM_OCInitStructure); // TIM_OC2Init(TIM3, &TIM_OCInitStructure); // TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); // // TIM_ITConfig(TIM3, TIM_IT_CC1 , ENABLE); // // TIM_ARRPreloadConfig(TIM3, ENABLE); /* TIM19 enable counter */ TIM_Cmd(TIM19, ENABLE); }[/mw_shl_code]
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
2条回答
正点原子
1楼-- · 2019-07-21 05:31
 精彩回答 2  元偷偷看……
mthgh0818
2楼-- · 2019-07-21 09:33
哥们,POT_SDADC_VREF的宏定义改了吗?官方例程对应的是外部参考电压

一周热门 更多>