实现功能:用按键来实现LED灯的亮灭。
按键是外部电路来决定高低电平的,若按键未按下时,默认为高电平;若按键按下时,为低电平。
按键检测主要是根据按键对应I/0口的电平状态,来生成按键信号。
硬件电路
KEY:
按键程序编写
1.读取I/O口函数
从stm8l15x_gpio.c中的GPIO_ReadInputDataBit()函数来看,该函数返回值是通过GPIO的IDR寄存器读取I/O口状态,然后&上相应的GPIO_Pin_x,最后再将结果强制转换为BitStatus。
STM8的写法返回值可能出现大于1的数,其原因在于原类型的数强制转换成BitStatus后,返回的结果仍为0或1以外的值(可能为0x02,0x04,0x08,0x20,0x40,0x80),强制无效,因为这些值在没法在枚举定义时的元素值中找到,其结果超出了枚举范围。
STM8固件库里的读取I/O口函数:
STM32固件库中的读取I/O口函数:
所以可以将STM8中的GPIO_ReadInputDataBit()函数改成如下:
BitStatus GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef GPIO_Pin)
{
if((GPIOx->ODR & (uint8_t)GPIO_Pin) != RESET)
{
return SET;
}
else
{
return RESET;
}
}
这样返回值就不会再出现大于1的值了。
2.KEY初始化函数
一般情况下,KEY的GPIO工作方式有两种:
1.浮空输入模式(GPIO_Mode_In_FL_No_IT、GPIO_Mode_In_FL_IT)
2.上拉输入模式(GPIO_Mode_In_PU_No_IT、GPIO_Mode_In_PU_IT)
由于硬件电路没有加上拉电阻,并且我不需要用到外部中断功能,我这里将按键I/0口设置为成GPIO_Mode_In_PU_No_IT。
/* Includes ------------------------------------------------------------------*/
#include "key.h"
#include "delay.h"
/* Parameter Definition ------------------------------------------------------------------*/
/*KEY GPIO*/
#define KEY1_PORT GPIOE
#define KEY2_PORT GPIOD
/*KEY PIN*/
#define KEY1_PIN GPIO_Pin_5
#define KEY2_PIN GPIO_Pin_0
#define KEY3_PIN GPIO_Pin_1
#define KEY4_PIN GPIO_Pin_2
/*KEY Read*/
#define KEY1 GPIO_ReadInputDataBit(KEY1_PORT, KEY1_PIN)
#define KEY2 GPIO_ReadInputDataBit(KEY2_PORT, KEY2_PIN)
#define KEY3 GPIO_ReadInputDataBit(KEY2_PORT, KEY3_PIN)
#define KEY4 GPIO_ReadInputDataBit(KEY2_PORT, KEY4_PIN)
/*KEY Press Value*/
#define KEY1_PRESS 1
#define KEY2_PRESS 2
#define KEY3_PRESS 3
#define KEY4_PRESS 4
/* Source Functions ------------------------------------------------------------------*/
void Key_Init(void)
{
/*KEY1 Init*/
GPIO_Init(KEY1_PORT,KEY1_PIN,GPIO_Mode_In_PU_No_IT);
/*KEY2 Init*/
GPIO_Init(KEY2_PORT,KEY2_PIN|KEY3_PIN|KEY4_PIN,GPIO_Mode_In_PU_No_IT);
}
3.KEY扫描函数
按键扫描是参照原子哥写的按键扫描,具体如下:
uint8_t Key_Scanf(void)
{
static uint8_t key_up=1;//按键按松开标志
if(key_up&&(KEY1==0||KEY2==0||KEY3==0|KEY4==0))
{
Delay_ms(10);//去抖动
key_up=0;
if(KEY1==0) return KEY1_PRESS;
else if(KEY2==0) return KEY2_PRESS;
else if(KEY3==0) return KEY3_PRESS;
else if(KEY4==0) return KEY4_PRESS;
}else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)key_up=1;
return 0;// 无按键按下
}
功能实现部分
主函数功能主要如下:
main.c 如下:
/* Includes ------------------------------------------------------------------*/
#include "stm8l15x.h"
#include "led.h"
#include "key.h"
#include "stdio.h"
/* Parameter Definition ------------------------------------------------------------------*/
uint8_t LED1_State = 1,LED2_State = 0;
/* Functions Declaration ------------------------------------------------------------------*/
void Key_Function(void);
void LED_Flash(void);
/* Source Functions ------------------------------------------------------------------*/
/**
* @brief CLK Config.
* @param None
* @retval None
*/
void Clk_Config(void)
{
CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);//系统1分频,16M
}
/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
/*System Init*/
Clk_Config();
Key_Init();
Led_Init();
/* Infinite loop */
while (1)
{
// LED_Flash();
Key_Function();
}
}
/**
* @brief LED Flash.
* @param None
* @retval None
*/
void LED_Flash(void)
{
Led_Set(LED2, LED2_State);
Led_Set(LED1, LED1_State);
LED1_State = !LED1_State;
LED2_State = !LED2_State;
Delay_ms(500);
}
/**
* @brief Key function.
* @param None
* @retval None
*/
void Key_Function(void)
{
uint8_t Buff[40];
uint8_t Key;
Key = Key_Scanf();
/*KEY1 Function*/
if(Key == KEY1_PRESS)
{
printf("KEY1 PRESS!rn");
LED1_State = !LED1_State;
}
/*KEY2 Function*/
if(Key == KEY2_PRESS)
{
LED2_State = !LED2_State;
}
/*KEY3 Function*/
if(Key == KEY3_PRESS)
{
LED1_State = 1;
}
/*KEY4 Function*/
if(Key == KEY4_PRESS)
{
LED2_State = 1;
}
/*LED Function*/
Led_Set(LED1, LED1_State);
Led_Set(LED2, LED2_State);
}
总结
由于以前编程的惯性思维(不常去看固件库里给的函数),在按键判断吃了大亏,算是“吃一堑,长一智”吧。
上一篇:单片机C语言程序与数据存储
下一篇:STM8L151C8学习笔记5:低功耗
推荐阅读最新更新时间:2024-11-13 14:02
设计资源 培训 开发板 精华推荐
- VFD时钟
- OP495GSZ-REEL H桥运算放大器典型应用
- LT3756IUD-1 降压-升压模式 LED 驱动器的典型应用电路
- AZ1117E 1.0A LOW DROPOUT LINEAR REGULATOR 3.3V输出典型应用
- 具有手动复位按钮的 LTC1728ES5-5 三路电源监视器的典型应用
- 具有跟踪功能的 LTM4648EY 四路输出 4 相稳压器的典型应用电路
- LT1086IM 高效双路线性电源的典型应用
- ADP130-1.2-EVALZ,基于 ADP130 的评估板、1.2V、350 mA 低 VIN、低静态电流、CMOS 线性稳压器
- 花样流水灯Ⅱ——谢铭园
- NX410818 板载 FET 1A 同步降压开关的典型应用