写一个 基于89C51单片机芯片, 4*4矩阵键盘 的C语言程序
时间: 2024-06-09 17:07:45 浏览: 194
基于AT89C51单片机的电子密码锁驱动程序
下面是一个基于89C51单片机芯片,4x4矩阵键盘的C语言程序。该程序使用了中断来处理按键事件,将按下的键值输出到串口。
```c
#include <reg51.h>
#define FREQ_OSC 11059200UL // 单片机外部晶振频率
#define BAUD_RATE 9600 // 串口波特率
#define TIMER0_RELOAD_VALUE 156 // 定时器0重装值,实现10ms定时
sbit ROW1 = P0^0;
sbit ROW2 = P0^1;
sbit ROW3 = P0^2;
sbit ROW4 = P0^3;
sbit COL1 = P0^4;
sbit COL2 = P0^5;
sbit COL3 = P0^6;
sbit COL4 = P0^7;
void init_serial_port();
void init_timer0();
void init_interrupts();
void scan_keypad();
void send_char(char c);
volatile unsigned char key_value;
void main()
{
init_serial_port();
init_timer0();
init_interrupts();
while (1)
{
if (key_value != 0)
{
send_char(key_value);
key_value = 0;
}
}
}
void init_serial_port()
{
TMOD = 0x20; // 定时器1工作在模式2,8位自动重装
TH1 = 256 - FREQ_OSC / 32 / 12 / BAUD_RATE; // 计算波特率重载值
SCON = 0x50; // 串口工作在模式1,启用接收
TR1 = 1; // 启动定时器1
}
void init_timer0()
{
TMOD |= 0x01; // 定时器0工作在模式1,16位自动重装
TH0 = (65536 - TIMER0_RELOAD_VALUE) / 256;
TL0 = (65536 - TIMER0_RELOAD_VALUE) % 256;
TR0 = 1; // 启动定时器0
}
void init_interrupts()
{
EA = 1; // 启用全局中断
ET0 = 1; // 启用定时器0中断
EX0 = 1; // 启用外部中断0
IT0 = 1; // 设置外部中断0为下降沿触发
}
void scan_keypad()
{
ROW1 = 0; ROW2 = 1; ROW3 = 1; ROW4 = 1;
if (COL1 == 0) key_value = '1';
if (COL2 == 0) key_value = '2';
if (COL3 == 0) key_value = '3';
if (COL4 == 0) key_value = 'A';
ROW1 = 1; ROW2 = 0; ROW3 = 1; ROW4 = 1;
if (COL1 == 0) key_value = '4';
if (COL2 == 0) key_value = '5';
if (COL3 == 0) key_value = '6';
if (COL4 == 0) key_value = 'B';
ROW1 = 1; ROW2 = 1; ROW3 = 0; ROW4 = 1;
if (COL1 == 0) key_value = '7';
if (COL2 == 0) key_value = '8';
if (COL3 == 0) key_value = '9';
if (COL4 == 0) key_value = 'C';
ROW1 = 1; ROW2 = 1; ROW3 = 1; ROW4 = 0;
if (COL1 == 0) key_value = '*';
if (COL2 == 0) key_value = '0';
if (COL3 == 0) key_value = '#';
if (COL4 == 0) key_value = 'D';
ROW1 = 1; ROW2 = 1; ROW3 = 1; ROW4 = 1;
}
void send_char(char c)
{
SBUF = c;
while (TI == 0);
TI = 0;
}
void timer0_isr() interrupt 1
{
TH0 = (65536 - TIMER0_RELOAD_VALUE) / 256;
TL0 = (65536 - TIMER0_RELOAD_VALUE) % 256;
scan_keypad();
}
void external0_isr() interrupt 0
{
key_value = 0;
}
```
在该程序中,我们首先设置了单片机的外部晶振频率和串口波特率。然后初始化了串口和定时器0,以及启用了全局中断和外部中断0。在主函数中,我们不断检查是否有按键被按下,如果有则将按键值输出到串口。
在定时器0中断服务程序中,我们使用了定时器0来实现10ms的定时,以便周期性地扫描键盘。在外部中断0服务程序中,我们将按键值清零,以便下一次扫描时检测到该按键被释放。
阅读全文