STM32F030 ADC1的DMA采样问题

来源:互联网 发布:手机时间提醒软件 编辑:程序博客网 时间:2024/06/03 21:51
搞了1天一直ADC没有出来,发现采处理的值一直是固定值..

去21IC求助贴.[STM32F0] STM32F030 ADC1采样问题请教

等了好久都没有人回复,但有人提醒我说需要等待DMA的数据完成.

后面对比了别人的代码,

/* ADC DMA request in circular mode */
ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);

别人有这句代码,于是我加上这个话,则能够正常采样到数据了,

所以,必须得添加,否则无法获取到采样值.


接着又发现DMA传输到指定的数组数据顺序错乱了.....

类似别人的求助贴:[STM32F0] STM32F030 多通道ADC DMA读取问题

后面解决方式,按照最后帖子的方式解决的

        " F0的ADC在使用之前需要校准。这个7位的校准值也是放在ADC_DR中的,它也会触发DMA请求。可以参照F0的ADC-DMA例程,先做ADC校准、然后再设置DMA,再使能ADC的DMA。"


直接插入代码,正确的初始化代码:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. typedef enum  
  2. {  
  3.     ADC_PORTA0 = ADC_Channel_0,      
  4.     ADC_PORTA1 = ADC_Channel_1,  
  5.     ADC_PORTA2 = ADC_Channel_2,  
  6.     ADC_PORTA3 = ADC_Channel_3,  
  7.     ADC_PORTA4 = ADC_Channel_4,  
  8.     ADC_PORTA5 = ADC_Channel_5,  
  9.     ADC_PORTA6 = ADC_Channel_6,  
  10.     ADC_PORTA7 = ADC_Channel_7,  
  11.     ADC_PORTA8 = ADC_Channel_8,  
  12.     ADC_PORTA9 = ADC_Channel_9,  
  13.     ADC_PORTA10 = ADC_Channel_10,  
  14.     ADC_PORTA11 = ADC_Channel_11,  
  15.     ADC_PORTA12 = ADC_Channel_12,  
  16.     ADC_PORTA13 = ADC_Channel_13,  
  17.     ADC_PORTA14 = ADC_Channel_14,  
  18.     ADC_PORTA15 = ADC_Channel_15,  
  19. }AD_PORT;  
  20.   
  21. typedef enum   
  22. {  
  23.     KEY_LINE_1,  
  24.     KEY_LINE_2,  
  25.     ADC_KEY_LINE_MAX = KEY_LINE_2,  
  26.     BATTERY_AD,  
  27.     ADC_NUM_CNT,    //ADC的总数  
  28. }ADC_NUM;  
  29.   
  30.   
  31. volatile u16 g_uADC_ConVal[ADC_NUM_CNT] = {0};      // ADC转换值  
  32.   
  33.   
  34. u32 const  g_uADNum[]=  
  35. {     
  36.     //KEYPORTA1,   
  37.     ADC_PORTA9,    
  38.     ADC_PORTA8,    
  39.     ADC_PORTA2,  
  40.     //KEYPORTA0,  
  41. };  
  42.   
  43.   
  44. void Adc_Init(void)  
  45. {  
  46.     ADC_DeInit(ADC1);     
  47.       
  48.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);  
  49.   
  50.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);  
  51.   
  52.     //打开DMA1的时钟  
  53.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  
  54.     //打开ADC1的时钟  
  55.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);  
  56.   
  57.     RCC_ADCCLKConfig(RCC_ADCCLK_PCLK_Div4);  
  58.   
  59.     //初始化IO口  
  60.     GPIO_InitTypeDef    GPIO_InitStruct;  
  61.     GPIO_StructInit(&GPIO_InitStruct);  
  62.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;  
  63.     GPIO_InitStruct.GPIO_Pin =  AD_KEY1_PIN;  
  64.     GPIO_Init(AD_KEY1_PORT,&GPIO_InitStruct);               // KEY1  
  65.     GPIO_InitStruct.GPIO_Pin =  AD_KEY2_PIN;  
  66.     GPIO_Init(AD_KEY2_PORT,&GPIO_InitStruct);               // KEY2  
  67.     GPIO_InitStruct.GPIO_Pin =  BATTERY_AD_PIN;  
  68.     GPIO_Init(BATTERY_AD_PORT,&GPIO_InitStruct);;           // 电池电源采样  
  69.   
  70.     //配置ADC1的DMA模式  
  71.     ADC_InitTypeDef ADC_InitStructure;  
  72.     DMA_InitTypeDef DMA_InitStructure;  
  73.     DMA_DeInit(DMA1_Channel1);  
  74.     DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(ADC1->DR);             //定义DMA外设基地址,即为存放转换结果的寄存器  
  75.     DMA_InitStructure.DMA_MemoryBaseAddr = (u32)g_uADC_ConVal;      //定义内存基地址  
  76.     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;          //定义AD外设作为数据传输的来源  
  77.     DMA_InitStructure.DMA_BufferSize = ADC_NUM_CNT;     //指定DMA通道的DMA缓存的大小,即需要开辟几个内存空间,本实验有两个转换通道,所以开辟两个  
  78.     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;    //设定寄存器地址固定  
  79.     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;         //设定内存地址递加,即每次DMA都是将该外设寄存器中的值传到三个内存空间中  
  80.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;     //设定外设数据宽度  
  81.     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;         //设定内存的的宽度  
  82.     DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                     //设定DMA工作再循环缓存模式  
  83.     DMA_InitStructure.DMA_Priority = DMA_Priority_High;                 //设定DMA选定的通道软件优先级  
  84.     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  
  85.     DMA_Init(DMA1_Channel1,&DMA_InitStructure);  
  86.   
  87.     /* ADC DMA request in circular mode */  
  88.     ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);                   //必须得添加,否则无法获取到采样值  
  89.   
  90.     ADC_StructInit(&ADC_InitStructure);  
  91.     ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;  
  92.     ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;                  //设定AD转化在连续模式  
  93.     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;         //不使用外部促发转换  
  94.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Left;                   //采集的数据在寄存器中以左对齐的方式存放  
  95.     ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Backward;  
  96.     ADC_Init(ADC1, &ADC_InitStructure);   
  97.   
  98.     for(u8 uCnt = 0;uCnt < ADC_NUM_CNT;uCnt++)  
  99.     {  
  100.         /* Convert the ADC1  with 55.5 Cycles as sampling time */   
  101.         ADC_ChannelConfig(ADC1, g_uADNum[uCnt] , ADC_SampleTime_55_5Cycles);    //设置指定ADC的规则组通道,设置它们的转化顺序和采样时间  
  102.     }  
  103.       
  104.     //ADC_ChannelConfig(ADC1, ADC_Channel_2 , ADC_SampleTime_55_5Cycles);   //设置指定ADC的规则组通道,设置它们的转化顺序和采样时间  
  105.     //ADC_ChannelConfig(ADC1, ADC_Channel_8 , ADC_SampleTime_55_5Cycles);   //设置指定ADC的规则组通道,设置它们的转化顺序和采样时间  
  106.     //ADC_ChannelConfig(ADC1, ADC_Channel_9 , ADC_SampleTime_55_5Cycles);   //设置指定ADC的规则组通道,设置它们的转化顺序和采样时间  
  107.     //ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);   
  108.   
  109.       
  110.     /* ADC Calibration */  
  111.     ADC_GetCalibrationFactor(ADC1);                     //校准ADC  
  112.   
  113.       
  114.     DMA_Cmd(DMA1_Channel1,ENABLE);  
  115.       
  116.     /* Enable ADC_DMA */  
  117.     ADC_DMACmd(ADC1, ENABLE);    
  118.   
  119.     ADC_Cmd(ADC1,ENABLE);                                                                   //使能指定的ADC1  
  120.     while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));         <span style="white-space:pre">    </span>//等待ADC准备好  
  121.   
  122.   
  123.     ADC_StartOfConversion(ADC1);                        //启动转换  
  124. }  


另外补充,ADC_ScanDirection_Upward及ADC_ScanDirection_Backward的简要说明。假设ADC1有18个通道,1,2....18

ADC_ScanDirection_Upward表示从1~18开始扫描

ADC_ScanDirection_Backward表示从18~1方向扫描

这样就决定了,用户指定的内存数组里面存值的顺序.

像上面的代码,则对应关系为g_uADC_ConVal[0]--->AIN9  g_uADC_ConVal[1]--->AIN8 g_uADC_ConVal[2]-->AIN2

阅读全文
0 0