技术标签: 单片机
#define KEY_CLO0_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_RESET)
#define KEY_CLO1_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_RESET)
#define KEY_CLO2_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_14,Bit_RESET)
#define KEY_CLO3_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_15,Bit_RESET)
#define KEY_CLO0_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_SET)
#define KEY_CLO1_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_SET)
#define KEY_CLO2_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_14,Bit_SET)
#define KEY_CLO3_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_15,Bit_SET)
来进行列扫描。
介绍完矩阵键盘的扫描原理了我们该通过keli来实现我们想要的功能啦,首先我们要进行的就是对我们所需要的端口进行配置,如下:
//端口的配置
void key_init(){
GPIO_InitTypeDef GPIO_InitStruture;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //打开PB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); //打开PE时钟
//定义PB12、PB13、PB14、PB15为推挽输出
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruture);
//定义PD8、PD9、PD10、PD11为上拉输入 分别定义为四行
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
GPIO_Init(GPIOD,&GPIO_InitStruture);
}
配置完我们所需要的端口,接下来我们就应该编写相关函数啦。
//如果为1,代表没有按键被按下,如果为0,代表有按键被按下
char KEY_ROW_SCAN(void)
{
//读出行扫描状态
Key_row[0] = GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_8)<<3;
Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_9)<<2);
Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_10)<<1);
Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11));
if(Key_row[0] != 0x0f) //不是1111,代表肯定有一个0行
{
delay_ms(10); //消抖
if(Key_row[0] != 0x0f)
//0111 1011 1101 1110
{
//printf("Key_Row_DATA = 0x%x\r\n",Key_row[0]);
switch(Key_row[0])
{
case 0x07: //0111 判断为该列第1行的按键按下
return 1;
case 0x0b: //1011 判断为该列第2行的按键按下
return 2;
case 0x0d: //1101 判断为该列第3行的按键按下
return 3;
case 0x0e: //1110 判断为该列第4行的按键按下
return 4;
default :
return 0;
}
}
else return 0;
}
else return 0;
}
char KEY_SCAN(void)
{
char Key_Num=0; //1-16对应的按键数
char key_row_num=0; //行扫描结果记录
KEY_CLO0_OUT_LOW;
if( (key_row_num=KEY_ROW_SCAN()) != 0 )
{
while(KEY_ROW_SCAN() != 0); //消抖
Key_Num = 0 + key_row_num;
}
KEY_CLO0_OUT_HIGH;
KEY_CLO1_OUT_LOW;
if( (key_row_num=KEY_ROW_SCAN()) != 0 )
{
while(KEY_ROW_SCAN() != 0);
Key_Num = 4 + key_row_num;
}
KEY_CLO1_OUT_HIGH;
KEY_CLO2_OUT_LOW;
if( (key_row_num=KEY_ROW_SCAN()) != 0 )
{
while(KEY_ROW_SCAN() != 0);
Key_Num = 8 + key_row_num;
}
KEY_CLO2_OUT_HIGH;
KEY_CLO3_OUT_LOW;
if( (key_row_num=KEY_ROW_SCAN()) != 0 )
{
while(KEY_ROW_SCAN() != 0);
Key_Num = 12 + key_row_num;
}
KEY_CLO3_OUT_HIGH;
return Key_Num;
}
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key16.h"
#include "stdio.h"
#include "usart.h"
int main(void)
{
vu8 key=0;
char key_confirm;
led_init();
delay_init();
key_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
while(1)
{
key_confirm = KEY_SCAN();
if(key_confirm>0&&key_confirm<17){
printf("Key_NUM = %d \r\n",key_confirm); //按下1-16个按键的操作
printf("= = = = = = = = = = = \r\n");
}
}
}
#include "key16.h"
#include "delay.h"
uint8_t Key_row[1]={
0xff}; //定义一个数组,存放行扫描状态
//端口的配置
void key_init(){
GPIO_InitTypeDef GPIO_InitStruture;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //打开PB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); //打开PE时钟
//定义PB12、PB13、PB14、PB15为推挽输出
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruture);
//定义PD8、PD9、PD10、PD11为上拉输入 分别定义为四行
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
GPIO_Init(GPIOD,&GPIO_InitStruture);
}
/***
*函数名:KEY_ROW_SCAN
*功 能:按键行扫描
*返回值:1~4,对应1~4行按键位置
*/
//如果为1,代表没有按键被按下,如果为0,代表有按键被按下
char KEY_ROW_SCAN(void)
{
//读出行扫描状态
Key_row[0] = GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_8)<<3;
Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_9)<<2);
Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_10)<<1);
Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11));
if(Key_row[0] != 0x0f) //不是1111,代表肯定有一个0行
{
delay_ms(10); //消抖
if(Key_row[0] != 0x0f)
//0111 1011 1101 1110
{
//printf("Key_Row_DATA = 0x%x\r\n",Key_row[0]);
switch(Key_row[0])
{
case 0x07: //0111 判断为该列第1行的按键按下
return 1;
case 0x0b: //1011 判断为该列第2行的按键按下
return 2;
case 0x0d: //1101 判断为该列第3行的按键按下
return 3;
case 0x0e: //1110 判断为该列第4行的按键按下
return 4;
default :
return 0;
}
}
else return 0;
}
else return 0;
}
/***
*函数名:KEY_SCAN
*功 能:4*4按键扫描
*返回值:0~16,对应16个按键
*/
char KEY_SCAN(void)
{
char Key_Num=0; //1-16对应的按键数
char key_row_num=0; //行扫描结果记录
KEY_CLO0_OUT_LOW;
if( (key_row_num=KEY_ROW_SCAN()) != 0 )
{
while(KEY_ROW_SCAN() != 0); //消抖
Key_Num = 0 + key_row_num;
}
KEY_CLO0_OUT_HIGH;
KEY_CLO1_OUT_LOW;
if( (key_row_num=KEY_ROW_SCAN()) != 0 )
{
while(KEY_ROW_SCAN() != 0);
Key_Num = 4 + key_row_num;
//printf("Key_Clo_2\r\n");
}
KEY_CLO1_OUT_HIGH;
KEY_CLO2_OUT_LOW;
if( (key_row_num=KEY_ROW_SCAN()) != 0 )
{
while(KEY_ROW_SCAN() != 0);
Key_Num = 8 + key_row_num;
//printf("Key_Clo_3\r\n");
}
KEY_CLO2_OUT_HIGH;
KEY_CLO3_OUT_LOW;
if( (key_row_num=KEY_ROW_SCAN()) != 0 )
{
while(KEY_ROW_SCAN() != 0);
Key_Num = 12 + key_row_num;
}
KEY_CLO3_OUT_HIGH;
return Key_Num;
}
#ifndef _KEY16_H
#define _KEY16_H
#include "sys.h"
#include "stm32f10x.h"
#include <string.h>
void key_init();
char KEY_SCAN(void);
char KEY_ROW_SCAN(void);
void HW_KEY_FUNCTION(void);
#define KEY_CLO0_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_RESET)
#define KEY_CLO1_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_RESET)
#define KEY_CLO2_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_14,Bit_RESET)
#define KEY_CLO3_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_15,Bit_RESET)
#define KEY_CLO0_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_SET)
#define KEY_CLO1_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_SET)
#define KEY_CLO2_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_14,Bit_SET)
#define KEY_CLO3_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_15,Bit_SET)
#endif
好啦,所有准备工作都完成啦!!又到了我们激动人心的时刻啦!!
运行成功图如下:
over。
Start1. 创建分布式存储可故障转移群集创建完毕后,接下来在群集中启用分布式存储(Storage Space Direct),来作为群集存储使用。1) 在启用分布式存储之前,首先需要处理所有磁盘,使所有磁盘处于可用状态磁盘要求为:用于存储空间直通的磁盘必须为空且没有分区或其他数据。 如果磁盘有分区或其他数据,那么它不会包含在存储空间直通系统中。2)下面,通过一个脚本,来清..._s2d 声明磁盘
为了解决单块式架构可用性低,可伸缩性差,集中发布的生命周期以及违反单一功能原则,微服务(Microservice)应运而生了,将功能按照边界拆分为单个服务,但是每个服务之间的通讯如何解决?Spring Cloud 的出现为我们解决分布式开发中常用的问题给出了完整的方案。Spring Cloud 基于Spring Boot ,为我们提供了配置管理,服务发现,断路器,代理服务等。基于Spring
JDK12安装配置(Win10)一、JDK12下载JDK12下载地址:https://www.oracle.com/technetwork/java/javase/downloads/jdk12-downloads-5295953.html1、选择Accept License Agreement2、点击下载对应系统安装文件二、JDK12安装右键点击下载文件,以管理员身份运行点击下...
时间限制: 1000 ms 内存限制: 32768 KB提交数: 8910 通过数: 5063【题目描述】已知线段的两个端点的坐标A(Xa,Ya),B(Xb,Yb),求线段AB的长度,保留到小数点后3位。【输入】第一行是两个实数Xa,Ya,即A的坐标。第二行是两个实数Xb,Yb,即B的坐标。输入中所有实数的绝对值均不超过1000010000。【输出】一个实...
简洁地解释如下:1) 首先我们仅考虑实信号。自相关的直观含义就是:把一个信号平移一段距离,跟原来有多相似。于是就有了自相关的定义:它代表了“移、乘、积”这三步操作。 如果只谈自相关,其实到此就可以结束了。只不过,在信号处理领域中还有一个叫“卷积”的东西,在别的地方(已知线性时不变系统的冲激响应和输入,求响应)有用。它跟自相关的定义很相似,包含了“卷、移、乘、积”..._自相关函数
文章目录第五章 数码管动态扫描第 1 节 项目背景第 2 节 设计目标第 3 节 设计实现3.1 顶层信号3.2 信号设计3.3 信号定义第四节 综合和上板4.1 新建工程4.2 综合4.3 配置管脚4.4 再次综合4.5 连接开发板4.6 上板第五章 数码管动态扫描第 1 节 项目背景led 数码管(LED Segment Displays)是由多个发光二极管封装在一起的器件,这些二极管组成“8”字型,在内部完成引线连接,只引出它们的各个笔划和公共电极。一般来说,led 数码管常用段数为 7 段_数码管动态扫描
这两天有个需求,点击按钮从SD卡解压压缩包,并读取压缩包内txt文档内容,然后在街面上显示出来。毕竟IO操作很耗时,如果文件较大会花费不少时间。所以,在处理数据的时候能给个进度就好了。我们通常的做法就是,点击按钮后弹出一个加载框或者加载进度条,等数据处理结束后,再让对话框消失。但是现在的需求是,用一个布局,左侧显示刷新列表,右侧显示ProgressBar。那么问题来了,ProgressBar显示的...
kettle是一个比较好用的ETL开源工具,之前一直使用的是6.1版本,最近项目组有小伙伴第一次使用,直接下载了7.1版本。在使用中关于资源库的使用和6.1版本略有不同,如何创建资源库这里就不赘述了,大家可以参考网上的方法。但是小伙伴反馈资源库每次在kettle关闭重新打开后就不能用了,甚至连右上角那个connect按钮也不见了。聪明的小伙伴已经找到原因了,是由于资源库中包含中文,但是在repositories.xml(系统盘用户目录.kettle目录下)中中文显示的是乱码,解决办法是删除这个文件里的内_webspoon idea 运行没有connect
ATEasy为测试工程师提供了多种好处,包括:1.综合框架Integrated FrameworkATEasy提供了一个简化的,易于遵循的框架,指导用户创建在实际的测试系统之后建模的可重用组件。 组件包括系统,驱动程序,程序,测试,命令(System, Drivers, Programs, Tests, Commands)等等。2.重用性和可扩展性Re-usability and ScalabilityATEasy框架为用户提供了创建可重复使用的软件组件的能力,如仪器驱动程序,系统组件和测试程序。 _ateasy
先讲讲在工作上的一个用法。生产上,用户晒单后,其中一个表中一个字段没有维护,打算手动用sql把线上一个月的数据维护一下。用到了concat()函数,拼接生成update语句:SELECT CONCAT('update gshop_order_product set isSun=1 where id=',order_product_id,';') FROM gshop_comments W..._mysql update concat
一切都是对象“如果我们说另一种不同的语言,那么我们就会发觉一个有些不同的世界。”——Luduing Wittgerstein(1889-1951)尽管Java是基于C++的,但是相比之下,Java是一种更“纯粹”的面向对象设计语言。Java语言假设我们只进行面向对象的程序设计;而C++不同,因为C++是C的一个超集,所以,C++在某些方面显得过于复杂。2.1 用引用操纵对象..._一切都是对象by
#include<stdio.h>int main(){ int n; int i,j,k; scanf("%d",&n);//此时输入的是上半部分的行数 下半部分的行数比下半部分少一行 故下半部分可以表示为n-1 for(i=1;i<=n;i++)//代表每一行的情况 { for(j=1;j<=n-i;j++)//按照行数依次可知前面空格的个数与行数成 n-i 的关系 pri..._空心菱形什么样