OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2297|回复: 1

一个关于用外部中断和定时器中断来读取4x4矩阵键盘的问题

[复制链接]

1

主题

3

帖子

0

精华

新手上路

积分
48
金钱
48
注册时间
2018-4-27
在线时间
5 小时
发表于 2018-4-27 23:38:09 | 显示全部楼层 |阅读模式
1金钱
这里用的是EXTI和TIM两个中断,按理来说EXTI是上升沿触发的,但是在这代码里,并不是按键以后只执行一次,而是不停的循环输出,问题定位在:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)定时器回调的

for(int j=1;j<5;j++) // 列切换电平扫描
{

KeyBoardColumnWritePin(j); // 列输出电平逐次置低

......
}
这个函数是修改列的电平来确定按下的键是哪一列的,最后有函数定义,注释掉这个就可以正常的上升沿触发的,可是不能实现我的功能.
我发现好像是在修改按键位置的列的电平从高到低时会出问题,可是不知道为什么,怎么修改,希望大家能帮忙看一下代码有没有问题,谢谢~

[mw_shl_code=c,true]uint8_t KeyPressRow;            // 存储按下键的行
uint8_t KeyPressColumn;         // 存储按下键的列
uint8_t KeyBoardPressedFlag=0;     // 是否按下键,在扫描步骤flag
uint8_t KeyBoardValue[5]={0,0,0,0,0};    // KeyBoardValue[1~4]存储扫描数据 KeyBoardValue[0]取其值或
/**
  * @brief  EXTI line detection callbacks.
  * @param  GPIO_Pin: Specifies the pins connected EXTI line
  * @retval None
  */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(GPIO_Pin);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_GPIO_EXTI_Callback could be implemented in the user file
   */
    // 上升沿触发KeyBoard5~8的EXTI线中断
    if(GPIO_Pin==KeyBoard5_Pin||GPIO_Pin==KeyBoard6_Pin||GPIO_Pin==KeyBoard7_Pin||GPIO_Pin==KeyBoard8_Pin)
    {
        #ifdef _KEYBOARD_DEBUG_
            printf("Testing EXTI:Trigger.\r\n");
        #endif
        if(KeyBoardPressedFlag==0)  // 检测是否按下键,在扫描步骤
        {
            KeyBoardPressedFlag=1;
            HAL_TIM_Base_Start_IT(&htim2);  // 开启消除抖动定时器
        }
    }
}

/**
  * @brief  Period elapsed callback in non blocking mode
  * @param  htim : TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(htim);
  /* NOTE : This function Should not be modified, when the callback is needed,
            the __HAL_TIM_PeriodElapsedCallback could be implemented in the user file
   */
    if(htim->Instance==htim2.Instance)
    {
        // APB1时钟:72MHz
        // PSC预分频器7200得到10000Hz频率
        // ARR自动重载寄存器100得到100Hz频率
        // TIM2 : 10ms
        if(KeyBoardReadPin()!=0)    // 正常按下按钮
        {
            for(int i=1;i<5;i++)    // 存储行
                if(KeyBoardValue!=0)
                    KeyPressColumn=i;
         
            for(int j=1;j<5;j++)    // 列切换电平扫描
            {
               
                KeyBoardColumnWritePin(j);  // 列输出电平逐次置低
               
                if(KeyBoardReadPin()==0)    // 列获取无高电平时则按键位于扫描行
                    KeyPressRow=j;
                #ifdef _KEYBOARD_DEBUG_
                    printf("%d %d %d %d\r\n",KeyBoardValue[1],KeyBoardValue[2],KeyBoardValue[3],KeyBoardValue[4]);
                #endif
            }
        KeyBoardColumnWritePin(0);  // 列输出电平全部置高
        KeyBoardPressPcocess(KeyPressRow,KeyPressColumn);   // 按键处理函数
        }
        HAL_TIM_Base_Stop_IT(&htim2);   // 停止消除抖动定时器
        KeyBoardPressedFlag=0;  //未按下键,不在扫描步骤
    }
}

// 读取行电平
uint8_t KeyBoardReadPin(void)
{
    KeyBoardValue[1]=HAL_GPIO_ReadPin(KeyBoard5_GPIO_Port,KeyBoard5_Pin);
    KeyBoardValue[2]=HAL_GPIO_ReadPin(KeyBoard6_GPIO_Port,KeyBoard6_Pin);
    KeyBoardValue[3]=HAL_GPIO_ReadPin(KeyBoard7_GPIO_Port,KeyBoard7_Pin);
    KeyBoardValue[4]=HAL_GPIO_ReadPin(KeyBoard8_GPIO_Port,KeyBoard8_Pin);
    KeyBoardValue[0]=(KeyBoardValue[1]<<3)|(KeyBoardValue[2]<<2)|(KeyBoardValue[3]<<1)|(KeyBoardValue[4]);
    return KeyBoardValue[0];
}

// 扫描列输出电平切换
void KeyBoardColumnWritePin(uint8_t KeyBoardColumnWritePinMode)
{
    switch(KeyBoardColumnWritePinMode)
    {
        case 0:
            // HHHH
            HAL_GPIO_WritePin(KeyBoard1_GPIO_Port,KeyBoard1_Pin,GPIO_PIN_SET);
            HAL_GPIO_WritePin(KeyBoard2_GPIO_Port,KeyBoard2_Pin,GPIO_PIN_SET);
            HAL_GPIO_WritePin(KeyBoard3_GPIO_Port,KeyBoard3_Pin,GPIO_PIN_SET);
            HAL_GPIO_WritePin(KeyBoard4_GPIO_Port,KeyBoard4_Pin,GPIO_PIN_SET);
            break;
        case 1:
            // LHHH
            HAL_GPIO_WritePin(KeyBoard1_GPIO_Port,KeyBoard1_Pin,GPIO_PIN_RESET);
            HAL_GPIO_WritePin(KeyBoard2_GPIO_Port,KeyBoard2_Pin,GPIO_PIN_SET);
            HAL_GPIO_WritePin(KeyBoard3_GPIO_Port,KeyBoard3_Pin,GPIO_PIN_SET);
            HAL_GPIO_WritePin(KeyBoard4_GPIO_Port,KeyBoard4_Pin,GPIO_PIN_SET);
            break;
        case 2:
            // HLHH
            HAL_GPIO_WritePin(KeyBoard1_GPIO_Port,KeyBoard1_Pin,GPIO_PIN_SET);
            HAL_GPIO_WritePin(KeyBoard2_GPIO_Port,KeyBoard2_Pin,GPIO_PIN_RESET);
            HAL_GPIO_WritePin(KeyBoard3_GPIO_Port,KeyBoard3_Pin,GPIO_PIN_SET);
            HAL_GPIO_WritePin(KeyBoard4_GPIO_Port,KeyBoard4_Pin,GPIO_PIN_SET);
            break;
        case 3:
            // HHLH
            HAL_GPIO_WritePin(KeyBoard1_GPIO_Port,KeyBoard1_Pin,GPIO_PIN_SET);
            HAL_GPIO_WritePin(KeyBoard2_GPIO_Port,KeyBoard2_Pin,GPIO_PIN_SET);
            HAL_GPIO_WritePin(KeyBoard3_GPIO_Port,KeyBoard3_Pin,GPIO_PIN_RESET);
            HAL_GPIO_WritePin(KeyBoard4_GPIO_Port,KeyBoard4_Pin,GPIO_PIN_SET);
            break;
        case 4:
            // HHHL
            HAL_GPIO_WritePin(KeyBoard1_GPIO_Port,KeyBoard1_Pin,GPIO_PIN_SET);
            HAL_GPIO_WritePin(KeyBoard2_GPIO_Port,KeyBoard2_Pin,GPIO_PIN_SET);
            HAL_GPIO_WritePin(KeyBoard3_GPIO_Port,KeyBoard3_Pin,GPIO_PIN_SET);
            HAL_GPIO_WritePin(KeyBoard4_GPIO_Port,KeyBoard4_Pin,GPIO_PIN_RESET);
            break;
    }
}

// 按键处理函数
void KeyBoardPressPcocess(uint8_t Row,uint8_t column)
{
    printf("Testing KeyBoard: ");
    printf("K%d (%d,%d)\r\n",(Row-1)*4+column,Row,column);
}[/mw_shl_code]
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2018-4-27 23:38:10 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-7 16:20

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表