您的位置:首页 > 其它

STM32F1xx 多路ADC 使用DMA转换结果顺序错乱问题

2017-01-04 10:22 288 查看
使用DMA获取多路ADC多路转换结果的过程中出现结果顺序错乱的问题。代码如下

void  Adc_Init()
{
//先初始化IO口
RCC->APB2ENR |= 1<<4;	//使能PORTC口时钟
GPIOC->CRL &= 0xFFFF000F;//PC1,PC2设置为模拟输入工作模式

RCC->APB2ENR |= 1<<9;	//ADC1时钟使能
RCC->APB2RSTR |= 1<<9;	//ADC1复位
RCC->APB2RSTR &= ~(1<<9);//复位结束

RCC->CFGR &= ~(3<<14);	//分频因子清零
RCC->CFGR |= 2<<14;		//分频因子设置,对应为6分频
//PCLK2/DIV6=12M ADC时钟设置为12M,ADC最大时钟不能超过14M!否则将导致ADC准确度下降!

ADC1->CR1 &= 0xF0FFFF;	//工作模式清零,
ADC1->CR1 |= 0<<16;		//独立工作模式
ADC1->CR1 |= 1<<8;	//扫描模式
ADC1->CR2 |= 1<<1;		//连续转换模式
ADC1->CR2 |= 1<<8;		//启用DMA模式
ADC1->CR2 &= ~(7<<17);	//清除外部事件触发
ADC1->CR2 |= 7<<17;		//使用软件控制转换
ADC1->CR2 |= 1<<20;		//使用用外部触发(SWSTART)!!!必须使用一个事件来触发
ADC1->CR2 &= ~(1<<11);	//右对齐
ADC1->SQR1 &= ~(0xF<<20);
ADC1->SQR1 |= 2<<20;	//3(channl 11,12,13)个转换在规则序列中 也就是只转换规则序列2

ADC1->SMPR1 &= ~(0x3F<<3);	//采样时间清空
ADC1->SMPR1 |= 0x2D<<3;	//55.5周期,提高采样时间可以提高精确度 约6us
ADC1->SQR3 &= 0xFFFF8000;//规则序列1 通道ch
ADC1->SQR3 |= 0x358B;	//12<<5+11

ADC1->CR2 |= 1<<0;		//开启AD转换器
ADC1->CR2 |= 1<<3;		//使能复位校准

while(ADC1->CR2&1<<3);	//等待校准寄存器复位完成
ADC1->CR2 |= 1<<2;		//启动校准
while(ADC1->CR2&1<<2);	//等待校准结束
ADC1->SR &= ~(1<1);		//clear SR:EOC bit
ADC1->CR2 |= 1<<22;		//启动规则转换通道
}
void DMA_Config(DMA_Channel_TypeDef*DMA_CHx, u32 cpar, u32 cmar, u16 cndtr)
{	RCC->AHBENR|=1<<0;			//开启DMA1时钟
delay_ms(5);				//等待DMA时钟稳定
DMA_CHx->CPAR=cpar;			//DMA1 外设地址
DMA_CHx->CMAR=cmar;	//DMA1,存储器地址
DMA_CHx->CNDTR=cndtr;		//DMA1,传输数据量
DMA_CHx->CCR=0x00000000;	//复位
DMA_CHx->CCR|=0<<4;			//传输方向:外设至存储器
DMA_CHx->CCR|=1<<5;			//循环模式
DMA_CHx->CCR|=0<<6;			//外设地址非增量模式
DMA_CHx->CCR|=1<<7;			//存储器增量模式
DMA_CHx->CCR|=1<<8;			//外设数据宽度为16位
DMA_CHx->CCR|=1<<10;		//存储器数据宽度16位
DMA_CHx->CCR|=2<<12;		//中等优先级
DMA_CHx->CCR|=0<<14;		//非存储器到存储器模式
DMA_CHx->CCR|=1<<0;			//开启DMA传输

}
这是两段初始化的代码,一开始的调用是DMA->ADC,结果在两路转换的结果错了,后来改为ADC->DMA 结果正确。但是到了使用三路ADC时就又错了本应该1-->2-->3 的结果变成2-->3-->1。即使在ADC校准后将SR->EOC位清除也没用。所以将ADC启动语句放到了DMA初始化函数中如下所示;

void DMA_Config(DMA_Channel_TypeDef*DMA_CHx, u32 cpar, u32 cmar, u16 cndtr)
{	RCC->AHBENR|=1<<0;			//开启DMA1时钟
delay_ms(5);				//等待DMA时钟稳定
DMA_CHx->CPAR=cpar;			//DMA1 外设地址
DMA_CHx->CMAR=cmar;	//DMA1,存储器地址
DMA_CHx->CNDTR=cndtr;		//DMA1,传输数据量
DMA_CHx->CCR=0x00000000;	//复位
DMA_CHx->CCR|=0<<4;			//传输方向:外设至存储器
DMA_CHx->CCR|=1<<5;			//循环模式
DMA_CHx->CCR|=0<<6;			//外设地址非增量模式
DMA_CHx->CCR|=1<<7;			//存储器增量模式
DMA_CHx->CCR|=1<<8;			//外设数据宽度为16位
DMA_CHx->CCR|=1<<10;		//存储器数据宽度16位
DMA_CHx->CCR|=2<<12;		//中等优先级
DMA_CHx->CCR|=0<<14;		//非存储器到存储器模式
DMA_CHx->CCR|=1<<0;			//开启DMA传输

ADC1->CR2 |= 1<<22;
}
在启动DMA后在启动ADC的连续转换功能。结果就对了。



经测试在校准的过程不会将SR:EOC位置位,而且也不会有DMA的TC中断产生。

关于转换中断在SCAN模式下有这样的规则



只有最后一个通道转换完毕后才会产生EOC中断。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: