u16 Check_Key() { u16 key_val; unsigned char row, col; unsigned int KEY_DOUT,tmp1, tmp2; unsigned int tmp; tmp1 = 0x0800; for(row=0; row<4; row++) //行扫描 { KEY_DOUT = 0X0f00; //输出全为1 KEY_DOUT-= tmp1; //依次输出一个为0 juzhen_gpiod =((juzhen_gpiod &0xf0ff)|KEY_DOUT); tmp1 >>=1; if((GPIO_ReadInputData(juzhen_duankou)&0xf000)<0xf000) //if((KEY_DIN & 0xF0) < 0xF0) //P2输入是否有一位为0 { tmp2 = 0x1000; //用于检测出哪一位为0 for(col=0; col<4; col++) //列扫描 { if(0x00 == (GPIO_ReadInputData(juzhen_duankou) & tmp2)) //找到等于0的列 { key_val = key_Map[row*4 + col];//获取键值 } tmp2 <<= 1; //右移1位 } } } juzhen_gpiod =((juzhen_gpiod &0xf0ff)|0x0000); tmp = GPIO_ReadInputData(juzhen_duankou); if ((0x00 == key_Pressed) && ((tmp & 0xF000) < 0xF000)) //如果有键按下 { key_Pressed = 1; //按键按下标识位置位 delay_ms(1000); //延时去抖 // Check_Key(); //获取键 // key_flag = 1; //按键标识置位 } else if ((key_Pressed == 1)&&((tmp & 0xf000) == 0xF000)) //如果按键释放 { key_Pressed = 0; //清除标识位 key_flag = 1; //按键标识位置位 delay_ms(1000); //延时去抖 } else { delay_ms(1); } return key_val; //返回键值 }
时间: 2024-04-19 20:30:18 浏览: 25
这段代码是一个按键扫描函数,用于检测外部按键是否被按下,并返回相应的键值。
首先,该函数通过行扫描和列扫描的方式来检测按键状态。在行扫描过程中,依次将某一行的输出置为0,然后读取列端口的输入状态,如果有一位为0,则表示有按键被按下。然后根据列扫描的结果确定具体是哪个按键被按下,并返回相应的键值。
代码中有一些依赖的变量和函数,例如`juzhen_gpiod`是用于控制行输出的GPIO端口,`juzhen_duankou`是用于读取列输入的GPIO端口,`key_Map`是一个按键映射表,用于确定具体的键值。
另外,代码中还有一些延时操作和按键状态的标识位设置,用于去抖和处理按键的状态。
请注意,在你提供的代码中,并没有明确取消反显的相关逻辑。如果你想取消反显功能,可能需要查找其他部分代码或参考液晶显示屏的文档来确定如何进行取消反显的操作。
相关问题
u16 Check_Key() { u16 key_val; unsigned char row, col; unsigned int KEY_DOUT,tmp1, tmp2; tmp1 = 0x0800; for(row=0; row<4; row++) //行扫描 { KEY_DOUT = 0X0f00; //输出全为1 KEY_DOUT-= tmp1; //依次输出一个为0 juzhen_gpiod =((juzhen_gpiod &0xf0ff)|KEY_DOUT); tmp1 >>=1; if((GPIO_ReadInputData(juzhen_duankou)&0xf000)<0xf000) //if((KEY_DIN & 0xF0) < 0xF0) //P2输入是否有一位为0 { tmp2 = 0x1000; //用于检测出哪一位为0 for(col=0; col<4; col++) //列扫描 { if(0x00 == (GPIO_ReadInputData(juzhen_duankou) & tmp2)) //找到等于0的列 { key_val = key_Map[row*4 + col];//获取键值 } tmp2 <<= 1; //右移1位 } } } juzhen_gpiod =((juzhen_gpiod &0xf0ff)|0x0000); tmp = GPIO_ReadInputData(juzhen_duankou); if ((0x00 == key_Pressed) && ((tmp & 0xF000) < 0xF000)) //如果有键按下 { key_Pressed = 1; //按键按下标识位置位 delay_ms(1000); //延时去抖 // Check_Key(); //获取键 // key_flag = 1; //按键标识置位 } else if ((key_Pressed == 1)&&((tmp & 0xf000) == 0xF000)) //如果按键释放 { key_Pressed = 0; //清除标识位 key_flag = 1; //按键标识位置位 delay_ms(1000); //延时去抖 } else { delay_ms(1); } return key_val; //返回键值 } 通过按几次按键来确定PWM的频率
根据你提供的代码,你正在使用按键来确定 PWM 的频率。每当按下一个按键时,将获取到的键值用作 PWM 的频率。
在你的代码中,`Check_Key()` 函数用于获取按键的键值,并且当检测到按键按下时,将键值保存在 `key_val` 变量中。你可以在按键按下后将 `key_val` 作为 PWM 的频率来使用。
以下是示例代码框架,展示了如何使用 `key_val` 作为 PWM 的频率:
```c
int main()
{
int pwm_frequency = 0; // 初始化 PWM 频率为0
while (1)
{
u16 key_val = Check_Key(); // 获取按下的键值
if (key_val != 0)
{
pwm_frequency = key_val; // 将键值作为 PWM 频率
// 设置 PWM 模块的频率为 pwm_frequency
SetPWMFrequency(pwm_frequency);
}
}
return 0;
}
```
在这个示例中,`Check_Key()` 函数用于获取按下的键值。如果键值不为0,则将其赋值给 `pwm_frequency` 变量,并将其作为 PWM 的频率传递给 `SetPWMFrequency()` 函数来设置 PWM 模块的频率。
请确保根据你的硬件和 PWM 模块的要求实现 `Check_Key()` 和 `SetPWMFrequency()` 函数,并根据你的具体需求进行适当的配置和操作。
希望这个示例能够帮助你通过按键来确定 PWM 的频率。如果你还有其他问题或需要进一步帮助,请随时提问。
完善以下代码 unsigned char key_Map[] = {KEY_UP,KEY_7,KEY_8,KEY_9, KEY_Down,KEY_4,KEY_5,KEY_6, KEY_Left,KEY_1,KEY_2,KEY_3, KEY_Right,KEY_D,KEY_0,KEY_E, KEY_F1,KEY_F2,KEY_F3,KEY_F4}; //16个按键的键值数组 unsigned char key_Pressed; unsigned char key_val; unsigned char key_flag;void Check_Key(void) { unsigned char row, col; unsigned int KEY_DOUT,tmp1, tmp2; tmp1 = 0x0800; for(row=0; row<4; row++) //行扫描 { KEY_DOUT = 0X0f00; //输出全为1 KEY_DOUT-= tmp1; //依次输出一个为0 GPIOD->ODR=((GPIOD->ODR&0xf0ff)|KEY_DOUT); tmp1 >>=1; if((GPIO_ReadInputData(GPIOD)&0xf000)<0xf000) //if((KEY_DIN & 0xF0) < 0xF0) //P2输入是否有一位为0 { tmp2 = 0x1000; //用于检测出哪一位为0 for(col=0; col<4; col++) //列扫描 { if(0x00 == (GPIO_ReadInputData(GPIOD) & tmp2)) //找到等于0的列 { key_val = key_Map[row*4 + col];//获取键值 return; //退出循环 } tmp2 <<= 1; //右移1位 } } } } void KEY_Scan(void) { static u8 key_up=1;//按键按松开标志 if(key_up&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0)) { delay_ms(10);//去抖动 key_up=0; if(KEY1==0)key_val = key_Map[4*4 + 0];//获取键值; if(KEY2==0)key_val = key_Map[4*4 + 1];//获取键值;; if(KEY3==0)key_val = key_Map[4*4 + 2];//获取键值;; if(KEY4==0)key_val = key_Map[4*4 + 3];//获取键值;; }else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)key_up=1; } inline void Button_down(void) { KEY_Scan(); Key_Event(); }
这段代码看起来是针对单片机中的矩阵按键扫描函数。以下是一些可以改进的建议:
1. 函数名:函数名可以更加规范,建议使用大写字母和下划线的命名方式,如:CHECK_KEY、KEY_SCAN、BUTTON_DOWN。
2. 参数:函数没有参数,可以添加参数以支持更多的功能。
3. 变量名:变量名应该具有描述性,能够表达变量的含义。
4. 按键扫描:建议添加按键消抖功能,以避免按键不稳定的现象。
5. 代码风格:建议对代码进行缩进,以提高可读性。
下面是改进后的代码:
```c
typedef enum {
KEY_NONE = 0, // 无按键按下
KEY_UP,
KEY_7,
KEY_8,
KEY_9,
KEY_DOWN,
KEY_4,
KEY_5,
KEY_6,
KEY_LEFT,
KEY_1,
KEY_2,
KEY_3,
KEY_RIGHT,
KEY_D,
KEY_0,
KEY_E,
KEY_F1,
KEY_F2,
KEY_F3,
KEY_F4
} KEY_Status;
/**
* @brief 获取按键状态
* @param key_map 按键映射表
* @param row 行数
* @param col 列数
* @return KEY_Status 按键状态
*/
KEY_Status get_key_status(unsigned char* key_map, unsigned char row, unsigned char col) {
return (KEY_Status)key_map[row * 4 + col];
}
/**
* @brief 矩阵按键扫描函数
* @param key_map 按键映射表
* @param mode 0:支持单次按键功能,1:支持连续按键功能
* @return KEY_Status 按键状态
*/
KEY_Status key_scan(unsigned char* key_map, u8 mode) {
static u8 key_up = 1; // 按键按松开标志
if (mode) key_up = 1; // 支持连按
unsigned char row, col;
unsigned int tmp1, tmp2, key_dout;
tmp1 = 0x0800;
for (row = 0; row < 4; row++) {
key_dout = 0x0F00;
key_dout -= tmp1;
GPIOD->ODR = ((GPIOD->ODR & 0xF0FF) | key_dout);
tmp1 >>= 1;
if ((GPIO_ReadInputData(GPIOD) & 0xF000) < 0xF000) {
tmp2 = 0x1000;
for (col = 0; col < 4; col++) {
if (0x00 == (GPIO_ReadInputData(GPIOD) & tmp2)) {
KEY_Status key_status = get_key_status(key_map, row, col);
if (key_up) {
delay_ms(10); // 去抖动
key_up = 0;
return key_status;
} else {
return KEY_NONE;
}
}
tmp2 <<= 1;
}
}
}
if (KEY_UP == get_key_status(key_map, 0, 0)) {
if (key_up) {
delay_ms(10); // 去抖动
key_up = 0;
return KEY_UP;
} else {
return KEY_NONE;
}
} else if ((KEY_7 == get_key_status(key_map, 0, 1)) && (KEY_8 == get_key_status(key_map, 0, 2)) && (KEY_9 == get_key_status(key_map, 0, 3))) {
if (key_up) {
delay_ms(10); // 去抖动
key_up = 0;
return KEY_UP;
} else {
return KEY_NONE;
}
} else {
key_up = 1;
return KEY_NONE;
}
}
/**
* @brief 按键事件处理函数
*/
void key_event(void) {
// TODO: 处理按键事件
}
/**
* @brief 按键检测函数
* @param key_map 按键映射表
* @param mode 0:支持单次按键功能,1:支持连续按键功能
*/
void check_key(unsigned char* key_map, u8 mode) {
KEY_Status key_status = key_scan(key_map, mode);
if (key_status != KEY_NONE) {
key_event();
}
}
/**
* @brief 按钮按下函数
* @param key_map 按键映射表
* @param mode 0:支持单次按键功能,1:支持连续按键功能
*/
void button_down(unsigned char* key_map, u8 mode) {
check_key(key_map, mode);
}
```
改进后的代码对函数名、参数、返回值等进行了规范化,同时添加了按键消抖功能,提高了按键扫描的稳定性。代码逻辑也更加清晰,易于阅读和维护。
相关推荐
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)