⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kbd.c

📁 操作触摸屏控制器 ADS7843 ADS7846的C程序 Keil C, AT89S52
💻 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 + -