请教下CH32V303CBT6的adc+dma,采集数据错位
1,初始化代码
ADC_InitTypeDef ADC_InitStructure = { 0 };
	GPIO_InitTypeDef GPIO_InitStructure = { 0 };
	DMA_InitTypeDef DMA_InitStructure = { 0 };
	NVIC_InitTypeDef NVIC_InitStructure = { 0 };

	RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA, ENABLE );
	RCC_APB2PeriphClockCmd ( RCC_APB2Periph_ADC1, ENABLE );
	RCC_AHBPeriphClockCmd ( RCC_AHBPeriph_DMA1, ENABLE );
	RCC_ADCCLKConfig ( RCC_PCLK2_Div8 );

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init ( GPIOA, &GPIO_InitStructure );

	ADC_DeInit ( ADC1 );
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStructure.ADC_NbrOfChannel = PD_CHANNEL_NUM;
	ADC_Init ( ADC1, &ADC_InitStructure );

	ADC_RegularChannelConfig ( ADC1, ADC_Channel_3, 1, ADC_SampleTime_239Cycles5 );
	ADC_RegularChannelConfig ( ADC1, ADC_Channel_6, 2, ADC_SampleTime_239Cycles5 );

	ADC_Cmd ( ADC1, ENABLE );

	ADC_BufferCmd ( ADC1, DISABLE ); // disable buffer
	ADC_ResetCalibration ( ADC1 );
	while (ADC_GetResetCalibrationStatus(ADC1))
	;
	ADC_StartCalibration ( ADC1 );
	while (ADC_GetCalibrationStatus(ADC1))
	;
	Calibrattion_Val = Get_CalibrationValue ( ADC1 );

	DMA_DeInit ( DMA1_Channel1 );
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32) &ADC1->RDATAR;
	DMA_InitStructure.DMA_MemoryBaseAddr = (u32) adc_dma_buf;
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
	DMA_InitStructure.DMA_BufferSize = ADC_DMA_BUF_SIZE * PD_CHANNEL_NUM;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
	DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	DMA_Init ( DMA1_Channel1, &DMA_InitStructure );

	DMA_ITConfig ( DMA1_Channel1, DMA_IT_TC, ENABLE );

	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init ( &NVIC_InitStructure );

2,数据采集够之后,在

DMA1_Channel1_IRQHandler

中,停止采集:

DMA_Cmd ( DMA1_Channel1, DISABLE );
		ADC_DMACmd ( ADC1, DISABLE );
		DMA1_Channel1->CNTR = 0;
		ADC_SoftwareStartConvCmd ( ADC1, DISABLE );

3,启动采集

DMA_Cmd ( DMA1_Channel1, DISABLE );

	DMA1_Channel1->CNTR = user_curve_avg_size * 2;
	DMA_Cmd ( DMA1_Channel1, ENABLE );
	ADC_DMACmd ( ADC1, ENABLE );
	ADC_SoftwareStartConvCmd ( ADC1, ENABLE );

问题,缓冲区是一个

adc_dma_buf[cnt][2]
就是两个通道交替保存采集的数据,多次启动-停止会发现有时候一通道的值会和二通道的值交换位置

在中断中增加一句“ADC_Cmd(ADC1, DIABLE);”即可,因为虽然你把DMA关闭了,但是你的ADC是循环转换的,实际上ADC还是在不停的采样数据,所以重新开启传输的时候有几率出现数据错位的情况。image.png


感谢,按照你的方法确实解决了问题,顺便请教下你,有没有滤波器相关的,我这边需要低通滤波器,已经用matlab把系数搞出来了


您好,目前没有滤波器相关例程


只有登录才能回复,可以选择微信账号登录