51单片机简易计算器矩阵键盘4行四列两个四位数码管显示代码
时间: 2023-11-13 10:03:47 浏览: 104
数码管显示4×4键盘矩阵按键_c_数码管_51单片机_protues_矩阵键盘_
5星 · 资源好评率100%
以下是基于51单片机的简易计算器矩阵键盘4行四列两个四位数码管显示代码,其中使用了定时器中断和数码管扫描技术:
```c
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit SCL = P1^0; // I2C 时钟
sbit SDA = P1^1; // I2C 数据
sbit D1 = P2^7;
sbit D2 = P2^6;
sbit D3 = P2^5;
sbit D4 = P2^4;
sbit L1 = P2^3;
sbit L2 = P2^2;
sbit L3 = P2^1;
sbit L4 = P2^0;
uchar cnt, key, flag;
uchar num1[4], num2[4], num3[4];
uchar op, result[4];
void delay(uint x) // 延时函数
{
uint i, j;
for (i = x; i > 0; i--)
for (j = 110; j > 0; j--);
}
void i2c_start() // I2C 起始信号
{
SDA = 1;
SCL = 1;
delay(1);
SDA = 0;
delay(1);
SCL = 0;
}
void i2c_stop() // I2C 停止信号
{
SDA = 0;
SCL = 1;
delay(1);
SDA = 1;
delay(1);
}
void i2c_write(uchar dat) // I2C 写入数据
{
uchar i;
for (i = 0; i < 8; i++)
{
SDA = dat & 0x80;
SCL = 1;
delay(1);
SCL = 0;
dat <<= 1;
}
SDA = 1;
SCL = 1;
delay(1);
SCL = 0;
}
uchar keypad_scan() // 扫描矩阵键盘
{
uchar key_val = 0;
uchar row, col;
for (col = 0; col < 4; col++)
{
P0 = 0x0f << 4;
P0 |= (1 << col) << 4;
delay(1);
row = P0 >> 4;
if (row != 0x0f)
{
switch (row)
{
case 0x07: key_val = col + 1; break;
case 0x0b: key_val = col + 5; break;
case 0x0d: key_val = col + 9; break;
case 0x0e: key_val = col + 13; break;
}
while (row != 0x0f)
{
delay(1);
row = P0 >> 4;
}
break;
}
}
return key_val;
}
void display() // 数码管显示函数
{
uchar i;
uchar code table[] = { // 数码管字符编码
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71
};
for (i = 0; i < 4; i++)
{
switch (i)
{
case 0: L1 = 0; L2 = 1; L3 = 1; L4 = 1; break;
case 1: L1 = 1; L2 = 0; L3 = 1; L4 = 1; break;
case 2: L1 = 1; L2 = 1; L3 = 0; L4 = 1; break;
case 3: L1 = 1; L2 = 1; L3 = 1; L4 = 0; break;
}
if (flag == 1) // 显示 num1
{
D1 = 0; D2 = 0; D3 = 0; D4 = 0;
P0 = table[num1[i]];
}
else if (flag == 2) // 显示 num2
{
D1 = 0; D2 = 0; D3 = 0; D4 = 0;
P0 = table[num2[i]];
}
else if (flag == 3) // 显示 num1 + num2
{
D1 = 0; D2 = 0; D3 = 0; D4 = 0;
P0 = table[num1[i]];
delay(1);
switch (op)
{
case 1: P0 = table[10]; break; // +
case 2: P0 = table[11]; break; // -
case 3: P0 = table[12]; break; // *
case 4: P0 = table[13]; break; // /
}
delay(1);
P0 = table[num2[i]];
}
else if (flag == 4) // 显示结果
{
D1 = 0; D2 = 0; D3 = 0; D4 = 0;
P0 = table[result[i]];
}
delay(1);
}
}
void timer0_init() // 定时器0初始化函数
{
TMOD &= 0xf0;
TMOD |= 0x01;
TH0 = 0xfc;
TL0 = 0x67;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void timer0_isr() interrupt 1 // 定时器0中断服务函数
{
TH0 = 0xfc;
TL0 = 0x67;
cnt++;
if (cnt >= 100)
{
cnt = 0;
key = keypad_scan();
if (key != 0)
{
switch (key)
{
case 1: num1[3]++; break;
case 2: num1[2]++; break;
case 3: num1[1]++; break;
case 4: op = 1; flag = 2; break; // +
case 5: num2[3]++; break;
case 6: num2[2]++; break;
case 7: num2[1]++; break;
case 8: op = 2; flag = 2; break; // -
case 9: num1[0]++; break;
case 10: num2[0]++; break;
case 11: op = 3; flag = 2; break; // *
case 12: flag = 3; break; // =
case 13: num1[3] = num1[2] = num1[1] = num1[0] = 0;
num2[3] = num2[2] = num2[1] = num2[0] = 0;
result[3] = result[2] = result[1] = result[0] = 0;
flag = 1; break; // C
case 14: op = 4; flag = 2; break; // /
}
}
if (num1[3] >= 10) { num1[3] = 0; num1[2]++; }
if (num1[2] >= 10) { num1[2] = 0; num1[1]++; }
if (num1[1] >= 10) { num1[1] = 0; num1[0]++; }
if (num2[3] >= 10) { num2[3] = 0; num2[2]++; }
if (num2[2] >= 10) { num2[2] = 0; num2[1]++; }
if (num2[1] >= 10) { num2[1] = 0; num2[0]++; }
if (flag == 3) // 计算结果
{
uchar n1 = num1[3] * 1000 + num1[2] * 100 + num1[1] * 10 + num1[0];
uchar n2 = num2[3] * 1000 + num2[2] * 100 + num2[1] * 10 + num2[0];
switch (op)
{
case 1: n1 += n2; break;
case 2: n1 -= n2; break;
case 3: n1 *= n2; break;
case 4: n1 /= n2; break;
}
result[3] = n1 / 1000;
result[2] = (n1 % 1000) / 100;
result[1] = (n1 % 100) / 10;
result[0] = n1 % 10;
flag = 4;
}
display();
}
}
void main()
{
flag = 1;
timer0_init();
while (1);
}
```
该代码实现了四则运算(加、减、乘、除)和清零功能。在使用时,需要连接矩阵键盘和两个四位数码管,并按照注释修改代码中相应的引脚定义。
阅读全文