题解:按钮加减计数器设计(单片机C51)(外部中断)

        需求:使用4位共阴极段码表及共阳极数码管,通过外部中断方式,实现两个按钮分配加1、减1功能。

        今天我就来讲解一下这道题:

目录

1.代码

1.1定义头文件

1.2定义延时函数(毫秒)

1.3定义主函数

1.4定义0~15共阴极数码管字符码

1.5定义中断

1.5.1IE寄存器(中断允许控制)(interrupt enable)

1.5.2IP寄存器

1.5.3定时控制寄存器TCON ( Timer control register )

1.5.4真-定义中断

1.5.5定义中断子程序

1.6计算与显示

1.6.1定义全局变量

1.6.2计算

1.6.3显示

1.7完整代码

2.仿真

3.效果


1.代码

1.1定义头文件

        首先我们定义单片机头文件<reg51.h>

#include<reg51.h>//单片机头文件

1.2定义延时函数(毫秒)

        我们在定义一下延时函数DelayMs(后面会用到),这里我们用两个for循环与一个传参来实现。

        第二个for循环循环120次得出1毫秒。

        第一个for循环与传参ms完成我们需要延时的毫秒。

void DelayMs (const int ms)//延时函数(毫秒)
{
    int i;
    for(i = 0;i < ms;i++)//循环几亳秒
    {
        int j;
        for(j = 0;j < 120;j++);
    }
}

1.3定义主函数

        因为是单片机,所以不需要返回值,所以用void main来定义主函数。

void main()//主函数
{
}

1.4定义0~15共​​​​​​阴极数码管字符码

        因为这个共极数码管字符码不需要做改变,所以我们用const把他锁上。

int mian()
{
    //定义0~15共阴极数码管字符码
    const unsigned char 1ed[] = {0X3F, 0X06, 0X5B, 0X4E, 0X66, 0X6D, 0X7D,0X7,0X7E,0X6E, 0X77, 0X7C, 0X39, 0X5E, 0X79, 0X71};
}

1.5定义中断

        首先我们先了解亿点点中断知识。

1.5.1IE寄存器(中断允许控制)(interrupt enable)

EXO(IE.0) 外部中断0允许位;(interrupt controller of external interrupt)
ETO(IE.1) 定时/计数器TO中断允许位 (interrupt controller of Timer0 interrupt)
EX1(IE.2) 外部中断0允许位
ET1(IE.3) 定时/计数器T1中断允许位
ES (IE.4) 串行口中断允许位; (interrupt controller of serial port)
EA(IE.7)

CPU 中断允许(总允许)位(global all interrupt )

1.5.2IP寄存器

PXO (IP.0) 外部中断0优先级设定位
PTO (IP.1) 定时/计数器TO优先级设定位
PX1 (IP.2) 外部中断0优先级设定位
PT1 (IP.3) 定时/计数器T1优先级设定位
PS   (IP.4) 串行口优先级设定位
PT2 (IP.5) 定时/计数器T2优先级设定位(80C52 的T2)

1.5.3定时控制寄存器TCON ( Timer control register )

ITO (TCON.0) 外部中断0触发方式控制(interruput-0 type control bit )
ITO=0 为电平触发方式
IT0=1 为边沿触发方式(下降沿有效)
IEO (TCON.1) 外部中断0中断请求标志位(external interrupt-0 flag)
IT1 (TCON.2) 外部中断1触发方式控制位
IE1 (TCON.3) 外部中断1中断请求标志位
TRO (TCON.4) 定时/计数器TO运行控制位( timer0 run control bit)
TR1 (TCON.6) 定时/计数器T1运行控制位
TFO(TCON.5) 定时/计数器TO溢出中断请求标志位
TF1 (TCON.7) 定时/计数器T1溢出中断请求标志位( timer1 overflow flag )

        OK,我们这中断知识了解这亿点点就可够了。

1.5.4真-定义中断

int mian()
{
    //定义中断
    IE=0xFF;
    ITO=1;//T1为边沿触发方式(下降沿有效)
    IT1=1;//T2为边沿触发方式(下降沿有效)
}

1.5.5定义中断子程序

    当然我们给配合两个子程序来用。

interrupt 0

指明是外部中断0
interrupt 1 指明是定时器中断0
interrupt 2 指明是外部中断1
interrupt 3 指明是定时器中断1
interrupt 4 指明是串行口中断
void Add() interrupt 0//T2加
{
    if (shu<9999)//防止数值溢出————出现野指针
    {
        shu++;//加
    }
}

void Sub() interrupt 2//T1减
{
    if (shu>0)//防止数值过小————出现野指针
    {
        shu--;//减
    }
}

1.6计算与显示

1.6.1定义全局变量

        先定义一个全局变量shu。

int shu = 1;//数(全局变量)

1.6.2计算

        因为要重复计算,所以我们计算把放到循环里。

int main()
{
    while (1)//死循环
    {
        //定义每一位
        int qian = shu/1000,//千
            bai = shu%1000/100,//百
            shi = shu%100/10,//十
            ge= shu%10;//个
    }
}

1.6.3显示

        因为要重复显示,所以我们再把显示放进去,并延时1毫秒(利用人的视觉误差)。

int main()
{
    while (1)//死循环
    {
        //亮个位
        P3=~ (0x10<<0);
        P2 = 1ed[ge];
        DelayMs (1) ;//延时1亳秒
        //亮十位
        P3=~ (0x10<<1);
        P2 = led[shi];
        DelayMs(1);//延时1亳秒
        //亮百位
        P3=~ (0x10<<2);
        P2 = 1ed[bai];
        DelayMs(1);//延时1亳秒
        //亮千位
        P3=~(0x10<<3) ;
        P2 = led[qian];
        DelayMs (1) ;//延时1亳秒
    }
}

1.7完整代码

#include<reg51.h>//单片机头文件(全局变量)

int shu = 1;//数

void DelayMs (const int ms)//延时函数-毫秒
{
    int i;
    for(i = 0;i < ms;i++)//循环几亳秒
    {
        int j;
        for(j = 0;j < 120;j++);
    }
}

void main()//主函数
{
    //定义0~15共阴极数码管字符码
    const unsigned char 1ed[] = {0X3F, 0X06, 0X5B, 0X4E, 0X66, 0X6D, 0X7D,0X7,0X7E,0X6E, 0X77, 0X7C, 0X39, 0X5E, 0X79, 0X71};
    //定义中断
    IE=0xFF;
    ITO=1;//T1为零终止一次
    IT1=1;//T2为零终止一次
    while (1)//死循环
    {
        //定义每一位
        int qian = shu/1000,//千
            bai = shu%1000/100,//百
            shi = shu%100/10,//十
            ge= shu%10;//个
        //亮个位
        P3=~ (0x10<<0);
        P2 = 1ed[ge];
        DelayMs (1) ;//延时1亳秒
        //亮十位
        P3=~ (0x10<<1);
        P2 = led[shi];
        DelayMs(1);//延时1亳秒
        //亮百位
        P3=~ (0x10<<2);
        P2 = 1ed[bai];
        DelayMs(1);//延时1亳秒
        //亮千位
        P3=~(0x10<<3) ;
        P2 = led[qian];
        DelayMs (1) ;//延时1亳秒
    }
}

void Add() interrupt 0//T2加
{
    if (shu<9999)//防止数值溢出————出现野指针
    {
        shu++;//加
    }
}

void Sub() interrupt 2//T1减
{
    if (shu>0)//防止数值过小————出现野指针
    {
        shu--;//减
    }
}

2.仿真

        因为这次程序非常简单,所以只需要4个元件:

        Component Mode中的7SEG-MPX4-CC(共阳极数码管)与AT89C51(单片机)与BUTTON(按钮)。

        Terminals Mode中的GROUND(负极)。

布局如下:

3.效果

制作不易,你懂得。 

按钮加减计数器

物联沃分享整理
物联沃-IOTWORD物联网 » 题解:按钮加减计数器设计(单片机C51)(外部中断)

发表评论