MAX7349和MAX7359均可管理多达64个按键,采用Maxim专有的低电压、低EMI静态按键扫描技术,并将去抖后的扫描结果编成键值,依据按键的键序将键值消息存放在FIFO中,手机处理器在适当的时候读取FIFO中的键值消息,即使处理器没有及时处理按键事件,按键消息也不会丢失,这对通常采用非实时操作系统的智能手机来说非常重要。与MAX7349相比,MAX7359增加了按键释放检测功能,即每次按下和释放按键都会生成一个键值消息,可更简便实现多键同时输入及组合键功能。另外,该系列器件优化了控制寄存器并增加存储键值消息的FIFO空间,即由MAX7349的存储8次按键增加到存储16次按键。
MAX7359还具有自动休眠和自动唤醒功能,以使器件的功耗最低。一个休眠周期后,自动休眠功能将器件置于低功耗状态(典型值1μA)。发生按键事件时,自动唤醒功能设置MAX7359返回至正常工作模式。FIFO消息的处理 处理读到的FIFO字节变量(假设变量名为:FIFO_BYTE)后,软件处理方法如下: (1)将从FIFO收到的非0x3f的字节变量FIFO_BYTE和0x3f取与(AND 0x3f),结果值为按键值(即0至63号键中某一个被按下或释放)。 (2)再将该FIFO_BYTE和0x40取与(AND 0x40),结果为0则说明按键被按下,结果非0则说明按键被释放。如果硬件布线时使用了63号和62号键,FIFO_BYTE处理复杂,请软件设计工程师参考MAX7359编程指南的62号和63号键处理方法。 (3)通常需要起一个定时器,定时检查还未收到键盘释放信息的键盘按下信息都是何时发生的,如果是当前时间减去按键按下的时间满足长按键时间,就可向上层软件发长按键消息。
//max7359.h
#ifndef _MAX7359_H_
#define _MAX7359_H_
#include "stm32f10x.h"
//max7359寄存器
#define MAX7359_KEYS_FIFO_REG 0x00 //上电默认为0x3F
#define MAX7359_CONFIGURATION_REG 0x01 //上电默认为0x0A
#define MAX7359_DEBOUNCE_REG 0x02 //上电默认为0xFF
#define MAX7359_INTERRUPT_REG 0x03 //上电默认为0x00
#define MAX7359_PORTS_REG 0x04 //上电默认为0xFE
#define MAX7359_KEY_REPEAT_REG 0x05 //上电默认为0x00
#define MAX7359_SLEEP_REG 0x06 //上电默认为0x07
//MAX7359读取结束键值
#define ENDofKEYNUM 63
//功能键宏定义
#define KEY_UP 16 //上
#define KEY_DOWN 17 //下
#define KEY_LEFT 18 //左
#define KEY_RIGHT 19 //右
#define KEY_CERTAIN 24 //确定
#define KEY_QUIT 25 //退出、删除
char KeyScan(void);
void MAX7359Init(void);
void ReadMAX7359(u8 *pBuffer);
#endif //_MAX7359_H_
//max7359.c
#include "MAX7359.h"
#include "i2c_ee.h"
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "stdio.h"
char bKeyFlag=0;
void MAX7359Init()
{
u8 MAX7359_CONFIGURATION_REG_Data=0x83;
u8 MAX7359_DEBOUNCE_REG_Data=0x0b;
u8 MAX7359_INTERRUPT_REG_Data=0x01;
u8 MAX7359_PORTS_REG_Data=0x40;
u8 MAX7359_KEY_REPEAT_REG_Data=0x0;
u8 MAX7359_SLEEP_REG_Data=0x03;
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
I2C_EE_ByteWrite(&MAX7359_DEBOUNCE_REG_Data,MAX7359_DEBOUNCE_REG);
//I2C_EE_ByteWrite((u8**)(0x4f),MAX7359_DEBOUNCE_REG);
I2C_EE_ByteWrite(&MAX7359_INTERRUPT_REG_Data,MAX7359_INTERRUPT_REG);
I2C_EE_ByteWrite(&MAX7359_PORTS_REG_Data,MAX7359_PORTS_REG);
I2C_EE_ByteWrite(&MAX7359_KEY_REPEAT_REG_Data,MAX7359_KEY_REPEAT_REG);
I2C_EE_ByteWrite(&MAX7359_SLEEP_REG_Data,MAX7359_SLEEP_REG);
I2C_EE_ByteWrite(&MAX7359_CONFIGURATION_REG_Data,MAX7359_CONFIGURATION_REG);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
//----PA2作为外部中断线2输入时,一定要配置为上拉输入模式、或者浮动输入模式、下拉输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //指定要以下边参数设置PA2,
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//GPIO_Mode_IN_FLOATING:引脚浮动输入模式、GPIO_Mode_IPU引脚上拉输入模式;GPIO_Mode_IPD引脚下拉输入模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //引脚允许的最大频率是50MHZ
GPIO_Init(GPIOA, &GPIO_InitStructure);
//--将PA2配置成外部中断2输入,外部中断信号在上升沿相应中断 --//
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource2);//将PA2与外中断线2连接起来
EXTI_InitStructure.EXTI_Line = EXTI_Line2; //所设置的外中断信号线的选择(0~15)
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //选择触发中断模式,还是事件模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//EXTI_Trigger_Rising; //外中断触发方式
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能外中断
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //使能按键所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
}
void ReadMAX7359(u8 *pBuffer) //测试时一般读出来是两个字节;第二个字节舍弃
{
int i;
for(i=0;;i++)
{
I2C_EE_BufferRead(&pBuffer[i], MAX7359_KEYS_FIFO_REG, 1);
//pBuffer[i]&=0x3f;
if(pBuffer[i]==ENDofKEYNUM) break;//ENDofKEYNUM=63,0x3f
}
}
void EXTI2_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line2) != RESET) //检查指定的EXTI0线路触发请求发生与否
{
LED0=!LED0;
LED1=!LED1;
TIM3->CNT=0;
TIM_Cmd(TIM3, ENABLE); //使能TIMx外设
printf("%c",KeyScan());
if(++bKeyFlag>=4) bKeyFlag=0;
}
EXTI_ClearITPendingBit(EXTI_Line2); //清除EXTI0线路挂起位
}
char KeyScan()
{
int i=0;
u8 cKeyData=0;
u8 rKeyBuffer[2]={0};
const u8 FunKeyData[6]={16,17,18,19,24,25};//功能键值数组
static vu8 OldKeyData=0x3f;
ReadMAX7359(rKeyBuffer);
//先判断功能键
for(i=0;i<6;i++)
{
if(FunKeyData[i]==rKeyBuffer[0]) {OldKeyData=0x3f; return FunKeyData[i];}
}
if(0==bKeyFlag)
{
switch(rKeyBuffer[0])
{
case 0: cKeyData='0'; break;
case 1: cKeyData='1'; break;
case 2: cKeyData='2'; break;
case 3: cKeyData='3'; break;
case 4: cKeyData='4'; break;
case 8: cKeyData='5'; break;
case 9: cKeyData='6'; break;
case 10: cKeyData='7'; break;
case 11: cKeyData='8'; break;
case 12: cKeyData='9'; break;
case 26: cKeyData='.'; break;
case 27: cKeyData='+'; break;
default: break;
}
}
if(1==bKeyFlag)
{
switch(rKeyBuffer[0])
{
case 0: cKeyData=' '; break;
case 1: cKeyData='q'; break;
case 2: cKeyData='a'; break;
case 3: cKeyData='d'; break;
case 4: cKeyData='g'; break;
case 8: cKeyData='j'; break;
case 9: cKeyData='m'; break;
case 10: cKeyData='p'; break;
case 11: cKeyData='t'; break;
case 12: cKeyData='w'; break;
case 26: cKeyData='.'; break;
case 27: cKeyData='-'; break;
default: break;
}
}
if(2==bKeyFlag)
{
switch(rKeyBuffer[0])
{
case 0: cKeyData='0'; break;
case 1: cKeyData='z'; break;
case 2: cKeyData='b'; break;
case 3: cKeyData='e'; break;
case 4: cKeyData='h'; break;
case 8: cKeyData='k'; break;
case 9: cKeyData='n'; break;
case 10: cKeyData='r'; break;
case 11: cKeyData='u'; break;
case 12: cKeyData='x'; break;
case 26: cKeyData='.'; break;
case 27: cKeyData='+'; break;
default: break;
}
}
if(3==bKeyFlag)
{
switch(rKeyBuffer[0])
{
case 0: cKeyData=' '; break;
case 1: cKeyData=','; break;
case 2: cKeyData='c'; break;
case 3: cKeyData='f'; break;
case 4: cKeyData='i'; break;
case 8: cKeyData='l'; break;
case 9: cKeyData='o'; break;
case 10: cKeyData='s'; break;
case 11: cKeyData='v'; break;
case 12: cKeyData='y'; break;
case 26: cKeyData='.'; break;
case 27: cKeyData='-'; break;
default: break;
}
}
OldKeyData=rKeyBuffer[0];
return cKeyData;
}