欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

STM32单片机利用定时器实现按键采集

程序员文章站 2022-03-03 19:46:19
源码下载链接:工程项目结构如下图所示:其中画红色方框部分为重要函数来进行讲解TIMx.c#include "TIMx/TIMx.h"#include "LED/LED.h"#include "UART/uart.h"#include "stdio.h"#include "KEY/key.h"extern u8 key_value; // 全局变量/** * 功能:初始化定时器 * 参数: * TIMx:指定待设置的定时器,TIM1-TIM4 *...

源码下载链接:https://taileliekaishi.lanzous.com/ifhJffitozg

工程项目结构如下图所示:

其中画红色方框部分为重要函数来进行讲解

STM32单片机利用定时器实现按键采集

TIMx.c

STM32单片机利用定时器实现按键采集

#include "TIMx/TIMx.h"
#include "LED/LED.h"
#include "UART/uart.h"
#include "stdio.h"
#include "KEY/key.h"

extern u8 key_value; // 全局变量
/**
 * 功能:初始化定时器
 * 参数:
 *      TIMx:指定待设置的定时器,TIM1-TIM4
 *      prescaler:设置预分频值 0-65535
 *      period:设置中断周期,即设置重装载寄存器的值 0-65535
 *      IT_Source:中断源,比如更新中断,四个通道的输入比较中断,取值查看:TIM_interrupt_sources 
 *      NewState:是否使能IT_Source参数指定的中断,ENABLE,DISENABLE
 * 返回值:None
 */
void initTIMx(TIM_TypeDef* TIMx,u16 prescaler,u16 period,u16 IT_Source,FunctionalState NewState)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    switch((u32)TIMx)
    {
        case (u32)TIM1: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);break; //开启定时器1时钟
        case (u32)TIM2: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);break; //开启定时器2时钟
        case (u32)TIM3: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);break; //开启定时器3时钟
        case (u32)TIM4: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);break; //开启定时器4时钟
        /*其他密度的单片机对case进行删减即可兼容,本程序针对中密度单片机*/
        default  :                                                     		break;
    }

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;                     //向上计数模式
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;                         //设置时钟分频因子,该分频不是预分频值,要区分
		TIM_TimeBaseStructure.TIM_Period = period;                                      //设置定时器周期
		TIM_TimeBaseStructure.TIM_Prescaler =prescaler;                                 //设置预分频值
    TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);                                 //生效更改

    TIM_Cmd(TIMx, ENABLE);                                                          //开启计数器

    TIM_ITConfig(TIMx,IT_Source,NewState);                                        //使能定时器更新中断      
}

/**
 * 功能:设置定时器周期,即设置重装载寄存器的值
 * 参数:
 *      TIMx:指定待设置的定时器,TIM1-TIM4
 *      period:设置中断周期,即设置重装载寄存器的值 0-65535
 * 返回值:None
 */
void setPeriod(TIM_TypeDef* TIMx,u16 period)
{
    TIM_SetAutoreload(TIMx, period);  //设置重装载值
}

/**
 * 功能:设置定时器预分频值
 * 参数:
 *      TIMx:指定待设置的定时器,TIM1-TIM4
 *      period:设置中断周期,即设置重装载寄存器的值 0-65535
 * 返回值:None
 */
void setPrescaler(TIM_TypeDef* TIMx,u16 prescaler)
{
    /*设置预分频值等于fCK_PSC/(PSC[15:0]+1)
     *fCK_PSC为内部输入时钟,默认72MHz,假如我们想要72000倍分频,即时钟周期1ms  
     *则我们传入的值应该是71999*/
    TIM_PrescalerConfig(TIMx, prescaler,TIM_PSCReloadMode_Update); //设置定时器周期
}


/****************************************定时器中断服务函数************************************************/
void TIM3_IRQHandler(void)   
{
	u8 key_cache = 0;
	
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) == SET)  //由于定时器中断源很多,因此要判断是哪个中断源触发的中断
	{
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //软件清除中断挂起位,否则会一直卡死在中断服务函数
		key_cache = getKeyValue(KEY_PRESS);
		
		/*在主函数执行Delay_ms延时函数时,在此期间30ms时间按键按下值更新为KEY_UP
		在此期间又过了30ms此时按键是没有按下的,但是值被更新为key_No
		等100ms执行完成后,明明在这100ms的时间段内按下了按键但是没有改变灯的闪烁的频率
		因为我们只需要采集按下的值 所以为了避免没有按下的值影响按下的值就进行下面的判断
		*/
		if(key_cache != KEY_NO)
		{
			key_value = key_cache;
		}
		
	}
}

main.c

#include "DELAY/Delay.h"
#include "NVIC/NVIC.h"
#include "TIMx/TIMx.h"
#include "KEY/key.h"
#include "LED/LED.h"

u8 key_value = KEY_NO;

int main(void)
{
    u16 xms = 100;
	/*初始化各外设*/ 
    initSysTick();  
	initLED();
	initKey();
    initNVIC(NVIC_PriorityGroup_2);
 // 每隔30ms执行一次中断服务函数:采集一次按键的值
	initTIMx(TIM3,7199,299,TIM_IT_Update,ENABLE);
	TIM_ARRPreloadConfig(TIM3,ENABLE);
    while (1)
    {
        if(key_value==KEY_UP)               //UP键按下
        { 
            xms = 100;
        }else if(key_value==KEY_DOWN)       //DOWN键按下
        {
            xms = 800;
        }else                               //没有按键按下或全按时不进行任何操作
        {

        }
		toggleLED();
		Delay_ms(xms);
    }
}

 

本文地址:https://blog.csdn.net/weixin_39903708/article/details/107944421