?? main.c
字號:
// ICC-AVR application builder : 2007-3-15 8:22:58
// Target : M16
// Crystal: 7.3728Mhz
// AVR 模擬比較器使用范例
/*
AVR的模擬比較器模塊可以用來比較接在AIN0(mega16 PB2的第二功能)和AIN1(PB3)兩個引腳的電壓大小。
程序操作流程:初始化 >> 開中斷 >> 中斷服務程序判斷,比較結果將會同步到
模擬比較器控制和狀態寄存器-ACSR的第五位ACO,檢測ACO的值就可以得出比較結果。AIN0<AIN1(ACO=0);AIN0>AIN1(ACO=1)
*/
#include <iom16v.h>
#include <macros.h>
#include "delay.h"
//管腳定義
#define LED0 0 //PB0
#define AIN_P 2 //PB2(AIN0)
#define AIN_N 3 //PB3(AIN1)
//宏定義
#define LED0_ON() PORTB|= (1<<LED0) //輸出高電平,燈亮
#define LED0_OFF() PORTB&=~(1<<LED0) //輸出低電平,燈滅
//常量定義
/*
模擬比較器的正輸入端由 ACBG位決定,=0選擇AIN0引腳,=1選擇1.23V內部能隙基準源
模擬比較器多工輸入 (不常用,因為ADC將無法使用)
可以選擇ADC7..0 之中的任意一個來代替模擬比較器的負極輸入端。
ADC復用器可用來完成這個功能。
當然,為了使用這個功能首先必須關掉ADC。
如果模擬比較器復用器使 能位(SFIOR 中的ACME) 被置位,且ADC 也已經關掉(ADCSRA 寄存器的ADEN 為0),
則可以通過ADMUX 寄存器的MUX2..0 來選擇替代模擬比較器負極輸入的管腳,
如果ACME 清零或ADEN 置位,則模擬比較器的負極輸入為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
void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00;
PORTB = ~((1<<AIN_P)|(1<<AIN_N)); //作模擬比較器輸入時,不可使能內部上拉電阻。
DDRB = (1<<LED0); //PB0作輸出
PORTC = 0x00; //m103 output only
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x00;
}
//初始化的步驟,關中斷,更改ACSR的值,配置模擬比較器,開中斷。
//Comparator initialize
// trigger on: Output toggle
void comparator_init(void)
{
ACSR = ACSR & 0xF7; //ensure interrupt is off before changing
//上面一句會使ACIE為零,不允許中斷
ACSR=(1<<ACIE);
// 使能模擬比較器中斷,比較器輸出變化即可觸發中斷,AIN0為正輸入端,AIN1為負輸入端。
}
#pragma interrupt_handler ana_comp_isr:17
void ana_comp_isr(void)
{
//analog comparator compare event
//硬件自動清除ACI標志位
delay_us(10);
if ((ACSR&(1<<ACO))==0) //檢測ACO
//Bit 5 ACO: 模擬比較器輸出 模擬比較器的輸出經過同步后直接連到ACO。
LED0_ON(); //如果AIN0<AIN1(ACO=0),LED亮
else
LED0_OFF(); //否則 LED滅
delay_ms(200); //當電壓差接近0V時,模擬比較器會產生臨界抖動,故延時200mS令肉眼能看到
}
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
comparator_init();
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x00; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
void main(void)
{
init_devices();
while(1)
;
}
/*
程序測試:
VCC VCC
| |
| | | |
AIN0--|W| |W|--AIN1 PB0---R---LED--
| | | | |
| | |
GND GND GND
兩個電位器,一端接VCC,一端接地,構成電位器分壓電路
AIN0和AIN1都分別接到電位器的中心抽頭。
PBO輸出串電阻驅動LED,高電平有效。
然后分別旋轉電位器,增減抽頭的電壓,將會發現PB0的輸出(LED0)會根據 AIN0/AIN1的電壓關系變動
由于電源紋波,IO電流及外界干擾的影響,當電壓差接近0V時,模擬比較器會產生臨界抖動,AIN0/AIN1對地并上小電容可以改善這種情況。
只有一個電位器時,可以變通
1 可以使能ACBG,利用1.23V內部能隙基準源代替AIN0作模擬比較器的正輸入端。
ACSR=(1<<ACIE)|(1<<ACBG);
2 可以使能ADC的內部2.56V電壓基準,然后把AIN0或AIN1連接到pin32 AREF腳。
ADCSRA=(1<<ADEN); //需要打開ADC
ADMUX=(1<<REFS1)|(1<<REFS0);
*/
/*
模擬比較器控制和狀態寄存器-ACSR
Bit 7 – ACD: 模擬比較器禁用
模擬比較器上電默認是已經工作中的,跟其他的模塊有所不同
ACD置位時,模擬比較器的電源被切斷。可以在任何時候設置此位來關掉模擬比較器。
這可以減少器件工作模式及空閑模式下的功耗。
改變ACD位時,必須清零ACSR 寄存器的ACIE位來禁止模擬比較器中斷。否則ACD改變時可能會產生中斷
Bit 6 – ACBG: 選擇模擬比較器的能隙基準源
ACBG 置位后,模擬比較器的正極輸入由1.23V能隙基準源所取代。否則, AIN0 連接到模擬比較器的正極輸入。
Bit 5 – ACO: 模擬比較器輸出
模擬比較器的輸出經過同步后直接連到ACO。同步機制引入了1-2 個時鐘周期的延時。
Bit 4 – ACI: 模擬比較器中斷標志
當比較器的輸出事件觸發了由ACIS1 及ACIS0 定義的中斷模式時,ACI 置位。
如果ACIE 和SREG 寄存器的全局中斷標志I 也置位,那么模擬比較器中斷服務程序即得以執行,同時ACI 被硬件清零。
ACI 也可以通過寫"1” 來清零。
Bit 3 – ACIE: 模擬比較器中斷使能
當ACIE 位被置"1” 且狀態寄存器中的全局中斷標志I 也被置位時,模擬比較器中斷被激活。
否則中斷被禁止。
Bit2 – ACIC: 模擬比較器輸入捕捉使能
這個功能用于檢測一些微弱的觸發信號源,節省一個外部運放。
ACIC置位后允許通過模擬比較器來觸發T/C1 的輸入捕捉功能。
此時比較器的輸出被直接連接到輸入捕捉的前端邏輯,從而使得比較器可以利用T/C1 輸入捕捉中斷邏輯的噪聲抑制器及觸發沿選擇功能。
為了使比較器可以觸發T/C1 的輸入捕捉中斷,定時器中斷屏蔽寄存器TIMSK 的TICIE1 必須置位。
ACIC 為"0” 時模擬比較器及輸入捕捉功能之間沒有任何聯系。
Bits 1, 0 – ACIS1, ACIS0: 模擬比較器中斷模式選擇
這兩位確定觸發模擬比較器中斷的事件。
ACIS1 ACIS0 中斷模式
0 0 比較器輸出變化即可觸發中斷
0 1 保留
1 0 比較器輸出的下降沿產生中斷
1 1 比較器輸出的上升沿產生中斷
需要改變ACIS1/ACIS0 時,必須清零ACSR 寄存器的中斷使能位來禁止模擬比較器中斷。否則有可能在改變這兩位時產生中斷。
*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -