ADC
12位ADC是一種逐次逼近型模拟數字轉換器。它有多達19個通道,可測量16個外部和2個内部信号源和Vbat通道。各通道的A/D轉換可以單次、連續、掃描或間斷模式執行。ADC的結果可以左對齊或右對齊方式存儲在16位資料寄存器中。
模拟看門狗特性允許應用程式檢測輸入電壓是否超出使用者定義的高/低閥值。
有16個多路通道。
通道選擇:
可以把轉換組織成兩組:規則組和注入組。在任意多個通道上以任意順序進行的一系列轉換構成成組轉換。例如,可以如下順序完成轉換:通道3、通道8、通道2、通道2、通道0、通道2、通道2、通道15。
規則組由多達16個轉換組成。規則通道和它們的轉換順序在ADC_SQRx寄存器中選擇。規則組中轉換的總數應寫入ADC_SQR1寄存器的L[3:0]位中。
注入組由多達4個轉換組成。注入通道和它們的轉換順序在ADC_JSQR寄存器中選擇。注入組裡的轉換總數目應寫入ADC_JSQR寄存器的L[1:0]位中。如果ADC_SQRx或ADC_JSQR寄存器在轉換期間被更改,目前的轉換被清除,一個新的啟動脈沖将發送到ADC以轉換新選擇的組。
單次轉換模式:
單次轉換模式下,ADC隻執行一次轉換。該模式既可通過設定ADC_CR2寄存器的ADON位(隻适用于規則通道)啟動也可通過外部觸發啟動(适用于規則通道或注入通道),這時CONT位為0。
一旦選擇通道的轉換完成:
如果一個規則通道被轉換:
─ 轉換資料被儲存在16位ADC_DR寄存器中
─ EOC(轉換結束)标志被設定 ─ 如果設定了EOCIE,則産生中斷。
如果一個注入通道被轉換:
─ 轉換資料被儲存在16位的ADC_DRJ1寄存器中
─ JEOC(注入轉換結束)标志被設定 ─ 如果設定了JEOCIE位,則産生中斷。
然後ADC停止
連續轉換模式:
在連續轉換模式中,目前面ADC轉換一結束馬上就啟動另一次轉換。此模式可通過外部觸發啟動或通過設定ADC_CR2寄存器上的ADON位啟動,此時CONT位是1。
每個轉換後:
如果一個規則通道被轉換:
─ 轉換資料被儲存在16位的ADC_DR寄存器中
─ EOC(轉換結束)标志被設定
─ 如果設定了EOCIE,則産生中斷。
注入通道不能被用于連續轉換模式,唯一的例外是當規則通道配置為連續轉換後,注入通道配置為自動轉換。
掃描模式:
此模式用來掃描一組模拟通道。
掃描模式可通過設定ADC_CR1寄存器的SCAN位來選擇。一旦這個位被設定,ADC掃描所有被ADC_SQRX寄存器(對規則通道)或ADC_JSQR(對注入通道)選中的所有通道。在每個組的每個通道上執行單次轉換。在每個轉換結束時,同一組的下一個通道被自動轉換。如果設定了CONT位,轉換不會在選擇組的最後一個通道上停止,而是再次從選擇組的第一個通道繼續轉換。
如果設定了DMA位,在每次EOC後,DMA控制器把規則組通道的轉換資料傳輸到SRAM中。而注入通道轉換的資料總是存儲在ADC_JDRx寄存器中。
在以下情況中,ADC_SR寄存器的EOC位将被設定:
在每個規則組序列結束後,如果EOCS位被清0
在每個規則通道轉換結束,如果EOCS位設定為1
注入通道轉換結束資料總是存放在ADC_JDRx寄存器中
注入通道管理:
觸發注入
清除ADC_CR1寄存器的JAUTO位,并且設定SCAN位,即可使用觸發注入功能。
1. 利用外部觸發或通過設定ADC_CR2寄存器的ADON位,啟動一組規則通道的轉換。
2. 如果在規則通道轉換期間産生一外部注入觸發或者JSWSTART位被設定,目前轉換被複位,注入通道序列被以單次掃描方式進行轉換。
3. 然後,恢複上次被中斷的規則組通道轉換。如果在注入轉換期間産生一規則事件,注入轉換不會被中斷,但是規則序列将在注入序列結束後被執行。
注:當使用觸發的注入轉換時,必須保證觸發事件的間隔長于注入序列。例如:序列長度為30個ADC時鐘周期(即2個具有3個時鐘間隔采樣時間的轉換),觸發之間最小的間隔必須是31個ADC時鐘周期。
自動注入
如果設定了JAUTO位,在規則組通道之後,注入組通道被自動轉換。這可以用來轉換在ADC_SQRx和ADC_JSQR寄存器中設定的多至20個轉換序列。
在此模式裡,必須禁止注入通道的外部觸發。
如果除JAUTO位外還設定了CONT位,規則通道至注入通道的轉換序列被連續執行。
間斷模式:
規則組
此模式通過設定ADC_CR1寄存器上的DISCEN位激活。它可以用來執行一個短序列的n次轉換(n<=8),此轉換是ADC_SQRx寄存器所選擇的轉換序列的一部分。數值n由ADC_CR1寄存器的DISCNUM[2:0]位給出。
一個外部觸發信号可以啟動ADC_SQRx寄存器中描述的下一輪n次轉換,直到此序列所有的轉換完成為止。總的序列長度由ADC_SQR1寄存器的L[3:0]定義。
例如:
n=3,被轉換的通道 = 0、1、2、3、6、7、9、10
第一次觸發:轉換的序列為 0、1、2
第二次觸發:轉換的序列為 3、6、7
第三次觸發:轉換的序列為 9、10,并産生EOC事件
第四次觸發:轉換的序列 0、1、2
注: 當以間斷模式轉換一個規則組時,轉換序列結束後不自動從頭開始。 當所有子組被轉換完成,下一次觸發啟動第一個子組的轉換。在上面的例子中,第四次觸發重新轉換第一子組的通道0、1和2
注入組
此模式通過設定ADC_CR1寄存器的JDISCEN位激活。在一個外部觸發事件後,該模式按通道順序逐個轉換ADC_JSQR寄存器中選擇的序列。
一個外部觸發信号可以啟動ADC_JSQR寄存器選擇的下一個通道序列的轉換,直到序列中所有的轉換完成為止。總的序列長度由ADC_JSQR寄存器的JL[1:0]位定義。
例如: n=1,被轉換的通道 = 1、2、3
第一次觸發:通道1被轉換
第二次觸發:通道2被轉換
第三次觸發:通道3被轉換,并且産生EOC和JEOC事件
第四次觸發:通道1被轉換
設定步驟:
1. 配置相關輸入通道的IO口。
2. 設定DMA
3. 如果雙重ADC或三重采樣,設定ADC的公共寄存器
4. 配置要使用到的ADC
程式:
/************************************
标題:一個ADC連續采樣
軟體平台:IAR for ARM6.21
硬體平台:stm32f4-discovery
主頻:168M
author:小船
data:2012-02-14
*************************************/
#include <stm32f4xx.h>
#include "MyDebugger.h"
__IO uint16_t ADC3ConvertedVault[10000];
char TXbuffer[] = "PC1輸入電壓為:x.xxxV\n\r";
void ADC3_IN11_Config(void);
void main ()
{
SCB->AIRCR = 0x05FA0000 | 0x400; //中斷優先級分組 搶占:響應=3:1
ADC3_IN11_Config();
MyDebugger_Init();
while(1)
{
};
}
void ADC3_IN11_Config(void)
{
/***GPIO設定***/
RCC->AHB1ENR |= (1<<2); //打開GPIOC時鐘
GPIOC->MODER &= 0xfffffff3;//PC1模拟模式
GPIOC->MODER |= 0x0000000C;
GPIOC->PUPDR &= 0xfffffff3;//無上拉無下拉
/***DMA設定***/
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;//傳送前清空DMA1_Stream5所有中斷标志
DMA2_Stream0->PAR = (uint32_t)&ADC3->DR;//設定外設位址
DMA2_Stream0->M0AR = (uint32_t)ADC3ConvertedVault; //設定記憶體位址
DMA2_Stream0->CR |= 0x0002800;//16位資料
DMA2_Stream0->NDTR = 10000; //設定dma傳輸資料的數量
/*
設定dma2通道2,即ADC3
優先級Medium
傳輸方向外設到記憶體
記憶體遞增模式
循環模式
傳輸完成中斷
*/
DMA2_Stream0->CR |= ( 0x04000000 | 0x00010000 | 0x0
| (1<<10) | (1<<8) | (1<<4) );
NVIC->IP[56] = 0xB0;
NVIC->ISER[1] |= (1<<(56-32));
DMA2_Stream0->CR |= 1; //DMA2資料流0使能
/***ADC3設定***/
RCC->APB2ENR |= (1<<10); //使能ADC3時鐘
ADC3->SQR1 = 0x00000000;//轉換一個通道
ADC3->SQR3 = 0x0000000B;//第一個通道為ADC3_in11
ADC3->CR1 &= 0x00000000;
ADC3->CR2 &= 0x00000000;
ADC3->CR2 |= (1<<1); //連續轉換
ADC3->CR2 |= (1<<9); //最後一次ADC轉換後發出dma請求
ADC3->CR2 |= (1<<0); //開啟AD轉換
ADC3->CR2 |= (1<<8);//ADC dma發送模式使能
ADC3->CR2 |= (1<<30); //規則通道轉換開始
}
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 += ADC3ConvertedVault[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));
}
}
運作結果:
生容易,活容易,工程師的生活不容易啊,路過歡迎光臨淘寶店,隻賺人氣
http://shop107449878.taobao.com