查阅大量资料和各个论坛 都没有得到一个全面详尽的答案
ADC采集工作在多通道连续扫描模式和连续转换模式 ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
DMA配置中 开启连续传输 (DMA_InitStructure.DMA_Mode = DMA_Mode_Circular ;)
首先DMA传输三个大致步骤 1.外设请求DMA传输 2.DMA传输数据到内存 3.传输完成进行下次传输或者停止传输(根据是否配置连续传输)
经过测试发现
1.DMA连续传输模式下 DMA产生中断请求后 进入中断函数后 DMA传输依然持续 除非ADC停止请求DMA传输
2.DMA是传输一次是传输整个DMA缓冲区 还是外设申请一次传一次 ?完成整个传输后产生中断标志:
手册中说
DMA_CNDTRx 寄存器对应 DMA_InitStructure.DMA_BufferSize = sizeof(DMA_Adc)/sizeof(vu16); 数据量大小为 30个u16
volatile u16 DMA_Adc[M][N]; //M=10 N=3
DMA_InitStructure.DMA_BufferSize = sizeof(DMA_Adc)/sizeof(vu16); 缓冲区大小为 30个u16
ADC1的通道1 完成一次扫描 ADC1转换完成后 申请DMA传输 ADC1将其12位数据寄存器的数据 存到DMA的缓存区
ADC1的通道2 完成一次扫描 ADC1转换完成后 申请DMA传输 ADC1将其12位数据寄存器中数据 存到DMA的缓存区
缓存区存满后 DMA传输数据到内存区 传输完成产生中断 这样的话就不高效 违背了DMA的初衷 而且手册中并未提到DMA可以缓存
所以DMA只是个桥接作用不起缓存作用 ADC1的通道1 完成一次扫描 ADC1转换完成后 申请DMA传输 DMA传输数据到内存
DMA_CNDTRx 寄存器减一 减到0 产生中断请求
有错误的地方还请指教
主函数就只有基本的初始化和while空循环和ADC_SoftwareStartConvCmd(ADC1, ENABLE);//ADC开始采集的启动函数
#include "adc.h"
volatile u16 DMA_Adc[M][N]; // M= 10 N=3 3¸öͨµÀ ÿ¸öͨµÀ²É¼¯10´Î volatile u16==vu16
u16 ADC_Value[N];
vu8 flag=0;
void ADC_Init_User()
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure; /* Configure the NVIC Preemption Priority Bits */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE ); //ʹÄÜADC1ͨµÀʱÖÓ
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //ÉèÖÃADC·ÖƵÒò×Ó6 72M/6=12,ADC×î´óʱ¼ä²»Äܳ¬¹ý14M
//PA1 ×÷ΪģÄâͨµÀÊäÈëÒý½Å
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; //¶ÔÓ¦adcͨµÀµÄ1 2 3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //Ä£ÄâÊäÈëÒý½Å
GPIO_Init(GPIOA, &GPIO_InitStructure);
//DMA1 Configuration ADC1¹ÒÔØÔÚDMA1µÄͨµÀ1
DMA_DeInit(DMA1_Channel1); //¸´Î»DMA1ͨµÀ1
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;//ÍâÉèADC1×÷Ϊ»ùµØÖ· &USART1->DR ÍâÉè´®¿Ú×÷Ϊ»ùµØÖ·
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)DMA_Adc; //¶¨ÒåDMA1µÄͨµÀµÄÄÚ´æ»ùµØÖ·
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //DMA´«Êä·½Ïò(ÍâÉèµ½ÄÚ´æ)
DMA_InitStructure.DMA_BufferSize = sizeof(DMA_Adc)/sizeof(vu16); //¶¨ÒåÖ¸¶¨DMAͨµÀµÄDMA»º´æ´óС
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //É趨ÍâÉèµØÖ·¼Ä´æÆ÷µÝÔöÓë·ñ£¬²»±ä£¬Disable
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //É趨ÍâÉèµØÖ·¼Ä´æÆ÷µÝÔöÓë·ñ£¬µÝÔö£¬Enable
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord ; //ÍâÉèÊý¾Ýµ¥Î»
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord ; //ÄÚ´æÊý¾Ýµ¥Î»
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular ; //DMAģʽ£ºÑ»·Ä£Ê½
DMA_InitStructure.DMA_Priority = DMA_Priority_High ; //¸ÃͨµÀÓÅÏȼ¶£º¸ß
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //½ûÖ¹ÄÚ´æµ½ÄÚ´æµÄ´«Êä
DMA_Init(DMA1_Channel1, &DMA_InitStructure); //³õʼ»¯DMA1ͨµÀ1
DMA_Cmd(DMA1_Channel1,ENABLE);//Æô¶¯DMA1µÄͨµÀ1
DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE); //¿ªÆô´«Êä½áÊøÖжÏ
//ÖжÏÓÅÏȼ¶NVICÉèÖÃ
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn; //TIM3ÖжÏ
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //ÏÈÕ¼ÓÅÏȼ¶0¼¶
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //´ÓÓÅÏȼ¶3¼¶
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨµÀ±»Ê¹ÄÜ
NVIC_Init(&NVIC_InitStructure); //³õʼ»¯NVIC¼Ä´æÆ÷
//ADC1 Configuration ×¢ ADC1 2 3 ¸÷¸öͨµÀ¶ÔÓ¦µÄIO»ù±¾¶¼ÊÇÒ»ÖµÄ
ADC_DeInit(ADC1); //¸´Î»ADC1
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC¹¤×÷ģʽ:ADC1ºÍADC2¹¤×÷ÔÚ¶ÀÁ¢Ä£Ê½
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //DISABLE=Ä£Êýת»»¹¤×÷ÔÚµ¥Í¨µÀģʽ
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //DISABLE=Ä£Êýת»»¹¤×÷ÔÚµ¥´Îת»»Ä£Ê½
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //ת»»ÓÉÈí¼þ¶ø²»ÊÇÍⲿ´¥·¢Æô¶¯
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADCÊý¾ÝÓÒ¶ÔÆë =µÍ12λÓÐЧ ×ó¶ÔÆë ¸ßÊ®¶þλÓÐЧ
ADC_InitStructure.ADC_NbrOfChannel = 3; //˳Ðò½øÐйæÔòת»»µÄADCͨµÀµÄÊýÄ¿ ¼¸¸öͨµÀ¾ÍÊǼ¸
ADC_Init(ADC1, &ADC_InitStructure); //¸ù¾ÝADC_InitStructÖÐÖ¸¶¨µÄ²ÎÊý³õʼ»¯ÍâÉèADCxµÄ¼Ä´æÆ÷
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_13Cycles5);//
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_13Cycles5);//
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_13Cycles5);//
ADC_DMACmd(ADC1,ENABLE); //¿ªÆôADCÓëDMAµÄÖ§³Ö
ADC_Cmd(ADC1, ENABLE); //ʹÄÜÖ¸¶¨µÄADC1
ADC_ResetCalibration(ADC1); //ʹÄܸ´Î»Ð£×¼
while(ADC_GetResetCalibrationStatus(ADC1)); //µÈ´ý¸´Î»Ð£×¼½áÊø
ADC_StartCalibration(ADC1); //¿ªÆôADУ׼
while(ADC_GetCalibrationStatus(ADC1)); //µÈ´ýУ׼½áÊø
// ADC_SoftwareStartConvCmd(ADC1, ENABLE); //ʹÄÜÖ¸¶¨µÄADC1µÄÈí¼þת»»Æô¶¯¹¦ÄÜ
}
void DMA1_Channel1_IRQHandler(void)
{
u8 i,j;
int sum;
for(i=0;i
sum=0;
for(j=0;j
sum+=DMA_Adc[j][i];
}
ADC_Value[i]=sum/10;//(float)sum/(10*4096)*3.3;
//ADC_Value[i]=(float)sum/10;
if(flag>0)
{
while(1){
OLED_ShowNum(1,2,DMA_Adc[0][0],4,12);
OLED_ShowNum(1,4,DMA_Adc[0][1],4,12);
OLED_ShowNum(1,6,DMA_Adc[1][0],4,12);
ADC_SoftwareStartConvCmd(ADC1, DISABLE);//¿ªÊ¼²É¼¯
ADC_Cmd(ADC1, DISABLE); //ʹÄÜÖ¸¶¨µÄADC1
}
}
else{
OLED_ShowNum(1,2,DMA_Adc[0][0],4,12);
OLED_ShowNum(1,4,DMA_Adc[0][1],4,12);
OLED_ShowNum(1,6,DMA_Adc[1][0],4,12);
DMA_ClearFlag(DMA1_FLAG_TC1);
}
flag++;
}
}