|
/*********************************************** **** AVR 模擬比較器使用范例 *** **** 編譯器:WINAVR20050214 *** ***********************************************/ /* 本程序簡(jiǎn)單的示范了如何使用ATMEGA16的模擬比較器 模擬比較器的設(shè)置 中斷方式--較常用 查詢(xún)方式不常用,檢測(cè)ACO即可,可用作DELTA-SIGMA A/D CONVERTER,校正后精度比較高,但速度低,用匯編可以略為提高速度。 出于簡(jiǎn)化程序考慮,各種數(shù)據(jù)沒(méi)有對(duì)外輸出,學(xué)習(xí)時(shí)建議使用JTAG ICE硬件仿真器 */ #i nclude #i nclude #i nclude #i nclude /* 宏INTERRUPT 的用法與SIGNAL 類(lèi)似,區(qū)別在于: SIGNAL 執(zhí)行時(shí)全局中斷觸發(fā)位被清除、其他中斷被禁止 INTERRUPT 執(zhí)行時(shí)全局中斷觸發(fā)位被置位、其他中斷可嵌套執(zhí) 另外avr-libc 提供兩個(gè)API 函數(shù)用于置位和清零全局中斷觸發(fā)位,它們是經(jīng)常用到的。 分別是:void sei(void) 和void cli(void) 由interrupt.h定義 注: 內(nèi)部函數(shù)_delay_ms() 最高延時(shí) 262.144mS@1MHz 該函數(shù)可以實(shí)現(xiàn)較精確的定時(shí),但用JTAG仿真時(shí)較麻煩---會(huì)進(jìn)入機(jī)器碼窗口(Disassembeler).注意跳開(kāi)該語(yǔ)段。 一旦JTAG仿真進(jìn)入該內(nèi)部函數(shù)語(yǔ)句,會(huì)變得像"死機(jī)"一樣(其實(shí)在運(yùn)行中),可以先[break],然后在后面的C語(yǔ)句設(shè)[breakpoint],[RUN]跳過(guò) for()/while()語(yǔ)句計(jì)算延時(shí)時(shí)間較麻煩。 為了使 _delay_ms()函數(shù)的延時(shí)正確,須在makefile中設(shè)定F_CPU為實(shí)際的系統(tǒng)時(shí)鐘頻 本范例為1MHz內(nèi)部RC振蕩器 即 F_CPU=1000000 */ //管腳定義 #define LED0 0 //PB0 #define AIN_P 2 //PB2(AIN0) #define AIN_N 3 //PB3(AIN1) //宏定義 #define LED0_ON() PORTB|= (1< //輸出高電平,燈亮 #define LED0_OFF() PORTB&=~(1< //輸出低電平,燈滅 //常量定義 /* 模擬比較器的正輸入端由 ACBG位決定,=0選擇AIN0引腳,=1選擇1.23V內(nèi)部能隙基準(zhǔn)源 模擬比較器多工輸入 (不常用,因?yàn)锳DC將無(wú)法使用) 可以選擇ADC7..0 之中的任意一個(gè)來(lái)代替模擬比較器的負(fù)極輸入端。 ADC復(fù)用器可用來(lái)完成這個(gè)功能。 當(dāng)然,為了使用這個(gè)功能首先必須關(guān)掉ADC。 如果模擬比較器復(fù)用器使 能位(SFIOR 中的ACME) 被置位,且ADC 也已經(jīng)關(guān)掉(ADCSRA 寄存器的ADEN 為0),則可以通過(guò)ADMUX 寄存器的MUX2..0 來(lái)選擇替代模擬比較器負(fù)極輸入的管腳,如果ACME 清零或ADEN 置位,則模擬比較器的負(fù)極輸入為AIN1。 */ #define AC_ADC0 0x00 //ADC0 #define AC_ADC1 0x01 //ADC1 #define AC_ADC2 0x02 //ADC2 #define AC_ADC3 0x03 //ADC3 #define AC_ADC4 0x04 //ADC4 #define AC_ADC5 0x05 //ADC5 #define AC_ADC6 0x06 //ADC6 #define AC_ADC7 0x07 //ADC7 SIGNAL(SIG_COMPARATOR) //模擬比較器中斷服務(wù)程序 { //硬件自動(dòng)清除ACI標(biāo)志位 _delay_us(10); if ((ACSR&(1< //檢測(cè)ACO LED0_ON(); //如果AIN0亮 else LED0_OFF(); //否則 LED滅 _delay_ms(200); //當(dāng)電壓差接近0V時(shí),模擬比較器會(huì)產(chǎn)生臨界抖動(dòng),故延時(shí)200mS令肉眼能看到 } int main(void) { //上電默認(rèn)DDRx=0x00,PORTx=0x00 輸入,無(wú)上拉電阻 PORTA=0xFF; PORTC=0xFF; //不用的管腳使能內(nèi)部上拉電阻。 PORTD=0xFF; PORTB=~((1< //作模擬比較器輸入時(shí),不可使能內(nèi)部上拉電阻。 DDRB= (1< //PB0作輸出 /* 模擬比較器控制和狀態(tài)寄存器-ACSR Bit 7 – ACD: 模擬比較器禁用 模擬比較器上電默認(rèn)是已經(jīng)工作中的,跟其他的模塊有所不同 ACD置位時(shí),模擬比較器的電源被切斷。可以在任何時(shí)候設(shè)置此位來(lái)關(guān)掉模擬比較器。 這可以減少器件工作模式及空閑模式下的功耗。 改變ACD位時(shí),必須清零ACSR 寄存器的ACIE位來(lái)禁止模擬比較器中斷。否則ACD改變時(shí)可能會(huì)產(chǎn)生中斷 Bit 6 – ACBG: 選擇模擬比較器的能隙基準(zhǔn)源 ACBG 置位后,模擬比較器的正極輸入由1.23V能隙基準(zhǔn)源所取代。否則, AIN0 連接到模擬比較器的正極輸入。 Bit 5 – ACO: 模擬比較器輸出 模擬比較器的輸出經(jīng)過(guò)同步后直接連到ACO。同步機(jī)制引入了1-2 個(gè)時(shí)鐘周期的延時(shí)。 Bit 4 – ACI: 模擬比較器中斷標(biāo)志 當(dāng)比較器的輸出事件觸發(fā)了由ACIS1 及ACIS0 定義的中斷模式時(shí),ACI 置位。 如果ACIE 和SREG 寄存器的全局中斷標(biāo)志I 也置位,那么模擬比較器中斷服務(wù)程序即得以執(zhí)行,同時(shí)ACI 被硬件清零。 ACI 也可以通過(guò)寫(xiě)"1” 來(lái)清零。 Bit 3 – ACIE: 模擬比較器中斷使能 當(dāng)ACIE 位被置"1” 且狀態(tài)寄存器中的全局中斷標(biāo)志I 也被置位時(shí),模擬比較器中斷被激活。 否則中斷被禁止。 Bit2 – ACIC: 模擬比較器輸入捕捉使能 這個(gè)功能用于檢測(cè)一些微弱的觸發(fā)信號(hào)源,節(jié)省一個(gè)外部運(yùn)放。 ACIC置位后允許通過(guò)模擬比較器來(lái)觸發(fā)T/C1 的輸入捕捉功能。 此時(shí)比較器的輸出被直接連接到輸入捕捉的前端邏輯,從而使得比較器可以利用T/C1 輸入捕捉中斷邏輯的噪聲抑制器及觸發(fā)沿選擇功能。 為了使比較器可以觸發(fā)T/C1 的輸入捕捉中斷,定時(shí)器中斷屏蔽寄存器TIMSK 的TICIE1 必須置位。 ACIC 為"0” 時(shí)模擬比較器及輸入捕捉功能之間沒(méi)有任何聯(lián)系。 Bits 1, 0 – ACIS1, ACIS0: 模擬比較器中斷模式選擇 這兩位確定觸發(fā)模擬比較器中斷的事件。 ACIS1 ACIS0 中斷模式 0 0 比較器輸出變化即可觸發(fā)中斷 0 1 保留 1 0 比較器輸出的下降沿產(chǎn)生中斷 1 1 比較器輸出的上升沿產(chǎn)生中斷 需要改變ACIS1/ACIS0 時(shí),必須清零ACSR 寄存器的中斷使能位來(lái)禁止模擬比較器中斷。否則有可能在改變這兩位時(shí)產(chǎn)生中斷。 */ ACSR=(1< // 使能模擬比較器中斷,比較器輸出變化即可觸發(fā)中斷,AIN0為正輸入端,AIN1為負(fù)輸入端。 sei(); //使能全局中斷 while (1); //主程序沒(méi)有任務(wù)。任何情況都必須是一個(gè)無(wú)限循環(huán)。 } /* 程序測(cè)試: 兩個(gè)電位器,一端接VCC,一端接地,構(gòu)成電位器分壓電路。 AIN0和AIN1都分別接到電位器的中心抽頭。 PBO輸出串電阻驅(qū)動(dòng)LED,高電平有效。 然后分別旋轉(zhuǎn)電位器,增減抽頭的電壓,將會(huì)發(fā)現(xiàn)PB0的輸出(LED0)會(huì)根據(jù) AIN0/AIN1的電壓關(guān)系變動(dòng)。 由于電源紋波,IO電流及外界干擾的影響,當(dāng)電壓差接近0V時(shí),模擬比較器會(huì)產(chǎn)生臨界抖動(dòng),AIN0/AIN1對(duì)地并上小電容可以改善這種情況。 在使用AVR51實(shí)驗(yàn)板時(shí),由于只有一個(gè)電位器,需要變通: 1、可以使能ACBG,利用1.23V內(nèi)部能隙基準(zhǔn)源代替AIN0作模擬比較器的正輸入端。 ACSR=(1< 2、可以使能ADC的內(nèi)部2.56V電壓基準(zhǔn),然后把AIN0或AIN1連接到pin32 AREF腳。 ADCSRA=(1< //需要打開(kāi)ADC ADMUX=(1< */ |