历史上的今天
返回首页

历史上的今天

今天是:2025年04月23日(星期三)

正在发生

2018年04月23日 | STM32F4(KEY)

2018-04-23 来源:eefocus

在实际的项目开发过程中,常常会遇到硬件电路的修改,然后修改的部分就需要修改驱动程序。想这样需求该来该去是程序员们最烦闷的事情(重复劳动痛不欲生啊~)。为了避免或减少重复劳动,就需要在程序的架构上下功夫。接下来以最常见的KEY驱动程序为例,进行程序结构设计。


1,开发环境

     1,固件库:STM32F4xx_DSP_StdPeriph_Lib_V1.8.0

     2,编译器:ARMCC V5.06

     3,IDE:Keil uVision5

     4,操作系统:Windows 10 专业版


2,程序源码

      KEY.h文件

/** 

  ****************************************************************************** 

  * @file    KEY.h 

  * @author  XinLi 

  * @version v1.0 

  * @date    24-October-2017 

  * @brief   Header file for KEY.c module. 

  ****************************************************************************** 

  * @attention 

  * 

  *

Copyright © 2017 XinLi

 

  * 

  * This program is free software: you can redistribute it and/or modify 

  * it under the terms of the GNU General Public License as published by 

  * the Free Software Foundation, either version 3 of the License, or 

  * (at your option) any later version. 

  * 

  * This program is distributed in the hope that it will be useful, 

  * but WITHOUT ANY WARRANTY; without even the implied warranty of 

  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 

  * GNU General Public License for more details. 

  * 

  * You should have received a copy of the GNU General Public License 

  * along with this program.  If not, see

  * 

  ****************************************************************************** 

  */  

  

#ifndef __KEY_H  

#define __KEY_H  

  

#ifdef __cplusplus  

extern "C" {  

#endif  

  

/* Header includes -----------------------------------------------------------*/  

#include "stm32f4xx.h"  

  

/* Macro definitions ---------------------------------------------------------*/  

#define KEYn                            (3)  

  

#define KEY1_RCC_AHB1Periph_GPIO        RCC_AHB1Periph_GPIOC  

#define KEY1_GPIO                       GPIOC  

#define KEY1_GPIO_Pin                   GPIO_Pin_2  

  

#define KEY2_RCC_AHB1Periph_GPIO        RCC_AHB1Periph_GPIOC  

#define KEY2_GPIO                       GPIOC  

#define KEY2_GPIO_Pin                   GPIO_Pin_3  

  

#define KEY3_RCC_AHB1Periph_GPIO        RCC_AHB1Periph_GPIOC  

#define KEY3_GPIO                       GPIOC  

#define KEY3_GPIO_Pin                   GPIO_Pin_4  

  

#define KEY_RCC_APB1Periph_TIM          RCC_APB1Periph_TIM2  

#define KEY_TIM                         TIM2  

#define KEY_TIM_Prescaler               (83)   /*!< Clock divided to 1MHz. */  

#define KEY_TIM_Period                  (4999) /*!< 5ms timer interrupt. */  

#define KEY_TIM_IRQn                    TIM2_IRQn  

#define KEY_TIM_IRQHandler              TIM2_IRQHandler  

#define KEY_TIM_IRQ_PreemptionPriority  (0)  

#define KEY_TIM_IRQ_SubPriority         (0)  

  

#define KEY_PRESS_STATUS                Bit_SET  

  

/* Type definitions ----------------------------------------------------------*/  

typedef enum  

{  

  KEY_Pin1 = 0,  

  KEY_Pin2 = 1,  

  KEY_Pin3 = 2  

}KEY_Pin;  

  

typedef enum  

{  

  KEY_NoPress    = 0,  

  KEY_ShortPress = 1,  

  KEY_LongPress  = 2  

}KEY_Status;  

  

/* Variable declarations -----------------------------------------------------*/  

/* Variable definitions ------------------------------------------------------*/  

/* Function declarations -----------------------------------------------------*/  

void KEY_Init(void);  

void KEY_DeInit(void);  

KEY_Status KEY_GetStatus(KEY_Pin pin);  

void KEY_SetShortPressCallback(KEY_Pin pin, void (*fun)(void));  

void KEY_SetLongPressCallback(KEY_Pin pin, void (*fun)(void));  

void KEY_ClearShortPressCallback(KEY_Pin pin);  

void KEY_ClearLongPressCallback(KEY_Pin pin);  

  

/* Function definitions ------------------------------------------------------*/  

  

#ifdef __cplusplus  

}  

#endif  

  

#endif /* __KEY_H */  


      KEY.c文件

/** 

  ****************************************************************************** 

  * @file    KEY.c 

  * @author  XinLi 

  * @version v1.0 

  * @date    24-October-2017 

  * @brief   KEY module driver. 

  ****************************************************************************** 

  * @attention 

  * 

  *

Copyright © 2017 XinLi

 

  * 

  * This program is free software: you can redistribute it and/or modify 

  * it under the terms of the GNU General Public License as published by 

  * the Free Software Foundation, either version 3 of the License, or 

  * (at your option) any later version. 

  * 

  * This program is distributed in the hope that it will be useful, 

  * but WITHOUT ANY WARRANTY; without even the implied warranty of 

  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 

  * GNU General Public License for more details. 

  * 

  * You should have received a copy of the GNU General Public License 

  * along with this program.  If not, see

  * 

  ****************************************************************************** 

  */  

  

/* Header includes -----------------------------------------------------------*/  

#include "KEY.h"  

#include  

  

/* Macro definitions ---------------------------------------------------------*/  

/* Type definitions ----------------------------------------------------------*/  

/* Variable declarations -----------------------------------------------------*/  

/* Variable definitions ------------------------------------------------------*/  

static      GPIO_TypeDef *KEY_GPIO[KEYn]                     = {KEY1_GPIO, KEY2_GPIO, KEY3_GPIO};  

static      uint16_t      KEY_GPIO_Pin[KEYn]                 = {KEY1_GPIO_Pin, KEY2_GPIO_Pin, KEY3_GPIO_Pin};  

static      uint32_t      KEY_RCC_AHB1Periph_GPIO[KEYn]      = {KEY1_RCC_AHB1Periph_GPIO, KEY2_RCC_AHB1Periph_GPIO, KEY3_RCC_AHB1Periph_GPIO};  

static __IO int           keyInputHighCount[KEYn]            = {0};  

static __IO int           keyInputLowCount[KEYn]             = {0};  

static __IO KEY_Status    keyStatus[KEYn]                    = {KEY_NoPress, KEY_NoPress, KEY_NoPress};  

static __IO KEY_Status    keyGetStatus[KEYn]                 = {KEY_NoPress, KEY_NoPress, KEY_NoPress};  

static __IO void        (*keyShortPressCallback[KEYn])(void) = {NULL};  

static __IO void        (*keyLongPressCallback[KEYn])(void)  = {NULL};  

  

/* Function declarations -----------------------------------------------------*/  

/* Function definitions ------------------------------------------------------*/  

  

/** 

  * @brief  Key initializes. 

  * @param  None. 

  * @return None. 

  */  

void KEY_Init(void)  

{  

  for(int i = 0; i < KEYn; i++)  

  {  

    GPIO_InitTypeDef GPIO_InitStructure = {0};  

      

    RCC_AHB1PeriphClockCmd(KEY_RCC_AHB1Periph_GPIO[i], ENABLE);  

      

    GPIO_InitStructure.GPIO_Pin   = KEY_GPIO_Pin[i];  

    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;  

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  

    GPIO_Init(KEY_GPIO[i], &GPIO_InitStructure);  

      

    keyInputHighCount[i]     = 0;  

    keyInputLowCount[i]      = 0;  

    keyStatus[i]             = KEY_NoPress;  

    keyGetStatus[i]          = KEY_NoPress;  

    keyShortPressCallback[i] = NULL;  

    keyLongPressCallback[i]  = NULL;  

  }  

    

  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure = {0};  

    

  RCC_APB1PeriphClockCmd(KEY_RCC_APB1Periph_TIM, ENABLE);  

    

  TIM_TimeBaseInitStructure.TIM_Prescaler     = KEY_TIM_Prescaler;  

  TIM_TimeBaseInitStructure.TIM_CounterMode   = TIM_CounterMode_Up;  

  TIM_TimeBaseInitStructure.TIM_Period        = KEY_TIM_Period;  

  TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;  

  TIM_TimeBaseInit(KEY_TIM, &TIM_TimeBaseInitStructure);  

    

  TIM_ClearFlag(KEY_TIM, TIM_FLAG_Update);  

  TIM_ITConfig(KEY_TIM, TIM_IT_Update, ENABLE);  

  TIM_Cmd(KEY_TIM, ENABLE);  

    

  NVIC_InitTypeDef NVIC_InitStructure = {0};  

    

  NVIC_InitStructure.NVIC_IRQChannel                   = KEY_TIM_IRQn;  

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = KEY_TIM_IRQ_PreemptionPriority;  

  NVIC_InitStructure.NVIC_IRQChannelSubPriority        = KEY_TIM_IRQ_SubPriority;  

  NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;  

  NVIC_Init(&NVIC_InitStructure);  

}  

  

/** 

  * @brief  Key de-initializes. 

  * @param  None. 

  * @return None. 

  */  

void KEY_DeInit(void)  

{  

  for(int i = 0; i < KEYn; i++)  

  {  

    keyInputHighCount[i]     = 0;  

    keyInputLowCount[i]      = 0;  

    keyStatus[i]             = KEY_NoPress;  

    keyGetStatus[i]          = KEY_NoPress;  

    keyShortPressCallback[i] = NULL;  

    keyLongPressCallback[i]  = NULL;  

  }  

    

  TIM_DeInit(KEY_TIM);  

  RCC_APB1PeriphClockCmd(KEY_RCC_APB1Periph_TIM, DISABLE);  

    

  NVIC_InitTypeDef NVIC_InitStructure = {0};  

    

  NVIC_InitStructure.NVIC_IRQChannel                   = KEY_TIM_IRQn;  

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = KEY_TIM_IRQ_PreemptionPriority;  

  NVIC_InitStructure.NVIC_IRQChannelSubPriority        = KEY_TIM_IRQ_SubPriority;  

  NVIC_InitStructure.NVIC_IRQChannelCmd                = DISABLE;  

  NVIC_Init(&NVIC_InitStructure);  

}  

  

/** 

  * @brief  Get key status. 

  * @param  [in] pin: That key. 

  * @return Key status. 

  */  

KEY_Status KEY_GetStatus(KEY_Pin pin)  

{  

  KEY_Status status = KEY_NoPress;  

    

  if(keyGetStatus[pin] != KEY_NoPress)  

  {  

    status            = keyGetStatus[pin];  

    keyGetStatus[pin] = KEY_NoPress;  

  }  

    

  return status;  

}  

  

/** 

  * @brief  Set key short press callback. 

  * @param  [in] pin: That key. 

  * @param  [in] fun: Function pointer. 

  * @return None. 

  */  

void KEY_SetShortPressCallback(KEY_Pin pin, void (*fun)(void))  

{  

  keyShortPressCallback[pin] = (__IO void (*)(void))fun;  

}  

  

/** 

  * @brief  Set key long press callback. 

  * @param  [in] pin: That key. 

  * @param  [in] fun: Function pointer. 

  * @return None. 

  */  

void KEY_SetLongPressCallback(KEY_Pin pin, void (*fun)(void))  

{  

  keyLongPressCallback[pin] = (__IO void (*)(void))fun;  

}  

  

/** 

  * @brief  Clear key short press callback. 

  * @param  [in] pin: That key. 

  * @param  [in] fun: Function pointer. 

  * @return None. 

  */  

void KEY_ClearShortPressCallback(KEY_Pin pin)  

{  

  keyShortPressCallback[pin] = NULL;  

}  

  

/** 

  * @brief  Clear key long press callback. 

  * @param  [in] pin: That key. 

  * @param  [in] fun: Function pointer. 

  * @return None. 

  */  

void KEY_ClearLongPressCallback(KEY_Pin pin)  

{  

  keyLongPressCallback[pin] = NULL;  

}  

  

/** 

  * @brief  This function handles TIM Handler. 

  * @param  None. 

  * @return None. 

  */  

void KEY_TIM_IRQHandler(void)  

{  

  if(TIM_GetITStatus(KEY_TIM, TIM_IT_Update) != RESET)  

  {  

    TIM_ClearITPendingBit(KEY_TIM, TIM_IT_Update);  

      

    for(int i = 0; i < KEYn; i++)  

    {  

      if(GPIO_ReadInputDataBit(KEY_GPIO[i], KEY_GPIO_Pin[i]) == KEY_PRESS_STATUS)  

      {  

        keyInputLowCount[i]++;  

          

        if(keyInputLowCount[i] > 1)  

        {  

          keyInputHighCount[i] = 0;  

        }  

          

        if(keyInputLowCount[i] > 100)  

        {  

          keyInputLowCount[i] = 0;  

          keyStatus[i]        = KEY_LongPress;  

          keyGetStatus[i]     = KEY_LongPress;  

            

          if(keyLongPressCallback[i] != NULL)  

          {  

            keyLongPressCallback[i]();  

          }  

        }  

      }  

      else  

      {  

        keyInputHighCount[i]++;  

          

        if(keyInputHighCount[i] > 1)  

        {  

          if((keyStatus[i] == KEY_NoPress) && (keyInputLowCount[i] > 1))  

          {  

            keyInputHighCount[i] = 0;  

            keyInputLowCount[i]  = 0;  

            keyStatus[i]         = KEY_ShortPress;  

            keyGetStatus[i]      = KEY_ShortPress;  

              

            if(keyShortPressCallback[i] != NULL)  

            {  

              keyShortPressCallback[i]();  

            }  

          }  

          else  

          {  

            keyInputHighCount[i] = 0;  

            keyInputLowCount[i]  = 0;  

            keyStatus[i]         = KEY_NoPress;  

          }  

        }  

      }  

    }  

  }  

}  


      main.c文件

/** 

  ****************************************************************************** 

  * @file    main.c 

  * @author  XinLi 

  * @version v1.0 

  * @date    24-October-2017 

  * @brief   Main program body. 

  ****************************************************************************** 

  * @attention 

  * 

  *

Copyright © 2017 XinLi

 

  * 

  * This program is free software: you can redistribute it and/or modify 

  * it under the terms of the GNU General Public License as published by 

  * the Free Software Foundation, either version 3 of the License, or 

  * (at your option) any later version. 

  * 

  * This program is distributed in the hope that it will be useful, 

  * but WITHOUT ANY WARRANTY; without even the implied warranty of 

  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 

  * GNU General Public License for more details. 

  * 

  * You should have received a copy of the GNU General Public License 

  * along with this program.  If not, see

  * 

  ****************************************************************************** 

  */  

  

/* Header includes -----------------------------------------------------------*/  

#include "main.h"  

#include "KEY.h"  

  

/* Macro definitions ---------------------------------------------------------*/  

/* Type definitions ----------------------------------------------------------*/  

/* Variable declarations -----------------------------------------------------*/  

/* Variable definitions ------------------------------------------------------*/  

static __IO int key1ShortPressCount = 0;  

static __IO int key1LongPressCount  = 0;  

static __IO int key2ShortPressCount = 0;  

static __IO int key2LongPressCount  = 0;  

  

/* Function declarations -----------------------------------------------------*/  

static void key1ShortPressCallback(void);  

static void key1LongPressCallback(void);  

  

/* Function definitions ------------------------------------------------------*/  

  

/** 

  * @brief  Main program. 

  * @param  None. 

  * @return None. 

  */  

int main(void)  

{  

  KEY_Init();  

  KEY_SetShortPressCallback(KEY_Pin1, key1ShortPressCallback);  

  KEY_SetLongPressCallback(KEY_Pin1, key1LongPressCallback);  

    

  for(;;)  

  {  

    KEY_Status status = KEY_GetStatus(KEY_Pin2);  

      

    if(status != KEY_NoPress)  

    {  

      if(status == KEY_ShortPress)  

      {  

        key2ShortPressCount++;  

      }  

      else  

      {  

        key2LongPressCount++;  

      }  

    }  

  }  

}  

  

/** 

  * @brief  Key 1 short press callback. 

  * @param  None. 

  * @return None. 

  */  

static void key1ShortPressCallback(void)  

{  

  key1ShortPressCount++;  

}  

  

/** 

  * @brief  Key 1 long press callback. 

  * @param  None. 

  * @return None. 

  */  

static void key1LongPressCallback(void)  

{  

  key1LongPressCount++;  

}  


3,注意

       修改接口需要注意,按键的检测电平、使用的TIM和增减按键的个数。对应修改KEY_PRESS_STATUS宏、TIM时钟配置函数和源文件的变量定义。



上一篇:STM32F4(BUZZ)

下一篇:STM32F4(LED)

推荐阅读

史海拾趣

南晶电子(DGNJDZ)公司的发展小趣事

南晶电子(DGNJDZ)成立于2011年,起初只是一家专注于半导体分立器件研发和生产的小型企业。创始人毛姬娜凭借其敏锐的市场洞察力和技术背景,带领团队攻克了一个又一个技术难关,逐渐在电子行业崭露头角。公司初期面临着资金短缺、技术瓶颈等重重困难,但毛姬娜和团队凭借坚韧不拔的精神,一步步走出了困境。

Enable Semiconductor Corp公司的发展小趣事

品质是Enable Semiconductor Corp公司的生命线。公司从原材料采购到产品生产、从质量检测到售后服务,都严格执行质量管理体系的要求。这种对品质的执着追求使得公司的产品在市场上享有良好的口碑。同时,公司还积极参与国际标准的制定和认证工作,不断提升产品的国际竞争力。

Deutsch公司的发展小趣事

Deutsch公司自创立之初,就注重技术创新和产品研发。在早期阶段,公司成功开发出一款具有突破性的电子元件,这款元件以其高性能和低成本迅速在市场上获得了认可。随着技术的不断进步,Deutsch公司不断推出创新产品,满足日益增长的市场需求。这些技术突破和产品创新不仅提升了公司的竞争力,也推动了整个电子行业的发展。

国兴(GOODSKY)公司的发展小趣事

随着全球环保意识的不断提高,电子行业的环保要求也日益严格。Deutsch公司积极响应环保号召,将环保和可持续发展作为公司的重要战略之一。公司投入大量资源研发环保型产品和技术,减少生产过程中的能源消耗和污染排放。同时,公司还积极参与环保公益活动,推动整个行业的绿色发展。这些努力不仅提升了公司的社会形象,也为公司的可持续发展奠定了坚实基础。

柯爱亚(ceaiya)公司的发展小趣事

作为一家有社会责任感的企业,柯爱亚积极参与各种公益活动。公司不仅捐款捐物支持灾区重建、教育事业等公益事业,还组织员工参与志愿者活动,为社会做出了积极贡献。这些行为展现了柯爱亚作为一家优秀企业的社会担当和良好形象。

请注意,以上故事框架仅供参考,具体内容需要根据柯爱亚公司的实际发展历程进行编写。

APEM公司的发展小趣事

APEM公司的创始人基恩·罗杰罗,在20世纪50年代初,看到了美国产品主导法国市场的商机。为了解决产品维修和备件订购的难题,他决定自己生产开关。罗杰罗的开关产品在尺寸和操作方式上与美国产品相似,但价格更亲民,交货时间更短。这一创新举措使APEM迅速在市场上站稳脚跟,为后续的发展奠定了坚实基础。

问答坊 | AI 解惑

VxWorks5.4->6.5移植--ifLib

目前在做VxWorks的应用程序代码移植,从5.4到6.5,在5.4的代码使用了ifLib库里的函数,如ifunit()、ifAddrGet()等;而在VxWorks6.5中,ifLib库已经没用,请问是用别的库来代替?若是,可否有针对性的对ifunit()做个移植的解释?谢谢!…

查看全部问答>

WINCE字体的问题!

请问:修改WINCE的字体变使它变小后,窗口上文字又显示不清晰!有什么好办法解决呀!谢谢了!…

查看全部问答>

求单片机控制程序源代码

各位大侠帮忙啊~ 求单片机控制程序源代码,单片机控制状态的转移  就是实现标签和阅读器的控制 希望做过有经验的 帮帮忙啊  感谢感谢…

查看全部问答>

自动控制原理

有没有对自动控制原理感兴趣的大师啊,交流下.…

查看全部问答>

测试设备,寻求合作!

水位、温度测试,用单片机实现,体积要小,数据传送800米,最好用mcs1200,熟悉者联系:437175689,诚求合作…

查看全部问答>

请问谁有 MST710 芯片驱动

请问谁有MSG710芯片驱动(最好是linux下面的)的,现在正在做模拟屏的驱动,第一次做芯片驱动又比较急,不知道该怎么下手,想要一份参考一下。谢谢。 luogk@magliving.com …

查看全部问答>

EE_FPGA基础教程系列 --NO.3-- 玩转LED

Table of Contents 1.        剧情回放        4 2.        玩转LED        4   2.1        硬件连接        4 ...…

查看全部问答>

用PADS logic做原理图封装时出现如下问题,请赐教

Error: Signal pin number invalid - Pin number 1 already exists on Gate A, Logical pin 1.Error: Signal pin number invalid - Pin number 2 already exists on Gate A, Logical pin 2.Error: Signal pin number invalid - Pin number 3 alread ...…

查看全部问答>

用MSP430 内置传感器测试温度时为什么在串口上显示的数据不对

我想用430内置传感器测试环境温度的变化,但是为什么在串口上现实的数据不变化呢 ?哪位高人给指点下,下面的程序有什么错误啊?     #include <msp430x14x.h>#define CPU_F ((double)8000000) #define delay_us(x) __delay_cycle ...…

查看全部问答>

STM32的RTC问题 难搞啊

被STM32的RTC搞晕的过来看看本来打算放弃内置的RTC而采用DS1302了,无奈1302的通信太慢,屡次不成功,就把扔在一边的老板子拿来又试了试,这次没用自己原来的程序,在网上又新找了一个,结果程序都不用动的居然就行了··· 芯片是VCT6,晶振是那 ...…

查看全部问答>