单元训练07:矩阵键盘的基本操作-sbit写法

蓝桥杯 小蜜蜂 单元训练07:矩阵键盘的基本操作

sbit写法中加入了定时器使用。

#include "stc15f2k60s2.h"

typedef unsigned char uint8_t;

uint8_t timerCounter = 0;
uint8_t timerEnable = 0;

#define LED(X)                   \
    {                            \
        P0 = X;                  \
        P2 = (P2 & 0x1f | 0x80); \
        P2 &= 0x1f;              \
    }
// 数码管
// 段选
#define COM(x)                 \
    {                          \
        P0 = x;                \
        P2 = P2 & 0x1F | 0xc0; \
        P2 &= 0x1F;            \
    }
// 位选
#define SEG(x)                 \
    {                          \
        P0 = x;                \
        P2 = P2 & 0x1F | 0xE0; \
        P2 &= 0x1F;            \
    }
code unsigned char Seg_Table[] =
    {
        0xc0, // 0
        0xf9, // 1
        0xa4, // 2
        0xb0, // 3
        0x99, // 4
        0x92, // 5
        0x82, // 6
        0xf8, // 7
        0x80, // 8
        0x90, // 9
        0x88, // A
        0x83, // b
        0xc6, // C
        0xa1, // d
        0x86, // E
        0x8e  // F
}; // 表不用记,官方提供资源包里面有。

// 数码管第一位显示
void DisplayNo1(uint8_t no)
{
    COM(0x01);
    SEG(Seg_Table[no]);
}

// 矩阵键盘 行
sbit row1 = P3 ^ 0;
sbit row2 = P3 ^ 1;
sbit row3 = P3 ^ 2;
sbit row4 = P3 ^ 3;
// 矩阵键盘 列
sbit col1 = P4 ^ 4;
sbit col2 = P4 ^ 2;
sbit col3 = P3 ^ 5;
sbit col4 = P3 ^ 4;

void ClearRow()
{
    row1 = 0;
    row2 = 0;
    row3 = 0;
    row4 = 0;

    col1 = 1;
    col2 = 1;
    col3 = 1;
    col4 = 1;
}
void ClearCol()
{
    col1 = 0;
    col2 = 0;
    col3 = 0;
    col4 = 0;

    row1 = 1;
    row2 = 1;
    row3 = 1;
    row4 = 1;
}

code uint8_t ArrayNum[4][4] = {
    {0, 1, 2, 3},
    {4, 5, 6, 7},
    {8, 9, 10, 11},
    {12, 13, 14, 15}};

uint8_t keyStatus;

uint8_t key_row;
uint8_t key_col;
uint8_t keyValue = 255;

void KeyScan()
{
    switch (keyStatus)
    {
    case 0:
        ClearCol();
        if ((row1 == 0) || (row2 == 0) || (row3 == 0) || (row4 == 0))
        {
            keyStatus = 1;
        }
        break;
    case 1:
        ClearCol();
        if (row1 == 0)
        {
            key_row = 1;
            keyStatus = 2;
        }
        else if (row2 == 0)
        {
            key_row = 2;
            keyStatus = 2;
        }
        else if (row3 == 0)
        {
            key_row = 3;
            keyStatus = 2;
        }
        else if (row4 == 0)
        {
            key_row = 4;
            keyStatus = 2;
        }
        break;
    case 2:
        ClearRow();
        if (col1 == 0)
        {
            key_col = 1;
            keyStatus = 3;
        }
        else if (col2 == 0)
        {
            key_col = 2;
            keyStatus = 3;
        }
        else if (col3 == 0)
        {
            key_col = 3;
            keyStatus = 3;
        }
        else if (col4 == 0)
        {
            key_col = 4;
            keyStatus = 3;
        }
        break;
    case 3:
        ClearRow();
        if ((col1 == 1) && (col2 == 1) && (col3 == 1) && (col4 == 1))
            keyStatus = 0;
        break;
    default:
        keyStatus = 0;
        break;
    }
}
void SegShow()
{
    if (timerEnable)
        KeyScan();
    timerEnable = 0;
    DisplayNo1(ArrayNum[key_row - 1][key_col - 1]);
}
void Timer0_Init(void) // 1毫秒@12.000MHz
{
    AUXR |= 0x80; // 定时器时钟1T模式
    TMOD &= 0xF0; // 设置定时器模式
    TL0 = 0x20;   // 设置定时初始值
    TH0 = 0xD1;   // 设置定时初始值
    TF0 = 0;      // 清除TF0标志
    TR0 = 1;      // 定时器0开始计时
    ET0 = 1;      // 使能定时器0中断
    EA = 1;
}

void main()
{
    Timer0_Init();

    LED(0xff);
    SEG(0xff);
    COM(0xff);

    while (1)
    {
        SegShow();
    }
}

void Timer0_Isr(void) interrupt 1
{
    if (timerCounter++ == 1) // 1ms
    {
        timerCounter = 0;
        timerEnable = 1;
    }
}

  • 11
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的C51程序,可以实现矩阵键盘的输入和数码管的显示功能。注意,这里使用的是普通的共阳数码管,如果使用共阴数码管需要修改代码: ```c #include <reg52.h> // 51单片机头文件 sbit LSA = P2^2; // 数码管LSA引脚连接的IO口 sbit LSB = P2^3; // 数码管LSB引脚连接的IO口 sbit LSC = P2^4; // 数码管LSC引脚连接的IO口 sbit D1 = P0^0; // 数码管第1位的IO口 sbit D2 = P0^1; // 数码管第2位的IO口 sbit D3 = P0^2; // 数码管第3位的IO口 sbit D4 = P0^3; // 数码管第4位的IO口 unsigned char code Nums[] = { // 数码管显示0~F的值 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71 }; unsigned char KeySta[4][4] = { // 矩阵键盘按键状态 {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1} }; void InitLcd() // 初始化数码管 { P0 = 0xff; // 数码管全部关闭 LSA = 0; LSB = 0; LSC = 0; // 数码管显示第一位 TMOD &= 0xf0; // 设置定时器为模式0 TH0 = 0x3c; TL0 = 0xb0; // 定时器初值,定时1ms ET0 = 1; // 开启定时器中断 TR0 = 1; // 开启定时器 } void Display(unsigned char num, unsigned char pos) // 在数码管的指定位置显示一个数字 { unsigned char tmp = Nums[num]; switch(pos) { case 1: D1 = 0; P0 = tmp; D1 = 1; break; case 2: D2 = 0; P0 = tmp; D2 = 1; break; case 3: D3 = 0; P0 = tmp; D3 = 1; break; case 4: D4 = 0; P0 = tmp; D4 = 1; break; default: break; } } void KeyDriver() // 矩阵键盘驱动程序 { unsigned char i, j; static unsigned char backup[4][4] = { // 矩阵键盘状态备份 {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1} }; for(i = 0; i < 4; i++) { for(j = 0; j < 4; j++) { if(KeySta[i][j] != backup[i][j]) { // 检测到按键状态改变 if(KeySta[i][j] == 0) { // 按键按下 Display(i * 4 + j, 1); // 在数码管第一位显示按键编号 } } backup[i][j] = KeySta[i][j]; // 备份按键状态 } } } void main() { InitLcd(); // 初始化数码管 while(1) { KeyDriver(); // 矩阵键盘驱动程序 } } void Timer0() interrupt 1 // 定时器0中断服务程序 { static unsigned char cnt = 0; static unsigned char pos = 1; TH0 = 0x3c; TL0 = 0xb0; // 定时器重新赋初值,定时1ms cnt++; if(cnt >= 100) { // 每100ms更新数码管显示位置 cnt = 0; pos++; if(pos > 4) pos = 1; } switch(pos) { // 控制数码管显示位置的选择 case 1: LSA = 0; LSB = 0; LSC = 0; break; case 2: LSA = 1; LSB = 0; LSC = 0; break; case 3: LSA = 0; LSB = 1; LSC = 0; break; case 4: LSA = 1; LSB = 1; LSC = 0; break; default: break; } } ``` 这段程序中,使用P2口的LSA、LSB、LSC三个引脚控制数码管的显示位置,使用P0口的D1~D4四个引脚控制数码管的亮灭。矩阵键盘的状态通过二维数组KeySta存储,在定时器中断服务程序Timer0中调用KeyDriver函数进行检测和处理。在按键按下时,将按键编号显示在数码管的第一位。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值