新聞中心

LPC1343內(nèi)部ADC的使用

作者: 時(shí)間:2016-11-23 來(lái)源:網(wǎng)絡(luò) 收藏
本節(jié)來(lái)講述LPC1343內(nèi)部ADC的使用。設(shè)計(jì)一個(gè)實(shí)驗(yàn),使用ADC的0通道進(jìn)行AD轉(zhuǎn)換,并且將轉(zhuǎn)換結(jié)果通過(guò)UART發(fā)送在PC端的串口終端軟件觀察。

本文引用地址:http://m.butianyuan.cn/article/201611/320275.htm

這次仍然以NXP提供的example作為例子,但是C工作方式眾多,所以該example用了許多的預(yù)編譯結(jié)構(gòu),筆者在此將本次實(shí)驗(yàn)不會(huì)用到的語(yǔ)句全部去掉,程序變得簡(jiǎn)潔,也更易于理解。

同樣的,在此節(jié)中將不再將所用到的寄存器一一列出,而只是一個(gè)各個(gè)寄存器設(shè)置的“線索”,因?yàn)橹链烁鱾€(gè)讀者一定已經(jīng)擁有了自己翻閱用戶手冊(cè)查看對(duì)應(yīng)寄存器內(nèi)容的能力。

從主函數(shù)我們可以看出本次實(shí)驗(yàn)的進(jìn)展過(guò)程:

int main (void)

{

uint32_t i,j;

UARTInit(115200);//初始化UART

ADCInit( ADC_CLK );//初始化ADC

while(1)

{

ADCRead( 0 );//讀取0通道轉(zhuǎn)換值

while ( !ADCIntDone );//等待讀取完成

ADCIntDone = 0;//清除讀取完成標(biāo)志

UARTBuffer[0]=(uint8_t)(*ADCValue>>8);//分離高2位數(shù)據(jù)

UARTBuffer[1]=(uint8_t)(*ADCValue);//分離低8位數(shù)據(jù)

UARTSend((uint8_t *)UARTBuffer, 2);//向UART發(fā)送數(shù)據(jù)

for(i=0;i<5000;i++)//延時(shí)

for(j=0;j<1000;j++);

}

}

大家應(yīng)該在幾個(gè)8位單片機(jī)上都設(shè)計(jì)過(guò)這種ADC轉(zhuǎn)換程序,相信大家也肯定經(jīng)歷過(guò)這個(gè)基礎(chǔ)的過(guò)程。

UART的初始化在上一節(jié)已經(jīng)詳述了,我們直接來(lái)看看ADC的初始化ADCInit():

void ADCInit( uint32_t ADC_Clk )

{

LPC_SYSCON->;PDRUNCFG &= ~(0x1<<4);//打開(kāi)ADC供電

LPC_SYSCON->SYSAHBCLKCTRL |= (1<<13);//開(kāi)啟ADC的AHB通道

LPC_IOCON->JTAG_TDI_PIO0_11 = 0x02;//選擇ADC0引腳功能

LPC_ADC->CR = ((SystemCoreClock/LPC_SYSCON->SYSAHBCLKDIV)/ADC_Clk-1)<<8;

#if ADC_INTERRUPT_FLAG//使用ADC中斷功能

NVIC_EnableIRQ(ADC_IRQn);

LPC_ADC->INTEN = 0x1FF;

#endif

return;

}

1、該函數(shù)唯一的參數(shù)填入欲設(shè)置的ADC工作速率,單位是Hz,本次實(shí)驗(yàn)填入4500000,即4.5MHz;

2、ADC初始化不同于前面其他設(shè)備的一個(gè)地方,在于它的電源是默認(rèn)關(guān)閉的,所以首先要打開(kāi)它的電源,明顯是一個(gè)降低功耗的措施;

3、ADC的工作速率,從用戶手冊(cè)可以查看到如下描述:

The APB clock (PCLK) is divided by CLKDIV +1 to produce the clock for the ADC, which should be less than or equal to 4.5 MHz.由此我們知道該ADC的最大驅(qū)動(dòng)時(shí)鐘頻率是4.5MHz。同時(shí)分頻數(shù)是CLKDIV +1,所以程序中要“ADC_Clk-1”,至于為什么要左移8位呢?那是因?yàn)樵O(shè)置的分頻數(shù)是存放于ADCCR(ADC控制寄存器)中的第8:15位。

4、如果使用中斷功能,則除了要設(shè)置NVIC控制器之外,還需要在ADCINTEN中打開(kāi)各個(gè)通道的中斷功能,當(dāng)某通道轉(zhuǎn)換完成時(shí),會(huì)觸發(fā)對(duì)于中斷。

初始化完畢之后,就可以開(kāi)啟ADC進(jìn)行轉(zhuǎn)換了。首先是ADCRead():

uint32_t ADCRead( uint8_t channelNum )

{

if ( channelNum >= ADC_NUM )//判斷通道號(hào)是否過(guò)大

{

channelNum = 0;//復(fù)位通道號(hào)

}

LPC_ADC->CR &= 0xFFFFFF00; //清除所有轉(zhuǎn)換通道的上一次選擇狀態(tài)

LPC_ADC->CR |= (1 << 24) | (1 << channelNum);//選擇通道,并開(kāi)啟轉(zhuǎn)換

return ( channelNum );//返回通道號(hào)

}

1、本函數(shù)要求填入的唯一參數(shù)是所希望進(jìn)行ADC的通道號(hào);

2、轉(zhuǎn)換前應(yīng)該清除上一次通道被選狀態(tài);

3、在CR控制器中的26:24位控制著ADC的多種轉(zhuǎn)換啟動(dòng)方式,本實(shí)驗(yàn)中使用最普通的一種:立即開(kāi)始轉(zhuǎn)換。

4、因?yàn)楸緦?shí)驗(yàn)使用了ADC的中斷功能,轉(zhuǎn)換結(jié)果在ADC中斷中存儲(chǔ),所以此函數(shù)在使用ADC中斷功能的情況下返回的是轉(zhuǎn)換的通道號(hào)。

ADC中斷功能的情況下返回的是轉(zhuǎn)換的通道號(hào)。

所以當(dāng)本函數(shù)運(yùn)行結(jié)束之后,ADC轉(zhuǎn)換開(kāi)始,等待進(jìn)入中斷服務(wù)函數(shù):

void ADC_IRQHandler (void)

{

uint32_t regVal;

LPC_ADC->CR &= 0xF8FFFFFF;

regVal = LPC_ADC->STAT;

if ( regVal & 0x0000FF00 )

{

regVal = (regVal & 0x0000FF00) >> 0x08;//如果有,確認(rèn)通道

switch ( regVal )//通過(guò)讀取轉(zhuǎn)換值來(lái)清除ADC數(shù)據(jù),注意這部分是錯(cuò)誤數(shù)據(jù),是丟棄的

{

case 0x01:regVal = LPC_ADC->DR0;break;

case 0x02:regVal = LPC_ADC->DR1;break;

case 0x04:regVal = LPC_ADC->DR2;break;

case 0x08:regVal = LPC_ADC->DR3;break;

case 0x10:regVal = LPC_ADC->DR4;break;

case 0x20:regVal = LPC_ADC->DR5;break;

case 0x40:regVal = LPC_ADC->DR6;break;

case 0x80:regVal = LPC_ADC->DR7;break;

default:break;

}

LPC_ADC->CR &= 0xF8FFFFFF;

ADCIntDone = 1;

return;

}

if ( regVal & ADC_ADINT )//判斷是否有任何一個(gè)通道轉(zhuǎn)換結(jié)束

{

switch ( regVal & 0xFF )

{

case 0x01:ADCValue[0] = ( LPC_ADC->DR0 >> 6 ) & 0x3FF;break;

case 0x02:ADCValue[1] = ( LPC_ADC->DR1 >> 6 ) & 0x3FF;break;

case 0x04:ADCValue[2] = ( LPC_ADC->DR2 >> 6 ) & 0x3FF;break;

case 0x08:ADCValue[3] = ( LPC_ADC->DR3 >> 6 ) & 0x3FF;break;

case 0x10:ADCValue[4] = ( LPC_ADC->DR4 >> 6 ) & 0x3FF;break;

case 0x20:ADCValue[5] = ( LPC_ADC->DR5 >> 6 ) & 0x3FF;break;

case 0x40:ADCValue[6] = ( LPC_ADC->DR6 >> 6 ) & 0x3FF;break;

case 0x80:ADCValue[7] = ( LPC_ADC->DR7 >> 6 ) & 0x3FF;break;

default:break;

}

ADCIntDone = 1;//讀取結(jié)束標(biāo)志

}

return;

}

1、進(jìn)入中斷服務(wù)程序之后,首先停止AD轉(zhuǎn)換;

2、和UART一樣,ADC中斷標(biāo)志也是通過(guò)讀取來(lái)清除的;

3、首先要檢查溢出錯(cuò)誤,如果有,則數(shù)據(jù)無(wú)效,要通道讀取來(lái)清除ADC轉(zhuǎn)換數(shù)據(jù)寄存器(ADCDR);

4、ADC中斷有兩種,一種是任何一個(gè)通道完成轉(zhuǎn)換都會(huì)觸發(fā),一種是某個(gè)中斷完成轉(zhuǎn)換就會(huì)觸發(fā),本實(shí)驗(yàn)中兩種中斷都打開(kāi)了,因此先判斷是否有轉(zhuǎn)換完成,再判斷是哪個(gè)通道完成轉(zhuǎn)換;

中斷函數(shù)的結(jié)束意味著讀取完成,剩下的就是將讀出數(shù)據(jù)發(fā)送到UART去顯示了。但在這之前,因?yàn)長(zhǎng)PC1343的ADC默認(rèn)情況下是10位精度,而我們的UART是以字符為數(shù)據(jù)長(zhǎng)度發(fā)送的,所以筆者特意將轉(zhuǎn)換結(jié)果轉(zhuǎn)換成了16位長(zhǎng)度,分兩次發(fā)送?,F(xiàn)將本次實(shí)驗(yàn)運(yùn)行過(guò)程概況如下:

UART初始化——ADC初始化——開(kāi)始轉(zhuǎn)換——轉(zhuǎn)換結(jié)束觸發(fā)中斷——判斷有無(wú)錯(cuò)誤——有錯(cuò)誤則放棄無(wú)效數(shù)據(jù),無(wú)錯(cuò)誤則讀出有效數(shù)據(jù)——數(shù)據(jù)處理——發(fā)至UART

附上運(yùn)行結(jié)果jpg兩張,第一張,0通道引腳接在GND:

第二張,0通道接在VCC 3.3:

理論上3.3V為滿賦值,轉(zhuǎn)換結(jié)果應(yīng)該是是11 1111 1111=0x3ff,不過(guò)實(shí)際并非如此,說(shuō)明其實(shí)我們板子上引出的電源還是有一定波動(dòng)的。



關(guān)鍵詞: LPC1343內(nèi)部AD

評(píng)論


技術(shù)專區(qū)

關(guān)閉