2021-06-15 STM32F103 Systicks Key 输出 使用固件库

本文展示了STM32 按键Systick 扫描 识别操作
内容涉及
IO口输入输出,枚举建立
按键按下有效,松开有效,长按有效,长按松开有效
Systicks 扫描方法


前言

这里只讲解核心部分的代码,有些变量的设置,头文件的包含等可能不会涉及到,完整的代码请参考本章配套的工程。 为了使工程更加有条理,我们把 LED 灯控制相关的代码独立分开存储,方便以后移植。 在“工程模板”之上新建“RCC_book.c”及“RCC_book.h”文件以及之前的 “Led_book.c”及“Led_book.h”文件

完整代码

一、 编程要点

按键:
1. 使能 GPIO 端口时钟;
2. 初始化 GPIO 目标引脚为输入模式(浮空输入);
3. 编写简单测试程序,检测按键的状态,实现按键控制 LED 灯。
Systicks:
1、设置重装载寄存器的值
2、清除当前数值寄存器的值
3、配置控制与状态寄存器

二、使用步骤

1.理解原理图

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

代码如下:
: STM32F103ZET6 输出口为PB5低电平点有效
: STM32F103ZET6 Key检测脚为PA8

2.建立Systicks输出的 头文件 Systick_book.h

代码如下(示例):

#ifndef  __SYSTIC_BOOK_H_
#define  __SYSTIC_BOOK_H_

#include "stm32f10x.h"
#include  "Key_book.h"
 
typedef enum {
    
    
		_Systick_us = 1,
		_Systick_ms = 2,
		_Systick_s = 3, 
} Systick_time_state_t;

void fn_Systick_Delay(uint32_t  _Delay_time , Systick_time_state_t  _Systick_time_state_t);
void fn_Systick_Delay_Handler_set(uint32_t  _Delay_ms , Systick_time_state_t  _Systick_time_state_t);
void fn_SysTick_delay_decrement(void);
void SysTick_Handler(void);

#endif

3.建立Systicks输出的 头文件 Systick_book.c

代码如下(示例):

#include "Systick_book.h"

/************************************************************
* @brief  
* void fn_Systick_Delay(uint32_t  _Delay_time , \
Systick_time_state_t  _Systick_time_state_t){
* @param  
* @retval 
*************************************************************/ 
void fn_Systick_Delay(uint32_t  _Delay_time , Systick_time_state_t  _Systick_time_state_t){
    
    
   uint32_t  i;
   if(_Systick_time_state_t == _Systick_us){
    
    SysTick_Config(SystemCoreClock/1000000);}
   if(_Systick_time_state_t == _Systick_ms){
    
    
    SysTick_Config(SystemCoreClock/1000);
   }  
   else{
    
    SysTick_Config(SystemCoreClock);}      
   for( i=0;i<_Delay_time ; i++){
    
    
    while(!((SysTick->CTRL)&(1<<16)));
   }
   SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;

}

/************************************************************
* @brief  
* void fn_Systick_Delay_Handler_set(uint32_t  _Delay_ms , \
*       Systick_time_state_t  _Systick_time_state_t){
* @param  
* @retval 
*************************************************************/ 
static uint32_t _SysTick_delay  = 0 ;
void fn_Systick_Delay_Handler_set(uint32_t  _Delay_ms , Systick_time_state_t  _Systick_time_state_t){
    
    
  if(_Systick_time_state_t == _Systick_us){
    
    SysTick_Config(SystemCoreClock/1000000);}
  if(_Systick_time_state_t == _Systick_ms){
    
    
      SysTick_Config(SystemCoreClock/1000);
  }  
  else{
    
    SysTick_Config(SystemCoreClock);}      
  _SysTick_delay = _Delay_ms ;
}

/************************************************************
* @brief  
* void fn_SysTick_delay_decrement(void)
* @param  
* @retval 
*************************************************************/ 
static uint32_t SysTick_delay = 0 ;
void fn_SysTick_delay_decrement(void){
    
    
  if(SysTick_delay++ > _SysTick_delay){
    
    
    SysTick_delay = 0;
    bkey_10ms = 1;
  }
}

/************************************************************
* @brief  
* void SysTick_Handler(void)
* @param  
* @retval 
*************************************************************/ 
void SysTick_Handler(void){
    
    
  fn_SysTick_delay_decrement();
}

4.建立Key采集的 头文件 Key_book.h

代码如下(示例):

#ifndef  __KEY_BOOK_H_
#define  __KEY_BOOK_H_


#include "stm32f10x.h"
#include "Led_book.h"

#define   KEY_IN_GPIO_Port      GPIOA
#define   KEY_IN_GPIO_Clock     RCC_APB2Periph_GPIOA
#define   KEY_IN_GPIO_Pin       GPIO_Pin_0
#define   KEY_IN_GPIO_Pin_Bit   0
#define   Key_IN_GPIO_Modle     GPIO_Mode_IN_FLOATING   //浮空输入


typedef union {
    
    
  struct{
    
    
    unsigned char BIT0:1;unsigned char BIT1:1;unsigned char BIT2:1;unsigned char BIT3:1;
    unsigned char BIT4:1;unsigned char BIT5:1;unsigned char BIT6:1;unsigned char BIT7:1;
    //unsigned char BIT8:1;unsigned char BIT9:1;unsigned char BIT10:1;unsigned char BIT11:1;
    //unsigned char BIT12:1;unsigned char BIT13:1;unsigned char BIT14:1;unsigned char BIT15:1;
  }DATA_BIT;
  uint8_t DATA_BYTE;
}Per_key_type;

extern volatile  Per_key_type key_flag;
  #define bkey_10ms         key_flag.DATA_BIT.BIT0
  #define bkey_judge        key_flag.DATA_BIT.BIT1
  #define bkey_judge_long   key_flag.DATA_BIT.BIT2
  #define bkey_Effect       key_flag.DATA_BIT.BIT3
  #define bkey_LongEffect   key_flag.DATA_BIT.BIT4
  #define bkey_Effect_Lose  key_flag.DATA_BIT.BIT5
  #define bkey_Effect_LLose key_flag.DATA_BIT.BIT6
  
void  fn_Key_GPIO_Config( GPIO_TypeDef* _GPIO_x , uint32_t _GPIO_Clock , uint16_t _GPIO_Pin_x , GPIOMode_TypeDef  _GPIOMode_TypeDef );
void  fn_Key_Init(void);
void  fn_key_judge(void);
void  fn_key_Effect(void);  
void  fn_key_Check(void);
#endif

5.建立Key采集的 头文件 Key_book.c

代码如下(示例):

#include  "Key_book.h"
 

volatile  Per_key_type key_flag;

/**************************************************************
* @brief  
* void  fn_Key_GPIO_Config( GPIO_TypeDef* _GPIO_x , uint32_t _GPIO_Clock , 
*                  uint16_t _GPIO_Pin_x , GPIOMode_TypeDef  _GPIOMode_TypeDef );
* @param  
* @retval 
*************************************************************/ 
void  fn_Key_GPIO_Config( GPIO_TypeDef* _GPIO_x , uint32_t _GPIO_Clock , uint16_t _GPIO_Pin_x , GPIOMode_TypeDef  _GPIOMode_TypeDef ){
    
    
    GPIO_InitTypeDef  GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = _GPIOMode_TypeDef;
    GPIO_InitStruct.GPIO_Pin = _GPIO_Pin_x;
    RCC_APB2PeriphClockCmd(_GPIO_Clock,ENABLE);
    GPIO_Init(_GPIO_x , &GPIO_InitStruct);  
}

/**************************************************************
* @brief  
* void fn_Key_Init(void);
* @param  
* @retval 
*************************************************************/ 
void  fn_Key_Init(void){
    
    
    fn_Key_GPIO_Config(KEY_IN_GPIO_Port,KEY_IN_GPIO_Clock,KEY_IN_GPIO_Pin,Key_IN_GPIO_Modle);
}

/************************************************************
* @brief  
* void  fn_key_judge(void);
* @param  
* @retval 
**************************************************************/ 
#define  _LONG_key  30
static uint16_t count_key ;
void  fn_key_judge(void){
    
    
   
   if(!bkey_10ms){
    
    return;}
   bkey_10ms = 0;
   if(GPIO_ReadInputDataBit(KEY_IN_GPIO_Port,KEY_IN_GPIO_Pin)){
    
    
     if(count_key++<3){
    
    return;}
     if(!bkey_judge){
    
    
       bkey_judge = 1;
       bkey_Effect = 1; 
     }else{
    
    
       if(count_key>_LONG_key){
    
    
          bkey_judge_long = 1;
          bkey_LongEffect = 1;
       }
     }
   }
   else{
    
    
     count_key = 0;
     if(bkey_judge){
    
    
        bkey_judge = 0;
        if(bkey_judge_long){
    
    
            bkey_judge_long = 0;
            bkey_Effect_LLose = 1;
        }else{
    
    
            bkey_judge_long = 0;
            bkey_Effect_Lose = 1;
        }
     }else{
    
    
        bkey_judge = 0;         
     }
  }
}

/************************************************************
* @brief  
* void fn_key_Effect(void);
* @param  
* @retval 
*************************************************************/ 
void  fn_key_Effect(void){
    
    
  if(bkey_Effect){
    
    
    bkey_Effect = 0;
    fn_LED_Corporate(LED_OUT_GPIO_Port,LED_OUT_GPIO_Pin,LED_Corporate_Toggle);
  }
}

/**************************************************************
* @brief  
* void fn_key_Check(void);
* @param  
* @retval 
*************************************************************/ 
void fn_key_Check(void){
    
    
  fn_key_judge();
  fn_key_Effect();
}

6.利用之前的LED输出的 头文件 Led_book.h

代码如下(示例):

#ifndef  __LED_BOOK_H_
#define  __LED_BOOK_H_

#include "stm32f10x.h"

#define   LED_OUT_GPIO_Port     GPIOB                 //GPIO Point
#define   LED_OUT_GPIO_Clock    RCC_APB2Periph_GPIOB  //GPIO clock
#define   LED_OUT_GPIO_Pin      GPIO_Pin_5             
#define   LED_OUT_GPIO_Pin_Bit  5
#define   LED_OUT_GPIO_Modle    GPIO_Mode_Out_PP


typedef enum {
    
    
		LED_Corporate_On = 1,
		LED_Corporate_OFF = 2,
		LED_Corporate_Toggle = 3, 
} LED_Corporate_state_t;

void fn_LED_GPIO_Config(GPIO_TypeDef* _GPIO_x , uint32_t _GPIO_Clock ,\
          uint16_t _GPIO_Pin_x , GPIOMode_TypeDef _GPIOMode_TypeDef);

void fn_LED_Corporate(GPIO_TypeDef* _GPIO_x , uint16_t _GPIO_Pin_x , \
          LED_Corporate_state_t _LED_Corporate_state_t );
  

#endif

7.利用之前的LED输出的 头文件 Led_book.c

代码如下(示例):

#include "Led_book.h"

#define LED_GPIO_Speed GPIO_Speed_10MHz 
void fn_LED_GPIO_Config(GPIO_TypeDef* _GPIO_x , uint32_t _GPIO_Clock ,uint16_t _GPIO_Pin_x , GPIOMode_TypeDef _GPIOMode_TypeDef){
    
    
  GPIO_InitTypeDef  GPIO_InitStruct;
  GPIO_InitStruct.GPIO_Mode = _GPIOMode_TypeDef;
  GPIO_InitStruct.GPIO_Pin = _GPIO_Pin_x;
  GPIO_InitStruct.GPIO_Speed = LED_GPIO_Speed;
  RCC_APB2PeriphClockCmd(_GPIO_Clock ,ENABLE);
  GPIO_Init(_GPIO_x , &GPIO_InitStruct) ; 
}

void fn_LED_Corporate(GPIO_TypeDef*  _GPIO_x , uint16_t  _GPIO_Pin_x , LED_Corporate_state_t  _LED_Corporate_state_t ){
    
    
  
  switch(_LED_Corporate_state_t){
    
    
    case  LED_Corporate_On :
      GPIO_SetBits(_GPIO_x,_GPIO_Pin_x);
      break;
		case  LED_Corporate_OFF:
      GPIO_ResetBits(_GPIO_x,_GPIO_Pin_x);
      break;
		case  LED_Corporate_Toggle:
      GPIO_ReadOutputDataBit(_GPIO_x,_GPIO_Pin_x)?GPIO_ResetBits(_GPIO_x,_GPIO_Pin_x):GPIO_SetBits(_GPIO_x,_GPIO_Pin_x);
      break;    
  }
}

//practice
//fn_LED_GPIO_Config (LED_OUT_GPIO_Port,LED_OUT_GPIO_Clock,LED_OUT_GPIO_Pin,LED_OUT_GPIO_Modle);
// while(1){
    
    
//  delay(10000);
//  fn_LED_Corporate(LED_OUT_GPIO_Port,LED_OUT_GPIO_Pin,LED_Corporate_Toggle);		 
// }	

8.建立Systicks Key输出的 主程序 main.c

代码如下(示例):

/**
  ******************************************************************************
  * @file    GPIO/JTAG_Remap/main.c 
  * @author  MCD Application Team
  * @version V3.5.0
  * @date    08-April-2011
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * 
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "PROJ_book.h" 

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
void delay(int x);
void fn_Main_Init(void);
int main(void)
{
    
     

//    fn_HRCC_SetSystic(RCC_PLLMul_9 );
//    fn_IRCC_SetSystic(RCC_PLLMul_9 );
//    fn_MCO_GPIO_Config();
      fn_Led_Init();
      fn_Key_Init();
      fn_Main_Init();
      fn_Systick_Delay_Handler_set(10,_Systick_ms);
      while(1){
    
    
        fn_key_Check();
      }
}

void fn_Main_Init(void){
    
    
  uint16_t  count_Init = 2;
  while(count_Init-->0){
    
    
    __LED_OUT__;
    fn_Systick_Delay(500,_Systick_ms);
    __LED_OUT__;
    fn_Systick_Delay(100,_Systick_ms);
    __LED_OUT__;
    fn_Systick_Delay(100,_Systick_ms);
    __LED_OUT__;
    fn_Systick_Delay(500,_Systick_ms);
  } 
}

void delay(int x){
    
    
	int y = 0xFFFFF;
	while((x--)>0){
    
    
		while((y--)>0){
    
    
			__NOP();
			__NOP();
			__NOP();
			__NOP();
			__NOP();
		}
	}
}
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/


www.firebbs.cn。


参考笔记。
STM32 Systick 笔记
STM32 RCC – RCC 程序

STM32 RCC – LED 程序

STM32 RCC – 主程序

09 _STM32f103 时钟树 RCC


总结

 SysTick简介:
系统定时器,24位,只能递减,存在于内核,嵌套在NVIC中,所有的Cortex-M内核的单片机都具有这个定时器。	

counter在时钟的驱动下,从reload初值开始往下递减计数到0:
   产生中断和置位COUNTFLAG标志。
   然后又从reload值开始重新递减计数,如此循环。
   1-t:一个计数循环的时间,跟reload和CLK有关
2-CLK:72M或者9M,由CTRL寄存器配置
3-RELOAD:24位,用户自己配置

t = reload * ( 1/clk )
Clk = 72M时,t = (72) *(1/ 72 M )= 1US
Clk = 72M时,t = (72000) *(1/ 72 M )= 1MS
时间单位换算: 
1s = 1000ms = 1000 000 us = 1000 000 000ns

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/u012651389/article/details/117932426