用51单片机计时器实现,使用矩阵键盘作为输入,设计一个倒计时装置。可用矩阵键盘S1-S9键输入1-500秒的倒计时,S10键启动倒计时,S11键重置。倒计时可以用数码管显示,倒计时结束后,数码管显示全0。
时间: 2023-06-27 12:01:55 浏览: 169
好的,这是一个简单的计时器设计,需要借助51单片机的计时器和矩阵键盘输入,下面是具体的实现步骤:
1. 确定硬件连接:将矩阵键盘的行列引脚分别连接到51单片机的端口上,数码管的引脚连接到51单片机的另一个端口上。
2. 初始化计时器:使用51单片机的定时器,设置计时器的计时周期为1秒,并将计时器中断打开。
3. 矩阵键盘扫描:使用循环扫描矩阵键盘的输入,判断当前按下的键位。
4. 输入倒计时时间:当输入按键为S1-S9时,将按键对应的数字存储到一个变量中,最多输入三位数字,即最大倒计时时间为500秒。
5. 启动倒计时:当按下S10键时,计时器开始倒计时,并在数码管上显示倒计时时间。
6. 倒计时中断:当计时器中断时,倒计时时间减1秒,并在数码管上重新显示倒计时时间。
7. 倒计时结束:当倒计时时间为0时,数码管显示全0,倒计时结束。
8. 重置倒计时:当按下S11键时,将倒计时时间和数码管中的数字重置为0。
以上是一个简单的倒计时器的设计实现过程,需要注意的是,在具体实现过程中,需要结合51单片机的具体开发工具和相关编程语言来实现。
相关问题
用51单片机计时器实现,倒计时使用单片机计时器实现,使用矩阵键盘作为输入,设计一个倒计时装置。可用矩阵键盘S1-S9键输入1-500秒的倒计时,S10键启动倒计时,S11键重置。倒计时可以用数码管显示,倒计时结束后,数码管显示全0。
好的,这是一个比较基础的单片机应用,下面我将给出一个简单的实现方法。
首先,我们需要确定使用的单片机型号,以及数码管和矩阵键盘的型号,然后进行硬件电路的连接。
接下来,我们就可以开始编写程序了,具体步骤如下:
1. 定义数码管显示的端口和位选信号端口。
2. 定义矩阵键盘的端口和扫描代码。
3. 定义定时器的中断服务程序,实现倒计时功能。
4. 实现主程序,处理矩阵键盘输入和数码管显示。
程序框图如下:
![倒计时程序框图](https://img-blog.csdnimg.cn/2021120815240095.png)
下面逐一解释各部分代码实现。
1. 数码管显示部分:
```c
//数码管位选信号端口
sbit dig1 = P1^0;
sbit dig2 = P1^1;
sbit dig3 = P1^2;
sbit dig4 = P1^3;
//数码管段选信号端口
sbit segA = P2^0;
sbit segB = P2^1;
sbit segC = P2^2;
sbit segD = P2^3;
sbit segE = P2^4;
sbit segF = P2^5;
sbit segG = P2^6;
sbit segDP = P2^7;
//数码管显示0~9
const unsigned char digCode[10] = {
0x3F, //0
0x06, //1
0x5B, //2
0x4F, //3
0x66, //4
0x6D, //5
0x7D, //6
0x07, //7
0x7F, //8
0x6F //9
};
//数码管显示函数
void display(unsigned char dig[], unsigned char num){
dig1 = 1; dig2 = 1; dig3 = 1; dig4 = 1; //关闭所有数码管
switch(num){ //根据num值选择位选信号
case 1: dig1 = 0; break;
case 2: dig2 = 0; break;
case 3: dig3 = 0; break;
case 4: dig4 = 0; break;
default: break;
}
P0 = digCode[dig[num-1]]; //根据数码管码表选定段选信号
}
```
2. 矩阵键盘部分:
```c
//矩阵键盘端口定义
sbit row1 = P3^0;
sbit row2 = P3^1;
sbit row3 = P3^2;
sbit row4 = P3^3;
sbit col1 = P3^4;
sbit col2 = P3^5;
sbit col3 = P3^6;
//矩阵键盘扫描函数
unsigned char keyScan(){
unsigned char keyValue = 0;
row1 = 0; row2 = 1; row3 = 1; row4 = 1; //扫描第一行
if(col1 == 0){ keyValue = 1; }
if(col2 == 0){ keyValue = 2; }
if(col3 == 0){ keyValue = 3; }
row1 = 1; row2 = 0; row3 = 1; row4 = 1; //扫描第二行
if(col1 == 0){ keyValue = 4; }
if(col2 == 0){ keyValue = 5; }
if(col3 == 0){ keyValue = 6; }
row1 = 1; row2 = 1; row3 = 0; row4 = 1; //扫描第三行
if(col1 == 0){ keyValue = 7; }
if(col2 == 0){ keyValue = 8; }
if(col3 == 0){ keyValue = 9; }
row1 = 1; row2 = 1; row3 = 1; row4 = 0; //扫描第四行
if(col1 == 0){ keyValue = 10; }
if(col2 == 0){ keyValue = 0; }
if(col3 == 0){ keyValue = 11; }
return keyValue;
}
```
3. 定时器部分:
```c
//定时器中断服务程序
void timer0() interrupt 1{
static unsigned char cnt = 0; //计数器
static unsigned int sec = 0; //秒数
cnt++;
if(cnt == 20){ //计数器达到20,表示1秒钟到了
sec--; //秒数减一
cnt = 0; //计数器清零
}
if(sec == 0){ //倒计时结束
TH0 = 0; TL0 = 0; //定时器清零
display(digCode, 1); display(digCode, 2); //数码管显示全0
display(digCode, 3); display(digCode, 4);
}
}
```
4. 主程序部分:
```c
//主程序
void main(){
unsigned char keyValue = 0; //存储矩阵键盘输入值
unsigned int sec = 0; //存储倒计时时间
unsigned char dig[4] = {0}; //存储要显示的数码管数值
TMOD = 0x01; //定时器0工作在模式1
TH0 = 0; TL0 = 0; //定时器清零
EA = 1; ET0 = 1; //打开总中断和定时器0中断
while(1){
keyValue = keyScan(); //扫描矩阵键盘
if(keyValue >= 1 && keyValue <= 9){ //输入倒计时时间
sec = sec * 10 + keyValue;
if(sec > 500){ sec = 500; } //最大倒计时时间为500秒
dig[0] = sec / 100; dig[1] = sec % 100 / 10; //分离出每一位数码管显示值
dig[2] = sec % 10; dig[3] = 0;
display(dig, 1); display(dig, 2); //数码管显示每一位
display(dig, 3); display(dig, 4);
}
else if(keyValue == 10){ //启动倒计时
TH0 = 0xFF; TL0 = 0xFE; //定时器初值为65536-50=65586
sec--; //秒数减一
}
else if(keyValue == 11){ //重置倒计时
TH0 = 0; TL0 = 0; //定时器清零
sec = 0; //秒数清零
dig[0] = 0; dig[1] = 0; //数码管显示全0
dig[2] = 0; dig[3] = 0;
display(dig, 1); display(dig, 2);
display(dig, 3); display(dig, 4);
}
else{ //其它情况,不进行任何操作
;
}
}
}
```
注意:以上代码为示例代码,具体实现需要根据硬件电路和单片机型号进行微调。
用51单片机,使用矩阵键盘作为输入,设计一个倒计时装置。可用矩阵键盘S1-S9键输入1-500秒的倒计时,S10键启动倒计时,S11键重置。倒计时可以用数码管显示,倒计时结束后,数码管显示全0。
这个倒计时装置的实现可以分为以下几个步骤:
1. 矩阵键盘的输入检测和处理:使用4行3列的矩阵键盘,对应P1.0-P1.3为行,P1.4-P1.6为列。扫描键盘时,先将所有列置高电平,然后循环将每一行置低电平,检测每列是否有按键按下。如果有按键按下,则记录下按键对应的数字(1-9),或者启动倒计时(S10键),或者重置(S11键)。
2. 倒计时的计算和显示:将按下的数字累加到倒计时总秒数中,然后每秒钟递减1,直到计数器归零。倒计时过程中,将计数器的值转换为BCD码,然后依次显示在4位共阳数码管上。
3. 重置功能的实现:将倒计时总秒数清零,并将数码管显示全0。
下面是详细的程序代码实现:
```c
#include <reg52.h>
// 数码管位选和段选定义
sbit DIG1 = P0^0;
sbit DIG2 = P0^1;
sbit DIG3 = P0^2;
sbit DIG4 = P0^3;
sbit SEG_A = P2^0;
sbit SEG_B = P2^1;
sbit SEG_C = P2^2;
sbit SEG_D = P2^3;
sbit SEG_E = P2^4;
sbit SEG_F = P2^5;
sbit SEG_G = P2^6;
sbit SEG_DP = P2^7;
// 矩阵键盘定义
sbit KBD_ROW1 = P1^0;
sbit KBD_ROW2 = P1^1;
sbit KBD_ROW3 = P1^2;
sbit KBD_ROW4 = P1^3;
sbit KBD_COL1 = P1^4;
sbit KBD_COL2 = P1^5;
sbit KBD_COL3 = P1^6;
// 常量定义
#define KEY_NONE 0
#define KEY_S1 1
#define KEY_S2 2
#define KEY_S3 3
#define KEY_S4 4
#define KEY_S5 5
#define KEY_S6 6
#define KEY_S7 7
#define KEY_S8 8
#define KEY_S9 9
#define KEY_START 10
#define KEY_RESET 11
#define MAX_COUNT 500
// 变量定义
unsigned int count; // 倒计时总秒数
unsigned char key; // 当前按下的键值
unsigned char disp[4]; // 数码管显示的BCD码
// 函数声明
void delayms(unsigned int ms);
void kbd_scan(void);
unsigned char kbd_get_key(void);
void disp_update(void);
void count_down(void);
// 主函数
void main() {
// 初始化
count = 0;
key = KEY_NONE;
disp[0] = 0;
disp[1] = 0;
disp[2] = 0;
disp[3] = 0;
while (1) {
// 检测键盘输入
kbd_scan();
// 处理键盘输入
if (key != KEY_NONE) {
switch (key) {
case KEY_START:
count_down();
break;
case KEY_RESET:
count = 0;
disp[0] = 0;
disp[1] = 0;
disp[2] = 0;
disp[3] = 0;
break;
default:
if (count < MAX_COUNT) {
count += key;
if (count > MAX_COUNT) {
count = MAX_COUNT;
}
disp_update();
}
break;
}
key = KEY_NONE;
}
}
}
// 延时函数,1ms
void delayms(unsigned int ms) {
unsigned int i, j;
for (i = 0; i < ms; i++) {
for (j = 0; j < 110; j++);
}
}
// 扫描键盘,检测当前按下的键值
void kbd_scan(void) {
unsigned char row;
unsigned char col;
unsigned char k;
for (col = 0; col < 3; col++) {
// 将列置高电平
switch (col) {
case 0: KBD_COL1 = 1; KBD_COL2 = 0; KBD_COL3 = 0; break;
case 1: KBD_COL1 = 0; KBD_COL2 = 1; KBD_COL3 = 0; break;
case 2: KBD_COL1 = 0; KBD_COL2 = 0; KBD_COL3 = 1; break;
}
// 检测每一行是否有按键按下
for (row = 0; row < 4; row++) {
switch (row) {
case 0: KBD_ROW1 = 0; KBD_ROW2 = 1; KBD_ROW3 = 1; KBD_ROW4 = 1; break;
case 1: KBD_ROW1 = 1; KBD_ROW2 = 0; KBD_ROW3 = 1; KBD_ROW4 = 1; break;
case 2: KBD_ROW1 = 1; KBD_ROW2 = 1; KBD_ROW3 = 0; KBD_ROW4 = 1; break;
case 3: KBD_ROW1 = 1; KBD_ROW2 = 1; KBD_ROW3 = 1; KBD_ROW4 = 0; break;
}
// 检测当前行是否有按键按下
if (KBD_COL1 == 0 || KBD_COL2 == 0 || KBD_COL3 == 0) {
delayms(10); // 延时去抖
if (KBD_COL1 == 0 || KBD_COL2 == 0 || KBD_COL3 == 0) {
// 记录按键值
k = row * 3 + col + 1;
if (k <= 9) {
key = k;
} else if (k == 10) {
key = KEY_START;
} else if (k == 11) {
key = KEY_RESET;
}
return;
}
}
}
}
key = KEY_NONE;
}
// 获取当前按下的键值
unsigned char kbd_get_key(void) {
unsigned char k;
do {
kbd_scan();
} while (key == KEY_NONE);
k = key;
key = KEY_NONE;
return k;
}
// 更新数码管显示
void disp_update(void) {
unsigned int t = count;
disp[0] = t % 10;
t /= 10;
disp[1] = t % 10;
t /= 10;
disp[2] = t % 10;
t /= 10;
disp[3] = t % 10;
}
// 倒计时函数
void count_down(void) {
unsigned int i;
while (count > 0) {
disp_update();
delayms(1000); // 延时1秒
count--;
}
disp[0] = 0;
disp[1] = 0;
disp[2] = 0;
disp[3] = 0;
}
```
需要注意的是,由于51单片机没有内置的定时器,所以倒计时的实现采用了延时函数。这种方法的精度较低,倒计时过程中可能会有一些误差。如果需要更高的精度,可以考虑使用外部定时器或者RTC芯片来实现倒计时功能。