有关4X4矩阵键盘FPGA的程序的分析,有谁帮我分析一下这个状态机的程序啊

有关4X4矩阵键盘FPGA的程序的分析,有谁帮我分析一下这个状态机的程序啊,第1张

是应该还有col的输出,这才是整个扫描程序的重点。亏悔如果扫描的原理懂了的话,程序好像也没这么难理解啊,简单讲一下,在NO_KEY_PRESSED,col输出0000,如果有按键按下,当前行的row连接到col,则按下的那一行电平为0,转到SCAN_COL0。行值由row可知,开始逐列销芦正扫描以确定列值;在SCAN_COL0状态,col输出1000,若是第一列的按键,则row应该变哗源为1111,即可确定是第一列,否则转到第二列扫描,col输出0100···类推

//按4X4键盘的F键 进入设定状态

//E D 键是前后移动键

//C按键是调整数值按键

#include "reg52.h"

#define uchar unsigned char

sbit RW=P2^1

sbit RS=P2^0

sbit E=P2^2

bit at=0

uchar code shen[]={"CLOCK!"}

uchar code word[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x20}

uchar dispbuf[8],h,m,s,counter

void delay()

{

uchar i

for(i=0i<255i++)

}

/*******写命令**********/

void lcd_wmc(uchar i)

{

P0=i

RS=0

RW=0

E=0

delay()

E=1

}

/*******写数据***********/

void lcd_wmd(uchar i)

{

P0=i

RS=1

RW=0

E=0

delay()

E=1

}

/*******初始化液晶*******/

void lcd_init()

{

uchar i

lcd_wmc(0x01)

lcd_wmc(0x38)

lcd_wmc(0x0c)

lcd_wmc(0x06)

lcd_wmc(0xc9)

for(i=0i<6i++)

lcd_wmd(shen[i])

lcd_wmc(0xc0)

}

/*******更新缓冲区子程序*******/

void newbuf()

{

dispbuf[0]=s%10

dispbuf[1]=s/10

dispbuf[3]=m%10

dispbuf[4]=m/10

dispbuf[6]=h%10

dispbuf[7]=h/10

}

/*******显示子程序**********/

void disp(uchar dispadd)

{

uchar tmp

lcd_wmc(dispadd)

tmp=dispbuf[7]

tmp=word[tmp]

lcd_wmd(tmp)

tmp=dispbuf[6]

tmp=word[tmp]

lcd_wmd(tmp)

tmp=dispbuf[5]

tmp=word[tmp]

lcd_wmd(tmp)

tmp=dispbuf[4]

tmp=word[tmp]

lcd_wmd(tmp)

tmp=dispbuf[3]

tmp=word[tmp]

lcd_wmd(tmp)

tmp=dispbuf[2]

tmp=word[tmp]

lcd_wmd(tmp)

tmp=dispbuf[1]

tmp=word[tmp]

lcd_wmd(tmp)

tmp=dispbuf[0]

tmp=word[tmp]

lcd_wmd(tmp)

}

/*********************键盘子程序***********************/

uchar keypro(void)

{

uchar scanl,scanh

P1=0x0f//先将所有行键肆升线拉低

if((P1&0x0f)!=0x0f) //如果列线有变化

{

delay()//延雹禅迟一段时间。

if((P1&0x0f)!=0x0f)//如果此时此刻列线还有变化,说明确实有按键按下

{

scanl=0xfe

while((scanl&0x10)!=0)

{

P1=scanl//给P1口赋扫描码,每次只拉低一行

if((P1&0xf0)!=0xf0) //如果判断为真,则说明找到了按键按下的行

{

scanh=(P1&0xf0)|0x0f//计算识别码

return (~scanh)+(~scanl)

}

else scanl=(scanl<<1)|0x01//否则依次将第二,第三,第四行稿老拉低

}

}

}

return 0//没有按键 按下 返回0

}

/********************时间调整子程序********************/

void adjustime()

{

uchar k

static uchar add

k=keypro()

switch(k)

{

case 0x88: if(!at){add=0xc1EA=0lcd_wmc(0xc1)lcd_wmc(0x0f)at=1}

else {lcd_wmc(0xc0)lcd_wmc(0x0c)at=0EA=1} break

case 0x48: if(at)

{

if(add==0xc1){add=0xc7lcd_wmc(add)}

else {add=add-3lcd_wmc(add)}

}

break

case 0x28: if(at)

{

if(add==0xc7) {add=0xc1lcd_wmc(add)}

else {add=add+3lcd_wmc(add)}

}

break

case 0x18: if(at)

{

if(add==0xc1) h++

if(h==24)

h=0

if(add==0xc4) m++

if(m==60)

m=0

if(add==0xc7) s++

if(s==60)

s=0

newbuf()

disp(0xc0)

lcd_wmc(add)

}

break

default: break

}

if(k!=0)

{

while((P1&0xf0)!=0xf0)

P1=0xf0

}

}

/*********************初始化子程序**********************/

void init()

{

TMOD=0x01

TH0=0x4c

TL0=0x00

EA=1

ET0=1

TR0=1

counter=0

h=12m=0s=0

dispbuf[2]=10

dispbuf[5]=10

}

/***************************主程序************************/

void main(void)

{

init()

lcd_init()

while(1)

{

adjustime()

if(!at)

{

//闪烁

if(counter<10)

{

dispbuf[2]=10

dispbuf[5]=10

}

else

{

dispbuf[2]=11

dispbuf[5]=11

}

//更新显示缓冲区及调用显示程序

if(counter==0)

{

newbuf()

disp(0xc0)

}

else if(counter==10)

disp(0xc0)

}

}

}

/*************************定时器0的中断**********************/

void Time0() interrupt 1 using 2//再次强调中断子程序执行时间越短越好

{

TH0=(65536-46075)/256

TL0=(65536-46075)%256

counter++

if(counter==20)

{

s++

counter=0

if(s==60)

{

m++

s=0

if(m==60)

{

h++

m=0

if(h==24)

h=0

}

}

}

}

这是一个数字时钟的程序,用矩阵键盘调时

********************************************//

unsigned char keymap[] = {1*********************************************************************

控制打开或者关闭键盘中断

SW= 0关闭端口中断

else

KEY_IE =0xf0/7 接上拉电阻

/控制键盘开关/消除抖动

Check_Key():

[p13]→ 1 2 3 4

[p12]→ 5 6 7 8

[p11]→ 9 10 11 12

[p10]→ 13 14 15 16

***************************************/

void Key_Event(void)

{

unsigned char tmp/

void delay(void)

{

unsigned int tmp/如果有键按下

{

delay()/ //是否P1IN的P1/ 列检测

{

if((KEY_IN tmp2) == 0x00) / 获取键值

return设置P1OUT全为0,P1.h>/ /p14\///

KEY_IES =0xf0 / /设置键盘逻辑键值

与程序计算键值的映射

tmp1 = 0x08/

void Check_Key(void)

{

unsigned char row P16\= 1/*******************************************

函数名称tmp2用于检测出哪一位为0

for(col = 0,15/ 获取 p1IN

if((tmp 0xf0) < /gt.4~P1,7,完成消抖功能

参数

if(Key_Val/

/msp430x14x/ //*******************************************

函数名称!=0)

{

Key_Event()/

KEY_OUT =0,仿哪并获取键值

参数打开端口中断

}

//

void Init_Keypad(void)

{

KEY_DIR = 0x0fP1.0~P1.4~p1P10***************************************

key_Val 对应键值

列row++) /5\/ /col lt;带携 ELSE

for(tmp = 12000

for(row = 0,4:t= tmp*5*clk 根据使用时钟调整tmp值

********************************************/ tmp2右移1位

}

}

}

}

/键值,9:delay

功能:扫描键盘的IO端口:无

返回值 ,12 /关键盘备行码中断

}

}

KEY_IFG=0KEY_OUT=0col++) / 4/ 0xf0) /row lt,14=1*端口1按键中断*/ / /行扫描

{

KEY_OUT = 0x0f / 40xf0) / /////tmp >

#pragma vector=PORT1_VECTOR

__interrupt void Port(void)

{

if((KEY_IFG0xf0):无

返回值 存放键值

void CtrlKey(unsigned char sw).4~P1<// 调用check_Key()!=0) /P1.7输出四位中有一个为0

tmp1 gt!=0有键按下

{

CtrlKey(0),等待按键输入

tmp = KEY_IN /***************全局变量***************/sw=0关 sw=1开

/// //

if((KEY_IN 0xf0)<退出循环

}

tmp2 < / / 是否是该列

#define KEY_DIR P1DIR

#define KEY_OUT P1OUT

#define KEY_IN P1IN

#define KEY_IE P1IE

#define KEY_IES P1IES

#define KEY_IFG P1IFG

//

}

//

void CtrlKey(unsigned char sw)

{

if(sw==0)

KEY_IE =0/中断标志清0

Key_Val = 0*******************************************

函数名称

}

// /P1msp430F149 4*4矩阵键盘P1口中断扫描

#includelt,847


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12559526.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-26
下一篇 2023-05-26

发表评论

登录后才能评论

评论列表(0条)

保存