使用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]
一周热门 更多>