|
在學(xué)習(xí) GRBL 中,涉及到很多 AVR 中斷、串口等相關(guān)知識(shí)。參考資料 MAKE:AVR PROGRAMMING
如果單獨(dú)列出來(lái),會(huì)減輕 學(xué)習(xí) GRBL 的負(fù)擔(dān)。
*************************
AVR 中斷
*************************
使用中斷,而不是 polling (輪詢方式),
One problem with polling in event loops is that there’s no concept of priority.
Handling multiple jobs at once is where interrupts excel.
Interrupts do just what they sound like—they interrupt the normal flow of the program.
When an interrupt is triggered, all of the variables that you’re using are stashed in memory and then a special function, called an interrupt service routine (ISRs), is run.
There are two flavors of external interrupts: the fancy interrupts, INT0 and INT1, and the pin-change interrupts.
The INT0 interrupt mechanism has more versatile triggering possibilities, allowing you trigger the interrupt on a rising voltage, a falling voltage, any change, or continuously for a low-voltage level.
there are only two of
these type interrupts: INT0 and INT1, on pins PD2 and PD3.
The PCINT system, on the other hand, allows you to treat every I/O pin on the AVR as an interrupt source if you so desire, but only detects changes (not their direction.
The pin-change interrupts are grouped together in banks, so it’s more accurate to say that there’s a pin-change interrupt for the “B” pins, one for the “C” pins, and one for the “D” pins.
We use pinmask registers to select which of the pins from within the bank we want to trigger the interrupt.
ISRs are special routines that run when their interrupt flag is set, and their interrupt vector is called.
這里,vector 表示 8位 無(wú)符號(hào)數(shù),是地址。
Pin-Change Interrupt Example
ISR(PCINT2_vect){
....
}
void initPinChangeInterrupt18(void){
PCICR |= (1 << PCIE2); /* set pin-change interrupt for D pins */
PCMSK2 |= (1 << PCINT18); /* set mask to look for PCINT18 / PD2 */
// PCMSK2 |= (1 << PD2); /* this will also work for the pin mask */
sei(); /* set (global) interrupt enable bit */
}
we’ll need to tell the AVR which pins we’d like for it to watch specifically.
This is done through the pin mask, which is just a normal 8-bit byte where the corresponding bit is set for each pin we’d like to be able to trigger the interrupt.
So if we want to trigger on PD2 and PD4, we can set the pin mask one of two ways.
We can either use the pins’ PCINTxx aliases, or the normal PD2 type pin references.
For instance:
PCMSK2 |= ( (1 << PCINT18) | (1 << PCINT20) );
or
PCMSK2 |= ( (1 << PD2) | (1 << PD4) );
both do the same thing: configure the pin-change interrupt to trigger if either PD2 and PD4 changes state.
結(jié)論,3段式
****************************
AVR 定時(shí)
*****************************
http://www.torrancerestoration.com/bbs/dpj-47869-1.html
使用定時(shí)器必須弄清的幾個(gè)概念
在MCU中(M16),定時(shí)器是獨(dú)立的一個(gè)模塊,M16有三個(gè)獨(dú)立的定時(shí)器模塊,即T/C0、T/C1和T/C2;其中T/C0和T/C2都是8位的定時(shí)器,而T/C1是一個(gè)16位的定時(shí)器。定時(shí)器的工作是獨(dú)立于CPU之外自行運(yùn)行的硬件模塊。
1、定時(shí)器何時(shí)開(kāi)始工作(或說(shuō)計(jì)數(shù))的?
當(dāng)TCCR0!=0x00任何模式下,只要MCU一上電,T/C就開(kāi)始計(jì)時(shí)工作。其實(shí)TCCR0主要是定時(shí)器的預(yù)分頻和波形模式、比較匹配模式的設(shè)置,說(shuō)到預(yù)分頻,不得不提一下這個(gè)模塊,這個(gè)模塊是T/C0、T/C1共用的一個(gè)模塊,但可以有不同的分頻設(shè)置。
2、定時(shí)器是如何進(jìn)行工作的:說(shuō)到定時(shí)器的工作,不得不說(shuō)三個(gè)個(gè)重要參數(shù):TCNT0、OCR0,TIMSK,TCNT0是設(shè)置定時(shí)器的計(jì)時(shí)初始值,定時(shí)器開(kāi)始工作后立即從TCNT0一直累加到0XFF,累加過(guò)程所消耗的時(shí)間就是我們需要的定時(shí)時(shí)間;OCR0是一個(gè)比較設(shè)定值,當(dāng)TCNT0的值累計(jì)到OCR0時(shí)(TNCT0==OCR0),如果有開(kāi)啟比較匹配中斷功能,那么此時(shí)就會(huì)產(chǎn)生比較中斷,所以,OCR0的值一般都是設(shè)置在TCNT0初始值和0XFF之間,之外的任何值都不會(huì)產(chǎn)生比較中斷。TIMSK是一個(gè)中斷使能位設(shè)置,就是我們需要計(jì)時(shí)器溢出中斷或是比較匹配中斷功能或兩者都要時(shí)就對(duì)TIMSK的相應(yīng)寄存器位進(jìn)行設(shè)置。
3、定時(shí)器的中斷使用,一個(gè)定時(shí)器可以有兩個(gè)中斷資源可利用,一個(gè)只溢出中斷,另一個(gè)是比較匹配中斷,如上面2所說(shuō)的。想說(shuō)明的溢出中斷子程序內(nèi)一般要有重載TCNT0的初始值,否則,TCNT0就會(huì)從0X00開(kāi)始累加計(jì)數(shù)到0XFF,所耗費(fèi)的時(shí)間就不我們想要的時(shí)間。比較中斷就是當(dāng)TCNT0==OCR0時(shí),發(fā)生比較匹配中斷;所以,中斷子程序中一般只插入少量的處理代碼,否則,會(huì)發(fā)生所謂的中斷套嵌的現(xiàn)象,由于M16不支持中斷套嵌,這樣會(huì)使得中斷子程序中的部分代碼無(wú)法執(zhí)行,嚴(yán)重時(shí)會(huì)造成系統(tǒng)崩潰。
4、TCNT0和OCR0的值換算:對(duì)于8bit的計(jì)時(shí)器,TCNT0一般可以由下面的公式換算:
TCNT0=256-(TV*F)/N;
TV: 所想要設(shè)定的定時(shí)時(shí)間,單位,us
F: 晶振頻率(MHz)
N: 分頻因子
void init_timer1()
{
//TCCR1A T/C1控制寄存器A
// -----------------------------------------------------------------
// | COM1A1| COM1A0| COM1B1| COM1B0| COM1C1| COM1C0| WGM11 | WGM10 |
// -----------------------------------------------------------------
//TCCR1B T/C1控制寄存器B
// -----------------------------------------------------------------
// | ICNC1 | ICES1 | - | WGM13 | WGM12 |CS12 |CS11 |CS10 |
// -----------------------------------------------------------------
//TCCR1C T/C1控制寄存器C
// -----------------------------------------------------------------
// | FOC1A | FOC1B | FOC1C | - | - | - | - | - |
// -----------------------------------------------------------------
// COM1A1,COM1A0:通道A的比較輸出模式
// COM1B1,COM1B0:通道B的比較輸出模式
// COM1C1,COM1C0:通道C的比較輸出模式
// WGM13,WGM12,WGM11,WGM10:波型發(fā)生模式:
// 比較輸出模式(CTC模式),非PWM
// 00普通端口操作,OC1A/OC1B/OC1C未連接
// 01比較匹配時(shí)OC1A/OC1B/OC1C電平取反
// 10比較匹配時(shí)清零OC1A/OC1B/OC1C(輸出低電平)
// 11比較匹配時(shí)置位OC1A/OC1B/OC1C(輸出高電平)
// 比較輸出模式(CTC模式),快速PWM
// 00普通端口操作,OC1A/OC1B/OC1C未連接
// 01WGM13為0時(shí)同上,為1時(shí) 比較匹配時(shí) OC1A電平取反,OC1B/OC1C保留
// 10比較匹配時(shí)OC1A/OC1B/OC1C清零,在TOP時(shí)OC1A/OC1B/OC1C置位
// 11比較匹配時(shí)OC1A/OC1B/OC1C置位,在TOP時(shí)OC1A/OC1B/OC1C清零
// 比較輸出模式(CTC模式),相位修正及相頻修正PWM
// 00普通端口操作,OC1A/OC1B/OC1C未連接
// 01WGM13為0:同上,為1時(shí) 比較匹配時(shí) OC1A電平取反,OC1B/OC1C保留
// 10升序計(jì)數(shù)匹配時(shí)將OC1A/OC1B/OC1C清零,降序計(jì)數(shù)匹配時(shí)將OC1A/OC1B/OC1C置位
// 11升序計(jì)數(shù)匹配時(shí)將OC1A/OC1B/OC1C置位,降序計(jì)數(shù)匹配時(shí)將OC1A/OC1B/OC1C清零
//
// 模式 WGM1x 工作模式說(shuō)明 TOP OCR1x更新時(shí)刻TOVn置位時(shí)刻
// 0 0000 普通模式 0xFFFF 立即 MAX
// 1 0001 8位相位修正PWM0x00FF TOP BOTTOM
// 2 0010 9位相位修正PWM0x01FF TOP BOTTOM
// 3 001110位相位修正PWM0x03FF TOP BOTTOM
// 4 0100 CTC OCRnA 立即 MAX
// 5 0101 8位快速PWM0x00FF TOP TOP
// 6 0110 9位快速PWM0x01FF TOP TOP
// 7 0111 10位快速PWM0x03FF TOP TOP
// 8 1000相位頻率修正PWM ICRn BOTTOM BOTTOM
// 9 1001相位頻率修正PWM OCRnA BOTTOM BOTTOM
// 10 1010 相位修正PWM ICRn TOP BOTTOM
// 11 1011 相位修正PWM OCRnA TOP BOTTOM
// 12 1100 CTC ICRn 立即 MAX
// 13 1101 保留 - - -
// 14 1110 快速PWM ICRn TOP TOP
// 15 1111 快速PWM OCRnA TOP TOP
// ICNC1:使能/禁止輸入捕捉噪聲抑制器
// ICES1:輸入捕獲觸發(fā)沿選擇,0為下降沿觸發(fā),1為上升沿觸發(fā)
// CS12,CS11,CS10:T/C0時(shí)鐘預(yù)分頻選擇
// 000:無(wú)時(shí)鐘,T/C不工作 001:1/1
// 010:1/8 011:1/64 100:1/256
// 101:1/1024110:外部T1腳下降沿驅(qū)動(dòng) 111:外部T1腳上升沿驅(qū)動(dòng)
// FOC1A,F(xiàn)OC1B,F(xiàn)OC1C:強(qiáng)制輸出比較通道A,B,C
TCCR1A = TCCR1B = TCCR1C = 0;
//TCNT1H,TCNT1L 定時(shí)/計(jì)數(shù)器1
//OCR1AH,OCR1AL 輸出比較寄存器1A
//OCR1BH,OCR1BL 輸出比較寄存器1B
//OCR1CH,OCR1CL 輸出比較寄存器1C
//ICR1H,ICR1L 輸入捕捉寄存器1
}
有個(gè)注意事項(xiàng),
看過(guò)很多實(shí)例代碼,沒(méi)有遵循上面的 位運(yùn)算 ,都是 unreadable。
|
|