课程资源
B站矩阵键盘课程
实现代码
Delay.c
void Delay(unsigned int xms)
{
while(xms--)
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
MatrixKey.c
#include <REGX52.H>
#include "Delay.h"
#define KEY_SCAN P1
void MatrixKey(unsigned char* keyValue)
{
KEY_SCAN = 0X0F;
if(KEY_SCAN!=0X0F)
{
Delay(10);
KEY_SCAN = 0X0F;
switch(KEY_SCAN)
{
case 0X07:*keyValue = 0;break;
case 0X0B:*keyValue = 1;break;
case 0X0D:*keyValue = 2;break;
case 0X0E:*keyValue = 3;break;
}
KEY_SCAN = 0XF0;
switch(KEY_SCAN)
{
case 0X70:*keyValue = *keyValue;break;
case 0XB0:*keyValue += 4;break;
case 0XD0:*keyValue += 8;break;
case 0XE0:*keyValue += 12;break;
}
while(KEY_SCAN!=0XF0)
{
Delay(10);
}
}
}
LCD1602.C
#include <REGX52.H>
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0
void LCD_Delay()
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
void LCD_WriteCommand(unsigned char Command)
{
LCD_RS=0;
LCD_RW=0;
LCD_DataPort=Command;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
void LCD_WriteData(unsigned char Data)
{
LCD_RS=1;
LCD_RW=0;
LCD_DataPort=Data;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD_WriteCommand(0x80|(Column-1));
}
else if(Line==2)
{
LCD_WriteCommand(0x80|(Column-1+0x40));
}
}
void LCD_Init()
{
LCD_WriteCommand(0x38);
LCD_WriteCommand(0x0c);
LCD_WriteCommand(0x06);
LCD_WriteCommand(0x01);
}
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char)
{
LCD_SetCursor(Line,Column);
LCD_WriteData(Char);
}
main.c
#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "MatrixKey.h"
unsigned char KeyValueTbl[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
unsigned char value;
void main()
{
LCD_Init();
LCD_ShowString(1,5,"Welcome!");
while(1)
{
MatrixKey(&value);
LCD_ShowChar(2,8,KeyValueTbl[value]);
}
}
出现的错误
MatrixKey函数与main函数之间逻辑关系错误 错误代码——MatrixKey()
unsigned char MatrixKey(void)
{
unsigned char keyValue = 0;
KEY_SCAN = 0X0F;
if(KEY_SCAN!=0X0F)
{
Delay(10);
KEY_SCAN = 0X0F;
switch(KEY_SCAN)
{
case 0X07:*keyValue = 0;break;
case 0X0B:*keyValue = 1;break;
case 0X0D:*keyValue = 2;break;
case 0X0E:*keyValue = 3;break;
}
KEY_SCAN = 0XF0;
switch(KEY_SCAN)
{
case 0X70:*keyValue = *keyValue;break;
case 0XB0:*keyValue += 4;break;
case 0XD0:*keyValue += 8;break;
case 0XE0:*keyValue += 12;break;
}
while(KEY_SCAN!=0XF0)
{
Delay(10);
}
}
return keyValue;
}
错误原因:
- 当按下按键松手后,返回keyValue值给value,然后接着将value值对应KeyValueTbl中的值在LCD输出
- 很快,再一次进入MatrixKey(),keyValue值重新赋值为0,此时没有按键按下,keyValue值返回值0赋值给value,将0在LCD屏幕输出
- 因为51单片机频率为12KHZ,运行程序速度很快,前两步骤间时间间隔很短,所以肉眼看上去屏幕输出永远为0(没有键值输入的情况)
- 所以,最根本的原因是给LCD屏幕输入的值没有保持到下一次按下按键就清零处理了,导致无法观察到每个按键的键值
改进方案
- 在main.c文件中设置全局变量value
unsigned char MatrixKey(void) 改为void MatrixKey(unsigned char* keyValue) - main函数中调用
MatrixKey(&value); 使每次keyValue的值能返回到value中,有按键时输出按键值;没有按键时输出上一次按键值
注意
void MatrixKey(unsigned char keyValue){...}
int main()
{
...
MatrixKey(value);
}
这种修改方式并不能使keyValue的值返回到value中,因为实际参数(value)只是把值复制给了形式参数(keyValue),在函数中对于形式参数的修改都不会影响到实际参数,即返回后value的值始终为0
小结
单片机编程过程中,while(1){…}循环体内的逻辑结构要考虑到单片机执行速度带来的问题,要充分考虑一次while循环对下一次循环带来的影响
|