资讯详情

单片机矩阵按键定时器消抖程序源码

芯片是采用的stc89c51单片机.

下面是矩阵的电路图,矩阵键盘是接在p2口的. 下面是单片机部分的图,显示等完整的原理图可以从 http://www.51hei.com/f/ks51.pdf 这里下载

下面是程序源码:

/********矩阵按键定时器消抖**************/ /** *时间:2014年3月18日20:27:23 *作者:寒竹子 *工程写法:用定时器为按键消抖不占用cpu的时间 **/

#include <reg52.h>

typedef unsigned int uint; typedef unsigned char uchar;

//138 sbit A0 = P1^0; sbit ADDR1 = P1^1; sbit ADDR2 = P1^2; sbit ADDR3 = P1^3; sbit ENLED = P1^4;

//KeyIn sbit KeyIn1 = P2^4; sbit KeyIn2 = P2^5; sbit KeyIn3 = P2^6; sbit KeyIn4 = P2^7;

//KeyOut sbit KeyOut1 = P2^3; sbit KeyOut2 = P2^2; sbit KeyOut3 = P2^1; sbit KeyOut4 = P2^0;

//数码管编码 uchar code 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" };

uchar key = 0;

//16个按键初始化1 uchar keysta[4][4] = { {1, 1, 1, 1}, //K1 - K4 {1, 1, 1, 1}, //K5 - K8 {1, 1, 1, 1}, //K9 - K 12 {1, 1, 1, 1} //K13 - K16 };

//16个按键的备份值初始值1 uchar keybackup[4][4] = { {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1} };

void keymatrixScan(); void timer0_init(); void refresh(); void HC138_init();

void main() { timer0_init(); HC138_init();

while (1) { keymatrixScan(); } }

/********timer0 init*************/ void timer0_init() { TMOD |= 0x01; TMOD &= 0xF1; //1111 0001,配置T0方式1 TH0 = 0xFC; TL0 = 0x67;//1ms TR0 = 1;//start T0 EA = 1; //open main int ET0 = 1;//open T0 int }

/***********HC138 init*********/ void HC138_init() { ADDR3 = 1; ENLED = 0;//使能U3 }

/***********刷新数码管************/ void refresh() { static uchar j = 0;//刷新数码管 P0 = 0xFF;//消隐 switch (j) { case 0: ADDR2 = 0; ADDR1 = 0; ADDR0 = 0; break; case 1: ADDR2 = 0; ADDR1 = 0; ADDR0 = 1; break; case 2: ADDR2 = 0; ADDR1 = 1; ADDR0 = 0; break; case 3: ADDR2 = 0; ADDR1 = 1; ADDR0 = 1; break; case 4: ADDR2 = 1; ADDR1 = 0; ADDR0 = 0; break; case 5: ADDR2 = 1; ADDR1 = 0; ADDR0 = 1; break; default: break; } P0 = table[key]; //在此处送入显示的数据,很正常的显示出来,当放到while(1)中时会出现抖动 j++; if (j >= 6) { j = 0; } }

/**********矩阵按键检测***********/ void keymatrixScan() { //16个按键检测 uchar i = 0, j = 0; for (i = 0; i < 4; i++) //4行 { for (j = 0; j < 4; j++) //4列 { if (keysta[j] != keybackup[j]) //检测第i行第j列按键是否有动作 { if (keybackup[j] == 0) //若第i行第j列的按键的前一个状态为0,则由0-1,即按键弹起 { key = i * 4 + j;//按键定位 } //备份当前按键的值,以备下一次比较 keybackup[j] = keysta[j]; } } } }

/**********timer0 int****************/ void timer0_int() interrupt 1 using 3 { static uchar keybuf[4][4] = { {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF} };//16个按键的扫描缓冲区 static uchar keyout = 0;//按键的列,即KeyOut1 - KeyOut4 uchar i = 0; TH0 = 0xFC; TL0 = 0x67; //1ms

refresh();

//扫描第keyout列的按键的值 keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KeyIn1;//将按键1的扫描值存入keybuf中 keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KeyIn2; keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KeyIn3; keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KeyIn4; //每1ms扫描一列,4ms扫描四列,共扫描四位,设定扫描16ms,即每个按键扫描4次

//更新消抖后按键的值 for (i = 0; i < 4; i++) //4行, 一列4个按键 { if ((keybuf[keyout] & 0x0F) == 0x00) //按键的缓冲区的低四位都是0,因为16ms只扫描了4次,移入了四位状态值 { keysta[keyout] = 0;//按键按下 } else if ((keybuf[keyout] & 0x0F) == 0x0F) //按键的缓冲区的第四位都是1 { keysta[keyout] = 1;//第keyout列第i行的按键弹起 } }

//列++ keyout++; //keyout 0-3 /*if (keyout >= 4) keyout = 0; */ keyout &= 0x03;//当keyout到4则会等于3 //通过keyout列数选中列 switch (keyout) { case 0: KeyOut1 = 0; KeyOut4 = 1; KeyOut2 = 1; KeyOut3 = 1; //选中第一列,上的第一行 break; case 1: KeyOut2 = 0; KeyOut1 = 1; KeyOut3 = 1; KeyOut4 = 1; break; case 2: KeyOut3 = 0; KeyOut1 = 1; KeyOut2 = 1; KeyOut4 = 1; break; case 3: KeyOut4 = 0; KeyOut1 = 1; KeyOut2 = 1; KeyOut3 = 1; break; default: break; } }

-电子元器件采购网(www.ruidan.com)是本土元器件目录分销商,采用“小批量、现货、样品”销售模式,致力于满足客户多型号、高质量、快速交付的采购需求。 自建高效智能仓储,拥有自营库存超过50,000种,提供一站式正品现货采购、个性化解决方案、选型替代等多元化服务。
锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台