このセクションで実装される機能は、静的デジタル チューブを制御して、開発ボード上のマトリックス キーボードを介して対応するキー値 0 ~ F を表示することです。
記事ディレクトリ
1. マトリックスボタンの概要
独立したキーボードがマイクロコントローラーに接続されている場合、各キーにはマイクロコントローラーの I/O ポートが必要です。マイクロコントローラー システムでさらに多くのボタンが必要な場合、独立したボタンを使用すると、多くの I/O ポート リソースが占有されます。
複数のボタンが使用される場合、I/O ポートのピンを減らすためにマトリックス ボタンが導入されます。たとえば、4*4 マトリックス キーボード。
4*4 マトリックス キーボードの場合、開発ボードは通常 16 個のキーを 4 行 4 列に配置します。最初の行は各ボタンの一端を接続して行ラインを形成し、最初の列は各ボタンの他端を接続して列ラインを形成します。したがって、4 行 4 列の合計 8 つのラインがあります。これらの 8 つの線をマイクロコントローラーの 8 つの I/O ポートに接続すると、プログラムを通じてキーボードをスキャンすることで 16 個のキーを検出できます。
独立キーボードでもマトリックスキーボードでも、マイコンがキーが押されたかどうかを検出する基準は同じで、そのキーに対応するI/Oポートがローレベルかどうかを検出します。独立したキーボードの一端はローレベルに固定され、マトリックスキーボードの両端はマイコンのI/Oポートに接続されており、検出時にはI/Oポートを介してローレベルを送信するようにプログラムする必要がありますマイクロコントローラーの。最も一般的に使用される検出方法は、行および列のスキャンおよびライン フリッピング方法です。
- 行・列スキャン方式で検出する場合は、最初に 1 列を Low レベルにして、残りの列をすべて High レベルにして、列数を決定し、各行が Low レベルであるかどうかを即座に検出します。ある行のレベルが低いことが検出された場合、行数が判明したので、現在押されているキーがどの行のどの列に属するかを確認できます。同様の方法で各列にローレベルを送信し、各行がローレベルになるかどうかを順番に検出することで、すべてのキーを検出することができます。キーが押されました。
- ライン反転方式で検出する場合、すべての行線がローレベルのときに、すべての列線がローレベルであるかどうかを確認し、そうであれば列線の値を記録し、すべての列線がローレベルになるように反転し、値を検出しますすべての行に対して。ボタンが押されると、行ラインの値も変化し、すべてのキーが検出できるように行ラインの値が記録されます。
マトリックス キーにもキー デバウンスが必要です。
2. ハードウェア設計
実装機能: 静的デジタル チューブを制御して、開発ボード上のマトリックス キーボードを通じて対応するキー値 0 ~ F を表示します。使用されるハードウェア リソースは次のとおりです。
- ダイナミックデジタルチューブ
- 4*4 マトリックスボタン
ハードウェア回路は次のとおりです。
上の図からわかるように、4*4 マトリックス ボタンから派生した 8 つの制御ピンは、51 マイクロコントローラーの P1 ポートに直接接続されています。
3. ソフトウェア設計
51 マイクロコントローラーがボタンが押されたかどうかを検出できるようにするには、マトリックス ボタンをマイクロコントローラー ピンを通じて制御する必要があります。
コードは次のように実装されます。
/*
实现功能:使用独立按键控制指示灯的亮灭
[2023-12-06] zoya
*/
#include "reg52.h"
typedef unsigned char u8;
typedef unsigned int u16;
#define GPIO_DIG P0 // 动态数码管
#define GPIO_KEY P1 // 矩阵按键
u8 keyVal; // 记录按键位置
u8 code smg[] = {
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71, 0x00}; // 共阴极数码管
// 延时函数,i=1延时10us
void delay(u16 i)
{
while(i--);
}
// 检测矩阵按键的哪个键按下,线翻转法检测哪个按键被按下
void KeyDown()
{
char a = 0;
GPIO_KEY = 0x0f; // 所有行线全部为低电平
if(0x0f != GPIO_KEY) // 检测是否有键被按下,如果有键被按下,GPIO_KEY不会为0x0f
{
delay(1000); // 延时10ms进行消抖
if(0x0f != GPIO_KEY) // 再次判断是否有键被按下
{
// 测试列
GPIO_KEY = 0x0f;
// 检测列是否有低电平
switch(GPIO_KEY)
{
case 0x07: keyVal = 0; break; // 第一列的某行被按下,假设是第一行
case 0x0b: keyVal = 1; break; // 第二列的某行被按下,假设是第一行
case 0x0d: keyVal = 2; break; // 第三列的某行被按下,假设是第一行
case 0x0e: keyVal = 3; break; // 第四列的某行被按下,假设是第一行
}
// 测试行
GPIO_KEY = 0xf0;
switch(GPIO_KEY)
{
case 0x70: keyVal = keyVal + 0; break; // 第一行的某列被按下
case 0xb0: keyVal = keyVal + 4; break; // 第二行的某列被按下
case 0xd0: keyVal = keyVal + 8; break; // 第三行的某列被按下
case 0xe0: keyVal = keyVal + 12; break; // 第四行的某列被按下
}
}
while((a <50) && (GPIO_KEY != 0xF0)) // 检测按键松手检测
{
delay(100);
a++;
}
}
}
void main()
{
while(1)
{
KeyDown();
GPIO_DIG = smg[keyVal];
}
}
シミュレーション結果: