问题描述:
使用ADC单独连续模式,DMA循环模式运行,调试时发现,若设置ADC取样时间很短将影响DMA传输中断函数的进入,ADC取样时间可选:3、15、28、56、84、112、144、480个时钟周期,实验发现,若选最低的3个或15个时钟周期作为取样时间,则DMA传输中断函数不能进入,若选择28个时钟周期及以后的6种取样时间,均可正常进入DMA传输中断函数。
结论:
经仿真显示,ADC状态寄存器ADC_SR的OVE位置1,说明ADC数据丢失溢出,通过调试非循环模式DMA启动经验,将DMA初始化(启动)置于ADC初始化(启动)前,问题解决。所以ADC的溢出发生在ADC启动后DMA配置过程中,若设置取样时间长的话,问题被避开了,但取样时间短的话,会造成溢出。
DMA按照需要启动需注意事项:
1、DMA传输完成中断函数里面对ADC的CR2寄存器DMA位置0,即关闭ADC的DMA传输;
void DMA2_Stream0_IRQHandler(void) //ADC3的DMA中断服务函数
{
u8 k;
if ((DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0) != RESET)) //传输完成标志且数据转移至缓存区后允许将数据存入缓冲区
{
ADC_DMACmd(ADC3, DISABLE); //关闭ADC的DMA传输
Disc_Times++; //记录进入中断的次数
for(k=0;k<16;k++) //将数据转移,防止被下一轮写入冲掉
{
PDChnl[2].SampleValue[k]=ADC3_ConvertedValue[k];
}
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0); //清除传输中断标志位
}
}
2、DMA启动前对通道传输数据的数量重新加载 DMA2_Stream0->NDTR = 0X10;
3、ADC的DMA启动前对ADC状态寄存器ADC_SR的溢出位OVE置0,ADC3->SR &=~0X1<<5 ;确保程序长期稳定运行,取样时间短时,容易发现问题;取样时间长时,程序运行几分钟后才会出错,容易忽视;
DMA2_Stream0->NDTR = 0X10; //重新装填DMA需要传输的数据个数
DMA_Cmd(DMA2_Stream0, ENABLE); //先使能DMA通道
ADC3->SR &=~0X1<<5 ; //将由硬件置1的ADC状态寄存器的溢出标志位清除,不然容易出错
ADC_DMACmd(ADC3, ENABLE); //再使能ADC的DMA传输
另记:
1、printf函数不能放在DMA中断函数里面,容易导致DMA中断处理不完,如果非要放,放在清除中断标志位处理函数后;
2、规则组转换完成中断不需要,因为用的是两个规则组传递完成的DMA中断,所以
“//ADC_ITConfig(ADC2,ADC_IT_EOC,ENABLE); //每个规则通道转换结束时中断 ” 删除;
3、“ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE); ”控制DMA传输一组数据后发不发送DMA请求,与ADC转换后发送DMA请求无关,每次 ADC转换完成后即进行DMA传输,应该是在ADC_DMACmd(ADC3, ENABLE)时内部进行了实现,我们不用担心不同步的问题。