stm32f407之三ADC交替採樣(操作寄存器)

三ADC交替採樣

       在多ADC模式中,ADC1爲主,ADC2或ADC3爲從,交替或者同時觸發,工作模式取決於ADC_CCR寄存器的MULTI[4:0]。

       多ADC模式中,轉換後的數據可以多模式的數據寄存器(ADC_CDR)中讀取。狀態可以在多模式的狀態寄存器(ADC_CSR)讀取。

        

 

 

 

多ADC模式下的DMA傳輸方式:

    方式1:每個AD轉換完都發出DMA請求,多模式的數據寄存器(ADC_CDR)用低位保存轉換結果。

1st request: ADC_CDR[31:0] = ADC1_DR[15:0]

2nd request: ADC_CDR[31:0] = ADC2_DR[15:0]

3rd request: ADC_CDR[31:0] = ADC3_DR[15:0]

4th request: ADC_CDR[31:0] = ADC1_DR[15:0]

 

      方式2:每兩個AD轉換完都發出DMA請求。

雙ADC模式:

高十六位保存ADC2結果,低十六位保存ADC1結果

1st request: ADC_CDR[31:0] = ADC2_DR[15:0] |ADC1_DR[15:0]

2nd request: ADC_CDR[31:0] = ADC2_DR[15:0] |ADC1_DR[15:0]

三ADC模式:

1st request: ADC_CDR[31:0] = ADC2_DR[15:0] |ADC1_DR[15:0]

2nd request: ADC_CDR[31:0] = ADC1_DR[15:0] |ADC3_DR[15:0]

3rd request: ADC_CDR[31:0] = ADC3_DR[15:0] |ADC2_DR[15:0]

4th request: ADC_CDR[31:0] = ADC2_DR[15:0] |ADC1_DR[15:0]

 

        方式2:每兩個AD轉換完都發出DMA請求。與方式2相似,但是DMA以半字方式傳輸。

用於6位或者8位分辨率中。

 雙ADC模式:

高8位保存ADC2結果,低8位保存ADC1結果

1st request: ADC_CDR[15:0] = ADC2_DR[7:0] | ADC1_DR[7:0]

2nd request: ADC_CDR[15:0] = ADC2_DR[7:0] | ADC1_DR[7:0]

 三ADC模式:

1st request: ADC_CDR[15:0] = ADC2_DR[7:0] | ADC1_DR[7:0]

2nd request: ADC_CDR[15:0] = ADC1_DR[7:0] | ADC3_DR[7:0]

3rd request: ADC_CDR[15:0] = ADC3_DR[7:0] | ADC2_DR[7:0]

4th request: ADC_CDR[15:0] = ADC2_DR[7:0] | ADC1_DR[7:0]

 

 

 

多ADC轉換模式:

1.     注入同步模式

2.     規則同步模式

3.     交替模式

4.     交替觸發模式

5.     規則同步+注入同步模式

6.     規則同步+交替觸發模式

 

 

 

交替模式配置步驟:

1. 配置相關輸入通道的IO口。

2. 設置DMA

3. 如果雙重ADC或三重採樣,設置ADC的公共寄存器

       a.     設置公共寄存器首先要打開任意一個ADC的時鐘,否則這部分數字電路是沒有開始工作的。

        b.     設置DMA模式

        c.     設置ADC轉換完成後,發送DMA請求

        d.     設置多ADC模式

        e.     設置兩次採樣間隔週期

4. 配置要使用到的ADC(必須ADC1爲主,其他爲從)。

 

 程序:

/************************************
    標題:ADC
    軟件平臺:IAR for ARM6.21
    硬件平臺:stm32f4-discovery
    主頻:168M
    
    author:小船
    data:2012-02-16
*************************************/

#include <stm32f4xx.h> 
#include "MyDebugger.h"

__IO uint16_t ADCConvertedVault[10000];
char TXbuffer[] = "PC1輸入電壓爲:x.xxxV\n\r";

void ADC_IO_Config(void);
void ADC_DMA_Config(void);

void ADC_Common_Config(void);

void ADC3_IN11_Config(void);
void ADC2_IN11_Config(void);
void ADC1_IN11_Config(void);

void main ()
{   
  SCB->AIRCR = 0x05FA0000 | 0x400;  //中斷優先級分組 搶佔:響應=3:1
 
  ADC_IO_Config();
  ADC_DMA_Config();
  
  ADC_Common_Config();
  
  ADC3_IN11_Config();
  ADC2_IN11_Config(); 
  ADC1_IN11_Config();
  
  ADC3->CR2 |= (1<<0);   //開啓ADC3轉換
  ADC2->CR2 |= (1<<0);   //開啓ADC2轉換
  ADC1->CR2 |= (1<<0);   //開啓ADC1轉換
   
  ADC1->CR2 |= (1<<30); //觸發轉換開始 
  
  MyDebugger_Init();

  while(1)
  {
  };
}

void ADC_Common_Config(void)
{
  RCC->APB2ENR |= ( (1<<8) | (1<<9) | (1<<10) ); //使能ADC時鐘
  ADC->CCR &= 0x00000000;
  
  /*
  DMA模式1
  最後一次ADC轉換後發出dma請求
  交錯模式
  2次採樣之間的延遲5個週期
  */
  ADC->CCR |= ( 0x00004000 | (1<<13) | 0x00000017 | 0x00000000);
    
}

/***ADC1設置***/
void ADC1_IN11_Config(void)
{   
  ADC1->SQR1 = 0x00000000;//轉換一個通道
  ADC1->SQR3 = 0x0000000B;//第一個通道爲ADC1_in11
  ADC1->CR1 &= 0x00000000; 
  ADC1->CR2 &= 0x00000000;  
  ADC1->CR2 |= (1<<1);  //連續轉換
  ADC1->CR2 |= (1<<9); //最後一次ADC轉換後發出dma請求

  ADC1->CR2 |= (1<<8);//ADC dma發送模式使能
}

/***ADC2設置***/
void ADC2_IN11_Config(void)
{   
  ADC2->SQR1 = 0x00000000;//轉換一個通道
  ADC2->SQR3 = 0x0000000B;//第一個通道爲ADC1_in11
  ADC2->CR1 &= 0x00000000; 
  ADC2->CR2 &= 0x00000000;  
  ADC2->CR2 |= (1<<1);  //連續轉換
  ADC2->CR2 |= (1<<9); //最後一次ADC轉換後發出dma請求
}

/***ADC3設置***/
void ADC3_IN11_Config(void)
{   
  ADC3->SQR1 = 0x00000000;//轉換一個通道
  ADC3->SQR3 = 0x0000000B;//第一個通道爲ADC3_in11
  ADC3->CR1 &= 0x00000000; 
  ADC3->CR2 &= 0x00000000;  
  ADC3->CR2 |= (1<<1);  //連續轉換
  ADC3->CR2 |= (1<<9); //最後一次ADC轉換後發出dma請求
}

/***GPIO設置***/
void ADC_IO_Config(void)
{
  RCC->AHB1ENR |= (1<<2); //打開GPIOC時鐘
  GPIOC->MODER &= 0xfffffff3;//PC1模擬模式
  GPIOC->MODER |= 0x0000000C;
  GPIOC->PUPDR &= 0xfffffff3;//無上拉無下拉  
}

/***DMA設置***/
void ADC_DMA_Config(void)
{   
  RCC->AHB1ENR |= (1<<22); //使能DMA2時鐘
  ADC3->CR2 &= ~(1<<8);//ADC3 dma發送模式除能
  DMA2_Stream0->CR &= 0xFFFFFFFE; //除能DMA2_Stream0
  while(DMA2_Stream0->CR & 0x00000001);//確保DMA可以被設置 
  DMA2->LIFCR |= 0x0000003D;//傳送前清空DMA2_Stream0所有中斷標誌 
  DMA2_Stream0->PAR = (uint32_t)&ADC->CDR;//設置外設地址
  DMA2_Stream0->M0AR = (uint32_t)ADCConvertedVault; //設置內存地址
  DMA2_Stream0->CR |= 0x0002800;//16位數據
  DMA2_Stream0->NDTR = 10000; //設置dma傳輸數據的數量
  /*
    設置dma2通道0,即ADC1
    優先級Medium
    傳輸方向外設到內存
    內存遞增模式
    循環模式
    傳輸完成中斷
  */
  DMA2_Stream0->CR |= ( 0x00000000 | 0x00010000 | 0x0 | (1<<10) | (1<<8) | (1<<4) ); 
  
  NVIC->IP[56] = 0xB0;
  NVIC->ISER[1] |= (1<<(56-32));
  
  DMA2_Stream0->CR |= 1; //DMA2數據流0使能
}

void DMA2_Stream0_IRQHandler (void)
{
  uint32_t i;
  uint32_t Average;
  if(DMA2->LISR & 0x00000010)
  {
      DMA2->LIFCR |= 0x00000010;
      for(i = 0; i < 10000; i++)  // 對一萬個數據取平均值
        Average += ADCConvertedVault[i];
      Average *= 3;
      Average /= 40960;
      TXbuffer[14] = ( Average / 1000 ) % 10 + 0x30;//轉換成ASCII碼
      TXbuffer[16] = ( Average / 100 ) % 10 + 0x30;
      TXbuffer[17] = ( Average / 10 ) % 10 + 0x30;
      TXbuffer[18] = Average % 10 + 0x30;
      MyDebugger_Message(TXbuffer, sizeof(TXbuffer)/sizeof(char));  
  }
}



 

 運行結果:






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章