Atmega16 單片機(jī)串口通信與外部中斷介紹
ATmega16單片機(jī)帶有一個(gè)全雙工的通用同步/異步串行收發(fā)模塊USART,該接口是一個(gè)高度靈活的串行通訊設(shè)備。其主要特點(diǎn)如下:
本文引用地址:http://m.butianyuan.cn/article/201611/317328.htm全雙工操作,可同時(shí)進(jìn)行收發(fā)操作;
支持同步或異步操作;
支持5、6、7、8和9位數(shù)據(jù)位,1位或者2位停止位的串行數(shù)據(jù)幀結(jié)構(gòu);
三個(gè)完全獨(dú)立的中斷,TX發(fā)送完成,TX發(fā)送數(shù)據(jù)寄存器空,RX接收完成;
支持多機(jī)通訊模式;
相關(guān)寄存器:
USART數(shù)據(jù)寄存器—UDR;
USART控制和狀態(tài)寄存器—UCSRA,UCSRB,UCSRC;
波特率寄存器—UBRRL和UBRRH;
串口背景知識(shí)
(1)串行通訊簡(jiǎn)介
串行同步通訊容易理解,約定一個(gè)同步時(shí)鐘,每一時(shí)刻傳輸線上的信息就是要傳送的信息單元。串行異步通訊是把一個(gè)字符看作一個(gè)獨(dú)立的信息單元,每一個(gè)字符中的各位是以固定的時(shí)間傳送。因此,這種傳送方式在同一字節(jié)內(nèi)部是同步的,而字符間是異步的。在異步通信中收發(fā)雙方取得同步的方法是采用在字符格式中設(shè)置起始位,而在字符結(jié)束時(shí)發(fā)送1~2個(gè)停止位。當(dāng)接收器檢測(cè)到起始位時(shí),便能知道經(jīng)接著的是有效的字符位,于是開(kāi)始接收字符,檢測(cè)到停止位時(shí),就將接收到的有效字符裝載到接收緩沖器中。最簡(jiǎn)單的串口通信使用3根線完成:(1)地線,(2)發(fā)送,(3)接收。由于串口通信是異步的,端口能夠在一根線上發(fā)送數(shù)據(jù)同時(shí)在另一根線上接收數(shù)據(jù)。其他線用于握手,但是不是必須的。串口通信最重要的參數(shù)是波特率、數(shù)據(jù)位、停止位和奇偶校驗(yàn)。對(duì)于兩個(gè)進(jìn)行通行的端口,這些參數(shù)必須匹配:
a,波特率:這是一個(gè)衡量通信速度的參數(shù)。它表示每秒鐘傳送的bit的個(gè)數(shù)。例如300波特表示每秒鐘發(fā)送300個(gè)bit。當(dāng)我們提到時(shí)鐘周期時(shí),我們就是指波特率例如如果協(xié)議需要4800波特率,那么時(shí)鐘是4800Hz。這意味著串口通信在數(shù)據(jù)線上的采樣率為4800Hz。通常電話線的波特率為14400,28800和36600。波特率可以遠(yuǎn)遠(yuǎn)大于這些值,但是波特率和距離成反比。高波特率常常用于放置的很近的儀器間的通信,典型的例子就是GPIB設(shè)備的通信。
b,數(shù)據(jù)位:這是衡量通信中實(shí)際數(shù)據(jù)位的參數(shù)。當(dāng)計(jì)算機(jī)發(fā)送一個(gè)信息包,實(shí)際的數(shù)據(jù)不會(huì)是8位的,標(biāo)準(zhǔn)的值是5、7和8位。如何設(shè)置取決于你想傳送的信息。比如,標(biāo)準(zhǔn)的ASCII碼是0~127(7位)。擴(kuò)展的ASCII碼是0~255(8位)。如果數(shù)據(jù)使用簡(jiǎn)單的文本(標(biāo)準(zhǔn)ASCII碼),那么每個(gè)數(shù)據(jù)包使用7位數(shù)據(jù)。每個(gè)包是指一個(gè)字節(jié),包括開(kāi)始/停止位,數(shù)據(jù)位和奇偶校驗(yàn)位。由于實(shí)際數(shù)據(jù)位取決于通信協(xié)議的選取,術(shù)語(yǔ)“包”指任何通信的情況。
c,停止位:用于表示單個(gè)包的最后一位。典型的值為1,1.5和2位。由于數(shù)據(jù)是在傳輸線上定時(shí)的,并且每一個(gè)設(shè)備有其自己的時(shí)鐘,很可能在通信中兩臺(tái)設(shè)備間出現(xiàn)了小小的不同步。因此停止位不僅僅是表示傳輸?shù)慕Y(jié)束,并且提供計(jì)算機(jī)校正時(shí)鐘同步的機(jī)會(huì)。適用于停止位的位數(shù)越多,不同時(shí)鐘同步的容忍程度越大,但是數(shù)據(jù)傳輸率同時(shí)也越慢。
d,奇偶校驗(yàn)位:在串口通信中一種簡(jiǎn)單的檢錯(cuò)方式。有四種檢錯(cuò)方式:偶、奇、高和低。當(dāng)然沒(méi)有校驗(yàn)位也是可以的。對(duì)于偶和奇校驗(yàn)的情況,串口會(huì)設(shè)置校驗(yàn)位(數(shù)據(jù)位后面的一位),用一個(gè)值確保傳輸?shù)臄?shù)據(jù)有偶個(gè)或者奇?zhèn)€邏輯高位。例如,如果數(shù)據(jù)是011,那么對(duì)于偶校驗(yàn),校驗(yàn)位為0,保證邏輯高的位數(shù)是偶數(shù)個(gè)。如果是奇校驗(yàn),校驗(yàn)位位1,這樣就有3個(gè)邏輯高位。高位和低位不真正的檢查數(shù)據(jù),簡(jiǎn)單置位邏輯高或者邏輯低校驗(yàn)。這樣使得接收設(shè)備能夠知道一個(gè)位的狀態(tài),有機(jī)會(huì)判斷是否有噪聲干擾了通信或者是否傳輸和接收數(shù)據(jù)是否不同步
通常異步通信的格式如圖:
USART接受以下30種組合的數(shù)據(jù)幀格式:
&8226; 1個(gè)起始位
&8226; 5、6、7、8或9個(gè)數(shù)據(jù)位
&8226;無(wú)校驗(yàn)位、奇校驗(yàn)或偶校驗(yàn)位
&8226; 1或2個(gè)停止位
數(shù)據(jù)幀以起始位開(kāi)始;緊接著是數(shù)據(jù)字的最低位,數(shù)據(jù)字最多可以有9個(gè)數(shù)據(jù)位,以數(shù)據(jù)的最高位結(jié)束。如果使能了校驗(yàn)位,校驗(yàn)位將緊接著數(shù)據(jù)位,最后是結(jié)束位。當(dāng)一個(gè)完整的數(shù)據(jù)幀傳輸后,可以立即傳輸下一個(gè)新的數(shù)據(jù)幀,或使傳輸線處于空閑狀態(tài)。
數(shù)據(jù)幀的結(jié)構(gòu)由UCSRB和UCSRC寄存器中的UCSZ2:0、UPM1:0、USBS設(shè)定。接收與發(fā)送使用相同的設(shè)置。設(shè)置的任何改變都可能破壞正在進(jìn)行的數(shù)據(jù)傳送與接收。
(2)串口的組成
串口由陰陽(yáng)兩種接口組成。最常使用的信號(hào)引腳是TD、RD和SG,因此最簡(jiǎn)單的串口調(diào)試只需要包含3條引線就可以了。在RS232(一種串行工業(yè)總線標(biāo)準(zhǔn))標(biāo)準(zhǔn)中,利用RD、TD作為接收、發(fā)送信號(hào)線,加入地線,約定好通訊的波特率,實(shí)現(xiàn)串行信號(hào)傳輸。
(3)串口電平轉(zhuǎn)換電路
PC的串口工作TTL信號(hào)是12V的,而在我們一般使用的電路板上,電源信號(hào)和TTL電平是5V的(在低功耗電路中是3.3V的),為了將信號(hào)轉(zhuǎn)化為可用,需要做串口的電平轉(zhuǎn)換。這一部分電路已經(jīng)有相應(yīng)的生產(chǎn)廠商做出了各種集成芯片,例如MAXIM公司的MAX232/MAX233芯片,就是實(shí)現(xiàn)5V電路中和PC實(shí)現(xiàn)串口通信的電平轉(zhuǎn)換芯片,而MAX3232/MAX3233可以實(shí)現(xiàn)3.3V的電平轉(zhuǎn)換。
串口寄存器介紹
USART I/O數(shù)據(jù)寄存器-UDR
USART發(fā)送數(shù)據(jù)緩沖寄存器和USART接收數(shù)據(jù)緩沖寄存器共享相同的I/O地址,稱(chēng)為USART數(shù)據(jù)寄存器或UDR。將數(shù)據(jù)寫(xiě)入U(xiǎn)DR時(shí)實(shí)際操作的是發(fā)送數(shù)據(jù)緩沖器存器(TXB),讀UDR時(shí)實(shí)際返回的是接收數(shù)據(jù)緩沖寄存器(RXB)的內(nèi)容。在5、6、7比特字長(zhǎng)模式下,未使用的高位被發(fā)送器忽略,而接收器則將它們?cè)O(shè)置為0。只有當(dāng)UCSRA寄存器的UDRE標(biāo)志置位后才可以對(duì)發(fā)送緩沖器進(jìn)行寫(xiě)操作。如果UDRE沒(méi)有置位,那么寫(xiě)入U(xiǎn)DR的數(shù)據(jù)會(huì)被USART發(fā)送器忽略。當(dāng)數(shù)據(jù)寫(xiě)入發(fā)送緩沖器后,若移位寄存器為空,發(fā)送器將把數(shù)據(jù)加載到發(fā)送移位寄存器。然后數(shù)據(jù)串行地從TxD引腳輸出。接收緩沖器包括一個(gè)兩級(jí)FIFO,一旦接收緩沖器被尋址FIFO就會(huì)改變它的狀態(tài)。因此不要對(duì)這一存儲(chǔ)單元使用讀-修改-寫(xiě)指令(SBI和CBI)。使用位查詢(xún)指令(SBIC和SBIS)時(shí)也要小心,因?yàn)檫@也有可能改變FIFO的狀態(tài)。
USART控制和狀態(tài)寄存器A-UCSRA
&8226; Bit 7 – RXC: USART接收結(jié)束
接收緩沖器中有未讀出的數(shù)據(jù)時(shí)RXC置位,否則清零。接收器禁止時(shí),接收緩沖器被刷新,導(dǎo)致RXC清零。RXC標(biāo)志可用來(lái)產(chǎn)生接收結(jié)束中斷(見(jiàn)對(duì)RXCIE位的描述)。
&8226; Bit 6 – TXC: USART發(fā)送結(jié)束
發(fā)送移位緩沖器中的數(shù)據(jù)被送出,且當(dāng)發(fā)送緩沖器(UDR)為空時(shí)TXC置位。執(zhí)行發(fā)送結(jié)束中斷時(shí)TXC標(biāo)志自動(dòng)清零,也可以通過(guò)寫(xiě)1進(jìn)行清除操作。TXC標(biāo)志可用來(lái)產(chǎn)生發(fā)送結(jié)束中斷(見(jiàn)對(duì)TXCIE位的描述)。
&8226; Bit 5 – UDRE: USART數(shù)據(jù)寄存器空
UDRE標(biāo)志指出發(fā)送緩沖器(UDR)是否準(zhǔn)備好接收新數(shù)據(jù)。UDRE為1說(shuō)明緩沖器為空,已準(zhǔn)備好進(jìn)行數(shù)據(jù)接收。UDRE標(biāo)志可用來(lái)產(chǎn)生數(shù)據(jù)寄存器空中斷(見(jiàn)對(duì)UDRIE位的描述)。復(fù)位后UDRE置位,表明發(fā)送器已經(jīng)就緒。
&8226; Bit 4 – FE:幀錯(cuò)誤
如果接收緩沖器接收到的下一個(gè)字符有幀錯(cuò)誤,即接收緩沖器中的下一個(gè)字符的第一個(gè)停止位為0,那么FE置位。這一位一直有效直到接收緩沖器(UDR)被讀取。當(dāng)接收到的停止位為1時(shí),F(xiàn)E標(biāo)志為0。對(duì)UCSRA進(jìn)行寫(xiě)入時(shí),這一位要寫(xiě)0。
&8226; Bit 3 – DOR:數(shù)據(jù)溢出
數(shù)據(jù)溢出時(shí)DOR置位。當(dāng)接收緩沖器滿(mǎn)(包含了兩個(gè)數(shù)據(jù)),接收移位寄存器又有數(shù)據(jù),若此時(shí)檢測(cè)到一個(gè)新的起始位,數(shù)據(jù)溢出就產(chǎn)生了。這一位一直有效直到接收緩沖器(UDR)被讀取。對(duì)UCSRA進(jìn)行寫(xiě)入時(shí),這一位要寫(xiě)0。
&8226; Bit 2 – PE:奇偶校驗(yàn)錯(cuò)誤
當(dāng)奇偶校驗(yàn)使能(UPM1 = 1),且接收緩沖器中所接收到的下一個(gè)字符有奇偶校驗(yàn)錯(cuò)誤時(shí)UPE置位。這一位一直有效直到接收緩沖器(UDR)被讀取。對(duì)UCSRA進(jìn)行寫(xiě)入時(shí),這一位要寫(xiě)0。
&8226; Bit 1 – U2X:倍速發(fā)送
這一位僅對(duì)異步操作有影響。使用同步操作時(shí)將此位清零。此位置1可將波特率分頻因子從16降到8,從而有效的將異步通信模式的傳輸速率加倍。
&8226; Bit 0 – MPCM:多處理器通信模式
設(shè)置此位將啟動(dòng)多處理器通信模式。MPCM置位后,USART接收器接收到的那些不包含地址信息的輸入幀都將被忽略。發(fā)送器不受MPCM設(shè)置的影響。詳細(xì)信息請(qǐng)參考P150“多處理器通訊模式”。
USART控制和狀態(tài)寄存器B-UCSRB
&8226; Bit 7 – RXCIE:接收結(jié)束中斷使能
置位后使能RXC中斷。當(dāng)RXCIE為1,全局中斷標(biāo)志位SREG置位,UCSRA寄存器的RXC亦為1時(shí)可以產(chǎn)生USART接收結(jié)束中斷。
&8226; Bit 6 – TXCIE:發(fā)送結(jié)束中斷使能
置位后使能TXC中斷。當(dāng)TXCIE為1,全局中斷標(biāo)志位SREG置位,UCSRA寄存器的TXC亦為1時(shí)可以產(chǎn)生USART發(fā)送結(jié)束中斷。
&8226; Bit 5 – UDRIE: USART數(shù)據(jù)寄存器空中斷使能
置位后使能UDRE中斷。當(dāng)UDRIE為1,全局中斷標(biāo)志位SREG置位,UCSRA寄存器的UDRE亦為1時(shí)可以產(chǎn)生USART數(shù)據(jù)寄存器空中斷。
&8226; Bit 4 – RXEN:接收使能
置位后將啟動(dòng)USART接收器。RxD引腳的通用端口功能被USART功能所取代。禁止接收器將刷新接收緩沖器,并使FE、DOR及PE標(biāo)志無(wú)效。
&8226; Bit 3 – TXEN:發(fā)送使能
置位后將啟動(dòng)將啟動(dòng)USART發(fā)送器。TxD引腳的通用端口功能被USART功能所取代。TXEN清零后,只有等到所有的數(shù)據(jù)發(fā)送完成后發(fā)送器才能夠真正禁止,即發(fā)送移位寄存器與發(fā)送緩沖寄存器中沒(méi)有要傳送的數(shù)據(jù)。發(fā)送器禁止后,TxD引腳恢復(fù)其通用I/O功能。
&8226; Bit 2 – UCSZ2:字符長(zhǎng)度
UCSZ2與UCSRC寄存器的UCSZ1:0結(jié)合在一起可以設(shè)置數(shù)據(jù)幀所包含的數(shù)據(jù)位數(shù)(字符長(zhǎng)度)。
&8226; Bit 1 – RXB8:接收數(shù)據(jù)位8
對(duì)9位串行幀進(jìn)行操作時(shí),RXB8是第9個(gè)數(shù)據(jù)位。讀取UDR包含的低位數(shù)據(jù)之前首先要讀取RXB8。
&8226; Bit 0 – TXB8:發(fā)送數(shù)據(jù)位8
對(duì)9位串行幀進(jìn)行操作時(shí),TXB8是第9個(gè)數(shù)據(jù)位。寫(xiě)UDR之前首先要對(duì)它進(jìn)行寫(xiě)操作。
USART控制和狀態(tài)寄存器C-UCSRC
&8226; Bit 7 – URSEL:寄存器選擇
通過(guò)該位選擇訪問(wèn)UCSRC寄存器或UBRRH寄存器。當(dāng)讀UCSRC時(shí),該位為1;當(dāng)寫(xiě)UCSRC時(shí),URSEL為1。
&8226; Bit 6 – UMSEL: USART模式選擇
通過(guò)這一位來(lái)選擇同步或異步工作模式。
&8226; Bit 5:4 – UPM1:0:奇偶校驗(yàn)?zāi)J?/p>
這兩位設(shè)置奇偶校驗(yàn)的模式并使能奇偶校驗(yàn)。如果使能了奇偶校驗(yàn),那么在發(fā)送數(shù)據(jù),發(fā)送器都會(huì)自動(dòng)產(chǎn)生并發(fā)送奇偶校驗(yàn)位。對(duì)每一個(gè)接收到的數(shù)據(jù),接收器都會(huì)產(chǎn)生一奇偶值,并與UPM0所設(shè)置的值進(jìn)行比較。如果不匹配,那么就將UCSRA中的PE置位。
&8226; Bit 3 – USBS:停止位選擇
通過(guò)這一位可以設(shè)置停止位的位數(shù)。接收器忽略這一位的設(shè)置。
&8226; Bit 2:1 – UCSZ1:0:字符長(zhǎng)度
UCSZ1:0與UCSRB寄存器的UCSZ2結(jié)合在一起可以設(shè)置數(shù)據(jù)幀包含的數(shù)據(jù)位數(shù)(字符長(zhǎng)度)。
&8226; Bit 0 – UCPOL:時(shí)鐘極性
這一位僅用于同步工作模式。使用異步模式時(shí),將這一位清零。UCPOL設(shè)置了輸出數(shù)據(jù)的改變和輸入數(shù)據(jù)采樣,以及同步時(shí)鐘XCK之間的關(guān)系。
USART波特率寄存器-UBRRL和UBRRH
UCSRC寄存器與UBRRH寄存器共用相同的I/O地址。
&8226; Bit 15 – URSEL:寄存器選擇
通過(guò)該位選擇訪問(wèn)UCSRC寄存器或
UBRRH寄存器。當(dāng)讀UBRRH時(shí),該位為0;當(dāng)寫(xiě)UBRRH時(shí),URSEL為0。
&8226; Bit 14:12 –保留位
這些位是為以后的使用而保留的。為了與以后的器件兼容,寫(xiě)UBRRH時(shí)將這些位清零。
&8226; Bit 11:0 – UBRR11:0: USART波特率寄存器
這個(gè)12位的寄存器包含了USART的波特率信息。其中UBRRH包含了USART波特率高4位,UBRRL包含了低8位。波特率的改變將造成正在進(jìn)行的數(shù)據(jù)傳輸受到破壞。寫(xiě)UBRRL將立即更新波特率分頻器。
進(jìn)行通信之前首先要對(duì)USART進(jìn)行初始化。初始化過(guò)程通常包括波特率的設(shè)定,幀結(jié)構(gòu)的設(shè)定,以及根據(jù)需要使能接收器或發(fā)送器。對(duì)于中斷驅(qū)動(dòng)的USART操作,在初始化時(shí)首先要清零全局中斷標(biāo)志位(全局中斷被屏蔽)
串口初始化:
使用串口->使能接收->使能發(fā)送->波特率(本例使用9600)->奇偶校驗(yàn)(disable)->數(shù)據(jù)位數(shù)(8bit)->中斷(RX Complete interrupt)
//ICC-AVR application builder : 2007-5-10下午08:51:56
// Target : M16
// Crystal: 11.059Mhz
//UART0 initialisation
// desired baud rate: 9600
// actual: baud rate:9600 (0.0%)
// char size: 8 bit
// parity: Disabled
void uart0_init(void)
{
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC = 0x86;
UBRRL = 0x47; //set baud rate lo
UBRRH = 0x00; //set baud rate hi
UCSRB = 0x98;
}
//省略了端口初始化
//call this routine to initialise all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
uart0_init();//注意這句調(diào)用串口初始化
MCUCR = 0x00;
GICR= 0x00;
TIMSK = 0x00; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialised
接收模塊(中斷接受):
#pragma interrupt_handler uart0_rx_isr:12
void uart0_rx_isr(void)
{
//uart has received a character in UDR
Data = UDR;
}
注意:Data必須是全局變量才能從函數(shù)中返回得到的值。
發(fā)送模塊(查詢(xún)發(fā)送):
void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1< /* Put data into buffer, sends the data */ UDR = data; } 小提示: 如果接受到一個(gè)字符后,馬上回復(fù),只需要在接收中斷函數(shù)的最后寫(xiě)值到UDR中即可: 如:#pragma interrupt_handler uart0_rx_isr:12 void uart0_rx_isr(void) { //uart has received a character in UDR Data = UDR;//從電腦接收的數(shù)據(jù)附值給變量Data UDR = Send_data;//將要發(fā)送的數(shù)據(jù)放到緩存區(qū)Send_data與Data可以相同 } 注:Send_data,Data必須是全局變量才能從函數(shù)中返回得到的值。 二 外部中斷 首先回顧一下中斷的含義。所謂中斷,是指當(dāng)計(jì)算機(jī)執(zhí)行正常程序時(shí),系統(tǒng)中出現(xiàn)某些急需處理的異常情況和特殊請(qǐng)求,CPU暫時(shí)中止現(xiàn)行程序,轉(zhuǎn)去對(duì)隨機(jī)發(fā)生的更緊迫事件進(jìn)行處理,處理完成后返回原來(lái)的程序繼續(xù)執(zhí)行。前面講的定時(shí)器中斷和串口中斷是中斷的兩種,現(xiàn)在介紹外部中斷。 Atmega 16有三個(gè)外部中斷源,通過(guò)引腳INT0、INT1與INT2觸發(fā)。中斷可以由下降沿、上升沿,或者是低電平觸發(fā)(INT2為邊沿觸發(fā)中斷)。當(dāng)外部中斷使能并且配置為電平觸發(fā)( INT0/INT1),只要引腳電平為低,中斷就會(huì)產(chǎn)生。 跟其他中斷使用一樣,使用外部中斷也要使能該中斷。 通用中斷控制寄存器-GICR &8226; Bit 7 – INT1:使能外部中斷請(qǐng)求1 當(dāng)INT1為1’,而且狀態(tài)寄存器SREG的I標(biāo)志置位,相應(yīng)的外部引腳中斷就使能了。MCU通用控制寄存器– MCUCR的中斷敏感電平控制1位1/0 (ISC11與ISC10)決定中斷是由上升沿、下降沿,還是INT1電平觸發(fā)的。只要使能,即使INT1引腳被配置為輸出,只要引腳電平發(fā)生了相應(yīng)的變化,中斷可將產(chǎn)生。 &8226; Bit 6 – INT0:使能外部中斷請(qǐng)求0 &8226; Bit 5 – INT2:使能外部中斷請(qǐng)求2 功能與使能外部中斷請(qǐng)求1相同 MCU控制寄存器-MCUCRMCU控制寄存器包含中斷觸發(fā)控制位與通用MCU功能 &8226; Bit 3, 2 – ISC11, ISC10:中斷1觸發(fā)方式控制 外部中斷1由引腳INT1激發(fā),如果SREG寄存器的I標(biāo)志位和相應(yīng)的中斷屏蔽位置位的話。觸發(fā)方式如Table 34所示。在檢測(cè)邊沿前MCU首先采樣INT1引腳上的電平。如果選擇了邊沿觸發(fā)方式或電平變化觸發(fā)方式,那么持續(xù)時(shí)間大于一個(gè)時(shí)鐘周期的脈沖將觸發(fā)中斷,過(guò)短的脈沖則不能保證觸發(fā)中斷。如果選擇低電平觸發(fā)方式,那么低電平必須保持到當(dāng)前指令執(zhí)行完成。 &8226; Bit 1, 0 – ISC01, ISC00:中斷0觸發(fā)方式控制 功能與中斷1觸發(fā)方式控制相同 MCU控制與狀態(tài)寄存器-MCUCSR &8226; Bit 6 – ISC2:中斷2觸發(fā)方式控制 異步外中斷2由外部引腳INT2激活,如果SREG寄存器的I標(biāo)志和GICR寄存器相應(yīng)的中斷屏蔽位置位的話。若ISC2寫(xiě)0,INT2的下降沿激活中斷。 若ISC2寫(xiě)1,INT2的上升沿激活中斷。INT2的邊沿觸發(fā)方式是異步的。只要INT2引腳上產(chǎn)生寬度大于Table 36所示數(shù)據(jù)的脈沖就會(huì)引發(fā)中斷。若選擇了低電平中斷,低電平必須保持到當(dāng)前指令完成,然后才會(huì)產(chǎn)生中斷。而且只要將引腳拉低,就會(huì)引發(fā)中斷請(qǐng)求。改變ISC2時(shí)有可能發(fā)生中斷。因此建議首先在寄存器GICR里清除相應(yīng)的中斷使能位INT2,然后再改變ISC2。最后,不要忘記在重新使能中斷之前通過(guò)對(duì)GIFR寄存器的相應(yīng)中斷標(biāo)志位INTF2寫(xiě)1’使其清零。 通用中斷標(biāo)志寄存器-GIFR &8226; Bit 7 – INTF1:外部中斷標(biāo)志1 INT1引腳電平發(fā)生跳變時(shí)觸發(fā)中斷請(qǐng)求,并置位相應(yīng)的中斷標(biāo)志INTF1。如果SREG的位I以及GICR寄存器相應(yīng)的中斷使能位INT1為”1”,MCU即跳轉(zhuǎn)到相應(yīng)的中斷向量。進(jìn)入中斷服務(wù)程序之后該標(biāo)志自動(dòng)清零。此外,標(biāo)志位也可以通過(guò)寫(xiě)入”1”來(lái)清零。 &8226; Bit 6 – INTF0:外部中斷標(biāo)志0 &8226; Bit 5 – INTF2:外部中斷標(biāo)志2 功能與外部中斷標(biāo)志1相同 外部中斷初始化: 使用中斷IT0、IT1、IT2(具體根據(jù)實(shí)際情況選定)—— 選擇個(gè)中斷觸發(fā)方式 (本例IT0低電平、IT1下降沿、IT2上升沿) //ICC-AVR application builder : 2007-5-11上午10:35:17 // Target : M16 // Crystal: 11.059Mhz #include #include 省略端口初始化 #pragma interrupt_handler int0_isr:2 void int0_isr(void)//中斷0 { //external interupt on INT0 } #pragma interrupt_handler int1_isr:3 void int1_isr(void)//中斷1 { //external interupt on INT1 } #pragma interrupt_handler int2_isr:19 void int2_isr(void)中斷2 { //external interupt on INT2 } //call this routine to initialise all peripherals void init_devices(void) { //stop errant interrupts until set up CLI(); //disable all interrupts port_init(); MCUCR = 0x08;//INT0、INT1觸發(fā)方式 MCUCSR = 0x40;//INT2觸發(fā)方式(這句要人工輸入) GICR= 0xE0; TIMSK = 0x00; //timer interrupt sources SEI(); //re-enable interrupts //all peripherals are now initialised } 簡(jiǎn)單實(shí)例參考程序 為了進(jìn)一步理解串口和外部中斷的使用,下面給出一簡(jiǎn)單實(shí)例。程序功能包含了串口和外部中斷,注意程序main函數(shù)while循環(huán)體中為空,說(shuō)明單片機(jī)上電以后什么也不干,外部中斷INT0,INT1,INT2分別為低電平,下降沿,上升沿觸發(fā)。INT0觸發(fā)后PORTA0為高,INT1觸發(fā)后PORTA1為高,INT2觸發(fā)后PORTA2為高。串口接受中斷為邊收邊發(fā)——從電腦發(fā)送一數(shù)據(jù)給單片機(jī)后,單片機(jī)馬上又把該數(shù)據(jù)發(fā)送給電腦。請(qǐng)仔細(xì)體會(huì),然后做后面的練習(xí)題。 //ICC-AVR application builder : 2007-5-11 ÏÂÎç 09:56:04 具體使用根據(jù)實(shí)際要求編寫(xiě), 如果不要發(fā)送給電腦就刪除此句 GICR= 0xE0; }
// Target : M16
// Crystal: 11.059Mhz
#include
#include
unsignedintData="0";
voidport_init(void)
{
PORTA = 0x00;
DDRA= 0xFF;
PORTB = 0xFF;
DDRB= 0x00;
PORTC = 0xFF;//m103 output only
DDRC= 0x00;
PORTD = 0xFF;
DDRD= 0x00;
}
//UART0 initialisation
// desired baud rate: 9600
// actual: baud rate:9600 (0.0%)
// char size: 8 bit
// parity: Disabled
voiduart0_init(void)
{
UCSRB = 0x00;//disable while setting baud rate
UCSRA = 0x00;
UCSRC = 0x86;
UBRRL = 0x47;//set baud rate lo
UBRRH = 0x00;//set baud rate hi
UCSRB = 0x98;
}
#pragma interrupt_handler uart0_rx_isr:12
voiduart0_rx_isr(void)//接收模塊
{
Data = UDR;//從電腦接受數(shù)據(jù)
//uart has received a character in UDR
UDR = Data;//將該數(shù)據(jù)發(fā)送給電腦,這樣做的目的是為了調(diào)試
}
#pragma interrupt_handler int0_isr:2
voidint0_isr(void)
{
PORTA = 0x01;//中斷0的函數(shù)體,在此寫(xiě)入INT0觸發(fā)后要做的事
//external interupt on INT0
}
#pragma interrupt_handler int1_isr:3
voidint1_isr(void)
{
PORTA = 0x02;//中斷1的函數(shù)體,在此寫(xiě)入INT1觸發(fā)后要做的事
//external interupt on INT1
}
#pragma interrupt_handler int2_isr:19
voidint2_isr(void)
{
PORTA = 0x04;//中斷2的函數(shù)體,在此寫(xiě)入INT2觸發(fā)后要做的事
//external interupt on INT2
}
//call this routine to initialise all peripherals
voidinit_devices(void)
{
//stop errant interrupts until set up
CLI();//disable all interrupts
port_init();
uart0_init();
MCUCR = 0x08;
MCUCSR = 0x40;//INT2(這句要人工輸入)
TIMSK = 0x00;//timer interrupt sources
SEI();//re-enable interrupts
//all peripherals are now initialised
}
voidUSART_Transmit(unsignedchardata )//發(fā)送模塊,該程序沒(méi)用到
{
/* Wait for empty transmit buffer */
while( !( UCSRA & (1<
UDR = data;
}
voidmain()
{
init_devices();
while(1)
{
;
}
評(píng)論