问题现象:
AD转换我采用扫描方式,数据采集好后,我采用DMA,搬走数据,发现平时都是好好的,只要旁边有变频器等干扰,数据往往会错位,
比如:
正常:
通道0->ADBUFF[0]
通道1->ADBUFF[1]
通道2->ADBUFF[2]
通道3->ADBUFF[3]
通道4->ADBUFF[4]
通道5->ADBUFF[5]
通道6->ADBUFF[6]
通道7->ADBUFF[7]
受干扰后变为:
通道0->ADBUFF[1]
通道1->ADBUFF[2]
通道2->ADBUFF[3]
通道3->ADBUFF[4]
通道4->ADBUFF[5]
通道5->ADBUFF[6]
通道6->ADBUFF[7]
通道7->ADBUFF[0]
我的问题具体是:
是DMA出错,搬错了,还是A/D扫描错位了?
如果是其中一个,如何健壮他?
ad配置的码:
void Adc_Init(void)
{
//先初始化IO口
RCC->APB2ENR|=1<<2; //使能PORTA口时钟
//GPIOA->CRL&=0XFFFFfff0;//PA0 anolog输入,为0000的时候为模拟输入
//通道10/11设置
RCC->APB2ENR|=1<<9; //ADC1时钟使能
RCC->APB2RSTR|=1<<9; //ADC1复位
RCC->APB2RSTR&=~(1<<9);//复位结束
RCC->CFGR&=~(3<<14); //分频因子清零 15:14 adcpre=10;
RCC->CFGR|=2<<14;
//SYSCLK/DIV2=12M ADC时钟设置为12M,ADC最大时钟不能超过14M!
//否则将导致ADC准确度下降!
// ADC1->CR1=000-0,000-0,00,0-0,000-0,111,-0,001-,000,0-0000
ADC1->CR1=0x0000e100;
ADC1->CR2=0x001e0101;
ADC1->SQR1=0x00700000;
ADC1->SQR2=0x000000e6;
ADC1->SQR3=0x0a418820;
//通道顺序:通道0,通道1,通道2,通道3,通道4,通道5,通道6,通道7,结束,
//设置通道0~7的采样时间
ADC1->SMPR1=0X00924924; //通道0,-7采样时间100 41.5周期
ADC1->SMPR2=0x24924924;
ADC1->CR2|=1<<0; //开启AD转换器
ADC1->CR2|=1<<3; //使能复位校准
while(ADC1->CR2&1<<3); //等待校准结束
//该位由软件设置并由硬件清除。在校准寄存器被初始化后该位将被清除。
ADC1->CR2|=1<<2; //开启AD校准
while(ADC1->CR2&1<<2); //等待校准结束
//该位由软件设置以开始校准,并在校准结束时由硬件清除
}
//启动转换序列
void adbegin(void)
{
ADC1->CR2|=1<<22; //启动规则转换通道
}
//dma配置的码:
//DMA1的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/8位数据宽度/存储器增量模式
//DMA_CHx  MA通道CHx
//cpar:外设地址
//cmar:存储器地址
//cndtr:数据传输量
void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
RCC->AHBENR|=1<<0; //开启DMA1时钟
delaynop(60000); //等待DMA时钟稳定
DMA_CHx->CPAR=cpar; //DMA1 外设地址
DMA_CHx->CMAR=(u32)cmar;//DMA1,存储器地址
DMA1_MEM_LEN=cndtr; //保存DMA传输数据量
DMA_CHx->CNDTR=cndtr; //DMA1,传输数据量
DMA_CHx->CCR=0X00000000;//复位
DMA_CHx->CCR|=0<<4; //从外设读
DMA_CHx->CCR|=0<<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|=1<<12; //中等优先级
DMA_CHx->CCR|=0<<14; //非存储器到存储器模式
}
//开启一次DMA传输
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
DMA_CHx->CCR&=~(1<<0); //关闭DMA传输
DMA_CHx->CNDTR=DMA1_MEM_LEN; //DMA1,传输数据量
DMA_CHx->CCR|=1<<0; //开启DMA传输
}
|