第六章 中断和动态数码管

什么叫中断?
对于这个问题,我的理解是,单片机的功能其实并没有我们想象中的那么强大,不同于我们人类大脑的是,单片机在同一个时间只能完成一件事情。所以,单片机在同一个时间内是无法同时完成数码管的刷新和一个数的分离计算。
所谓中断,即在一个事情发生之后又发生另一件事情,这个时候,如果这个事情的优先级高的话,系统 优先处理更高优先级的一件事。
例如,你在看电视的时候,水烧开了,你就得先去冲水然后在回来看电视,冲水就是一个中断,而水开就是中断的原因,称为中断源。
51单片机的中断优先级只有两个。
作业:1.尝试修改程序,让我们的数码管只显示有效位,也就是高位的0不显示。
2.尝试写一个从999999开始倒计时的程序,并且改用定时器T1的中断来完成,通过写这个程序来掌握定时器和中断的应用。
参考答案
1.

#include <reg52.h>

sbit dula=P2^6;
sbit wela=P2^7;

unsigned char code tableChar[]=
{
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,
};
unsigned char divide[]={0,0,0,0,0,0};
unsigned char i=0;
signed int j=0;
unsigned long sec=0;
unsigned int cnt=0;
unsigned char light[]={0xdf,0xcf,0xc7,0xc3,0xc1,0xc0}; //有效位的真值表

void main()
{
    TMOD=0x01;
    TH0=0xfc;   //setting 10ms
    TL0=0x66;
    TR0=1;
    EA=1;
    ET0=1;
    while(1)
    {
        if(cnt>=1000)
        {
            cnt=0;
            sec++;
            divide[0]=sec%10;divide[1]=sec/10%10;divide[2]=sec/100%10;
            divide[3]=sec/1000%10;divide[4]=sec/10000%10;divide[5]=sec/100000;
            for(j=5;j>=0;j--)
            {if(divide[j]>0) //用于计算数码管到有效位的地方
                break;
            }
        }   
    }

}
void T0_Timer() interrupt 1
{
    TH0=0xfc;
    TL0=0x66;
    cnt++;
    wela=1;
    P0=0xff;
    switch(i)
    {
        case 0: P0=0xfe|light[j];wela=0;dula=1;P0=tableChar[divide[5]];dula=0;i++;break;//或运算用于关闭是零的数码管
        case 1: P0=0xfd|light[j];wela=0;dula=1;P0=tableChar[divide[4]];dula=0;i++;break;
        case 2: P0=0xfb|light[j];wela=0;dula=1;P0=tableChar[divide[3]];dula=0;i++;break;
        case 3: P0=0xf7|light[j];wela=0;dula=1;P0=tableChar[divide[2]];dula=0;i++;break;
        case 4: P0=0xef|light[j];wela=0;dula=1;P0=tableChar[divide[1]];dula=0;i++;break;    //1101 1111
        case 5: P0=0xdf|light[j];wela=0;dula=1;P0=tableChar[divide[0]];dula=0;i=0;break;
        default:break;
    }

}

2.

#include <reg52.h>

sbit dula=P2^6;
sbit wela=P2^7;

unsigned long sec=999999;
unsigned int cnt=0;
unsigned char i=0;
unsigned char code tableChar[]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,
};
unsigned char divide[]={0,0,0,0,0,0};

void main()
{
    TMOD=0x01;
    TH0=0xfc;
    TL0=0x66;
    TR0=1;
    EA=1;
    ET0=1;
    while(1)
    {
        if(cnt>=1000)
        {
            cnt=0;
            sec--;
            divide[0]=sec%10;divide[1]=sec/10%10;divide[2]=sec/100%10;
            divide[3]=sec/1000%10;divide[4]=sec/10000%10;divide[5]=sec/100000;
        }
    }
}

void T0_Timer() interrupt 1
{
    TH0=0xfc;
    TL0=0x66;
    cnt++;
    wela=1;
    P0=0xff;
    switch(i)
    {
        case 0: P0=0xfe;wela=0;dula=1;P0=tableChar[divide[5]];dula=0;i++;break;
        case 1: P0=0xfd;wela=0;dula=1;P0=tableChar[divide[4]];dula=0;i++;break;
        case 2: P0=0xfb;wela=0;dula=1;P0=tableChar[divide[3]];dula=0;i++;break;
        case 3: P0=0xf7;wela=0;dula=1;P0=tableChar[divide[2]];dula=0;i++;break;
        case 4: P0=0xef;wela=0;dula=1;P0=tableChar[divide[1]];dula=0;i++;break; 
        case 5: P0=0xdf;wela=0;dula=1;P0=tableChar[divide[0]];dula=0;i=0;break;
        default:break;
    }
}

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
AT89C51动态数码管显示6数字的实现步骤如下: 1. 定义6个IO口分别连接6个数码管的数码引脚,同时定义一个IO口连接数码管选引脚。 2. 初始化定时器,设置定时器的计数器初值、计数器模式、定时器中断允许等参数。 3. 在定时器中断服务函数中编写控制数码管的代码,实现每隔一段时间更新数码管显示的数字。 4. 在主函数中编写将要显示的数字转换为数码管的对应数字的逻辑,实现动态显示。 具体的实现细节需要根据具体的硬件平台和使用的编译器来进行调整。下面是一个简单的示例代码: ```c #include <reg51.h> sbit LED1 = P1^0; // 数码管1引脚 sbit LED2 = P1^1; // 数码管2引脚 sbit LED3 = P1^2; // 数码管3引脚 sbit LED4 = P1^3; // 数码管4引脚 sbit LED5 = P1^4; // 数码管5引脚 sbit LED6 = P1^5; // 数码管6引脚 sbit DIG = P1^6; // 数码管选引脚 unsigned char code LEDChar[] = { // 数码管显示的字符编码 0x3f, // 0 0x06, // 1 0x5b, // 2 0x4f, // 3 0x66, // 4 0x6d, // 5 0x7d, // 6 0x07, // 7 0x7f, // 8 0x6f // 9 }; void Timer0() interrupt 1 { // 定时器中断服务函数 static unsigned char i = 0; switch (i) { case 0: DIG = 0; LED1 = LEDChar[1]; break; case 1: DIG = 1; LED1 = 0xff; break; case 2: DIG = 0; LED2 = LEDChar[2]; break; case 3: DIG = 1; LED2 = 0xff; break; case 4: DIG = 0; LED3 = LEDChar[3]; break; case 5: DIG = 1; LED3 = 0xff; break; case 6: DIG = 0; LED4 = LEDChar[4]; break; case 7: DIG = 1; LED4 = 0xff; break; case 8: DIG = 0; LED5 = LEDChar[5]; break; case 9: DIG = 1; LED5 = 0xff; break; case 10: DIG = 0; LED6 = LEDChar[6]; break; case 11: DIG = 1; LED6 = 0xff; break; } i++; if (i == 12) i = 0; } void main() { TMOD = 0x01; // 定时器0工作在模式1 TH0 = 0xfc; // 设置定时器初值 TL0 = 0x66; EA = 1; // 开启全局中断 ET0 = 1; // 开启定时器0中断 TR0 = 1; // 启动定时器0 while (1) { unsigned int num = 123456; // 将要显示的数字 unsigned char digit[6]; // 数字的每一 digit[0] = num / 100000; // 计算第1数字 digit[1] = num / 10000 % 10; // 计算第2数字 digit[2] = num / 1000 % 10; // 计算第3数字 digit[3] = num / 100 % 10; // 计算第4数字 digit[4] = num / 10 % 10; // 计算第5数字 digit[5] = num % 10; // 计算第6数字 // 控制数码管显示每一数字 LED1 = LEDChar[digit[0]]; LED2 = LEDChar[digit[1]]; LED3 = LEDChar[digit[2]]; LED4 = LEDChar[digit[3]]; LED5 = LEDChar[digit[4]]; LED6 = LEDChar[digit[5]]; } } ``` 这是一个简单的示例代码,具体的实现方式还需要根据具体的硬件平台和使用的编译器进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值