📄 kbd.c
字号:
/*----------Copyright 2006-2010 武汉菱电汽车电子有限公司-----------------------
* 项目名称: 汽车诊断仪
* 开发工具: uV2 Keil C51
* 程序名称: KBD.c
* 作者: 朱坤
* 写作时间: 2006/03/10
*
* 程序说明:
* 触摸屏或按键处理
* 扫描间隔时间 4mS
*
* 修改记录:
*
*---------------------------------------------------------------------------*/
//#pragma SRC
//#pragma SMALL
//#pragma OPTIMIZE(SIZE)
#include "kbd.H"
#include "buz.h"
#include <stdio.h>
/* 键盘驱动 */
#define KBD_PORT P1
#define KBD_MASK 0x0e0
/* 定义 ADS7843 接口 */
sbit ADS_DCLK = KBD_PORT^7;
sbit ADS_DO = KBD_PORT^6;
sbit ADS_DI = KBD_PORT^5;
/* ADS7843 控制字节位定义
S A2 A1 A0 MODE SER/DFR PD1 PD0
7 S Start Bit. Control byte starts with first HIGH bit on DIN.
6-4 A2-A0 Channel Select Bits
3 MODE 12-Bit(LOW)/8-Bit(HIGH) Conversion
2 SER/DFR Single-Ended(HIGH)/Differential(LOW) Reference
1-0 PD1-PD0 Power-Down Mode */
//#define ADS_SEL12 /* 选择 12 位或 8 位模式 */
#define ADS_IX 1
#define ADS_IY 5
#define ADS_I3 2
#define ADS_I4 6
#define ADS_M12 0 /* 12 bits */
#define ADS_M8 1 /* 8 bits */
#define ADS_SE 1 /* Single-Ended */
#define ADS_DF 0 /* differential */
/* No power-down between conversions, device is always powered */
#define ADS_PD 3
#ifdef ADS_SEL12
/* S A2 A1 A0 MODE SER/DFR PD1 PD0 */
#define ADS_XCON (0x80|ADS_PD|(ADS_SE << 2)|(ADS_M12 << 3)|(ADS_IX << 4))
#define ADS_YCON (0x80|ADS_PD|(ADS_SE << 2)|(ADS_M12 << 3)|(ADS_IY << 4))
#define ADS_3CON (0x80|ADS_PD|(ADS_SE << 2)|(ADS_M12 << 3)|(ADS_I3 << 4))
#define ADS_4CON (0x80|ADS_PD|(ADS_SE << 2)|(ADS_M12 << 3)|(ADS_I4 << 4))
#define ADS_MAXBIT 16 /* 16 Bit Clock */
#else
#define ADS_XCON (0x80|ADS_PD|(ADS_SE << 2)|(ADS_M8 << 3)|(ADS_IX << 4))
#define ADS_YCON (0x80|ADS_PD|(ADS_SE << 2)|(ADS_M8 << 3)|(ADS_IY << 4))
#define ADS_3CON (0x80|ADS_PD|(ADS_SE << 2)|(ADS_M8 << 3)|(ADS_I3 << 4))
#define ADS_4CON (0x80|ADS_PD|(ADS_SE << 2)|(ADS_M8 << 3)|(ADS_I4 << 4))
#define ADS_MAXBIT 12 /* 12 Bit Clock */
#endif
/* 每个通道采样 5 次, 取中间一次的值 */
#define ADSSMPMAX 3
/* 最大的合法采样值 */
#define ADSVALMAX 0x0F0
/* ADS 通道 */
BOOLEAN bADSChCnt;
/* False: 键盘输入, 否则为触摸屏输入 */
BOOLEAN bEnOSC;
/* False: 无键输入, 否则有键按下 */
BOOLEAN bSWState;
union {
struct{
sADSBlockType *spADSblk;
u8 uSADSCntr; /* ADS 采样计数 */
u8 uSyTmp; /* 暂存 Y 方向的值 */
} S_ADS;
struct{
FourBytes dSBuf; /* 存储扫描键 */
u8 uSDebounce; /* 键抖动时间 4mS */
} S_KBD;
} data S_SCAN;
u8 idata uADSTemp[ADSSMPMAX]; /* 采样值缓存 */
#define uADSCntr S_SCAN.S_ADS.uSADSCntr
#define uADSyTmp S_SCAN.S_ADS.uSyTmp
#define dSWBuf S_SCAN.S_KBD.dSBuf
#define uDebounce S_SCAN.S_KBD.uSDebounce
u8 data uKeyBuf; /* 键扫描结果, 0 表示没有键 */
/* 键盘扫描, 每 4mS 执行一次 */
void KBDScan(void)
{
u8 uScan;
u8 uI;
FourBytes dKeyGet; /* 扫描结果 */
/* 输入方式 */
KBD_PORT |= KBD_MASK;
uScan = 0x0fe;
dKeyGet.d_form = 0;
for(uI=0; uI<8; uI++){ /* 扫描 8 次 */
XBYTE[Addr_KBD] = uScan;
uScan = (uScan << 1) + 1 ;
dKeyGet.d_form = (dKeyGet.d_form | (u32)(KBD_PORT & KBD_MASK)) << 3;
}
/* 键盘扫描关闭 */
XBYTE[Addr_KBD] = 0x0ff;
if (dSWBuf.d_form != dKeyGet.d_form){
uDebounce = 25; // 100mS(On 4mS)
dSWBuf.d_form = dKeyGet.d_form;
} else if (uDebounce-- == 0){
uDebounce = 25;
/* 分析扫描结果 */
uI = 0;
uScan = 0;
while ((uScan != 0x0ff) && (uI++ < KEYMAX)){
if (~(dKeyGet.b_form.hh & 0x80)){
if (uScan){
uScan = 0x0ff; /* 多键同时按下 */
} else {
uScan = uI; /* 有键按下, 记录键位号 */
}
}
dKeyGet.d_form <<= 1;
}
/* 处理扫描键 */
if (uScan == 0x00){
bSWState = FALSE; /* 所有键都释放 */
} else if (~bSWState){
SetBuzCntr(BuzCntrShort); /* 蜂鸣器短鸣一声*/
uKeyBuf = uScan;
bSWState = TRUE; /* 下一个处理状态 */
}
} /* if (dSWBuf.d_form != dKeyGet.d_form) */
}
/* 输出控制字节 */
void ADS_Wr8(u8 uCon)
{
u8 i;
//ADS_DO = 1;
for (i=0; i<8; i++){
ADS_DCLK = 0;
if (ValBit(uCon,7)){
ADS_DI = 1;
} else {
ADS_DI = 0;
}
uCon <<= 1;
ADS_DCLK = 1;
}
ADS_DCLK = 0;
}
/* 读入数据 */
u8 ADS_Rd8(void)
{
u8 i;
u8 uData; /* 存储读入数据 */
/* 准备输入 */
ADS_DO = 1;
ADS_DI = 0;
for (i=0; i<ADS_MAXBIT; i++){
ADS_DCLK = 0;
if (i < 9){
uData <<= 1;
if (ADS_DO){
uData |= 1;
}
}
ADS_DCLK = 1;
}
ADS_DCLK = 0;
return uData;
}
/* 键盘/触摸屏 检测 */
void InitKBD(void)
{
/* 启动 ADS7843 采样, /CS 总是低电位 */
ADS_Wr8(ADS_3CON);
/* 延时 */
bADSChCnt = FALSE;
uADSCntr = 0;
XBYTE[Addr_KBD] = 0x0ff; /* 键盘扫描关闭 */
if (ADS_Rd8() > 0x50){
KBD_PORT |= KBD_MASK;
bEnOSC = FALSE; /* 键盘 */
} else {
bEnOSC = TRUE; /* 触摸屏 */
}
}
/* 触摸屏处理, 每 4mS 执行一次 */
void OSCScan(void)
{
u8 i, j, k;
if (S_SCAN.S_ADS.spADSblk != NULL){
/* 选择通道 */
ADS_Wr8(bADSChCnt? ADS_YCON : ADS_XCON);
/* 采样 */
i = uADSCntr++;
uADSTemp[i] = j = ADS_Rd8();
if (i != 0){
/* 如果两次采样值差值超过30,则重新启动采样 */
k = uADSTemp[i - 1];
if (((k >= j) ? (k - j) : (j - k)) > 30) {
uADSCntr = 0;
} else {
/* 按升序排列 */
while ((i != 0) &&
(j < uADSTemp[i - 1])){
uADSTemp[i] = uADSTemp[i - 1];
i--;
uADSTemp[i] = j;
}
/* 同一个通道下一次采样 */
if (uADSCntr >= ADSSMPMAX){
/* 对采样数据进行处理 */
if (bADSChCnt){
/* 没有触摸触摸屏 */
if ((uADSyTmp > 0x0f0) && /* ! 这两个参数可能需要调整 */
(uADSTemp[1] < 0x10)){
bSWState = FALSE; /* 空闲状态 */
} else if (~bSWState){
SetBuzCntr(BuzCntrShort); /* 蜂鸣器短鸣一声 */
bSWState = TRUE; /* 下一个处理状态 */
//uKeyBuf = Scan_P(uADSTemp[1], uADSyTmp);
}
/* 准备下一次采样 */
bADSChCnt = FALSE;
} else {
uADSyTmp = uADSTemp[1];
bADSChCnt = TRUE;
}
uADSCntr = 0;
}
}
}
}
}
/* 触摸屏数据处理 */
u8 Scan_P(uPx, uPy)
{
sADSBlockType *pADSblk;
pADSblk = S_SCAN.S_ADS.spADSblk;
while (pADSblk->uxMin != 0x00){
if ((pADSblk->uxMin <= uPx) &&
(pADSblk->uxMax >= uPx) &&
(pADSblk->uyMin <= uPy) &&
(pADSblk->uyMax >= uPy)){
return pADSblk->uKeyCode;
break;
}
// 处理下一个数据块
pADSblk++;
}
}
/* 设置触摸屏的区域指针 */
void SetOSC(sADSBlockType *xp)
{
S_SCAN.S_ADS.spADSblk = xp;
}
/*----------Copyright 2006-2010 武汉菱电汽车电子有限公司---------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -