【51單片機(jī)系列】C51中的中斷系統(tǒng)擴(kuò)展實(shí)驗(yàn)

本文是關(guān)于51單片機(jī)中斷系統(tǒng)的擴(kuò)展實(shí)驗(yàn)。

一、 擴(kuò)展實(shí)驗(yàn)一:使用外部中斷0控制蜂鳴器,外部中斷1控制直流電機(jī)

外部中斷擴(kuò)展實(shí)驗(yàn)一實(shí)現(xiàn)的功能:使用外部中斷0控制蜂鳴器發(fā)聲/不發(fā)聲,外部中斷1控制直流電機(jī)轉(zhuǎn)動/停止。

由蜂鳴器的內(nèi)容可以知道,蜂鳴器分為有源蜂鳴器和無源蜂鳴器;蜂鳴器有兩個管腳,要使蜂鳴器發(fā)聲,需要有電流通過蜂鳴器,即管腳一端接正極,管腳另一端接負(fù)極。有源蜂鳴器只需給一定的電壓即可發(fā)聲,無源蜂鳴器需要一定頻率的脈沖才可發(fā)聲。這里設(shè)計了兩種蜂鳴器,都由外部中斷0控制。

直流電機(jī)的驅(qū)動方式與蜂鳴器類似。

proteus中硬件設(shè)計如下,為顯示蜂鳴器的發(fā)聲,這里使用了一個LED顯示發(fā)聲與否。蜂鳴器的一端連接到電源,另一端經(jīng)過ULN2003芯片連接P1.5口,當(dāng)P1.5=0時蜂鳴器發(fā)聲;直流電機(jī)的一端連接到電源,另一端經(jīng)過ULN2003連接到P1.0口,當(dāng)P1.0=0時電機(jī)轉(zhuǎn)動。為體現(xiàn)中斷,使用獨(dú)立按鍵模塊連接到P3.2和P3.3口,當(dāng)按鍵按下,蜂鳴器發(fā)聲或電機(jī)轉(zhuǎn)動。

proteus設(shè)計外部中斷控制蜂鳴器和直流電機(jī)

軟件設(shè)計如下:

/*
    實(shí)現(xiàn)功能:外部中斷0控制蜂鳴器發(fā)聲,外部中斷1控制直流電機(jī)轉(zhuǎn)動
        - 與外部中斷0和外部中斷1有關(guān)的有兩個寄存器IE和TCON,
        - IE是中斷允許控制寄存器,TCON是中斷請求標(biāo)志寄存器。
        - IE中包括了
            - 總中斷允許位(EA)
            - 外部中斷0/1允許位(EX0/EX1)
            - 定時器0/1允許位(ET0/ET1)
            - 串口中斷允許位(ES);
        - TCON中的低四位是外部中斷允許和觸發(fā)方式控制位,包括了
            - IT0/IT1是外部中斷0/1觸發(fā)方式控制位,0表示低電平觸發(fā),1表示下降沿觸發(fā);
            - IE0/IE1是外部中斷0/1請求標(biāo)志位
    [2023-12-19] zoya
*/

#include "reg52.h"
#include "typedef.h"
#include "Delay.h"

sbit BEEP = P1^5;
sbit MOTOR = P1^0;
sbit CTR_INT0 = P3^2;
sbit CTR_INT1 = P3^3;

/*************************************************************************
* 函數(shù)名:      IntInit
* 函數(shù)功能: 外部中斷0/1初始化,設(shè)置中斷觸發(fā)方式為邊沿觸發(fā)
* 輸入:           void
* 輸出:           void
**************************************************************************/
void IntInit()
{
    // 1. 設(shè)置中斷觸發(fā)方式
    IT0=1;
    IT1=1;
    // 2. 打開外部中斷0/1
    EX0=1;
    EX1=1;
    // 3. 打開總中斷
    EA=1;
}


void main()
{
    MOTOR=0;
    BEEP=0;
    IntInit(); 
    while(1);
}

/*************************************************************************
* 函數(shù)名:      Int0
* 函數(shù)功能: 外部中斷0中斷服務(wù)函數(shù),
*                       控制蜂鳴器發(fā)聲
* 輸入:           void
* 輸出:           void
**************************************************************************/
void Int0() interrupt 0
{
    delayms(10);  // 按鍵延時消抖
    if(0 == CTR_INT0){
        BEEP = ~BEEP;
    }
}

/*************************************************************************
* 函數(shù)名:      Int1
* 函數(shù)功能: 外部中斷1中斷服務(wù)函數(shù),
*                       控制直流電機(jī)轉(zhuǎn)動
* 輸入:           void
* 輸出:           void
**************************************************************************/
void Int1() interrupt 2
{
    delayms(10);  // 按鍵延時消抖
    if(0 == CTR_INT1)
    {
        MOTOR=~MOTOR;
    }
}

仿真結(jié)果:

外部中斷控制蜂鳴器和直流電機(jī)

二、擴(kuò)展實(shí)驗(yàn)二:修改定時器初值,設(shè)定3秒鐘的定時時間讓LED模塊閃爍

如何計算定時器初值?

以使用12MHz的晶振頻率計算。如果使用的是12MHz晶振,單片機(jī)內(nèi)部的時鐘頻率為12分頻即12/12MHz=1MHz;那么對應(yīng)的機(jī)器周期為1/1MHz=1us。即使用12MHz晶振的機(jī)器周期為1us。

如果要定時1ms,需要計數(shù)1ms/1us=1000個,定時器使用方式1工作,那么初值為2^{16}-1000 = 64536 = 0xFC18。即初值THx=0xfc,TLx=0x18。

如果要定時1s,可以通過初值設(shè)置定時1ms,當(dāng)定時結(jié)束重新賦初值,并設(shè)定一個全局變量累計定時1ms的次數(shù),當(dāng)該全局變量累計1000次時表示定時1s。

如果要設(shè)定3s時間,可以通過初值設(shè)定定時3ms,其它同定時1ms。定時3ms需要計數(shù)3ms/1us=3000,定時器使用方式1工作,初值為2^{16} - 3000 = 62536 = 0xF448,即初值THx=0xF4,TLx=0x48。

該實(shí)驗(yàn)在前面使用示例的基礎(chǔ)上更改計數(shù)初值即可實(shí)現(xiàn)定時3s實(shí)現(xiàn)LED模塊的閃爍。proteus中設(shè)計LED模塊如下,定時器模塊在單片機(jī)內(nèi)部。

proteus設(shè)計定時器控制LED模塊閃爍

軟件設(shè)計如下:

/*
    實(shí)現(xiàn)功能:定時器0定時3s實(shí)現(xiàn)LED模塊亮滅
        - 與定時/計數(shù)器工作有關(guān)的寄存器有IE、TCON、TMOD、THx、TLx
        - IE是中斷允許控制寄存器,TCON是中斷請求標(biāo)志寄存器,TMOD是定時/計數(shù)器工作方式寄存器
        - THx和TLx是計數(shù)初值賦值寄存器。
        
        - IE中包括了
            - 總中斷允許位(EA)
            - 外部中斷0/1允許位(EX0/EX1)
            - 定時器0/1允許位(ET0/ET1)
            - 串口中斷允許位(ES);
        
        - TCON中的高四位用于控制定時/計數(shù)器的啟動和中斷申請,包括TR0/1、TF0/1
            - TR0/TR1是T0/T1運(yùn)行控制位,TR0=1時開始工作,TR0=0時停止工作,TR1與TR0類似;
            - TF0/TF1是T0/T1溢出中斷請求標(biāo)志位,溢出時由硬件自動置位,CPU響應(yīng)中斷后由硬件自動清0
                可隨時查詢該位狀態(tài),也可軟件置1或清0.
                
        - TMOD高四位控制T1,低四位控制T0,高四位和低四位分別為有GATE、C/T、M1M0
            - GATE是門控位,
                - GATE=0表示不受外部中斷信號影響,僅TR0/TR1控制定時/計數(shù)器工作,
                - GATE=1表示受外部中斷信號影響,即TR0/TR1+INT0控制定時/計數(shù)器工作
            - C/T是定時/計數(shù)器模式選擇位,C/T=0為定時模式,C/T=1為計數(shù)模式;
            - M1M0是工作方式設(shè)置位,有四種方式:00 01 10 11
    [2023-12-20] zoya
*/

#include "reg52.h"
#include "typedef.h"
#include "Delay.h"

#define GPIO_LED P2
/*************************************************************************
* 函數(shù)名:      Timer0Init
* 函數(shù)功能: 定時器0初始化,工作方式1定時3ms,僅TR0啟動或停止計數(shù)
* 輸入:           void
* 輸出:           void
**************************************************************************/
void Timer0Init()
{
    // 1. 設(shè)置工作方式1,僅TR0控制
    TMOD |= 0x01;
    // 2. 設(shè)置定時3ms的初值,0xf448
    TH0 = 0xf4;
    TL0 = 0x48;
    // 3. 打開中斷允許位
    EA = 1;
    ET0 = 1;
    // 4. 置位TR0,開始計數(shù)
    TR0 = 1;
}


void main()
{
    Timer0Init(); 
    while(1);
}


/*************************************************************************
* 函數(shù)名:      Timer0
* 函數(shù)功能: 定時器0中斷服務(wù)函數(shù),定時3s控制LED模塊亮滅
* 輸入:           void
* 輸出:           void
**************************************************************************/
void Timer0() interrupt 1
{
    static u16 i;
    // 重新賦初值
    TH0 = 0xf4;
    TL0 = 0x48;
    i++;
    if(1000 == i)
    {
        i=0;
        GPIO_LED = ~GPIO_LED;
    }
}

仿真結(jié)果:

定時器0定時3s控制LED模塊亮滅

三、擴(kuò)展實(shí)驗(yàn)三:使用定時器1和數(shù)碼管設(shè)計一個數(shù)字時鐘

定時器的設(shè)置參考擴(kuò)展實(shí)驗(yàn)二。

數(shù)字時鐘采用24小時制,顯示使用“00-00-00”格式。

這里數(shù)碼管使用一個八位一體的共陰極數(shù)碼管,使用芯片74HC138控制數(shù)碼管的位選,使用芯片74HC245控制數(shù)碼管的段選;P0口控制74HC245的輸入,P2.2 ~ P2.4控制74HC138的輸入。proteus設(shè)計如下:

proteus設(shè)計定時器1和數(shù)碼管實(shí)現(xiàn)一個數(shù)字時鐘

軟件設(shè)計如下:

/*
    實(shí)現(xiàn)功能:定時器1和數(shù)碼管設(shè)計一個數(shù)字時鐘
        - 與定時/計數(shù)器工作有關(guān)的寄存器有IE、TCON、TMOD、THx、TLx
        - IE是中斷允許控制寄存器,TCON是中斷請求標(biāo)志寄存器,TMOD是定時/計數(shù)器工作方式寄存器
        - THx和TLx是計數(shù)初值賦值寄存器。
        
        - IE中包括了
            - 總中斷允許位(EA)
            - 外部中斷0/1允許位(EX0/EX1)
            - 定時器0/1允許位(ET0/ET1)
            - 串口中斷允許位(ES);
        
        - TCON中的高四位用于控制定時/計數(shù)器的啟動和中斷申請,包括TR0/1、TF0/1
            - TR0/TR1是T0/T1運(yùn)行控制位,TR0=1時開始工作,TR0=0時停止工作,TR1與TR0類似;
            - TF0/TF1是T0/T1溢出中斷請求標(biāo)志位,溢出時由硬件自動置位,CPU響應(yīng)中斷后由硬件自動清0
                可隨時查詢該位狀態(tài),也可軟件置1或清0.
                
        - TMOD高四位控制T1,低四位控制T0,高四位和低四位分別為有GATE、C/T、M1M0
            - GATE是門控位,
                - GATE=0表示不受外部中斷信號影響,僅TR0/TR1控制定時/計數(shù)器工作,
                - GATE=1表示受外部中斷信號影響,即TR0/TR1+INT0控制定時/計數(shù)器工作
            - C/T是定時/計數(shù)器模式選擇位,C/T=0為定時模式,C/T=1為計數(shù)模式;
            - M1M0是工作方式設(shè)置位,有四種方式:00 01 10 11
        
        使用一個八位一體的共陰極數(shù)碼管顯示時間,74HC138芯片控制數(shù)碼管的位選,74HC245控制數(shù)碼管的段選。
    [2023-12-20] zoya
*/

#include "reg52.h"
#include "typedef.h"
#include "Delay.h"

#define GPIO_DISPLAY P0
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

// 共陰極數(shù)碼管的碼表,0-9以及:
u8 code smg[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x67, 0x40};

static u16 h, m, s;

/*************************************************************************
* 函數(shù)名:      Timer0Init
* 函數(shù)功能: 定時器0初始化,工作方式1定時3ms,僅TR0啟動或停止計數(shù)
* 輸入:           void
* 輸出:           void
**************************************************************************/
void Timer1Init()
{
    // 1. 設(shè)置工作方式1,僅TR0控制
    TMOD |= 0x10;
    // 2. 設(shè)置定時1ms的初值,0xFC18
    TH1 = 0xFC;
    TL1 = 0x18;
    // 3. 打開中斷允許位
    EA = 1;
    ET1 = 1;
    // 4. 置位TR1,開始計數(shù)
    TR1 = 1;
}

void DigDisplay()
{

    LSA=0; LSB=0; LSC=0; GPIO_DISPLAY = smg[h/10];
    delayms(1);
    LSA=1; LSB=0; LSC=0; GPIO_DISPLAY = smg[h%10];
    delayms(1);
    LSA=0; LSB=1; LSC=0; GPIO_DISPLAY = smg[10];
    delayms(1);
    LSA=1; LSB=1; LSC=0; GPIO_DISPLAY = smg[m/10];
    delayms(1);
    LSA=0; LSB=0; LSC=1; GPIO_DISPLAY = smg[m%10];
    delayms(1);
    LSA=1; LSB=0; LSC=1; GPIO_DISPLAY = smg[10];
    delayms(1);
    LSA=0; LSB=1; LSC=1; GPIO_DISPLAY = smg[s/10];
    delayms(1);
    LSA=1; LSB=1; LSC=1; GPIO_DISPLAY = smg[s%10];
    delayms(1);
}

void main()
{
    GPIO_DISPLAY = 0x00;
    Timer1Init(); 
    while(1)
    {
        DigDisplay();
    }
}

/*************************************************************************
* 函數(shù)名:      Timer1
* 函數(shù)功能: 定時器1中斷服務(wù)函數(shù),控制數(shù)碼管顯示
* 輸入:           void
* 輸出:           void
**************************************************************************/
void Timer1() interrupt 3
{
    static u16 j;
    // 重新賦初值
    TH1 = 0xFC;
    TL1 = 0x18;
    j++;
    if(1000 == j)
    {
        j=0;
        s++;
        if(60 == s)
        {
            s=0; m++;
            if(60 == m)
            {
                m=0; h++;
                if(24 == h)
                {
                    h=0;
                }
            }
        }
    }
}

仿真結(jié)果:

定時器1和數(shù)碼管實(shí)現(xiàn)一個數(shù)字時鐘
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容