51单片机定时器/计数器:使用矩阵按键1-9在数码管中输入时间(最长99秒),按下独立按键K1开始计时,计时结束时蜂鸣器会响

相信大家在拿到这种题目时会非常头疼,因为其中涉及到的元素太多了,在网上查找的话又都是一些写的很复杂的代码,很难短时间看懂,为此,我把我写的简易代码为大家献上,方便大家快速上手,能轻松通过实验室考核。

效果视频:【51单片机倒计时】https://www.bilibili.com/video/BV12w411T7N2?vd_source=9215ca1d564d248da9d7f7a69f4f40d7

一.了解需要用到的函数

1.定时器初始化函数可以直接拿来用,理解为给定时器重置,清除上一次已使用过的值)

#include<REGX52.H>


void Timer0_Init()        //1毫秒@12.000MHz
{
    TMOD &= 0xF0;            //设置定时器模式
    TMOD |= 0x01;            //设置定时器模式
    TH0 = (65536-45872)/256;      //装好初值
    TL0 = (65536-45872)%256;
    TF0 = 0;                //清除TF0标志
    TR0 = 1;                //定时器0开始计时
    ET0=1;                //打开定时器0中断允许
    EA=1;                   //打开总中断
    PT0=0;                
}

2.延迟函数(它的作用可以简单理解为让某个状态保持一段时间,比如让LED一直亮3s)

#include<REGX52.H>

void Delay(unsigned int xms)        //@12.000MHz
{
    unsigned char i, j;
    while(xms)
    {
        i = 2;
        j = 239;
            do
            {
                while (--j);
            } while (--i);
            xms--;
    }
}

3.矩阵按键输入函数作用为返回按下的按键所代表的值,具体的原理看这里[6-1] 矩阵键盘_哔哩哔哩_bilibili

#include<REGX52.h>
#include"Delay.h"

unsigned char MatrixKey()
{
    unsigned char KeyNumber=0;
    
    P1=0xFF;
    P1_3=0;
    if(P1_7==0){Delay(60);while(P1_7==0){Delay(60);KeyNumber=1;}}
    if(P1_6==0){Delay(60);while(P1_6==0){Delay(60);KeyNumber=5;}}
    if(P1_5==0){Delay(60);while(P1_5==0){Delay(60);KeyNumber=9;}}
    if(P1_4==0){Delay(60);while(P1_4==0){Delay(60);KeyNumber=13;}}

    P1=0xFF;
    P1_2=0;
    if(P1_7==0){Delay(60);while(P1_7==0){Delay(60);KeyNumber=2;}}
    if(P1_6==0){Delay(60);while(P1_6==0){Delay(60);KeyNumber=6;}}
    if(P1_5==0){Delay(60);while(P1_5==0){Delay(60);KeyNumber=10;}}
    if(P1_4==0){Delay(60);while(P1_4==0){Delay(60);KeyNumber=14;}}

    P1=0xFF;
    P1_1=0;
    if(P1_7==0){Delay(60);while(P1_7==0){Delay(60);KeyNumber=3;}}
    if(P1_6==0){Delay(60);while(P1_6==0){Delay(60);KeyNumber=7;}}
    if(P1_5==0){Delay(60);while(P1_5==0){Delay(60);KeyNumber=11;}}
    if(P1_4==0){Delay(60);while(P1_4==0){Delay(60);KeyNumber=15;}}

    P1=0xFF;
    P1_0=0;
    if(P1_7==0){Delay(60);while(P1_7==0){Delay(60);KeyNumber=4;}}
    if(P1_6==0){Delay(60);while(P1_6==0){Delay(60);KeyNumber=8;}}
    if(P1_5==0){Delay(60);while(P1_5==0){Delay(60);KeyNumber=12;}}
    if(P1_4==0){Delay(60);while(P1_4==0){Delay(60);KeyNumber=16;}}

    return KeyNumber;
}

4.数码管显示函数(顾名思义,具体的原理看这里[4-1] 静态数码管显示_哔哩哔哩_bilibili

#include<REGX52.H>
#include"Delay.h"

void Nixie(unsigned char Location,Number)
{
    unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0X77,0X7C,0X39,0X5E,0X79,0X71,0X00};
    switch(Location)
    {
        case 1:P2_4=1;P2_3=1;P2_2=1;break;
        case 2:P2_4=1;P2_3=1;P2_2=0;break;
        case 3:P2_4=1;P2_3=0;P2_2=1;break;
        case 4:P2_4=1;P2_3=0;P2_2=0;break;
        case 5:P2_4=0;P2_3=1;P2_2=1;break;
        case 6:P2_4=0;P2_3=1;P2_2=0;break;
        case 7:P2_4=0;P2_3=0;P2_2=1;break;
        case 8:P2_4=0;P2_3=0;P2_2=0;break;    
    }    
    P0=NixieTable[Number];
    //消影
    Delay(1);
    P0=0x00;
}

5.蜂鸣器函数(作用为让蜂鸣器响一定的时间,时间单位为ms)

#include<REGX52.H>
#include<INTRINS.H>        

//蜂鸣器私有延迟函数
void Buzzer_Delay500us()        //@12.000MHz
{
    unsigned char i;

    _nop_();
    i = 247;
    while (--i);
}

//蜂鸣器端口:
sbit Buzzer=P1^5;

//蜂鸣器鸣响,单位为ms
void Buzzer_Time(unsigned int ms)
{
    unsigned int i;
    for(i=0;i<ms*2;i++)
             {
                 Buzzer=!Buzzer;
                Buzzer_Delay500us();
             }
}

二.清楚了各个函数的作用后,我们需要添加各个函数到工程中

1.创建文件

2.把相应的函数复制过来

3.先编译,然后点击“是”

4.文件名:相应的函数名+.c

5.双击Source Group 1

6.添加函数的.c文件到工程中

7.再次创建一个文件,按下面的格式输入该函数的.h代码(每个函数的.h代码都是相同模板的)

8.双击Source Group 1,选择图示文件类型

9.添加函数的.h文件到工程中

三.创建名称为main.c的文件,粘贴复制下面的main函数和中断函数

//调用添加到工程中的各个函数

#include<REGX52.H>
#include"Delay.h"
#include"Nixie.h"
#include"Buzzer.h"
#include"MatrixKey.h"
#include"Timer0.h"    

//flag1,flag2为标志位,作用是根据需要让数码管显示不同的数

unsigned int shu,num,num1=0,num2=0,flag1=0,flag2=0;
char shi=0,ge=0;        //shi为十位数字,ge为个位数字
void main()
{
        while(1)
        {
            num=MatrixKey();                //把矩阵键盘输入的数字赋值给num
            if(num)
            {
                shu=num;                //shu变量为存储num值的中间变量
                flag1++;
            }

            if(flag1==1)
                shi=shu;                //矩阵键盘第一次按下产生的值赋值给十位数字

            if(flag1>=1)
                Nixie(7,shi);                //数码管显示十位数字

            if(flag1==2)
                ge=shu;                      //矩阵键盘第二次按下产生的值赋值给个位数字

            if(flag1==2)
                Nixie(8,ge);                /数码管显示个位数字

            if(P3_1==0)                //按下独立按键K1后开始倒计时
            {
                Delay(60);
                while(P3_1==0)
                {
                    Delay(60);
                    flag1=0;
                    flag2++;
                    Timer0_Init();    //初始化中断函数(中断函数从你打开单片机开始就一直在自动执行)
                    num2++;            //让中断函数开始对ge和shi两个变量发挥作用
                }    
            }

            if(flag2>0)
            {
                    Nixie(7,shi);         //数码管显示倒计时时的十位数字
                    Nixie(8,ge);        //数码管显示倒计时时的个位数字
            }    
        }
}


void TimerI_Routine(void) interrupt 1          //1为定时器/计数器0的中断号
{
    TH0 = (65536-45872)/256;  //方式1需要重装初值
    TL0 = (65536-45872)%256;
    
    num1++;   //mun1变量自加1
    if(num1 == 20 && num2 > 0)   //判断定时时间是否等于1s 
    {
        num1 = 0;   //清零,好判断下次计时
        ge--;     
        if(ge<0)
        {
            ge=9;
            shi--;
        }
        if( shi < 0) //判断是否计时结束
        {
            shi=0;          
            ge=0;      
            Buzzer_Time(10000); 
        }
    }
}

    

四.    编译主函数,将代码烧录到单片机中

烧录后的操作顺序:先后按下矩阵键盘上的两个数字(只能按1-9)在数码管上显示十位和个位数字→按下独立按键K1→数码管开始倒计时,结束后蜂鸣器自动响。

补充:

若用的和我一样用的是普中ISP烧录软件,注意每次烧录时的波特率,一定要改为9600

供参考的数据类型的范围:

  • 6
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

终章之下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值