一、静态数码管
#include <stc15f2k60s2.h>
sbit relay=P0^4; //sbit是定义特殊功能寄存器的位变量
sbit buzzer=P0^6;
void SysInit()
{
P2=(P2&0x1f)|0x80;P0=0xff;P2&=0x1f;
P2=(P2&0x1f)|0xa0;relay=0;buzzer=0;P2&=0x1f;
P2=(P2&0x1f)|0xe0;P0=0xff;P2&=0x1f;
P2=(P2&0x1f)|0xc0;P0=0x00;P2&=0x1f;
}
void main()
{
SysInit();
P2=(P2&0x1f)|0xe0;P0=0xc0;P2&=0x1f;
P2=(P2&0x1f)|0xc0;P0=0xff;P2&=0x1f;P0=0xff;
}
二、独立按键与矩阵按键
1.独立按键
独立按键学习点:
(1)注意J5跳线调到btn,四个独立按键是左边s7,s6,s5,s4
(2)每个键设置了三种工作状态,利用定时中断没10ms去读取一次按键值,
由于static char btn_state是个静态变量,上次读的结果是记住了的,这样就可以用来记下按下、抖动、松开几个状态,
没10ms读一次按键,还取到了消抖的作用,所以独立按键这个程序是比较全面的。
(3)使用这段代码的方法是,每隔10ms,btnkey=scanbtn(); btnkey为1就是s7,2为s6,3为s5,4为s4,0为没有按键
参考网址:
https://blog.csdn.net/lin5103151/article/details/103544509
1.状态机
//状态机消抖,可以用10ms延时查询,也可以用10ms中断查询,建议用中断
#define key_input P3
#define key_state_0 0 //判断按键是否按下
#define key_state_1 1 //判断按键是否抖动
#define key_state_2 2 //判断按键是否弹起
#define key_mask 0x0f //屏蔽不需要的IO
char read_key()
{
static key_state = 0;
char key_press,key_return = 0;
key_press = key_input & key_mask;
switch(key_state)
{
case key_state_0:
if(key_press != key_mask)
key_state = key_state_1;
break;
case key_state_1:
if(key_press != key_mask)
{
if(key_press == 0x0e) key_return = 1; //S7
if(key_press == 0x0d) key_return = 2; //S6
if(key_press == 0x0b) key_return = 3; //S5
if(key_press == 0x07) key_return = 4; //S4
key_state = key_state_2;
}
else
key_state = key_state_0;
break;
case key_state_2:
if(key_press == 0x0f) key_state = key_state_0;
break;
}
return key_return;
}
//test
#include <STC15F2K60S2.H>
void main()
{
u8 i=0;
sys_init();
while(1)
{
i = read_key();
delay_ms(10);
if(i == 1)
{
//做你想做的事
}
if(i == 2)
{
//同上
}
}
}
2.状态机(坐标系)
#define state_0 0 //消抖
#define state_1 1 //是否按下
#define state_2 2 //判断按键是否上
u8 key_num=0;
void key_scanf(void)
{
static u8 key_state = 0;
switch(key_state)
{
case state_0:
P3 = 0x0f; //消抖
if(P3!=0x0f)
key_state = state_1;//消抖完后进入到按键中
break;
case state_1:
if(!P30|!P31|!P32|!P33)
{
if(!P30) key_num = 4;
if(!P31) key_num = 3;
if(!P32) key_num = 2;
if(!P33) key_num = 1;
key_state = state_2;
}
else
key_state = state_0;
break;
case state_2:
//P3 = 0x0f; //消抖
if(P3 == 0x0f)
key_state = state_0;//消抖完后进入到按键中
break;
}
}
3.三行代码
/*******************************************************
Name : key_read
Function : (1) No Key :ReadDate=0;Trg=0;Cont=0
(2) S7 is 0 : KEYPORT=0xfe;ReadDate=0x01;Trg = 0x01 & (0x01 ^ 0x00) = 0x01;Cont=0x01
(3) when S7 is always 0 : Trg = 0x01 & (0x01 ^ 0x01) = 0x00;Cont=0x01
(4) when S7 is 1 : Trg = 0x01 & (0x00 ^ 0x01) = 0;Cont=0
Example:
if(Trg & 0x08) //one key
if(Cont & 0x08) //long key
{
time_count++;
if(time_count == 100)
{
time_count = 0;
SendString(*long !\r\n);
}
}
*******************************************************/
u8 Trg; //触发
u8 Cont; //持续
void key_read()
{
unsigned char ReadDate = KEYPORT ^ 0xff; //ReadDate:读取的键值 ^:异或
Trg = ReadDate & (ReadDate ^ Cont);
Cont = ReadDate;
}
2.矩阵按键
1.状态机
//---------------------------4x4矩阵按键--------------------------------
#define kbd_io P3
#define state_0 0 //是否按下
#define state_1 1 //是否是抖动
#define state_2 2 //判断是否弹起
#define kbd_maskrow 0x0f //屏蔽不需要的IO
u8 key_num=16;
//col co2 co3 co4 rowl row2 row3 row4
//P44 P42 P35 P34 P33 P32 P31 P30
void scankbd()
{
static char kbd_state = 0;
unsigned char kbd_press;
char row;
switch(kbd_state)
{
case state_0:
kbd_io=0x0f; P42=0; P44=0;
kbd_press =kbd_io;
if(kbd_press != kbd_maskrow)
kbd_state = state_1;
break;
case state_1:
kbd_press =kbd_io;
if(kbd_press != kbd_maskrow){
if((kbd_io&0x08)==0) row=0;
if((kbd_io&0x04)==0) row=1;
if((kbd_io&0x02)==0) row=2;
if((kbd_io&0x01)==0) row=3;
kbd_io=0xf0; P42=1;P44=1;
if(P44==0) key_num=row;
if(P42==0) key_num=row+4;
if((kbd_io&0x20)==0) key_num=row+8;
if((kbd_io&0x10)==0) key_num=row+12;
kbd_state = state_2;
}
else
kbd_state = state_0;
break;
case state_2:
kbd_io=0x0f; P42=0; P44=0;
kbd_press =kbd_io;
if(kbd_press == 0x0f) kbd_state = state_0;
break;
default:
break;
}
}
2.状态机(坐标系)
#define state_0 0 // 消抖
#define state_1 1 //按键是否按下
#define state_2 2 //按键弹起
uchar key_num = 0xff;
void key_scanf(void)
{
static uchar stats = 0;
uchar key_x,key_y=0;
switch(stats)
{
case state_0:
P3 = 0x0f;P42=0;P44=0;
if(P3!=0x0f)
stats = state_1;
break;
case state_1:
if(!P30|!P31|!P32|!P33)
{
if(!P30) key_y = 4;
if(!P31) key_y = 3;
if(!P32) key_y = 2;
if(!P33) key_y = 1;
}
P3 = 0xf0;P42=1;P44=1;
if(!P34|!P35|!P42|!P44)
{
if(!P34) key_x = 4;
if(!P35) key_x = 3;
if(!P42) key_x = 2;
if(!P44) key_x = 1;
key_num = key_x*4 +key_y -5;
stats = state_2;
}
else
state = state_0;
break;
case state_2:
P3 = 0x0f;P42=0;P44=0;
if(P3==0x0f)
state = state_0;
break;
}
}
3.三行代码(了解)
//#define SetKeyBoard(x) P4= (P4&0xEB) | ((x>>7)<<4) | (((x>>6)&0x01)<<2);P3= (P3&0xC0) | (x&0x3F)// 0xEB - 0x1110 1011 P4.2 P4.4
#define SetKeyBoard(x) P4 = (x>>3) | (x>>4);P3 = x
#define GetKeyBoard() ((P4&0x10)<<3) | ((P4&0x04)<<4) | (P3&0x3F)
unsigned char Trg;
unsigned char Cont;
/**
* @brief 三行按键-矩阵键盘,提供简化版本,大家自行消化理解
* @param None
* @retval None
* @author dianshe.taobao.com
*/
void KeyRead( void )
{
unsigned char ReadData;
SetKeyBoard(0x0f);
ReadData=GetKeyBoard();
SetKeyBoard(0xf0);
ReadData=(ReadData | GetKeyBoard())^0xff;
Trg = ReadData & (ReadData ^ Cont);
Cont = ReadData;
}
/**
* @brief 按键处理函数
* @param None
* @retval None
* @author dianshe.taobao.com
*/
void KeyProc(void)
{
if (Trg) // 如果有按下
{
P2=0x80;P0=Trg^0xff;;P2=0x00;
}
if (Cont) // 如果按键被按着不放
{
}
if (Trg ==0 & Cont==0) //按键放开
{
}
}