中级会员
- 积分
- 384
- 金钱
- 384
- 注册时间
- 2023-7-23
- 在线时间
- 89 小时
|
4金钱
最近为了练手,在网上找了一个按键实验的代码根据精英版的知识改造一下,没想到bug不少。以下是主函数的代码:
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "key.h"
//ALIENTEK精英STM32F103开发板 实验0
//新建工程 实验
//技术支持:www.openedv.com
//广州市星翼电子科技有限公司
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
uart_init(72,115200); //串口初始化为115200
/* LED端口初始化 开始*/
// 开启GPIOB 端口时钟
RCC->APB2ENR |= (1<<3);
RCC->APB2ENR |= (1<<6);
//清空控制PB5的端口位
GPIOB->CRL &= ~( 0x0F<< (4*5));
// 配置PB5为通用推挽输出,速度为10M
GPIOB->CRL |= (1<<(4*5));
GPIOB->ODR|=1<<5;
//清空控制PE5的端口位
GPIOE->CRL &= ~( 0x0F<< (4*5));
// 配置PE5为通用推挽输出,速度为10M
GPIOE->CRL |= (1<<(4*5));
GPIOE->ODR|=1<<5;
/* 按键端口初始化 */
Key_GPIO_Config();
/* LED端口初始化 结束*/
PEout(5)=!PEout(5);
PBout(5)=!PBout(5);
/* 轮询按键状态,若按键按下则反转LED */
while(1)
{
if( Key_Scan(PEin(3)) == KEY_ON )
{
/*LED2反转*/
PBout(5)=!PBout(5);
}
if( Key_Scan(PEin(4)) == KEY_ON )
{
/*LED1反转*/
PEout(5)=!PEout(5);
}
}
}
这是key.c的代码
#include "key.h"
#include "sys.h"
/**
* @brief 配置按键用到的I/O口
* @param 无
* @retval 无
*/
void Key_GPIO_Config(void)
{
/*开启按键端口的时钟*/
RCC->APB2ENR|=1<<6;
GPIOE->CRL &= ~( 0x0F<< (4*4));
GPIOE->CRL |= (0X8<<(4*4));
GPIOE->ODR |= (1<<4);
GPIOE->CRL &= ~( 0x0F<< (4*3));
GPIOE->CRL |= (0X8<<(4*3));
GPIOE->ODR |= (1<<3);
}
/*
* 函数名:Key_Scan
* 描述 :检测是否有按键按下
* 输入 :GPIOx:x 可以是 A,B,C,D或者 E
* GPIO_Pin:待读取的端口位
* 输出 :KEY_OFF(没按下按键)、KEY_ON(按下按键)
*/
u8 Key_Scan(u8 KEYxIDR)
{
/*检测是否有按键按下 */
if(KEYxIDR == KEY_ON )
{
/*等待按键释放 */
while(KEYxIDR == KEY_ON);
return KEY_ON;
}
else
return KEY_OFF;
}
以下是key。h的代码:
#include "sys.h"
#define KEY_ON 1
#define KEY_OFF 0
void Key_GPIO_Config(void);
u8 Key_Scan(u8 KEYxIDR);
结果是灯会亮,但是不能根据按键闪。
然后我有根据原子代码在基础上稍作修改结果灯灵敏度很差。这是主程序代码
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "key.h"
//ALIENTEK精英STM32F103开发板 实验0
//新建工程 实验
//技术支持:www.openedv.com
//广州市星翼电子科技有限公司
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
/* LED端口初始化开始 */
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
uart_init(72,115200); //串口初始化为115200
// 开启GPIOB 端口时钟
RCC->APB2ENR |= (1<<3);
RCC->APB2ENR |= (1<<6);
//清空控制PB5的端口位
GPIOB->CRL &= ~( 0x0F<< (4*5));
// 配置PB5为通用推挽输出,速度为10M
GPIOB->CRL |= (1<<(4*5));
GPIOB->ODR|=1<<5;
//清空控制PE5的端口位
GPIOE->CRL &= ~( 0x0F<< (4*5));
// 配置PE5为通用推挽输出,速度为10M
GPIOE->CRL |= (1<<(4*5));
GPIOE->ODR|=1<<5;
//led初始化结束
/* 按键端口初始化 */
Key_GPIO_Config();
PEout(5)=!PEout(5);
PBout(5)=!PBout(5);
/* 轮询按键状态,若按键按下则反转LED */
while(1)
{
if( key_scan(0) == KEY0_PRES )
{
/*LED0反转*/
PBout(5)=!PBout(5);
}
if( key_scan(0) == KEY1_PRES )
{
/*LED1反转*/
PEout(5)=!PEout(5);
}
}
}
以下是key。h的内容
#include "sys.h"
#define KEY1 PEin(3)
#define KEY0 PEin(4)
#define KEY0_PRES 2
#define KEY1_PRES 1
void Key_GPIO_Config(void);
uint8_t key_scan(uint8_t mode);
以下是key.c的内容
#include "key.h"
#include "sys.h"
/**
* @brief 配置按键用到的I/O口
* @param 无
* @retval 无
*/
void Key_GPIO_Config(void)
{
/*开启按键端口的时钟*/
RCC->APB2ENR|=1<<6;
GPIOE->CRL &= ~( 0x0F<< (4*4));
GPIOE->CRL |= (0X8<<(4*4));
GPIOE->ODR |= (1<<4);
GPIOE->CRL &= ~( 0x0F<< (4*3));
GPIOE->CRL |= (0X8<<(4*3));
GPIOE->ODR |= (1<<3);
}
/*
* 函数名:Key_Scan
* 描述 :检测是否有按键按下
*/
uint8_t key_scan(uint8_t mode)
{
static uint8_t key_up = 1; /* 按键按松开标志 */
uint8_t keyval = 0;
if (mode) key_up = 1; /* 支持连按 */
if (key_up && (KEY0 == 0 || KEY1 == 0 )) /* 按键松开标志为1, 且有任意一个按键按下了 */
{
delay_ms(10); /* 去抖动 */
key_up = 0;
if (KEY0 == 0) keyval = KEY0_PRES;
if (KEY1 == 0) keyval = KEY1_PRES;
}
else if (KEY0 == 1 && KEY1 == 1) /* 没有任何按键按下, 标记按键松开 */
{
key_up = 1;
}
return keyval; /* 返回键值 */
}
我的板子梅问题用原子的代码按键灵敏很合适。
|
最佳答案
查看完整内容[请看2#楼]
这个while等待抬起一股51的味道
我按着不放你怎么处理呢?
你测试的时候应该是没有按着不放的
那代码也没有什么卡顿,他灵敏度也没有什么问题的
你现在的现象应该是不跟手
你可以试试先两个按键控制一个灯,不要用翻转了 ,一个按键亮一个按键灭
如果这样没有问题的话,那就是重复触发的问题了
你缺少一个消除抖动和只执行一次的标志位
你按下一次按键他可能翻转了10次 那就是还在原来的状态,所以你会感觉卡顿
|