C51相关实验
- LED (P2 / 0~7)
- 蜂鸣器 (P2^5)
- 数码管 (P0 0~7 段 ,P2 2~4 位)
- 独立按键 (P3^1 P3^0 P3^2 P3^3)
- 直流电机 (J47 5v 01~04)
- 综合实验
- 矩阵按键 (P1组 0~7)
- LED点阵
LED (P2 / 0~7)
//功能:1.让开发板的LED全亮,2,点亮某一个LED,3.让LED3以5Hz的频率闪动
#include "reg52.h"
#define LED P2
sbit led1 = LED^1;
void main(void)
{
LED = 0xff;//LED全灭
led1 = 0;
while(1)//保持应用程序不退出
{
}
}
LED 输出端是高电平 所以要让LED点亮只需要让MCU输出低电平即可,内置引脚是
P2
,所以要让哪个亮只需要让哪个引脚为0 例子:LED^3=0;让第三个LED亮起
蜂鸣器 (P2^5)
对于无源蜂鸣器,通过改变脉冲频率就可以调节蜂鸣器的音调,产生各种不同的音色,音调的声音。
对于无源蜂鸣器,通过改变脉冲占空比(高电平占用脉冲周期的百分比)就可以改变蜂鸣器声音的大小。
//功能:让蜂鸣器以100HZ频率,50%音量,响10s
#include "reg52.h"
typedef unsigned int u16;
typedef unsigned char u8;
//定义BEEP的控制引脚
sbit BEEP = P2^5;//申明蜂鸣器的控制引脚
//以秒为单位的延时器
void delay_ms(unsigned int ms){
unsigned int i,j;
for(i=ms;i>0;i--)
for(j=123;j>0;j--);
}
//u8frequency:蜂鸣器的工作频率,范围2Hz-1KHz
//u8duty:蜂鸣器脉冲占空比,范围0-100;
//times:以秒为单位的时间,范围大于0
void Beep(u8 u8frequency,u8 u8duty,u8 times)
{
u16 i;
u16 period ,on_time ,off_time;
//参数校验 防止越界
if(u8frequency>1000) u8frequency = 1000;
if(u8frequency==0) u8frequency = 10;
if(u8duty>100)u8duty = 100;
if(u8duty == 0)u8duty = 1;
if(times == 0)times = 1;
period = 1000/u8frequency;//以毫秒为单位的周期
on_time = period/100*u8duty; //计算高电平的时间,以毫秒为单位 1周期内高电平
off_time = period - on_time;
for(i=0;i<u8frequency*times;i++)//遍历10s内所有的脉冲
{
BEEP = 1;
delay_ms(on_time);
BEEP = 0;
delay_ms(off_time);
}
}
void main()
{
Beep(100,50,10);
while(1) //保持应用程序不退出
{
}
}
多频率
//功能:/* 多频率声音输出:
//需求:蜂鸣器应能够输出不同频率的声音。
//实现:定义一个频率数组u16 frequencies[] = {1000, 1500, 2000, 2500}包含若干个频率值。程序会循环遍历这些频率,产生相应的声音。
#include "reg52.h"
typedef unsigned int u16;
typedef unsigned char u8;
typedef unsigned long u32;
//定义BEEP的控制引脚
sbit BEEP = P2^5;//申明蜂鸣器的控制引脚
//u16Frequency:蜂鸣器的工作频率,范围2Hz-5KHz
//u8duty:蜂鸣器脉冲占空比,范围0-100;
//u16durations:以秒为单位的时间,范围大于0
void Beep(u16 u16Frequency,u8 u8duty,u16 u16durations);
//以毫秒为单位的延时
void delay_ms(unsigned int ms){
unsigned int i,j;
for(i=ms;i>0;i--)
for(j=123;j>0;j--);
}
//以10微秒为单位的延时
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
void main()
{
u16 u16Freqs[] = {1000,1500,2000,3000};//定义一个频率数组
u8 u8duty = 50;
u8 i;
u8 num = sizeof(u16Freqs)/sizeof(u16Freqs[0]);
for(i=0;i<num;i++)
{
Beep(u16Freqs[i],u8duty,2);
delay_ms(1000);//每次蜂鸣器在切换频率之间,停1s
}
while(1) //保持应用程序不退出
{
}
}
void Beep(u16 u16Frequency,u8 u8duty,u16 u16durations)
{
u16 i;
u32 period ,on_time ,off_time;
//参数校验
if(u16Frequency>5000) u16Frequency = 5000;
if(u16Frequency==0) u16Frequency = 1000;
if(u8duty>100)u8duty = 100;
if(u8duty == 0)u8duty = 1;
if(u16durations == 0)u16durations = 1;
period = 1000000/u16Frequency;//以微秒为单位的脉冲周期
on_time = period/100*u8duty; //计算高电平的时间,以微秒为单位
off_time = period - on_time;
for(i=0;i<u16Frequency*u16durations;i++)//遍历所有的脉冲
{
BEEP = 0;
delay_10us(on_time/10);//延时是以10us为单位的延时,这里需要除10
BEEP = 1;
delay_10us(off_time/10);
}
}
数码管 (P0 0~7 段 ,P2 2~4 位)
数码管是一种半导体发光器件,其基本单元是发光二极管。
按发光二极管单元连接方式可分为共阳极数码管和共阴极数码管。
共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数 码管。
共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数 码管。
共阴或者共阳,
a-g+小数点
总共8段对应8个引脚,下面是对应显示,a-g从低到高
LED数码管显示器工作方式有两种:静态显示方式和动态显示方式。
静态显示的特点:每个数码管的段选必须接一个8位数据线来保持显示的字形码。
静态显示:也就是不需要刷新显示写在while
外面,反之写在里面
1.定义数码管的端口的IO。#define SMG_1 P0
2.定义数码管编码数据 u8 smg_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//数码管显示
#include "reg52.h"
// 数码管控制引脚别名
#define SMG P0
// 毫秒延时函数
void delay_ms(unsigned int ms) {
unsigned int i, j;
for (i = 0; i < ms; i++) {
for (j = 0; j < 123; j++); // 123 是一个经验值,根据实际情况调整
}
}
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
// 0-F 共阴八段数码管编码
u8 smg_code[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};
// 数码管位选引脚
sbit SMG_22 = P2^2; // 第一个数码管控制位
sbit SMG_23 = P2^3; // 第二个数码管控制位
sbit SMG_24 = P2^4; // 第三个数码管控制位
void SMG_display(void)
{
u8 i;
for(i=0;i<8;i++)
{
//从高到低
//SMG_22=i%2;
//SMG_23=(i/2)%2;
//SMG_24=i/4;
//从低到高
SMG_22=!(i%2);
SMG_23=!((i/2)%2);
SMG_24=!(i/4);
SMG=smg_code[i];
delay_ms(1);
SMG = 0;//消影
}
}
void main(void) {
u16 i;
while(1) {
SMG_display();
}
}
独立按键 (P3^1 P3^0 P3^2 P3^3)
从上图中可以看出,4个独立按键的控制管脚连接到51单片机的P3.0-P3.3 脚上。其中K1连接在P3.1上,K2连接在P3.0上,K3连接在P3.2上,K4连接 在P3.3上。4个按键另一端全部连接在GND,当按键按下后,对应IO口即为低 电平。
由于机械按键大概有10ms 的误差
按键控制LED灯亮
//独立按键 按键1LED1亮
#include "reg52.h"
//毫秒延时函数
void delay_ms(unsigned int ms) {
unsigned int i, j;
for (i = 0; i < ms; i++) {
for (j = 0; j < 123; j++); // 123 是一个经验值,可以根据实际情况调整
}
}
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
//定义独立按键引脚
sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
//定义LED灯引脚
sbit LED1=P2^0;
sbit LED2=P2^1;
sbit LED3=P2^2;
sbit LED4=P2^3;
//独立按键控制led灯
void key_contralled()
{
if(KEY1==0)
{
delay_ms(10);//消抖
if(KEY1==0) LED1=!LED1;
delay_ms(200);
}
if(KEY2==0)
{
delay_ms(10);//消抖
if(KEY2==0) LED2=!LED2;
delay_ms(200);
}
if(KEY3==0)
{
delay_ms(10);//消抖
if(KEY3==0) LED3=!LED3;
delay_ms(200);
}
if(KEY4==0)
{
delay_ms(10);//消抖
if(KEY4 ==0) LED4=!LED4;
delay_ms(200);
}
}
void main(void)
{
while(1)//保持程序不退出
{
key_contralled();
}
}
直流电机 (J47 5v 01~04)
原理图:默认J47 接电源 P1 ^ 0~
P1 ^ 3 对应OUT1~
OUT4 ,当MCU输出端为高电平
时直流电机不工作,低电平
时直流电机开始工作,由于内部工作时非门逻辑
,所以在用代码实现的时候也就是 高电平即1
开始工作,反之0
不工作
//功能:控制直流电机运行5s后停
//接线:J47的1脚----直流电机任意一个引脚
// J47的2脚----直流电机的另外一引脚
#include "reg52.h"
typedef unsigned int u16;
typedef unsigned char u8;
typedef unsigned long u32;
//定义直流电机的控制引脚
sbit DC_MOTOR = P1^0;
//以毫秒为单位的延时
void delay_ms(unsigned int ms){
unsigned int i,j;
for(i=ms;i>0;i--)
for(j=123;j>0;j--);
}
//以10微秒为单位的延时
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
void MOTOR_Run(u8 u8duration);
void main()
{
DC_MOTOR = 0;//关闭直流电机
MOTOR_Run(5);
while(1) //保持应用程序不退出
{
}
}
void MOTOR_Run(u8 u8duration)
{
DC_MOTOR = 1;//打开直流电机
delay_ms(1000*u8duration);
DC_MOTOR = 0;//关闭直流电机
}
综合实验
//功能:
/*
● 增加预置时间和计数值的变量。
● 数码管的前4位显示预置时间,后4位显示计数值。
● 按键检测和预置时间调整功能。
● 直流电机运行和停止的逻辑。
● k1加
● k2减
● k3,开始计数,直流机电要转,到计数等于预值时,直流电机停转,蜂鸣器响1s
● k4,暂停/恢复
预值范围10--40
分析:
1.数码管显示模块 (8+3)IO output
2.按键扫描模块 4IO input
3.定时器模块
4.功能模块(直流电机+蜂鸣器) 2IO output
*/
#include "reg52.h"
typedef unsigned int u16;
typedef unsigned char u8;
typedef unsigned long u32;
//定义直流电机的控制引脚
sbit DC_MOTOR = P1^0;
//定义BEEP的控制引脚
sbit BEEP = P2^5;//申明蜂鸣器的控制引脚
//u8frequency:蜂鸣器的工作频率,范围2Hz-1KHz
//u8duty:蜂鸣器脉冲占空比,范围0-100;
//times:以秒为单位的时间,范围大于0
void Beep(u8 u8frequency,u8 u8duty,u8 times);
//以毫秒为单位的延时
void delay_ms(unsigned int ms){
unsigned int i,j;
for(i=ms;i>0;i--)
for(j=123;j>0;j--);
}
//0-F共阴八段数码管编码
u8 smg_code[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//定义数码管段选引脚
#define SMG P0
//定义数码管的位选引脚
sbit SMG_22 = P2^2;
sbit SMG_23 = P2^3;
sbit SMG_24 = P2^4;
//u8code表示8位数码管要显示的编码
void SMG_Display(u8 u8code[]);
//定义LED的控制引脚
sbit LED1 = P2^0;
sbit LED2 = P2^1;
sbit LED3 = P2^2;
sbit LED4 = P2^3;
//定义独立按键的控制引脚
sbit KEY1 = P3^1;
sbit KEY2 = P3^0;
sbit KEY3 = P3^2;
sbit KEY4 = P3^3;
//定义键值
#define KEY_UNPRESS 0
#define KEY1_PRESS 1
#define KEY2_PRESS 2
#define KEY3_PRESS 3
#define KEY4_PRESS 4
u8 Key_Scan(void);//返回被按下的独立按键值
//以10微秒为单位的延时
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
#define PRESEC_MIN 10
#define PRESEC_MAX 40
static u8 g_u8PreSec = PRESEC_MIN;//预值时间
static u8 g_u8CurSec = 0; //计数时间
void main()
{
u8 u8code[8] = {0};
u8 u8key = KEY_UNPRESS;
u8 i = 0;//秒时间计数器
DC_MOTOR = 0;//关闭直流电机
while(1) //保持应用程序不退出
{
//按键扫描
u8key = Key_Scan();
switch(u8key)
{
case KEY1_PRESS: //+
if(g_u8PreSec<PRESEC_MAX)
{
g_u8PreSec++;
}
break;
case KEY2_PRESS: //-
if(g_u8PreSec>PRESEC_MIN)
{
g_u8PreSec--;
}
break;
case KEY3_PRESS: //start
DC_MOTOR = 1;
break;
case KEY4_PRESS: //pause+resume
DC_MOTOR = !DC_MOTOR;
break;
default:
break;
}
//定时器,每秒更新一次
if(i == 100)
{
i = 0;
if(DC_MOTOR)
{
g_u8CurSec++;
}
}
//功能模块,直流电机及蜂鸣器
if((g_u8CurSec == g_u8PreSec) && DC_MOTOR)
{
DC_MOTOR = 0;
Beep(3000,80,1);
g_u8CurSec = 0;
}
//数码管显示
u8code[2] = smg_code[g_u8PreSec/10];//预值时间的十位
u8code[3] = smg_code[g_u8PreSec%10];//预值时间的个位
u8code[6] = smg_code[g_u8CurSec/10];//计数时间的十位
u8code[7] = smg_code[g_u8CurSec%10];//计数时间的个位
SMG_Display(u8code);
delay_ms(1);
i++;
}
}
void Beep(u8 u8frequency,u8 u8duty,u8 times)
{
u16 i;
u16 period ,on_time ,off_time;
//参数校验
if(u8frequency>1000) u8frequency = 1000;
if(u8frequency==0) u8frequency = 10;
if(u8duty>100)u8duty = 100;
if(u8duty == 0)u8duty = 1;
if(times == 0)times = 1;
period = 1000/u8frequency;//以毫秒为单位的周期
on_time = period/100*u8duty; //计算高电平的时间,以毫秒为单位
off_time = period - on_time;
for(i=0;i<u8frequency*times;i++)//遍历10s内所有的脉冲
{
BEEP = 1;
delay_ms(on_time);
BEEP = 0;
delay_ms(off_time);
}
}
void SMG_Display(u8 u8code[])
{
//u8code放的是当前每位数码管的段码
u8 i;
for(i=0;i<8;i++)
{
switch(i)
{
case 0: SMG_24 = 1;SMG_23 = 1;SMG_22 = 1;break;//7位
case 1: SMG_24 = 1;SMG_23 = 1;SMG_22 = 0;break;//6位
case 2: SMG_24 = 1;SMG_23 = 0;SMG_22 = 1;break;//5位
case 3: SMG_24 = 1;SMG_23 = 0;SMG_22 = 0;break;//4位
case 4: SMG_24 = 0;SMG_23 = 1;SMG_22 = 1;break;//3位
case 5: SMG_24 = 0;SMG_23 = 1;SMG_22 = 0;break;//2位
case 6: SMG_24 = 0;SMG_23 = 0;SMG_22 = 1;break;//1位
case 7: SMG_24 = 0;SMG_23 = 0;SMG_22 = 0;break;//0位
default:break;
}
//数码管段选
SMG = u8code[i];
delay_ms(1);//当前位的数码管显示保持时间
SMG = 0;//消影
}
}
u8 Key_Scan(void)//返回被按下的独立按键值
{
u8 u8key = KEY_UNPRESS;
if(KEY1 == 0)
{
//消抖
delay_ms(10);
if(KEY1 == 0)//再次确认状态
{
u8key = KEY1_PRESS;
}
}
if(KEY2 == 0)
{
//消抖
delay_ms(10);
if(KEY2 == 0)
{
u8key = KEY2_PRESS;
}
}
if(KEY3 == 0)
{
//消抖
delay_ms(10);
if(KEY3 == 0)//再次确认状态
{
u8key = KEY3_PRESS;
}
}
if(KEY4 == 0)
{
//消抖
delay_ms(10);
if(KEY4 == 0)//再次确认状态
{
u8key = KEY4_PRESS;
}
}
while((KEY1==0)||(KEY2==0)||(KEY3==0)||(KEY4==0));//防抖防止按键触发多次未弹起
return u8key;
}
注意
:在这里面使用的计时器是以为一次循环
大概时间,凑够1s来实现1s刷新数码管,数码管的数显时间大概在10ms
。
矩阵按键 (P1组 0~7)
实现原理:按钮按下后当前行列电平都为低电平,从而判断出哪个按钮被按下了,那么找出当前按下按钮,就可以设置P1 ^7~4 前4个为低电平(0
),后四个为高电平P1 ^3~0(F
),当前引脚P1
不等于0F 那么就证明这一列有被按下的按键,然后在翻转F0 不等于这个证明哪行有被按下的
//功能:以列扫描的方式实现矩阵按键,并在数码管上显示键值
#include "reg52.h"
typedef unsigned int u16;
typedef unsigned char u8;
typedef unsigned long u32;
//以毫秒为单位的延时
void delay_ms(unsigned int ms){
unsigned int i,j;
for(i=ms;i>0;i--)
for(j=123;j>0;j--);
}
//0-F共阴八段数码管编码
u8 smg_code[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//定义数码管段选引脚
#define SMG P0
//定义数码管的位选引脚
sbit SMG_22 = P2^2;
sbit SMG_23 = P2^3;
sbit SMG_24 = P2^4;
//u8code表示8位数码管要显示的编码
void SMG_Display(u8 u8code[]);
//定义矩阵按键的控制引脚
#define KEY_PORT P1
//定义键值
#define KEY_UNPRESS 0
#define KEY1_PRESS 1
#define KEY2_PRESS 2
#define KEY3_PRESS 3
#define KEY4_PRESS 4
#define KEY5_PRESS 5
#define KEY6_PRESS 6
#define KEY7_PRESS 7
#define KEY8_PRESS 8
#define KEY9_PRESS 9
#define KEY10_PRESS 10
#define KEY11_PRESS 11
#define KEY12_PRESS 12
#define KEY13_PRESS 13
#define KEY14_PRESS 14
#define KEY15_PRESS 15
#define KEY16_PRESS 16
u8 Key_Scan(void);//返回被按下的独立按键值
u8 Key_ColScan(void);//返回被按下的矩阵按键值
//以10微秒为单位的延时
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
void MOTOR_Run(u8 u8duration);
#define PRESEC_MIN 10
#define PRESEC_MAX 40
static u8 g_u8PreSec = PRESEC_MIN;//预值时间
static u8 g_u8CurSec = 0; //计数时间
void main()
{
u8 u8code[8] = {0};
u8 u8key = KEY_UNPRESS;
while(1) //保持应用程序不退出
{
//按键扫描
u8key = Key_ColScan();
if(u8key!=KEY_UNPRESS)
{
//数码管显示
u8code[6] = smg_code[u8key/10];//十位
u8code[7] = smg_code[u8key%10];//个位
}
SMG_Display(u8code);
delay_ms(1);
}
}
void SMG_Display(u8 u8code[])
{
u8 i;
for(i=0;i<8;i++)
{
switch(i)
{
case 0: SMG_24 = 1;SMG_23 = 1;SMG_22 = 1;break;//7位
case 1: SMG_24 = 1;SMG_23 = 1;SMG_22 = 0;break;//6位
case 2: SMG_24 = 1;SMG_23 = 0;SMG_22 = 1;break;//5位
case 3: SMG_24 = 1;SMG_23 = 0;SMG_22 = 0;break;//4位
case 4: SMG_24 = 0;SMG_23 = 1;SMG_22 = 1;break;//3位
case 5: SMG_24 = 0;SMG_23 = 1;SMG_22 = 0;break;//2位
case 6: SMG_24 = 0;SMG_23 = 0;SMG_22 = 1;break;//1位
case 7: SMG_24 = 0;SMG_23 = 0;SMG_22 = 0;break;//0位
default:break;
}
//数码管段选
SMG = u8code[i];
delay_ms(1);//当前位的数码管显示保持时间
SMG = 0;//消影
}
}
//这是通过一个个扫描实现的
u8 Key_ColScan(void)//返回被按下的矩阵按键值
{
u8 u8key = KEY_UNPRESS;
//扫描第一列 设置11110111 从高到低 P17-P10
KEY_PORT = 0xF7; //将矩阵按键第一列变为独立按键且没有按下的状态
if(KEY_PORT!=0xF7) //第一列有按键状态变化
{
delay_ms(10); //消抖
if(KEY_PORT!=0xF7) //再次确认
{
switch(KEY_PORT)
{
case 0x77: u8key = KEY1_PRESS; break;
case 0xb7: u8key = KEY5_PRESS; break;
case 0xd7: u8key = KEY9_PRESS; break;
case 0xe7: u8key = KEY13_PRESS; break;
default:
break;
}
}
}
while(KEY_PORT!=0xF7); //等待第一列所有按键弹起
//扫描第二列
KEY_PORT = 0xFb; //将矩阵按键第2列变为独立按键且没有按下的状态
if(KEY_PORT!=0xFb) //第2列有按键状态变化
{
delay_ms(10); //消抖
if(KEY_PORT!=0xFb) //再次确认
{
switch(KEY_PORT)
{
case 0x7b: u8key = KEY2_PRESS; break;
case 0xbb: u8key = KEY6_PRESS; break;
case 0xdb: u8key = KEY10_PRESS; break;
case 0xeb: u8key = KEY14_PRESS; break;
default:
break;
}
}
}
while(KEY_PORT!=0xFb); //等待第2列所有按键弹起
//扫描第3列
KEY_PORT = 0xFd; //将矩阵按键第3列变为独立按键且没有按下的状态
if(KEY_PORT!=0xFd) //第3列有按键状态变化
{
delay_ms(10); //消抖
if(KEY_PORT!=0xFd) //再次确认
{
switch(KEY_PORT)
{
case 0x7d: u8key = KEY3_PRESS; break;
case 0xbd: u8key = KEY7_PRESS; break;
case 0xdd: u8key = KEY11_PRESS; break;
case 0xed: u8key = KEY15_PRESS; break;
default:
break;
}
}
}
while(KEY_PORT!=0xFd); //等待第3列所有按键弹起
//扫描第4列
KEY_PORT = 0xFe; //将矩阵按键第4列变为独立按键且没有按下的状态
if(KEY_PORT!=0xFe) //第4列有按键状态变化
{
delay_ms(10); //消抖
if(KEY_PORT!=0xFe) //再次确认
{
switch(KEY_PORT)
{
case 0x7e: u8key = KEY4_PRESS; break;
case 0xbe: u8key = KEY8_PRESS; break;
case 0xde: u8key = KEY12_PRESS; break;
case 0xee: u8key = KEY16_PRESS; break;
default:
break;
}
}
}
while(KEY_PORT!=0xFe); //等待第4列所有按键弹起
return u8key;
}
//通过翻转实现 初始状态设置地位为1 高位为0 也就是00001111 全不通
u8 Key_ColScan(void)//返回被按下的矩阵按键值
{
u8 u8key = KEY_UNPRESS;
u8 row,col;
//扫描第一列
KEY_PORT = 0x0F; //无按键按下矩阵状态
if (KEY_PORT!=0x0F){ //证明有按键按下
delay_ms(10); //有个10ms机械按键的触发时间
if(KEY_PORT!=0x0F){
switch(KEY_PORT)
{
case 0x0E:
col=4;
break;
case 0x0d:
col=3;
break;
case 0x0b:
col=2;
break;
case 0x07:
col=1;
break;
default:break;
}
//翻转,将矩阵按键所有的行引脚拉高,所有的列引脚拉低
KEY_PORT=0xF0;
switch(KEY_PORT)
{
case 0xE0:
row=4;
break;
case 0xd0:
row=3;
break;
case 0xb0:
row=2;
break;
case 0x70:
row=1;
break;
default:break;
}
while(KEY_PORT!=0xF0);//等待按键弹起
}
}
u8key=(row-1)*4+col;
return u8key;
}
LED点阵
LED点阵