一、电路原理
1.1. 矩阵键盘电路
1.2. gd32f103单片机端是iic,中间经过一个pca9535芯片。
1.3 pca9535 的功能请参考相关文档
这里主要用到的是设置输入输出模式,读取输入值,输出高或者输出低等功能。
二、基本要求
2.1 单个按键识别
2.2 组合键识别(一般是两个按键同时按下)
2.3 按键消抖
2.4 防止识别重复按键,不需要识别长短按键。
三、前期已经完成的识别程序
3.1 程序基本原理描述(称为行扫描模式)
3.1.1 L信号(P1端口)作输入模式,H信号(P0端口)作输出模式,任意时刻只有一个H信号为低电平,其他为高电平。
使用i计数,i=0时,H1为低,其他(H2-H6)输出高,读取L信号,如果都为1(取低6位,0x3f),则表示没有按键被按下,如果不等于0x3f,则表示有按键被按下,有按键被按下,则需要循环6次,判断其中的哪些位(考虑多个按键被按下的情况)为0,则为0的位表示有按键被按下,这样就找到了被按下的按键。
其他行依次类推,i=1时,H2输出低,其他(H1,H3-H6)输出高。
L信号是输入引脚,外部电路有10K上拉电阻,如果不跟外部连接的话,读信号肯定是个高电平,所以没有按键按下时,判断为高电平。
如果按键按下,同时按键所在的H信号正好也是低电平的话,按键闭合导致电路形成回路,上拉电阻的一端(这一端正好接着L信号)电压被拉低为0,L读到的正好也是低电平,这时可以判断按键被按下。特别说明,H信号为高的时候,即使按键被按下,L信号仍然是高,没法得出按键被按下的情况。所以这里一定要某一个H信号(比如H1)为低,其他H信号(则是H2-H6)为高,就能够分辨是哪一行有按键了。
3.1.2 按键也要消抖,这里是连续采集到两次,则认为识别到了一个有效按键。
g_btns_info.pressCnt[index]++;
3.1.3 按键也要防止重复识别,按下一次就识别一次,不能因为久按而识别多次。
if(g_btns_info.pressCnt[index] < 2)
{
g_btns_info.pressCnt[index]++;
if(g_btns_info.pressCnt[index] == 2)//检测到不止1次
3.1.4 我程序中有串口上报键值的部分,可以注释掉。printf是串口打印,用于调试
send_btn_change_to_cpu(index+1,1); //发送按键按下/松开
3.2 源程序
结构体
typedef struct btn_info{
uint8_t value[KEY_MAX]; //0表示松开,1表示按下
uint8_t reportEn[KEY_MAX]; //1,需要上报,0不需要上报
uint16_t pressCnt[KEY_MAX]; //消抖,长按区分
}BTN_INFO;
//只有6行,这些数字用于分别扫描每一行
const static uint8_t key_scan_line[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
// 6*6 的键盘矩阵,总共有33个按键,按键个数在h文件中定义
static BTN_INFO g_btns_info;
TaskHandle_t TaskHandle_key_Matrix; //存放按键任务指针
//端口的配置
void matrix_keys_init(void)
{
uint8_t outcfg_dat[2]={0,0xff}; //IIC芯片GPIO输出模式,对应的位要设置为0
//1. iic的初始化
nca9555_init(NCA9555_IIC_CONTROLER);
//矩阵按键,P0端口配置为输出,P1端口配置为输入,因为P1端口上用了上拉电阻
nca9555_write_2config(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,outcfg_dat);
nca9555_write_outport(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0, 0); //P0端口输出0
#ifdef BTNS_USE_INT //宏在btns_leds.h中定义
//中断引脚初始化
//2. 中断引脚的初始化 PB12,外部中断12
//2.1 时钟使能
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_AF);
gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ, GPIO_PIN_12);
//2.2 复用为外部中断引脚,
gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_12);
//设置触发方式,低电平触发
exti_init(EXTI_12, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_enable(EXTI_12);
exti_interrupt_flag_clear(EXTI_12);
//2.3 nvic允许中断
//中断控制器使能,使用的是外部中断12
nvic_irq_enable(EXTI10_15_IRQn, 7, 0); //允许中断,并设置优先级
//初始化之后读取一次
matrix_keys_row_scan();
#endif
memset(&g_btns_info,0,sizeof(g_btns_info)); //数据清零
}
static uint8_t matrix_keys_row_scan(void)
{
uint8_t key_row_dat;
//读取P1(L信号)端口的值
if(nca9555_read_inport(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,1,&key_row_dat) == 0) //表示读取成功
{
if((key_row_dat&0x3f) != 0x3f) //只判断低6位,不相等表示有按键按下
{
return key_row_dat&0x3f;
}
else
{
return 0x3f;
// printf("ERROR: KEY_ROW_SCAN key_row_dat == 0x3f\r\n");
}
}
else //iic读取失败
{
printf("ERROR: KEY_ROW_SCAN nca9555_read_inport\r\n");
return 0xff;
}
}
/***
*函数名:KEY_SCAN
*功 能:6*6按键扫描
*返回值:1~36,对应36个按键,0表示没有检测到
*/
char matrix_keys_scan(void)
{
uint8_t key_row_num=0; //行扫描结果记录
uint8_t i,j;
uint8_t index; //
static uint8_t release_report = 0; //松开上报。
key_row_num = matrix_keys_row_scan();
if(key_row_num < 0x3f) //读取到了一个有效的按键触发
{
for(i=0;i<COL_NUM;i++) //每一列扫描一次
{
//分六次,对行信号进行分别输出,任意时刻,只有一个行信号是0,其他都是高电平
if(nca9555_write_outport(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0, key_scan_line[i])) //P0端口输出0
{
printf("ERROR: KEY_ROW_SCAN nca9555_write_outport i=%d\r\n",i);
continue; //写入失败,直接往下试试
// return -1;
}
//再次读取输入
key_row_num = matrix_keys_row_scan();
for(j=0;j<ROW_NUM;j++) //每一行扫描一次
{
index = 6*i+j;
if(!((key_row_num>>j)&(1))) //按下
{
if(g_btns_info.pressCnt[index] < 2)
{
g_btns_info.pressCnt[index]++;
if(g_btns_info.pressCnt[index] == 2)//检测到不止1次
{ //条件限制上报一次
g_btns_info.value[index] = 1;
// g_btns_info.reportEn[index] = 1; //按下上报
send_btn_change_to_cpu(index+1,1); //发送按键按下/松开
printf("----btn:%d press\r\n",index+1);
release_report = 1; //记录需要释放标志
}
}
}
else //松开
{
if(g_btns_info.value[index]) //之前的状态是按下
{
g_btns_info.value[index] = 0;
// g_btns_info.reportEn[index] = 2; //松开上报
send_btn_change_to_cpu(index+1,0); //发送按键按下/松开
printf("++++btn:%d release\r\n",index+1);
g_btns_info.pressCnt[index] = 0;
}
}
}
}
}
else
{
if(release_report) //需要上报释放信息。
{
for(index=0;index<COL_NUM*ROW_NUM;index++)
{
if(g_btns_info.value[index]) //之前的状态是按下
{
g_btns_info.value[index] = 0;
// g_btns_info.reportEn[index] = 2; //松开上报
send_btn_change_to_cpu(index+1,0); //发送按键按下/松开
printf("#####btn:%d release\r\n",index+1);
g_btns_info.pressCnt[index] = 0;
}
}
// btn_start_scan = 0; //按键不再扫描
release_report = 0;
}
}
//设置输出0,这样按下时,L端就会变为0,触发中断
nca9555_write_outport(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0, 0);
return 0;
}
#ifdef BTNS_USE_INT
//外部中断12的处理函数,按键按下和松开都会触发中断!!!!
void exint12_handle(void)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTaskNotifyFromISR(TaskHandle_key_Matrix, 0, eIncrement, &xHigherPriorityTaskWoken); //唤醒休眠的任务
//并且禁止中断
exti_interrupt_disable(EXTI_12); //扫描完毕之后再使能
}
#endif
//freeRTos任务
void task_matrix_keys_scan(void* arg)
{
//1. 矩阵按键扫描初始化
matrix_keys_init();
while(1)
{
//等待任务被唤醒
ulTaskNotifyTake(pdFALSE, portMAX_DELAY); //减1,然后无限等待
{
matrix_keys_scan();
vTaskDelay(30); //延时30ms
#ifdef BTNS_USE_INT
exti_interrupt_enable(EXTI_12); //扫描完毕之后再使能
#endif
}
}
}
单个按键的识别是正常的,不在同列的组合按键也是没有问题的。
四、遇到的问题
4.1 部分组合键不能识别
同一列(同一根L线上)比如A2+A8这种类似的组合都不能正常识别。
按下A2时,(程序打印)提示A2被按下,A2不松开的情况下,同时按下A8,程序提示A2松开。
反之,先按下A8,提示A8按下,同时把A2也按下,提示A8松开。
4.2 不正常的组合键的示波器波形(测试L引脚上的信号)
4.3 正常的按键的示波器波形(测试L引脚上的信号)
4.4 大致原因
从示波器来看的话,很明显的低电平没有拉下去,而单片机将那样的一个电平识别为高。
软件得到高电平,认为第一次的按键被释放。(实际是两个按键同时按下了)。
这确实是个芯片问题,没想到9535这个芯片输出低的时候,阻抗这么大,还是说两个按键同时按下之后,实际是芯片内部电路被短路了,因为有一个引脚是高,而另一个引脚是低,这个时候电流大,导致芯片内部一些保护措施?
H中只有一个为低,两个按键按下后,所以必然会有这样的问题是存在的。(这里假设A2和A8同时按下 的情况)
五、问题的解决
5.1 考虑列扫描的方式
行扫描有问题,那能不能换成列扫描呢?
两个按键在同一个列上,那换成列扫描,两个按键就肯定不会在同一行,这个确实是可以的。
然而,我尝试了一下,发现可以解决这个问题,但是同一行的两个按键又不可识别了。
这里因为行没有接上拉电阻,我只能用默认这个H的信号为低电平,有按键按下时是高电平
//只有6行,这些数字用于分别扫描每一行
const uint8_t key_scan_line[] = {0x1,0x2,0x4,0x8,0x10,0x20};
//端口的配置,全部配置为输入接口
void matrix_keys_init(void)
{
uint8_t outcfg_dat[2]={0xff,0xff}; //IIC芯片GPIO输出模式,对应的位要设置为0
//1. iic的初始化
nca9555_init(NCA9555_IIC_CONTROLER);
//矩阵按键,P0端口配置为输出,P1端口配置为输入,因为P1端口上用了上拉电阻
nca9555_write_2config(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,outcfg_dat);
// nca9555_write_outport(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0, 0); //P0端口输出0
//默认是输入,把输入寄存器读出来一次,读出来的值不关心
nca9555_read_inport(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0,outcfg_dat);
nca9555_read_inport(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,1,outcfg_dat);
//P1 端口的输出寄存器全部配置为0,表示输出的时候会输出低电平
outcfg_dat[0] = 0;
outcfg_dat[1] = 0;
nca9555_write_2outport(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,outcfg_dat);
//key_board cs引脚PE8,不需要??
// rcu_periph_clock_enable(RCU_GPIOE);
// gpio_init(GPIOE, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_8);
// gpio_bit_reset(GPIOE, GPIO_PIN_8);
#ifdef BTNS_USE_INT //宏在btns_leds.h中定义
//中断引脚初始化
//2. 中断引脚的初始化 PB12,外部中断12
//2.1 时钟使能
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_AF);
gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ, GPIO_PIN_12);
//2.2 复用为外部中断引脚,
//GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource9);
gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_12);
//设置触发方式,低电平触发
exti_init(EXTI_12, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_enable(EXTI_12);
exti_interrupt_flag_clear(EXTI_12);
//2.3 nvic允许中断
//中断控制器使能,使用的是外部中断12
nvic_irq_enable(EXTI10_15_IRQn, 1, 2); //允许中断,并设置优先级
//初始化之后读取一次
//matrix_keys_row_scan();
#endif
memset(&g_btns_info,0,sizeof(g_btns_info)); //数据清零
}
uint8_t matrix_keys_row_scan(void)
{
uint8_t key_row_dat;
nca9555_write_config(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0, 0x0); //设置输出,释放一下电平
nca9555_write_config(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0, 0xff); //设置输入
//读P0端口,没有按键时,应该是0,有按键时不是0
if(nca9555_read_inport(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0,&key_row_dat) == 0) //表示读取成功
{
if((key_row_dat & 0x3f) != 0) //只判断低6位,不相等表示有按键按下
{
return key_row_dat&0x3f;
}
else
{
return 0x7f;
// printf("ERROR: KEY_ROW_SCAN key_row_dat == 0x3f\r\n");
}
}
else //iic读取失败
{
printf("ERROR: KEY_ROW_SCAN nca9555_read_inport\r\n");
return 0xff;
}
}
char matrix_keys_scan(void)
{
// uint8_t Key_Num=0xff; //1-16对应的按键数
uint8_t key_row_num=0; //行扫描结果记录
uint8_t i,j;
uint8_t index; //
static uint8_t release_report = 0; //松开上报。
key_row_num = matrix_keys_row_scan();
if(key_row_num < 0x3f) //读取到了一个有效的按键触发
{
for(i=0;i<COL_NUM;i++) //每一列扫描一次
{
//P1端口只有一个引脚为输入模式,其他为输出,并且输出低电平
if(nca9555_write_config(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,1, key_scan_line[i]))
{
printf("ERROR: KEY_ROW_SCAN nca9555_write_outport i=%d\r\n",i);
continue; //写入失败,直接往下试试
// return -1;
}
//再次读取输入
key_row_num = matrix_keys_row_scan();
// printf("i = %d num = %#x\r\n",i,key_row_num);
if(key_row_num >= 0x3f)
continue;
for(j=0;j<ROW_NUM;j++) //每一行扫描一次
{
index = 6*i+j;
if(((key_row_num>>j)&(1))) //按下
{
if(g_btns_info.pressCnt[index] < 2)
{
g_btns_info.pressCnt[index]++;
if(g_btns_info.pressCnt[index] == 2)//检测到不止1次
{ //条件限制上报一次
g_btns_info.value[index] = 1;
// g_btns_info.reportEn[index] = 1; //按下上报
send_btn_change_to_cpu(index+1,1); //发送按键按下/松开
printf("----btn:%d press\r\n",index+1);
release_report = 1; //记录需要释放标志
}
}
}
else //松开
{
if(g_btns_info.value[index]) //之前的状态是按下
{
g_btns_info.value[index] = 0;
// g_btns_info.reportEn[index] = 2; //松开上报
send_btn_change_to_cpu(index+1,0); //发送按键按下/松开
printf("++++btn:%d release\r\n",index+1);
g_btns_info.pressCnt[index] = 0;
}
}
}
}
}
else
{
if(release_report) //需要上报释放信息。
{
for(index=0;index<COL_NUM*ROW_NUM;index++)
{
if(g_btns_info.value[index]) //之前的状态是按下
{
g_btns_info.value[index] = 0;
// g_btns_info.reportEn[index] = 2; //松开上报
send_btn_change_to_cpu(index+1,0); //发送按键按下/松开
printf("####btn:%d release\r\n",index+1);
g_btns_info.pressCnt[index] = 0;
}
}
btn_start_scan = 0; //按键不再扫描
release_report = 0;
}
}
//P1端口全部改为输入模式
//nca9555_write_config(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0, 0x0); //设置输出,释放一下电平
nca9555_write_config(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,1, 0xff);
// nca9555_write_config(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0, 0xff);
//nca9555_write_outport(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0, 0);
return 0;
}
5.2 在原有行扫描的基础上,增加列扫描方式。
后来发现如果按下两个键的时候,软件检测到了按键松开,那我能否在检测到松开的时候,再进行一次列扫描呢?
答案是可以的,经过一番调试,已经能够正常识别了。
(这里因为行没有接上拉电阻,我只能用默认这个H的信号为低电平,有按键按下时是高电平)
注意增加的两个函数
//检测到按键释放后,扫描一次行。
//P1(L信号)输出高,P0(H信号) 改为输入,读到某些位高电平表示有按键被按下,如果是0则表示按键都松开
//col : 0-5 分别表示L1 - L6
uint8_t matrix_keys_col_scan(uint8_t col)
//识别是哪个按键
//col : 0-5 分别表示L1 - L6
void matrix_keys_scan_col(uint8_t col,uint8_t dat)
#if 1 //2023-02-09 增加
//检测到按键释放后,扫描一次行。
//P1(L信号)输出高,P0(H信号) 改为输入,读到某些位高电平表示有按键被按下,如果是0则表示按键都松开
//col : 0-5 分别表示L1 - L6
uint8_t matrix_keys_col_scan(uint8_t col)
{
uint8_t outcfg_dat[2]={0xff,0}; //P0改为输入,P1改为输出,并且输出高
uint8_t key_row_dat;
uint8_t outdat = 0;
uint8_t ret;
//P0改输入之前,先输出0,释放一下电平
nca9555_write_outport(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0, 0);
//配置
nca9555_write_2config(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,outcfg_dat);
// nca9555_write_config(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0, 0x0); //设置输出,释放一下电平
// nca9555_write_config(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0, 0xff); //设置输出,释放一下电平
//P1 输出1
outdat = 1<< col;
nca9555_write_outport(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,1, outdat); //P1(L信号)端口输出0
//读P0(H信号)端口,没有按键时,应该是0,有按键时不是0
if(nca9555_read_inport(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0,&key_row_dat) == 0) //表示读取成功
{
if((key_row_dat & 0x3f) != 0) //只判断低6位,不相等表示有按键按下
{
ret = key_row_dat&0x3f;
}
else
{
ret = 0x7f;
// printf("ERROR: KEY_ROW_SCAN key_row_dat == 0x3f\r\n");
}
}
else //iic读取失败
{
printf("ERROR: KEY_ROW_SCAN nca9555_read_inport\r\n");
ret = 0xff;
}
//配置,默认是P0(H信号)输出,P1(L信号) 改为输入
outcfg_dat[0]=0;
outcfg_dat[1]=0xff;
nca9555_write_2config(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,outcfg_dat);
return ret;
}
//识别是哪个按键
//col : 0-5 分别表示L1 - L6
void matrix_keys_scan_col(uint8_t col,uint8_t dat)
{
uint8_t index,j;
if(!dat || (dat >= 0x3f))
return;
for(j=0;j<ROW_NUM;j++) //每一行扫描一次
{
index = 6*j+col;
if(((dat>>j)&(1))) //高电平表示按下,低表示松开
{
if(!g_btns_info.value[index])
{
// g_btns_info.pressCnt[index]++;
// if(g_btns_info.pressCnt[index] == 2)//检测到不止1次
{ //条件限制上报一次
g_btns_info.value[index] = 1;
// g_btns_info.reportEn[index] = 1; //按下上报
send_btn_change_to_cpu(index+1,1); //发送按键按下/松开
printf("@#@#btn:%d press\r\n",index+1);
// release_report = 1; //记录需要释放标志
}
}
}
else if(g_btns_info.value[index]) //之前的状态是按下
{
g_btns_info.value[index] = 0;
// g_btns_info.reportEn[index] = 2; //松开上报
send_btn_change_to_cpu(index+1,0); //发送按键按下/松开
printf("@@@btn:%d release\r\n",index+1);
g_btns_info.pressCnt[index] = 0;
}
}
}
#endif
/***
*函数名:KEY_SCAN
*功 能:6*6按键扫描
*返回值:1~36,对应36个按键,0表示没有检测到
*/
char matrix_keys_scan(void)
{
uint8_t key_row_num=0; //行扫描结果记录
uint8_t i,j;
uint8_t index,col_dat; //
static uint8_t release_report = 0; //松开上报。
key_row_num = matrix_keys_row_scan();
if(key_row_num < 0x3f) //读取到了一个有效的按键触发
{
for(i=0;i<COL_NUM;i++) //每一列扫描一次
{
if(nca9555_write_outport(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0, key_scan_line[i])) //P0端口输出0
{
printf("ERROR: KEY_ROW_SCAN nca9555_write_outport i=%d\r\n",i);
continue; //写入失败,直接往下试试
// return -1;
}
//再次读取输入
key_row_num = matrix_keys_row_scan();
for(j=0;j<ROW_NUM;j++) //每一行扫描一次
{
index = 6*i+j;
if(!((key_row_num>>j)&(1))) //按下
{
if(g_btns_info.pressCnt[index] < 2)
{
g_btns_info.pressCnt[index]++;
if(g_btns_info.pressCnt[index] == 2)//检测到不止1次
{ //条件限制上报一次
g_btns_info.value[index] = 1;
// g_btns_info.reportEn[index] = 1; //按下上报
send_btn_change_to_cpu(index+1,1); //发送按键按下/松开
printf("----btn:%d press\r\n",index+1);
release_report = 1; //记录需要释放标志
}
}
}
else //松开
{
if(g_btns_info.value[index]) //之前的状态是按下
{
#if 1
col_dat = matrix_keys_col_scan(j);
// printf("j = %d dat = %#x,index = %d\r\n",j,col_dat,index);
if(col_dat >= 0x3f)
{
g_btns_info.value[index] = 0;
// g_btns_info.reportEn[index] = 2; //松开上报
send_btn_change_to_cpu(index+1,0); //发送按键按下/松开
printf("++++btn:%d release\r\n",index+1);
g_btns_info.pressCnt[index] = 0;
}
else{
matrix_keys_scan_col(j,col_dat);
}
#else
g_btns_info.value[index] = 0;
// g_btns_info.reportEn[index] = 2; //松开上报
send_btn_change_to_cpu(index+1,0); //发送按键按下/松开
printf("++++btn:%d release\r\n",index+1);
g_btns_info.pressCnt[index] = 0;
#endif
}
}
}
}
}
else
{
if(release_report) //需要上报释放信息。
{
for(index=0;index<COL_NUM*ROW_NUM;index++)
{
if(g_btns_info.value[index]) //之前的状态是按下
{
#if 1
j = index%6;
col_dat = matrix_keys_col_scan(j);
// printf("22- j = %d dat = %#x,index = %d\r\n",j,col_dat,index);
if(col_dat >= 0x3f)
{
g_btns_info.value[index] = 0;
// g_btns_info.reportEn[index] = 2; //松开上报
send_btn_change_to_cpu(index+1,0); //发送按键按下/松开
printf("####btn:%d release\r\n",index+1);
g_btns_info.pressCnt[index] = 0;
}
#else
g_btns_info.value[index] = 0;
// g_btns_info.reportEn[index] = 2; //松开上报
send_btn_change_to_cpu(index+1,0); //发送按键按下/松开
printf("#####btn:%d release\r\n",index+1);
g_btns_info.pressCnt[index] = 0;
#endif
}
}
// btn_start_scan = 0; //按键不再扫描
release_report = 0;
}
}
nca9555_write_outport(NCA9555_IIC_CONTROLER,KEYS_IIC_ADDR,0, 0);
return 0;
}
以为这是一个死结,但是只要能想到办法,还是可以解决的。
两个键组合已经没有问题了,但是这个软件仍然有bug,三个键组合的时候,还是有些不能识别的情况,如同在一个列上两个按下,第三个与其中一个同行,这样无法识别第三个按键的按下和松开,好在项目没有这个需求,先这样吧。文章来源:https://www.toymoban.com/news/detail-611029.html
感谢大家多来批评指正。谢谢文章来源地址https://www.toymoban.com/news/detail-611029.html
到了这里,关于32单片机矩阵键盘-同列组合键不能识别故障-已解决的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!