2019-01-25 16:58:34 Xiaomo_haa 阅读数 619
  • 按键-第1季第9部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第9个课程,综合解决了独立按键和矩阵式按键的处理方法,涉及到:IO的输入输出、按键抖动和消抖、中断的引入和相关概念、矩阵式键盘的原理和编程等。目的是对单片机常见输入设备按键进行全方位学习。

    2185 人正在学习 去看看 朱有鹏

独立按键

使用独立按键时,请将开发板上面的J5跳线帽接到BTN端,此时为独立按键模式。

独立按键原理很简单,根据原理图

此时一旦按键按下,相应的I/O口就是接地状态,为低电平。

写单片机时我们都知道按键按下需要消抖,我们之前是使用delay延时程序消抖,但是不建议在程序中使用delay,我们可以使用定时器延时来完成消抖。

我们之前写独立按键原理都是

检测按键按下—>延时消抖—>再次检测按键是否还在按下状态—>确认按键按下—>操作—>检测按键是否松开—>延时消抖—>再次检测按键是否松开—>确定按键松开—>操作

但是对于多个按键来说,这样就显得繁琐了,所以在这里介绍一种简单一些的方法。

使用定时器消抖

我们使用定时器定时2ms,然后每次中断扫描一下按键,将扫描值左移至一个变量中,每移动一次就判断当前连续的8次按键状态是不是全1或者全0,如果是全1则判断为弹起,如果是全0则判断为按下,如果是0和1交错,就认为是抖动,不做任何判定。

利用这种方法就可以避免通过延时消抖占用单片机执行时间,而是转化成了一种按键状态判定而非按键过程判定,我们只对当前按键的连续16ms的状态进行判断,而不再关心它在这16ms内都做了什么事情。

void Key_Scan(void)
{
	u16 i;
	static u8 keybuff[] = {0xff,0xff,0xff,0xff};
	keybuff[0] = (keybuff[0]<<1)|s4;
	keybuff[1] = (keybuff[1]<<1)|s5;
	keybuff[2] = (keybuff[2]<<1)|s6;
	keybuff[3] = (keybuff[3]<<1)|s7;
	for(i = 0;i < 4;i ++)
	{
		if(keybuff[i] == 0xff)		//连续扫描8次都是1,16ms内都是弹起状态,按键已松开
		{
			KeySta[i] = 1;
		}
		else if(keybuff[i] == 0x00)	//连续扫描8次都是0,16ms内都是按下状态,按键已按下
		{
			KeySta[i] = 0;
		}
		else	//其他状态键值不稳定,不作处理
		{}
	}
}

这个算法就是经常使用的一种比较好的方法,我比较推荐这种方法,不建议在程序中加入延时。

 

 

 

 

 

2019-10-19 18:38:05 XiaoCaiDaYong 阅读数 526
  • 按键-第1季第9部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第9个课程,综合解决了独立按键和矩阵式按键的处理方法,涉及到:IO的输入输出、按键抖动和消抖、中断的引入和相关概念、矩阵式键盘的原理和编程等。目的是对单片机常见输入设备按键进行全方位学习。

    2185 人正在学习 去看看 朱有鹏

学习单片机都要学习流水灯,因为流水灯比较简单,易于实现,效果也比较好呈现。

本次是通过按键控制流水灯,按键按一下启动流水灯,按键的使用,在单片机开发中是必不可少的。

这里我用的单片机型号为STM32F103VET

8个LED灯接在了PA口的低八位。

注意点:

1.开启GPIOA和GPIOB的时钟

2.设置GPIOA口的工作模式,和GPIOB口的工作模式

          GPIOA:

                 1)打开0-7  IO口

                 2)设置8个口为推挽输出

                 3)速度为50MHz

          GPIOB:(和按键相接)

                1)设置0口

                2)为上拉输入

工程布局如下图:

代码也比较简单,代码如下:(这里我没有将代码模块化,只在main函数中实现,便于初学者理解,以后的代码会逐渐模块化)

#include "stm32f10x.h"                  // Device header
#include "stm32f10x_gpio.h"

void delay(void);
int main(void)
{
	unsigned char temp=0XF0;
	RCC_DeInit();	//	将外设RCC寄存器重设为缺省值
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	//	使能或者失能APB2外设时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitTypeDef GPIO_InitStruct;	//	定义结构体 包含了外设GPIO的配置信息	
	GPIO_DeInit(GPIOA);		//	将外设GPIOA寄存器重设为缺省值
	GPIO_DeInit(GPIOB);
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;	//  选中低8为管脚
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;	//	推挽输出
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;	//	最高输出速率50MHz
	GPIO_Init(GPIOA,&GPIO_InitStruct);	//	根据GPIO_InitStruct中指定的参数初始化外设GPIOA寄存器
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStruct);
	
	GPIO_Write(GPIOA,0X00F0);
	while(1)
	{
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == 0)	//	检查按键是否按下
		{
			delay();	//	消抖
			if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == 0)	//	再次判断按键是否按下
			{
				temp = ~temp;
				GPIO_Write(GPIOA,temp);
				while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == 0);		//	开关松开检测
			}
		}
	}
}

void delay(void)
{
	int i,j;
	for(i=0;i<400;i++)
	{
		for(j=0;j<400;j++);
	}
}

效果就是流水灯了,请自行测试。

代码链接,其实上面已经把代码贴出了,大家不需要化积分下载。

https://download.csdn.net/download/xiaocaidayong/11884602

 

2019-09-13 11:43:30 qq_36893568 阅读数 88
  • 按键-第1季第9部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第9个课程,综合解决了独立按键和矩阵式按键的处理方法,涉及到:IO的输入输出、按键抖动和消抖、中断的引入和相关概念、矩阵式键盘的原理和编程等。目的是对单片机常见输入设备按键进行全方位学习。

    2185 人正在学习 去看看 朱有鹏

一个I/O驱动发光二极管并扫描按键
由于51系列单片机的管脚有限,那我们就可以利用51系列单片机的I/O口可被设置成弱上拉、强上拉(推挽)输出、仅为输入(高阻)、开漏输出等四种工作模式的特征。可以将单片机的I/O口同时作为发光二极管的驱动和按键检测扫描使用,这样可以大大节省51系列单片机的I/O口。
在这里插入图片描述

当驱动发光二极管时,将I/O口设置为强推挽输出模式,输出高电平即可点亮发光二极管。

当检测按键时,将I/O口设置为弱上拉输入模式,再读取外部I/O口的状态, 即可检测按键状态。

本人博客仅仅代表我个人见解。如有错误请各位大牛留言指出,谢谢!!

2018-10-07 16:36:02 wgf248679370 阅读数 1238
  • 按键-第1季第9部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第9个课程,综合解决了独立按键和矩阵式按键的处理方法,涉及到:IO的输入输出、按键抖动和消抖、中断的引入和相关概念、矩阵式键盘的原理和编程等。目的是对单片机常见输入设备按键进行全方位学习。

    2185 人正在学习 去看看 朱有鹏

stm32F1系列的单片机学习笔记

今天主要完成了通过按键控制led灯和蜂鸣器,以下是我的感受和感想。
不管是对于led的驱动、蜂鸣器还是对按键的驱动首先要了解的是对IO端口的使能处理,然后是对IO口的输入输出模式,速度以及某一端口,主要是调用GPIO_Init()这个函数,后面就是针对某一单一东西进行编程,例如对于按键扫描处理,对于按键扫描有着固定的函数,主要就是返回值不一样,返回值也是最重要的,在主函数里面体现出那个按键被扫描出来了,就通过这个利用case和switch进行相关的操作代码。

2018-03-19 21:15:00 qq_41864439 阅读数 146
  • 按键-第1季第9部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第9个课程,综合解决了独立按键和矩阵式按键的处理方法,涉及到:IO的输入输出、按键抖动和消抖、中断的引入和相关概念、矩阵式键盘的原理和编程等。目的是对单片机常见输入设备按键进行全方位学习。

    2185 人正在学习 去看看 朱有鹏

本课题CPU使用51系列 C51设计,最大程度降低成本。

一、硬件电路设计

1、红外接收电路直接接单片机的串口

2、按键采用IO矩阵扫描方式,假设4×4=16,则4IO作为输出扫描口,4IO作为输入口,然后进行组合就可以得到键值

3、摇头:控制摇头电机正反转

4、送风模式:自然风,睡眠风,正常风

5、风速显示:采用圆盘式,旋转彩灯对应风速模式和档位模式显示,彩灯旋转速度和密度不同。

二、软件设计:

首先根据功能进行主程序任务划分,主程序主要工作是进行上述模式、风速、显示、遥控、按键、摇头等进行扫描及时关照到每个任务的状态,必须保证扫描时间实时性,不能因为某个环节步骤耽误,会影响整体程序的响应失效。

因此主程序会依次扫描 模式(正常(内含档位)、自然、睡眠,内涵档位及风速显示)、摇头(开机、不摇头、关机),因此遥控协议必须包含上述信息,接收的的协议应该都有以上这些参数,而不是仅仅一个功能码来表示,应该一包都含有上述参量。有默认值,修改后会存储。

中断程序 主要用来实现时序操作,通讯用串口+定时器来做,键盘、显示全部用定时器扫描,如果出现两个定时情况,如显示,首先是显扫用一个定时器,然后是各种变换的旋转彩灯模式用一个定时器,旋转彩灯的显示看作是数据。把旋转彩灯模式放在定时中断里,主程序只是用一个标志来确定,这样即使主程序不断循环,一个模式标志的话,也不会因为重复循环导致执行断点需要记忆的问题,一切浪费时间的运行都在定时器里自动运行,不占用CPU资源,只要主程序提供一个指示。

另外,对于多种模式,如何把不规律的东西变成有规律的东西,例如一个旋转彩灯,可能是对应一串不连续的IO操作,毫无规律,但是有规律的是每个节拍的变化,1、2、3、4、5。。。这个顺序就是规律,因此,可以用一个变量的递增变化产生的有规律的数字来把不规律的操作规律化,串起来。

    总结以上,就是一个典型的多任务、多时序前后台系统的实现,如果全部在主程序实现,可见是无法保证实时性的,因为里面延时的操作太多,必须保证主程序扫描的快速响应,因此把大量消耗时间的任务都放在了中断中进行,有多个定时组合的任务就用多个定时器协助完成,例如显示,一方面需要显示扫描,把内容呈现在显示管上,另一方面显示管上的内容还在随时间规律变化,因此还需要一个定时器来定时推出不同数据到显示管上;这就需要两个定时器,全用一个定时器的话如果定时中断的程序执行时间超过显示器扫描时间的话会影响显示效果。因此在前后台系统里面,定时器就是实现多任务的有力武器。

   本课题关键:串口接收函数,串口和定时器配合,小RAM小buf串口数据接收解析方法;4×4键盘扫描键值原理;2定时器配合流水彩灯显示原理;主程序多任务运行响应原理;中断程序实现多定时操作原理;不规律中寻找规律串起来原理。

没有更多推荐了,返回首页