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));
}
}
執行結果: