按键FIFO实现以及单片机时间片轮循法实现

这篇具有很好参考价值的文章主要介绍了按键FIFO实现以及单片机时间片轮循法实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

本文简介

实验平台

正文

一、主函数实现

二、按键驱动

C文件

H文件

三、SYSTICK定时器实现时间片轮循法方法

C文件

H文件


本文简介


本文主要介绍一套按键驱动代码以及使用SYSTICK定时器实现延时和嵌入式单片机时间片轮循法实现。

实验平台

①单片机型号:STM32F103RCT6

②编译软件:KEIL5

③硬件平台:正点原子STM32-MINI开发板

④仿真器:J-Link

版权声明
①作者:KELIN

②声明:本文主要参考安富莱的BSP驱动,如若有误解的地方,请联系纠正。

③纠错/业务合作:1546730313@qq.com文章来源地址https://www.toymoban.com/news/detail-541067.html

正文

一、主函数实现

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "key.h"
#include "timer.h"

void led_blink(void)
{
	static uint8_t i=0;
	
	
	if(!i){
		LED1=0;
		i=1;
	}else{
		LED1=1;
		i=0;
	}

}

 int main(void)
 {	
	u8 t=0;	  
	delay_init();
	LED_Init();		  	 	//初始化与LED连接的硬件接口
	bk_api_key_init();
	SysTick_Init();
	//LED0=0;					//点亮LED
	while(1)
	{
		if(s_Tmr.Flag_1ms){
			s_Tmr.Flag_1ms=0;
            task_x();
		}
		if(s_Tmr.Flag_10ms){
			s_Tmr.Flag_10ms=0;
			bk_api_key_scan();		//得到键值
			t = bk_api_key_fifo_out();
			if (t != KEY_NONE){
				switch(t){
					case KEY_1_DOWN:
						LED0=0;
					break;
					case KEY_1_UP:
						LED0=1;
					break;			
					case KEY_1_LONG:
						LED0=1;				
					break;			
				}
			}
		}
		if(s_Tmr.Flag_100ms){
			s_Tmr.Flag_100ms=0;
			
            task_xx();
		}
		if(s_Tmr.Flag_500ms){
			s_Tmr.Flag_500ms=0;
		     task_xxx();
		}
		if(s_Tmr.Flag_1s){
			s_Tmr.Flag_1s=0;
			led_blink();
		}
	}
}

二、按键驱动

C文件

#include "key.h"

//全局变量
static KEY_T s_tBtn[KID_BUTT];
static KEY_FIFO_T s_tKey;		/* 按键FIFO变量,结构体 */


//函数声明
static void bk_api_key_hal_init(void);
static void bk_api_key_var_init(void);




static uint8_t IsKeyDown1(void) 
{
    if (!GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)){
        return 1;
	}else{ 
        return 0;
	}
}

static uint8_t IsKeyDown2(void) 
{
    if (!GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)){
        return 1;
	}else{ 
        return 0;
	}
}

static uint8_t IsKeyDown3(void) 
{
    if (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)){
        return 1;
	}else{ 
        return 0;
	}
}

/*
*********************************************************************************************************
*	函 数 名: bk_api_key_init
*	功能说明: 初始化按键
*	形    参:  无
*	返 回 值: 无
*********************************************************************************************************
*/
void bk_api_key_init(void)
{
	bk_api_key_hal_init();
	bk_api_key_var_init();
}


/*
*********************************************************************************************************
*	函 数 名: bk_api_key_hal_init
*	功能说明: 初始化按键硬件
*	形    参:  无
*	返 回 值: 无
*********************************************************************************************************
*/
static void bk_api_key_hal_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);//使能PORTA,PORTC时钟

	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//关闭jtag,使能SWD,可以用SWD模式调试
	
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_15;//PA15
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
 	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA15
	
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_5;//PC5
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
 	GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC5
 
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;//PA0
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉	  
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0	
}

/*
*********************************************************************************************************
*	函 数 名: bk_api_key_var_init
*	功能说明: 初始化按键变量
*	形    参:  无
*	返 回 值: 无
*********************************************************************************************************
*/
static void bk_api_key_var_init(void)
{
    uint8_t i;

	/* 给每个按键结构体成员变量赋一组缺省值 */
	for (i = 0; i < KID_BUTT; i++)
	{
		s_tBtn[i].LongTime = KEY_LONG_TIME;			/* 长按时间 0 表示不检测长按键事件 */
		s_tBtn[i].Count = KEY_FILTER_TIME / 2;		/* 计数器设置为滤波时间的一半 */
		s_tBtn[i].State = 0;						/* 按键缺省状态,0为未按下 */
		s_tBtn[i].RepeatSpeed = 0;					/* 按键连发的速度,0表示不支持连发 */
		s_tBtn[i].RepeatCount = 0;					/* 连发计数器 */
	}
	/* 如果需要单独更改某个按键的参数,可以在此单独重新赋值 */
	/* 比如,我们希望按键1按下超过1秒后,自动重发相同键值 */
	s_tBtn[KID_K1].LongTime = 200;
	s_tBtn[KID_K1].RepeatSpeed = 5;	/* 每隔50ms自动发送键值 */
	
	s_tBtn[KID_K2].LongTime = 200;
	s_tBtn[KID_K2].RepeatSpeed = 5;	/* 每隔50ms自动发送键值 */
	
	s_tBtn[KID_JOY_U].LongTime = 200;
	s_tBtn[KID_JOY_U].RepeatSpeed = 5;	/* 每隔50ms自动发送键值 */

	/* 判断按键按下的函数 */
	s_tBtn[0].IsKeyDownFunc = IsKeyDown1;
	s_tBtn[1].IsKeyDownFunc = IsKeyDown2;

	/* 组合键 */
    s_tBtn[2].IsKeyDownFunc = IsKeyDown3;
}

/*
*********************************************************************************************************
*	函 数 名: bk_api_key_set_keyParam
*	功能说明: 设置按键参数
*	形    参:_ucKeyID : 按键ID,从0开始
*			_LongTime : 长按事件时间
*			 _RepeatSpeed : 连发速度
*	返 回 值: 无
*********************************************************************************************************
*/
void bk_api_key_set_keyParam(uint8_t _ucKeyID, uint16_t _LongTime, uint8_t  _RepeatSpeed)
{
	s_tBtn[_ucKeyID].LongTime = _LongTime;			/* 长按时间 0 表示不检测长按键事件 */
	s_tBtn[_ucKeyID].RepeatSpeed = _RepeatSpeed;	/* 按键连发的速度,0表示不支持连发 */
	s_tBtn[_ucKeyID].RepeatCount = 0;				/* 连发计数器 */
}


//清空缓冲区
void bk_api_key_fifo_clearKey(void)
{
	s_tKey.Read = s_tKey.Write;
}

/*
*********************************************************************************************************
*	函 数 名: bk_api_key_fifo_in
*	功能说明: 将1个键值压入按键FIFO缓冲区。可用于模拟一个按键。
*	形    参:  _KeyCode : 按键代码
*	返 回 值: 无
*********************************************************************************************************
*/
void bk_api_key_fifo_in(uint8_t _keyCode)
{
    s_tKey.Buf[s_tKey.Write] = _keyCode;

    if(++s_tKey.Write >= KEY_FIFO_SIZE){
        s_tKey.Write = 0;
    }
}

/*
*********************************************************************************************************
*	函 数 名: bk_api_key_fifo_out
*	功能说明: 从按键FIFO缓冲区读取一个键值。
*	形    参:  无
*	返 回 值: 按键代码
*********************************************************************************************************
*/
uint8_t bk_api_key_fifo_out(void)
{
    uint8_t ret=KEY_NONE;

    if(s_tKey.Read == s_tKey.Write){
        //缓冲区为空
        return KEY_NONE;
    }else{
        ret = s_tKey.Buf[s_tKey.Read];
        if(++s_tKey.Read >= KEY_FIFO_SIZE){
            s_tKey.Read=0;
        }
    }
    return ret;
}

/*
*********************************************************************************************************
*	函 数 名: bk_api_key_getState
*	功能说明: 读取按键的状态
*	形    参:  _ucKeyID : 按键ID,从0开始
*	返 回 值: 1 表示按下, 0 表示未按下
*********************************************************************************************************
*/
uint8_t bk_api_key_getState(KEY_ID_E _ucKeyID)
{
	return s_tBtn[_ucKeyID].State;
}

/*
*********************************************************************************************************
*	函 数 名: bk_api_key_detectKey
*	功能说明: 检测一个按键。非阻塞状态,必须被周期性的调用。
*	形    参:  按键结构变量指针
*	返 回 值: 无
*********************************************************************************************************
*/
void bk_api_key_detectKey(uint8_t i)
{
    KEY_T *pBtn=0;

    //如果没有初始化按键函数,则报错
    // if (s_tBtn[i].IsKeyDownFunc == 0)
    // {
    //     printf("Fault : DetectButton(), s_tBtn[i].IsKeyDownFunc undefine");
    // }

    pBtn = &s_tBtn[i];

    if(pBtn->IsKeyDownFunc()){
        //有按键按下 1:滤波
        if(pBtn->Count < KEY_FILTER_TIME){
            pBtn->Count=KEY_FILTER_TIME;
        }else if(pBtn->Count < 2 * KEY_FILTER_TIME){
            pBtn->Count++;
        }else{
            //2:短按
            if(pBtn->State == 0){
                pBtn->State = 1;
                //短按按下
                bk_api_key_fifo_in((uint8_t)3*i+1);
            }
            //3:长按
            if(pBtn->LongTime > 0){
                if(pBtn->LongCount < pBtn->LongTime){
                    //长按时间未到
                    if(++pBtn->LongCount >= pBtn->LongTime){
                        //长按按下
                        bk_api_key_fifo_in((uint8_t)3*i+3);
                    }
                }else{
                    //4:检测长按持续
                    if(pBtn->RepeatSpeed > 0){
						if(++pBtn->RepeatCount >= pBtn->RepeatSpeed){
							//检测到长按持续
							pBtn->RepeatCount = 0;
							//长按按键后,每隔RepeatSpeed ms发送一次短按
							bk_api_key_fifo_in((uint8_t)3*i+1);
						}
                    }
                }
            }
        }
    }else{
        //没有按键按下
        if(pBtn->Count > KEY_FILTER_TIME){
            pBtn->Count = KEY_FILTER_TIME;
        }else if(pBtn->Count != 0){
            //松开防抖
            pBtn->Count--;
        }else{
            if(pBtn->State == 1){
                //5:有按键按下->弹起
                pBtn->State=0;
                bk_api_key_fifo_in((uint8_t)3*i+2);
            }
        }
        pBtn->LongCount = 0;
        pBtn->RepeatCount=0;
    }
}

/*
*********************************************************************************************************
*	函 数 名: bk_api_key_scan
*	功能说明: 扫描所有按键。非阻塞,被systick中断周期性的调用
*	形    参:  无
*	返 回 值: 无
*********************************************************************************************************
*/
void bk_api_key_scan(void)
{
    uint8_t i;

    for(i=0;i<KID_BUTT;i++){
        bk_api_key_detectKey(i);
    }
}

H文件

#ifndef __KEY_H
#define __KEY_H	 
#include "sys.h"
 

#define KEY0_PRES	1		//KEY0  
#define KEY1_PRES	2		//KEY1 
#define WKUP_PRES	3		//WK_UP  


/* 按键ID, 主要用于bsp_KeyState()函数的入口参数 */
typedef enum
{
	KID_K1 = 0,
	KID_K2,

	KID_JOY_U,


    KID_BUTT
}KEY_ID_E;


/*
	每个按键对应1个全局的结构体变量。
*/
typedef struct
{
	/* 下面是一个函数指针,指向判断按键手否按下的函数 */
	uint8_t (*IsKeyDownFunc)(void); /* 按键按下的判断函数,1表示按下 */

	uint8_t  Count;			/* 滤波器计数器 */
	uint16_t LongCount;		/* 长按计数器 */
	uint16_t LongTime;		/* 按键按下持续时间, 0表示不检测长按 */
	uint8_t  State;			/* 按键当前状态(按下还是弹起) 0:弹起  1:按下*/
	uint8_t  RepeatSpeed;	/* 连续按键周期 */
	uint8_t  RepeatCount;	/* 连续按键计数器 */
}KEY_T;

/*
	定义键值代码, 必须按如下次序定时每个键的按下、弹起和长按事件

	推荐使用enum, 不用#define,原因:
	(1) 便于新增键值,方便调整顺序,使代码看起来舒服点
	(2) 编译器可帮我们避免键值重复。
*/
typedef enum
{
	KEY_NONE = 0,			/* 0 表示按键事件 */

	KEY_1_DOWN,				/* 1键按下 1*/ 
	KEY_1_UP,				/* 1键弹起 2*/
	KEY_1_LONG,				/* 1键长按 3*/

	KEY_2_DOWN,				/* 2键按下 4*/
	KEY_2_UP,				/* 2键弹起 5*/
	KEY_2_LONG,				/* 2键长按 6*/
	/* 组合键 */
	KEY_9_DOWN,				/* 9键按下 7*/
	KEY_9_UP,				/* 9键弹起 8*/
	KEY_9_LONG,				/* 9键长按 9*/
}KEY_ENUM;


#define KEY_FILTER_TIME   10
#define KEY_LONG_TIME     100			


/* 按键FIFO用到变量 */
#define KEY_FIFO_SIZE	10
typedef struct
{
	uint8_t Buf[KEY_FIFO_SIZE];		/* 键值缓冲区 */
	uint8_t Read;					/* 缓冲区读指针1 */
	uint8_t Write;					/* 缓冲区写指针 */
	uint8_t Read2;					/* 缓冲区读指针2 */
}KEY_FIFO_T;

void bk_api_key_init(void);
void bk_api_key_scan(void);
void bk_api_key_fifo_in(uint8_t _keyCode);
uint8_t bk_api_key_fifo_out(void);
#endif

三、SYSTICK定时器实现时间片轮循法方法

C文件

#include "timer.h"
//#include "core_cm3.h"
//#include "system_stm32f10x.h"

SYS_SOFT_TMR	s_Tmr={0};

/* 这2个全局变量转用于 bsp_DelayMS() 函数 */
static volatile uint32_t s_uiDelayCount = 0;
static volatile uint8_t s_ucTimeOutFlag = 0;

/*
* 函数名:SysTick_Init
* 描述         :启动系统滴答定时器 SysTick
* 输入  : 无
* 输出  :无
* 调用  : 外部调用
*/
void SysTick_Init(void)
{
	SysTick_Config(SystemCoreClock/1000);         //1ms定时器
    //SysTick->CTRL &= SysTick_CTRL_ENABLE_Msk;                         //若无法启动则关闭
}

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{

	/* 每隔1ms进来1次 (仅用于 bsp_DelayMS) */
	if (s_uiDelayCount > 0)
	{
		if (--s_uiDelayCount == 0)
		{
			s_ucTimeOutFlag = 1;
		}
	}	
	s_Tmr.Count_1ms++;
	s_Tmr.Flag_1ms=1;
	if(s_Tmr.Count_1ms>=10){
		s_Tmr.Count_1ms=0;
		s_Tmr.Flag_10ms=1;
		s_Tmr.Count_10ms++;
		if(s_Tmr.Count_10ms>=10){
			s_Tmr.Count_10ms=0;
			s_Tmr.Flag_100ms=1;
			s_Tmr.Count_100ms++;
			if(s_Tmr.Count_100ms>=5){
				s_Tmr.Count_100ms=0;
				s_Tmr.Flag_500ms=1;
				s_Tmr.Count_500ms++;
				if(s_Tmr.Count_500ms>=2){
					s_Tmr.Count_500ms=0;
					s_Tmr.Flag_1s=1;
				}
			}
		}
	}
}

/*
*********************************************************************************************************
*	函 数 名: bk_sys_timer_idle
*	功能说明: 空闲时执行的函数。一般主程序在for和while循环程序体中需要插入 CPU_IDLE() 宏来调用本函数。
*			 本函数缺省为空操作。用户可以添加喂狗、设置CPU进入休眠模式的功能。
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void bk_sys_timer_idle()
{
	/* --- 喂狗 */

	/* --- 让CPU进入休眠,由Systick定时中断唤醒或者其他中断唤醒 */

	/* 对于 emWin 图形库,可以插入图形库需要的轮询函数 */
	//GUI_Exec();

	/* 对于 uIP 协议实现,可以插入uip轮询函数 */	
}

/*
*********************************************************************************************************
*	函 数 名: bk_sys_timer_delay_ms
*	功能说明: ms级延迟,延迟精度为正负1ms
*	形    参:  n : 延迟长度,单位1 ms。 n 应大于2
*	返 回 值: 无
*********************************************************************************************************
*/
void bk_sys_timer_delay_ms(uint32_t n)
{
	if (n == 0)
	{
		return;
	}
	else if (n == 1)
	{
		n = 2;
	}

	DISABLE_INT();  			/* 关中断 */

	s_uiDelayCount = n;
	s_ucTimeOutFlag = 0;

	ENABLE_INT();  				/* 开中断 */

	while (1)
	{
		bk_sys_timer_idle();				/* CPU空闲执行的操作, 见 bsp.c 和 bsp.h 文件 */

		/*
			等待延迟时间到
			注意:编译器认为 s_ucTimeOutFlag = 0,所以可能优化错误,因此 s_ucTimeOutFlag 变量必须申明为 volatile
		*/
		if (s_ucTimeOutFlag == 1)
		{
			break;
		}
	}
}


/*
*********************************************************************************************************
*    函 数 名: bk_sys_delay_us
*    功能说明: us级延迟。 必须在systick定时器启动后才能调用此函数。
*    形    参:  n : 延迟长度,单位1 us
*    返 回 值: 无
*********************************************************************************************************
*/
void bk_sys_delay_us(uint32_t n)
{
    uint32_t ticks;
    uint32_t told;
    uint32_t tnow;
    uint32_t tcnt = 0;
    uint32_t reload;
       
	reload = SysTick->LOAD;                
    ticks = n * (SystemCoreClock / 1000000);	 /* 需要的节拍数 */  
    
    tcnt = 0;
    told = SysTick->VAL;             /* 刚进入时的计数器值 */

    while (1)
    {
        tnow = SysTick->VAL;    
        if (tnow != told)
        {    
            /* SYSTICK是一个递减的计数器 */    
            if (tnow < told)
            {
                tcnt += told - tnow;    
            }
            /* 重新装载递减 */
            else
            {
                tcnt += reload - tnow + told;    
            }        
            told = tnow;

            /* 时间超过/等于要延迟的时间,则退出 */
            if (tcnt >= ticks)
            {
            	break;
            }
        }  
    }
} 

H文件

#ifndef __TIMER_H__
#define __TIMER_H__

#include "sys.h"  

typedef struct{
	volatile uint8_t  Count_1ms;	/* 计数器 */
	volatile uint8_t  Flag_1ms;		/* 定时到达标志  */
	volatile uint8_t  Count_10ms;	/* 计数器 */
	volatile uint8_t  Flag_10ms;	/* 定时到达标志  */
	volatile uint8_t  Count_100ms;	/* 计数器 */
	volatile uint8_t  Flag_100ms;	/* 定时到达标志  */
	volatile uint8_t  Count_500ms;	/* 计数器 */
	volatile uint8_t  Flag_500ms;	/* 定时到达标志  */
	volatile uint8_t  Count_1s;		/* 计数器 */
	volatile uint8_t  Flag_1s;		/* 定时到达标志  */
}SYS_SOFT_TMR;

extern SYS_SOFT_TMR	s_Tmr;//全局声明

/* 开关全局中断的宏 */
#define ENABLE_INT()	__set_PRIMASK(0)	/* 使能全局中断 */
#define DISABLE_INT()	__set_PRIMASK(1)	/* 禁止全局中断 */


void SysTick_Init(void);
void bk_sys_timer_delay_ms(uint32_t n);
void bk_sys_delay_us(uint32_t n);
#endif

到了这里,关于按键FIFO实现以及单片机时间片轮循法实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C51单片机的电子时钟(数码管显示+独立按键模块修改及暂停时间)

    IMG_1120 通过查看这三个原理图我们可以得知控制K1、K2、K3及K4是通过P31、P30、P32及P33来实现的,控制8个数码管是P22、P23及P24来实现, 控制发光二极管则由P00-P07来实现。 代码分为三部分分别为main.c、key.h、key.c scankey()函数的主要代码,通过软件入手提高系统的可靠性,防止外

    2024年02月05日
    浏览(53)
  • 一周学完C51单片机(1)点亮LED灯以及按键控制

    首先找到单片机的原理图,找到LED模块。我这里是P2口是连接了LED灯,通过此原理图我们可以看到 我们只需将单片机的IO口置为低电平,就可以点亮LED灯。 因为代码比较简单,我就分别展示一下代码,一颗LED灯的亮灭,流水灯 延时函数可以通过小工具来实现,选择好系统的频

    2024年02月08日
    浏览(44)
  • 32单片机按键扫描 实现长短按

    key.c key.h

    2024年02月03日
    浏览(42)
  • C51单片机按键控制流水灯模式(定时器版本)以及定时器时钟

      上篇文章我们学了关于定时器的三大组成部分及许多寄存器的概念问题,这篇文章我们就要开始讲解实操部分。 首先,我们先来看看本文最后写成的代码:      以上三张是代码的主函数,此外,代码中还需用到的独立按键检测代码在下面:  注意:头文件中#ifndef和#def

    2023年04月17日
    浏览(48)
  • 【51单片机】矩阵按键实现数码管显示

    闲的没事看一看玩一玩········· 矩阵按键 数码管是一种导体发光器件,其基本单元是发光二极管。按发光二极管单元连接方式可分为共阳极数码管和共阴极数码管 共阴极数码管是指将所有发光二极管的阴极接到一起形成共阴极的数码管,共阴极的数码管在应用时将公共

    2024年02月02日
    浏览(59)
  • 51单片机实现倒计时,按键控制倒计时

    基于AT89C52的答辩倒计时。四个按键分别控制倒计时开始,暂停,时间加和减。剩下30S时蜂鸣器响,倒计时结束蜂鸣器响。  

    2024年02月07日
    浏览(56)
  • 51单片机入门 - 详解定时器实现按键控制流水灯方向

    操作系统:Windows 10 x84-64 单片机:STC89C52RC 编译器:SDCC 烧录软件:stcgal 1.6 开发板:普中51单片机开发板A2套件(2022) 在 VS Code 中新建项目到烧录的过程: 左侧EIDE图标 - 新建项目 - 空项目 - 8位MCU项目 - 保存文件夹。 更改构建配置: SDCC ;更改烧录配置: stcgal 。 在项目文件

    2024年02月06日
    浏览(46)
  • 基于51单片机利用中断实现100以内的按键计数(Proteus仿真)

    https://mp.weixin.qq.com/s?__biz=Mzg4Mzc3NDUxOQ==mid=2247484090idx=3sn=ed67cb438e25cc13b32ac6c48ccebecbchksm=cf4307e2f8348ef424109aacc5bb64a6f20d53581d57f15377ec67383e01a69e7a0292b500f6token=3445295lang=zh_CN#rd https://mp.weixin.qq.com/s?__biz=Mzg4Mzc3NDUxOQ==mid=2247484090idx=3sn=ed67cb438e25cc13b32ac6c48ccebecbchksm=cf4307e2f8348ef424109aacc5bb64a6f20d535

    2024年02月04日
    浏览(41)
  • 51单片机实现按键、键盘的功能,五面拿下阿里飞猪offer

    } /******************************************************************************* 函 数 名 : main 函数功能 : 主函数 输 入 : 无 输 出 : 无 *******************************************************************************/ void main() { led=0; while(1) { keypros(); //按键处理函数 } } 矩阵键盘代码 /************************************

    2024年04月11日
    浏览(46)
  • STM32 -- 实现按键的长按与短按检测(其他单片机可移植)

    目录 资源获取 一 前言 二 思路  三 实现代码 1.主要代码 四 完整代码 Key.h Key.c 该改进版本(1ms太繁琐了,我改成了25ms检测一次)   1.定时器部分 2.按键检测部分  五、参考 欢迎关注微信公众号--星之援工作室 发送(长短按检测) 今天在逛博客的时候,偶然看到了一

    2024年02月12日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包