相信大家在拿到这种题目时会非常头疼,因为其中涉及到的元素太多了,在网上查找的话又都是一些写的很复杂的代码,很难短时间看懂,为此,我把我写的简易代码为大家献上,方便大家快速上手,能轻松通过实验室考核。
效果视频:【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。
供参考的数据类型的范围: