STM32多通道ADC操作


轉載自:http://www.cnblogs.com/nixianmin/p/3190531.html

今天嘗試了下STM32的ADC采樣,並利用DMA實現采樣數據的直接搬運存儲,這樣就不用CPU去參與操作了。

  找了不少例子參考,ADC和DMA的設置了解了個大概,並直接利用開發板來做一些實驗來驗證相關的操作,保證自己對各部分設置的理解。

  我這里用了3路的ADC通道,1路外部變阻器輸入,另外兩路是內部的溫度采樣和Vrefint,這樣就能組成連續的采樣,來測試多通道ADC自動掃描了,ADC分規則轉換和注入轉換,其實規則轉換就是按照既定的設定來順序轉換,而注入轉換就是可以在這順序隊列中插隊一樣,能夠提前轉換了。

  初始化設置:

復制代碼
 1 //PC0 FOR ANAGLE SAMPLE
 2 static void Protect_ClkInit(void)
 3 {
 4     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOC,ENABLE);
 5     RCC_ADCCLKConfig(RCC_PCLK2_Div6);
 6     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
 7 }
 8 
 9 static void Protect_GPIOInit(void)
10 {
11     GPIO_InitTypeDef GPIO_InitStructure;
12 
13     /*GPIO PhaseA_H 初始化*/
14     GPIO_InitStructure.GPIO_Pin = ADC_PIN; //這里是需要設置的ADC管腳
15     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
16     GPIO_Init(TIMER_GPIO_AH_PORT, &GPIO_InitStructure);
17 }
18 
19 static void Protect_AdcInit(void)
20 {
21     ADC_InitTypeDef ADC_InitStructure;
22     
23     ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
24     ADC_InitStructure.ADC_ScanConvMode = ENABLE;
25     ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //設置為連續
26     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
27     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
28     ADC_InitStructure.ADC_NbrOfChannel = 3; //注意數字3,表示采集ADC1的三個通道
29     ADC_Init(ADC1, &ADC_InitStructure);
30     
31     ADC_TempSensorVrefintCmd(ENABLE); //開啟內部溫度檢測的ADC通道
32     ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_7Cycles5); //注意這里的掃描順序的RANK參數(即1、2、3)
33     ADC_RegularChannelConfig(ADC1,ADC_Channel_TempSensor,2,ADC_SampleTime_7Cycles5); //注意掃描周期的設置
34     ADC_RegularChannelConfig(ADC1,ADC_Channel_Vrefint,3,ADC_SampleTime_7Cycles5);
35     
36     ADC_DMACmd(ADC1, ENABLE);
37     /* Enable ADC1 external trigger */
38     ADC_ExternalTrigConvCmd(ADC1, DISABLE);
39 
40     ADC_Cmd(ADC1, ENABLE);
41 
42     ADC_ResetCalibration(ADC1);
43 
44     while(ADC_GetResetCalibrationStatus(ADC1));
45 
46     ADC_StartCalibration(ADC1);
47 
48     while(ADC_GetCalibrationStatus(ADC1));
49 
50 }
51 
52 static void Protect_DMAInit(void)
53 {
54 
55     DMA_InitTypeDef DMA_InitStructure;
56 
57     /* DMA1 channel1 configuration ----------------------------------------------*/
58     DMA_DeInit(DMA1_Channel1);
59     DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & (ADC1->DR);
60     DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;
61     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
62     DMA_InitStructure.DMA_BufferSize = 3; //DMA通道的DMA緩存大小,單位為數據單位
63     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外設地址固定
64     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //外設地址遞增
65     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //半字
66     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
67     DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //循環模式
68     DMA_InitStructure.DMA_Priority = DMA_Priority_High;
69     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
70     DMA_Init(DMA1_Channel1, &DMA_InitStructure);
71 
72     /* Enable DMA1 channel1 */
73     DMA_Cmd(DMA1_Channel1, ENABLE);
74 }
復制代碼

  設置好后測試,發現一個比較嚴重的問題,我在調變阻器的時候,發現會影響其他2路采樣的數據,且數據變化比較大,我就先測試ADC的參考電壓即Vref+和Vref-,沒發現變化,那采樣的初始化是否會有問題,在網上找了不少的資料,都沒表明我的設置有問題,不過還是發現了一個不同,就是ADC_sampling_time的時間不同。那么我就把它設置成:

1     ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_239Cycles5);
2     ADC_RegularChannelConfig(ADC1,ADC_Channel_TempSensor,2,ADC_SampleTime_239Cycles5);
3     ADC_RegularChannelConfig(ADC1,ADC_Channel_Vrefint,3,ADC_SampleTime_239Cycles5);

  即最大的采樣時間,結果發現確實是這個問題,后來又試了下其他幾個采樣時間,最短也要ADC_SampleTime_71Cycles5,不然數據都會被影響,大概采樣周期不能太短, 不然DMA數據傳輸可能會被影響。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM