在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 單片機(jī)學(xué)習(xí)之十二:按鍵控制跑馬燈(中斷)

            單片機(jī)學(xué)習(xí)之十二:按鍵控制跑馬燈(中斷)

            作者: 時(shí)間:2016-11-18 來(lái)源:網(wǎng)絡(luò) 收藏
            一、實(shí)驗(yàn)現(xiàn)象:

            本文引用地址:http://www.biyoush.com/article/201611/315887.htm

            二極管作左右跑馬燈,當(dāng)按下外部按鍵K0時(shí),8個(gè)二極管全部閃爍5次后從K0按下之前的位置繼續(xù)作跑馬燈。

            二、實(shí)驗(yàn)?zāi)康?/p>

            掌握堆棧在中斷程序中的作用

            掌握讓程序保護(hù)現(xiàn)場(chǎng)的方法

            三、實(shí)驗(yàn)任務(wù)分析:

            有了以前各個(gè)試驗(yàn)的經(jīng)驗(yàn),相信這個(gè)試驗(yàn)對(duì)我們來(lái)說(shuō),難度不是很大。我們唯一接觸到的新的知識(shí)點(diǎn)是:讓程序從返回中斷之前的位置繼續(xù)執(zhí)行跑馬燈,那么如何能夠讓程序在進(jìn)入中斷之前記住當(dāng)時(shí)所處的位置,在執(zhí)行中斷之后,能夠返回這個(gè)地方繼續(xù)往下執(zhí)行呢?

            我們可以這樣作:在進(jìn)入中斷之前,把該時(shí)刻的程序信息放到一個(gè)地方保存下來(lái),在返回中斷之前,再到這個(gè)地方把我們存放的程序信息取出來(lái)。這樣不就可以從進(jìn)入中斷的位置開(kāi)始重新執(zhí)行程序了嗎?那么,這個(gè)暫存數(shù)據(jù)的地方在哪里呢?

            單片機(jī)給我們考慮的很周到,允許我們從內(nèi)部RAM中指定一個(gè)空間專(zhuān)門(mén)來(lái)作這個(gè)工作,這個(gè)空間就是堆棧。并且單片機(jī)還專(zhuān)門(mén)給了我們一個(gè)8位的堆棧指針,讓我們用它來(lái)開(kāi)辟堆??臻g。(為什么是8位呢?因?yàn)閮?nèi)部RAM的地址空間是256字節(jié),所以8位就足夠拉。)

            例如:假如我們給堆棧指針賦值:mov sp,#70h,就表示我們把內(nèi)部數(shù)據(jù)RAM的地址為70h開(kāi)始的單元設(shè)為堆棧啦。

            那么,我們一般把內(nèi)部數(shù)據(jù)RAM的那些地方作為堆棧呢?讓我們來(lái)復(fù)習(xí)一下內(nèi)部RAM的結(jié)構(gòu)吧。

            前面我們已經(jīng)說(shuō)過(guò),內(nèi)部RAM共有256字節(jié),分為兩組。還記得它們各自的功能嗎?高128字節(jié)是特殊功能寄存器區(qū),我們沒(méi)有辦法利用,那就打低128字節(jié)的主意吧。我們?cè)賮?lái)看看低128字節(jié)的RAM空間分配。

            我們發(fā)現(xiàn)在低128字節(jié)中,工作寄存器區(qū)和位尋址區(qū)的地址已經(jīng)分配好了,我們可以利用的只有30h~7fh的數(shù)據(jù)緩沖區(qū)了。所以我們的堆棧指針只能設(shè)在這個(gè)區(qū)域,從30h以后的范圍為宜。在該程序中,我們把堆棧設(shè)在70h的位置。

            好啦,知道堆棧設(shè)在哪里,下面我們就要考慮如何把程序運(yùn)行的相關(guān)信息放入堆棧拉。那么,程序運(yùn)行的相關(guān)信息在哪里呢?

            由于在主程序中,我們讓程序作左右跑馬燈。還記得試驗(yàn)三嗎,我們的左右跑馬燈是通過(guò)把寄存器a中的數(shù),通過(guò)進(jìn)位標(biāo)志CY(程序狀態(tài)字PSW的最高位),進(jìn)行左右環(huán)移來(lái)實(shí)現(xiàn)的。同時(shí),由于寄存器a是單片機(jī)中最最常用的寄存器,我們?cè)谥袛喑绦蛑幸惨玫剿?。為了避免中斷程序改變寄存器a的值,所以我們?cè)谥袛喾?wù)程序開(kāi)始之前,把a(bǔ)的值放到堆棧中保存起來(lái)。同樣我們也要把psw的值也保存起來(lái)。在返回主程序之前,再把它們?nèi)〕鰜?lái),這樣就可以使得程序從進(jìn)入中斷之前的位置開(kāi)始,繼續(xù)作跑馬燈。

            把數(shù)據(jù)存入堆棧和從堆棧中取出,是通過(guò)堆棧操作指令完成的。

            例如:如果想把a(bǔ)中的數(shù)據(jù)存入堆棧,就:push acc;如果想把a(bǔ)的內(nèi)容從堆棧中取出,就:pop acc。(一般稱(chēng)之為:壓入,彈出)。

            還需要說(shuō)明一點(diǎn)的是:堆棧中的數(shù)據(jù)是采用“后進(jìn)先出”的結(jié)構(gòu)方式處理的。就像我們摞盤(pán)子一樣,最后摞進(jìn)去的盤(pán)子,取得時(shí)候是最先取出的。所以我們壓入數(shù)據(jù)后,再?gòu)棾龅臅r(shí)候要特別注意順序,后壓入的要先彈出,不要弄錯(cuò)啦。

            現(xiàn)在來(lái)看看這個(gè)試驗(yàn)的程序吧。

            四、實(shí)驗(yàn)程序如下:

            org 0000h

            ljmp start

            org 0013h

            ljmp ext1

            org 0020h

            start: clr p1.5 ;避免蜂鳴器響

            setb ea ;CPU開(kāi)中斷

            setb ex1 ;允許外部中斷1申請(qǐng)中斷

            setb it1 ;設(shè)置外部中斷1跳變方式觸發(fā)

            mov sp,#70h ;設(shè)置堆棧入口

            loop1: lcall light1 ;調(diào)用左右跑馬燈子程序

            ljmp loop1

            ;以下是中斷服務(wù)程序

            ext1: clr ea ;關(guān)閉CPU中斷

            push acc ;把寄存器a的內(nèi)容壓入堆棧

            push psw ;把程序狀態(tài)字壓入堆棧

            lcall keyreader ;調(diào)用鍵識(shí)別子程序

            pass: pop psw ;恢復(fù)現(xiàn)場(chǎng),注意順序,要先彈出程序狀態(tài)字

            pop acc ;彈出寄存器a的內(nèi)容,

            setb ea ;CPU開(kāi)中斷

            reti ;中斷返回

            light1: mov a,#0ffh ;light1是左右跑馬燈子程序,大家可以參考試驗(yàn)三的內(nèi)容

            clr c

            mov r7,#08h

            lloop: rlc a

            mov p0,a

            lcall del100ms

            djnz r7,lloop

            mov r6,#06h

            rloop: rrc a

            mov p0,a

            lcall del100ms

            djnz r6,rloop

            ret

            keyreader: mov a,p1 ;keyreader是鍵識(shí)別子程序,大家可以參考試驗(yàn)7

            anl a,#0fh

            cjne a,#0dh,pass

            lcall del10ms

            mov a,p1

            anl a,#0fh

            cjne a,#0dh,pass

            lcall light2 ;如果確定K0按鍵按下,調(diào)用燈光閃爍子程序

            ret

            light2: mov a,#00h ;light2是讓燈光閃爍5次的子程序

            mov r5,#10

            loop2: mov p0,a

            call del10ms

            cpl a ;把a(bǔ)寄存器中的數(shù)據(jù)取反

            djnz r5,loop2;

            ret

            del10ms: mov r4,#15h ;延時(shí)10ms子程序

            del1: mov r3,#0ffh

            del2: djnz r3,del3

            djnz r4,del1

            ret;

            del100ms:mov r2,#0c8h ;延時(shí)100ms子程序

            del3: mov r1,#0ffh

            del4: djnz r1,del4

            djnz r2,del3

            ret

            end

            大家把這個(gè)程序下載到學(xué)習(xí)板上看看,會(huì)發(fā)現(xiàn)每次按下按鍵的時(shí)候,程序進(jìn)入中斷后,在返回的時(shí)候,會(huì)回到那個(gè)位置繼續(xù)開(kāi)始左右循環(huán)。這就是由于我們?cè)谶M(jìn)入中斷的時(shí)候保護(hù)了現(xiàn)場(chǎng)的緣故。

            五、幾點(diǎn)說(shuō)明

            主程序是左右跑馬燈,其中用到了r7,r6寄存器,還調(diào)用了100ms延時(shí),所以也用到了r2,r1寄存器。所以我們要特別注意,在中斷服務(wù)程序中,要避免使用這幾個(gè)寄存器。否則,就會(huì)導(dǎo)致在中斷程序中,修改了r寄存器的內(nèi)容,導(dǎo)致返回主程序的時(shí)候出現(xiàn)問(wèn)題。

            在中斷服務(wù)程序中,用到了10ms延時(shí)程序,這個(gè)延時(shí)程序使用的寄存器是r4,r3。另外,還調(diào)用了light2子程序,其中用到了r5寄存器。所以。主程序和中斷服務(wù)程序用到的寄存器r就沒(méi)有沖突。

            那么如果由于條件的限制,使得主程序和中斷程序的寄存器的數(shù)量較多,一組8個(gè)寄存器不夠,該怎么辦呢?

            我們也可以象保護(hù)a寄存器一樣,在進(jìn)入中斷之后,首先把某一個(gè)在中斷服務(wù)程序中也要用到的r寄存器的內(nèi)容壓入堆棧,在退出中斷之前再?gòu)棾鰜?lái)。

            或者我們就重新選擇寄存器區(qū)吧,由于我們?nèi)笔∈褂玫氖?區(qū)的寄存器組,所以我們就改變psw程序狀態(tài)字中的rs1和rs0,就可以換另外的一組寄存器區(qū)了。例如,我們?cè)谶M(jìn)入中斷服務(wù)程序之后,寫(xiě)這樣的兩條指令:

            clr rs1

            setb rs0

            這樣,我們就用了1區(qū)的8個(gè)寄存器,這樣就沒(méi)有問(wèn)題啦。



            評(píng)論


            技術(shù)專(zhuān)區(qū)

            關(guān)閉