ARM(IMX6U)裸机按键输入实验(BSP+SDK、GPIO输入与输出、按键消抖)

2023-10-31

参考:Linux之ARM(IMX6U)裸机按键输入实验(GPIO的输出与输入)
作者:一只青木呀
发布时间: 2020-08-17 21:43:37
网址:https://blog.csdn.net/weixin_45309916/article/details/108057687


前面几篇文章试验都是讲解如何使用 I.MX6U 的 GPIO 输出控制功能, I.MX6U 的 IO 不仅能作为输出,而且也可以作为输入I.MX6U-ALPHA 开发板上有一个按键,按键连接了一个 IO,将这个 IO 配置为输入功能,读取这个 IO 的值即可获取按键的状态(按下或松开)。本篇文章通过这个按键来控制蜂鸣器的开关

1、按键输入简介

按键就两个状态:按下或弹起,将按键连接到一个 IO 上,通过读取这个 IO 的值就知道按键是按下的还是弹起的。至于按键按下的时候是高电平还是低电平要根据实际电路来判断。

I.MX6U-ALPHA 开发板上有一个按键 KEY0,本篇文章我们将会编写代码通过这个 KEY0 按键来控制开发板上的蜂鸣器,按一下 KEY0 蜂鸣器打开,再按一下蜂鸣器就关闭

2、硬件原理图分析

本试验我们用到的硬件有:

1) LED 灯 LED0。
2)蜂鸣器。
3) 1 个按键 KEY0。

原理图

按键 KEY0 的原理图如图 15.2.1 所示:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
从图可以看出,按键 KEY0 是连接到 I.MX6U 的 UART1_CTS 这个 IO 上的, KEY0接了一个 10K 的上拉电阻,因此KEY0 没有按下的时候 UART1_CTS 应该是高电平,当 KEY0按下以后 UART1_CTS 就是低电平,采用轮询方式检测。

配置寄存器为GPIO

在这里插入图片描述

在这里插入图片描述

配置寄存器的电器属性

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

描述
bit 16 0 HYS 关闭
bit [15:14] 11 默认 22K 上拉
bit [13] 1 pull 功能
bit [12] 1 pull/keeper 使能
bit [11] 0 关闭开路输出
bit [7:6] 10 速度 100Mhz
bit [5:3] 000 关闭输出
bit [0] 0 低转换率

3、实验程序的编写

本次实在在上一次实验的基础上完成(蜂鸣器实验),我们把上一篇的代码复制一份,在上面做修改,重新创建 VSCode 工程,工作区名字为“key”,在工程目录的 bsp 文件夹中创建名为“key”和“gpio”两个文件夹。按键相关的驱动文件都放到“key”文件夹中,本次试验我们对 GPIO 的操作编写一个函数集合,也就是编写一个 GPIO驱动文件, GPIO 的驱动文件放到“gpio”文件夹里面。

新建 bsp_gpio.c 和 bsp_gpio.h 这两个文件,将这两个文件都保存到刚刚创建的 bsp/gpio 文件夹里面

3.1、bsp_gpio.h

#ifndef __BSP_KEY_H
#define __BSP_KEY_H

#include "imx6ul.h"

typedef enum _gpio_pin_direction {//枚举类型

    kGPIO_DigitalInput = 0U,  /*输入*/
    kGPIO_DigitalOutput = 1U,  /*输出*/

}gpio_pin_direction_t;

typedef struct _gpio_pin_config {

    gpio_pin_direction_t direction;  /*gpio方向:输入还是输出*/
    uint8_t  outputLogic;  /*如果是输出的话,默认输出低电平*/

}gpio_pin_config_t;


void gpio_init(GPIO_Type *base,int pin, gpio_pin_config_t *config);
int gpio_pinread(GPIO_Type *base,int pin);
void gpio_pinwrite(GPIO_Type *base,int pin,int value);


#endif // !__BSP_KEY_H

bsp_gpio.h 中定义了一个枚举类型 gpio_pin_direction_t 和结构体 gpio_pin_config_t,枚举类型 gpio_pin_direction_t 表示 GPIO 方向,输入或输出。结构体 gpio_pin_config_t 是 GPIO 的配置结构体,里面有 GPIO 的方向和默认输出电平两个成员变量

3.2、bsp_gpio.c

#include "bsp_gpio.h"


/*
 * @description : GPIO 初始化。
 * @param - base : 要初始化的 GPIO 组。
 * @param - pin : 要初始化 GPIO 在组内的编号。
 * @param - config : GPIO 配置结构体。
 * @return : 无
 */

void gpio_init(GPIO_Type *base,int pin, gpio_pin_config_t *config)
{
    if(config->direction == kGPIO_DigitalInput)  /*输入*/
    {
        base->GDIR &= ~(1 << pin);

    }
    else  /*输出*/
    {
        base->GDIR |= (1 << pin);
        gpio_pinwrite(&base,pin,config->outputLogic); /*默认输出电平*/
    }
    
}

/*
 * @description : 读取指定 GPIO 的电平值 。
 * @param – base : 要读取的 GPIO 组。
 * @param - pin : 要读取的 GPIO 脚号。
 * @return : 无
 */

int gpio_pinread(GPIO_Type *base,int pin)
{
    return (((base->DR) >> pin) & 0x1);
}

/*
 * @description : 指定 GPIO 输出高或者低电平 。
 * @param – base : 要输出的的 GPIO 组。
 * @param - pin : 要输出的 GPIO 脚号。
 * * @param – value : 要输出的电平, 1 输出高电平, 0 输出低低电平
 * @return : 无
 */

void gpio_pinwrite(GPIO_Type *base,int pin,int value)
{
    if(value == 0U)
    {
        base->DR &= ~(1U<<pin);  /*输出低电平*/

    }
    else
    {
        base->DR |= (1U << pin);  /*输出高电平*/
    }
    
}

文件 bsp_gpio.c 中有三个函数: gpio_init、 gpio_pinread 和 gpio_pinwrite,函数 gpio_init 用于初始化指定的 GPIO 引脚,最终配置的是 GDIR 寄存器,此函数有三个参数,这三个参数的含义如下:

参数 含义
base 要初始化的 GPIO 所属于的 GPIO 组,比如 GPIO1_IO18 就属于 GPIO1 组。
pin 要初始化 GPIO 在组内的标号,比如 GPIO1_IO18 在组内的编号就是 18。
config 要初始化的 GPIO 配置结构体,用来指定 GPIO 配置为输出还是输入。

函数 gpio_pinread 是读取指定的 GPIO 值,也就是读取 DR 寄存器的指定位,此函数有两个参数和一个返回值,参数含义如下:

参数 含义
base 要读取的 GPIO 所属于的 GPIO 组,比如 GPIO1_IO18 就属于 GPIO1 组。
pin 要读取的 GPIO 在组内的标号,比如 GPIO1_IO18 在组内的编号就是 18。
返回值 读取到的 GPIO 值,为 0 或者 1。

函数 gpio_pinwrite 是控制指定的 GPIO 引脚输入高电平(1)或者低电平(0),就是设置 DR 寄存器的指定位,此函数有三个参数,参数含义如下:

参数 含义
base 要设置的 GPIO 所属于的 GPIO 组,比如 GPIO1_IO18 就属于 GPIO1 组。
pin 要设置的 GPIO 在组内的标号,比如 GPIO1_IO18 在组内的编号就是 18。
value 要设置的值, 1(高电平)或者 0(低电平)。

我们以后就可以使用函数 gpio_init 设置指定 GPIO 为输入还是输出,使用函数 gpio_pinread和 gpio_pinwrite 来读写指定的 GPIO

接下来编写按键驱动文件,新建 bsp_key.c 和 bsp_key.h 这两个文件,将这两个文件都保存到刚刚创建的 bsp/key 文件夹里面

3.3、gpio_key.h

#ifndef __BSP_KEY_H
#define __BSP_KEY_H

#include "imx6ul.h"
#include "bsp_delay.h"

/*定义按键值  枚举 方便有多个按键 这里只有一个按键*/
enum keyvalue {
    KEY_NONE =0,
    KEY_VALUE ,
};

/*函数声明*/
void key_init();
int key_get_value();

#endif // !__BSP_KEY_H

bsp_key.h 文件中定义了一个枚举类型: keyvalue, 此枚举类型表示按键值, 因为 I.MX6UALPHA 开发板上只有一个按键,因此枚举类型里面只到 KEY0_VALUE

3.4、gpio_key.c(按键消抖delay完再读取状态值)

#include "bsp_key.h"

/*
 * @description : 初始化按键
 * @param : 无
 * @return : 无
 */

void key_init(void)
{
    gpio_pin_config_t key_config;

    /* 1、初始化 IO 复用, 复用为 GPIO1_IO18  .h文件找到这个宏*/
    IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);

    /* 2、、配置 UART1_CTS_B 的 IO 属性
     *bit 16:0 HYS 关闭
     *bit [15:14]: 11 默认 22K 上拉
     *bit [13]: 1 pull 功能
     *bit [12]: 1 pull/keeper 使能
     *bit [11]: 0 关闭开路输出
     *bit [7:6]: 10 速度 100Mhz
     *bit [5:3]: 000 关闭输出
     *bit [0]: 0 低转换率
    */                                              //0xf080演算过程如下图所示
   IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xf080);

   /* 3、初始化 GPIO GPIO1_IO18 设置为输入*/
   key_config.direction=kGPIO_DigitalInput;
   gpio_init(GPIO1,18,&key_config);
   //或者不用库函数 直接操作结构体里的寄存器:
   //GPIO1->GDIR &= ~(1<<18);

}

/*
* @description : 获取按键值
* @param : 无
* @return : 0 没有按键按下,其他值:对应的按键值
*/
int key_get_value(void)
{
    int ret =0;
    static unsigned char release =1; /*为1表示按键处于释放状态*/

    if((release == 1) &&  (gpio_pin_read(GPIO1,18) == 0))//释放状态下检测到按键被按下
    {
        delay(10);  /*按键消抖处理 大概10ms就够了*/
        release = 0;
        if(gpio_pin_read(GPIO1,18) == 0)//延时10ms读取还是0 说明按键按下是有效的
        {
            ret = KEY_VALUE;
        }

    }
    else if(gpio_pin_read(GPIO1,18) == 1)//没有被按下
    {
        ret =0;
        release = 1;
    }
    return ret;
}

程序中2、配置 UART1_CTS_B 的 IO 属性的演算过程:这里是引用
按键消抖原理:
在这里插入图片描述

bsp_key.c 中一共有两个函数: key_init 和 key_getvalue, key_init 是按键初始化函数,用来初始化按键所使用的 UART1_CTS 这个 IO。函数 key_init 先设置 UART1_CTS 复用为GPIO1_IO18,然后配置 UART1_CTS 这个 IO 为速度为 100MHz,默认 22K 上拉。最后调用函数 gpio_init 来设置 GPIO1_IO18 为输入功能。

函数 key_getvalue 用于获取按键值,此函数没有参数,只有一个返回值,返回值表示按键值,返回值为 0 的话就表示没有按键按下,如果返回其他值的话就表示对应的按键按下了。获取按键值其实就是不断的读取 GPIO1_IO18 的值,如果按键按下的话相应的 IO 被拉低,那么GPIO1_IO18 值就为 0,如果按键未按下的话 GPIO1_IO18 的值就为 1。此函数中静态局部变量release 表示按键是否释放。

3.5、main.c


#include "main.h"

int main() 
{
    int i=0;
    int keyvalue=0;   
    unsigned char led_status= OFF;
    unsigned char beep_status= OFF;



    clk_enable(); //使能外设时钟
    led_init(); //初始化LED
    init_beep();//初始化蜂鸣器
    key_init(); //初始化key
    
    while(1)
    {
        //按键控制蜂鸣器
        keyvalue = key_getvalue();
        if(keyvalue)//值为正 表示有效的按键值
        {
            switch (keyvalue)//按键状态
            {
	            case KEY_VALUE://这里只写了一种case
	                beep_status=!beep_status;
	                beep_switch(beep_status);
	                break;
	            
	            default:
	                break;
            }
        }
        
        i++;
        if(i==50)//50*10=500ms  灯亮灭一次
        {
            i=0;
            led_status=!led_status;
            led_switch(LED0,led_status);
        }

    }

    return 0;
}

main.c 函数先初始化 led 灯、蜂鸣器和按键,然后在 while(1)循环中不断的调用函数key_getvalue 来读取按键值,如果 KEY0 按下的话就打开/关闭蜂鸣器。 LED0 作为系统提示指示灯闪烁,闪烁周期大约为 500ms。

4、编译下载验证

4.1、连接脚本的编写

SECTIONS
{
    . = 0x87800000;
    .text :
    {
        obj/start.o
        *(.text)
    }
    .rodata ALIGN(4) : {*(.rodata*)}
    .data ALIGN(4) : {*(.data)}
    . = ALIGN(4) ;
    __bss_start = .;
    .bss ALIGN(4) : { *(.bss) *(COMMON)}
    __bss_end = .;
}

这里注意bss段需要四字节对其,否则会清除其他字段的内容,造成程序的崩溃

4.2、Makefile的编写

CROSS_COMPILE 	?= arm-linux-gnueabihf-
TARGET		  	?= key

CC 				:= $(CROSS_COMPILE)gcc
LD				:= $(CROSS_COMPILE)ld
OBJCOPY 		:= $(CROSS_COMPILE)objcopy
OBJDUMP 		:= $(CROSS_COMPILE)objdump

INCDIRS 		:= imx6ul \
				   bsp/clk \
				   bsp/led \
				   bsp/delay \
				   bsp/beep \
				   bsp/gpio \
				   bsp/key
				   			   
SRCDIRS			:= project \
				   bsp/clk \
				   bsp/led \
				   bsp/delay \
				   bsp/beep \
				   bsp/key \
				   bsp/gpio 
				   
				   
INCLUDE			:= $(patsubst %, -I %, $(INCDIRS))

SFILES			:= $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.s))
CFILES			:= $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))

SFILENDIR		:= $(notdir  $(SFILES))
CFILENDIR		:= $(notdir  $(CFILES))

SOBJS			:= $(patsubst %, obj/%, $(SFILENDIR:.s=.o))
COBJS			:= $(patsubst %, obj/%, $(CFILENDIR:.c=.o))
OBJS			:= $(SOBJS) $(COBJS)

VPATH			:= $(SRCDIRS)

.PHONY: clean
	
$(TARGET).bin : $(OBJS)
	$(LD) -Timx6ul.lds -o $(TARGET).elf $^
	$(OBJCOPY) -O binary -S $(TARGET).elf $@
	$(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis

$(SOBJS) : obj/%.o : %.s
	$(CC) -Wall -nostdlib -c -O2  $(INCLUDE) -o $@ $<

$(COBJS) : obj/%.o : %.c
	$(CC) -Wall -nostdlib -c -O2  $(INCLUDE) -o $@ $<
	
clean:
	rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)	

4.3、编译下载

使用 Make 命令编译代码,编译成功以后使用软件 imxdownload 将编译完成的 key.bin 文件下载到 SD 卡中,命令如下:

chmod 777 imxdownload              //给予 imxdownload 可执行权限,一次即可
./imxdownload key.bin  /dev/sdd    //烧写到 SD 卡中

烧写成功以后将 SD 卡插到开发板的 SD 卡槽中,然后复位开发板。如果代码运行正常的话 LED0 会以大约 500ms 周期闪烁, 按下开发板上的 KEY0 按键,蜂鸣器打开,再按下 KEY0按键,蜂鸣器关闭

具体烧写过程请参考程序烧写到SD卡详情

出现的问题(清除BSS段代码4字节对齐)

在这里插入图片描述

解决方法:

在这里插入图片描述
编译再次查看反汇编文件中BSS段的地址

按照四字节对齐原则,发现往后移动了,能被4整除
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ARM(IMX6U)裸机按键输入实验(BSP+SDK、GPIO输入与输出、按键消抖) 的相关文章

  • 从 Visual Studio 交叉编译 ARM7 代码

    是否可以从 Visual Studio 2008 2010 Express 或 Professional 编译 ARM7 如果是这样 可以指导我如何做吗 我读过有关 Yagarto 工具链的其他帖子 这一切是如何融入图片中的 我在这个领域非
  • 对 -finstrument-functions 的未定义引用

    我正在尝试跟踪内核函数并且我正在使用 finstrument functions这样做 但我收到未定义的参考错误 如下所示 arch arm kernel elf c 9 undefined reference to cyg profile
  • 抢占和上下文切换的区别

    一点介绍 我目前正在编写一个小型 读微型 RTOS 内核 它应该与内核中的大多数内容是一体的 然而 我找不到关于下面列出的一些事情的太多信息 这会很有帮助 除此之外 它实际上不是某种大学项目 而是我按照自己的意愿做的事情 回答所有问题的一个
  • 通用 ELF 中的重定位(EM:40)

    我尝试从 Ubuntu 交叉编译到Friendly arm 但出现了奇怪的错误 root kevin VirtualBox home kevin Desktop makef make ARCH arm CROSS COMPILE arm n
  • 如何创建具有自定义外设和内存映射的 QEMU ARM 机器?

    我正在为 Cortex M3 cpu 编写代码 并且正在使用以下命令执行单元测试qemu arm二进制 现在一切都很好 但我想知道我是否能够使用测试整个系统qemu system arm 我的意思是 我想为 qemu 编写自定义 机器 我将
  • Android 上原生的自修改代码

    我正在尝试在 Android 上制作一些自修改本机代码并在模拟器中运行它 我的示例基于 android ndk 中的 Hello JNI 示例 它看起来像这样 define NOPE LENGTH 4 typedef void FUNC v
  • 如何在 ARM 架构上从 RAM 运行代码

    我正在对 ARM Cortex R4 进行编程 并且有一些二进制文件 我想从 TCRAM 执行它们 只是为了看看性能的提升是否足够好 我知道我必须编写一个函数来将二进制文件复制到 RAM 这可以通过链接器脚本来完成 并且知道二进制文件的大小
  • ARM 的启动过程是怎样的?

    我们知道 对于X86架构 按下电源按钮后 机器开始执行0xFFFFFFF0处的代码 然后开始执行BIOS中的代码以进行硬件初始化 BIOS 执行后 它使用引导加载程序将操作系统映像加载到内存中 最后 操作系统代码开始运行 对于ARM架构 使
  • 将结构体偏移属性赋予汇编器

    如何将 C 结构体的偏移量发送到汇编代码 例如 在我的 C 代码中 typedef struct unsigned int a unsigned int b CMyStruct 我向 ASM 函数发送一个 CMyStruct 结构的指针 假
  • 用于 RHEL 的 gdb-multiarch

    我正在尝试寻找方法来运行gdb 多架构RHEL 中的命令 我已经安装了用于 ARM 处理的 QEMU 模拟器 我想安装GDB进行调试 我能够安装GDB 多体系结构在 Ubuntu 中运行命令成功 sudo apt get GDB multi
  • C 嵌入式应用程序中 time() 函数的问题

    我在用time 在 ARM 微控制器上 处理器一到达此函数就会重新启动 奇怪的是 当我处于调试模式时 代码运行得很好 但一旦我想将其应用到独立模式 我就会遇到重置 我是否忽略了什么 这个功能有替代品吗 代码部分是这样的 include
  • 读取和打印手臂组件中的字符串

    我正在使用 ARMSim 刚刚开始学习汇编 所以如果我看起来一无所知 请原谅我 但我正在尝试从输入文件中读取字符串 然后将其打印到输出屏幕 到目前为止我有 equ SWI Open 0x66 open a file equ SWI Clos
  • 源和目标具有不同的 EABI 版本

    我正在尝试使用 ARM 工具链编译 so 文件 但是我不断收到这个错误 错误 源对象的 EABI 版本为 0 但目标对象的 EABI 版本为 5 我无法更改工具链中的任何内容 因为我必须使用给定的工具链 我以前从未见过这个错误 我使用了这个
  • 尝试使用 qemu-arm 运行arm二进制文件时如何解决“加载共享库时出错”?

    我正在运行 Linux Mint 14 并安装了 qemu qemu user 和 gnueabi 工具链 我编译了 test carm linux gnueabi gcc test c o test 当我尝试跑步时qemu arm usr
  • 使用 Android NDK 使用 -fsigned-char 进行构建安全吗?

    为了与其他平台保持一致 我需要使用signed char在我正在处理的一些本机代码中 但默认情况下在Android NDK上char类型是unsigned 我尝试明确使用signed char类型 但它生成太多警告differ in sig
  • 在 Intel 机器上构建 Apple Silicon 二进制文件

    如何在 macOS 11 Intel 上编译 C 项目以在 Silicon 上运行 我当前的构建脚本很简单 configure make sudo make install 我尝试过使用 host and target标志与aarch64
  • Beaglebone Black 的 U-boot 无法构建 - 目标 CPU 不支持 THUMB 指令

    我正在尝试按照 Chris Simmonds 的 掌握嵌入式 Linux 编程 中的说明为 Beagle Bone Black 构建 u boot 我已经构建了交叉工具链 现在正在尝试使用该工具链构建 Das U boot 但由于不支持 T
  • DS-5:什么是 FVP、RTSM、基础模型、AEM 模型、快速模型、CADI?

    DS 5 模拟器使用了很多术语 如 FVP RTSM 快速模型 基础模型 AEM 模型 CADI Arm的文档中提供的解释不是很清楚 这些术语的含义是什么 作为 DS 5 的最终用户我应该关心哪些术语 Model 软件模拟的行业术语 就 A
  • 使用 NEON 优化 Cortex-A8 颜色转换

    我目前正在执行颜色转换例程 以便从 YUY2 转换为 NV12 我有一个相当快的函数 但没有我预期的那么快 主要是由于缓存未命中 void convert hd uint8 t orig uint8 t result uint32 t wi
  • gdb 不会从外部架构读取核心文件

    我正在尝试在 Linux 桌面上读取 ARM 核心文件 但似乎无法找出我的核心文件 有什么方法可以指示 gdb 我的核心文件是什么类型吗 file daemon daemon ELF 32 bit LSB executable ARM ve

随机推荐

  • Jupyter Notebook导入和删除虚拟环境

    在Jupyter Notebook中加载虚拟环境 比如现在我创建了一个虚拟环境名为pytorch 那么首先我先进入虚拟环境 activate pytorch Linux下需要使用source activate 然后运行 conda inst
  • Android init.rc整理

    AIL概述 init rc由AIL语言编写而成 可以参考system core init README md来学习AIL语法相关知识 不同Android版本关于AIL的说明存在一些细微差异 但基本语法和总的思路是不变的 往往我们可以先查看对
  • 2021哈工大机器翻译实验室经验贴(回忆版)

    哈工大机器翻译实验室 有两轮 一轮笔试 一轮面试 第一轮笔试题 根据本人的回忆 3道简答 5道编程题 60分钟 一 简答题 1 Windows下的软件Office 在Ubuntu环境下能否运行 说明理由 2 已知账户名和账户密码 说明登录到
  • 反射与线程间通讯

    反射 一 在运行状态中 对于任意一个类 都能够获取到这个类的所有属性和方法 对于任意一个对象 都能够调用它的任意一个方法和属性 包括私有的方法和属性 这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制 通俗点讲 通过
  • 设置linearlayout最大高度_数据中心:主要设备用房高度需求及建筑层高规划

    主要设备用房高度需求 数据中心主要设备用房为35KV开闭所 10KV开闭所 低压变配电房 动力 低压变配电房 IT UPS 柴油发电机组 冷冻机房 IT机房模块间等 35KV开闭所通常单独设置不在IT机房大楼内布置 本文不再讨论 各设备用房
  • Nginx服务优化

    配置nginx隐藏版本号 隐藏nginx版本号 避免安全漏洞泄漏 方法一 修改配置文件法 root www conf vim usr local nginx confnginx conf 17 http 18 include mime ty
  • 图解---散列表(hash表)的基本原理以及hash冲突(碰撞)--易懂版

    图解 散列表 hash表 的基本原理以及hash冲突 碰撞 易懂版 散列表为什么诞生 它用于做什么 先说说数组 数组的优点是查找比较快 但是添加和删除效率比较低 再说说链表 链表的优点是添加和删除效率比较快 相对于数组 但是遍历需要一个指针
  • 一种软件网络验证方式的实现 + 网络验证转本地验证的一种实现(附VC源码)...

    目前很多软件都是通过网络验证来实现的 一种比较流行的方式便是把服务器端 如验证网页 放在服务器上 软件为客户端 当软件注册或启动时通过网络与服务器端进行数据交换 重新实现验证的目的 个人觉得网络验证将是一种趋势 做得好的网络验证方式将是对软
  • Spring 源码 事件监听

    2019独角兽企业重金招聘Python工程师标准 gt gt gt spring 监听器 一 事件监听机制概述 二 事件监听机制结构 三 Spring监听机制架构 Spring的Application拥有发布事件并且注册事件监听器的能力 拥
  • python验证码识别MuggleOCR通用识别使用

    先来看看MuggleOCR简介 白嫖 这是一个为麻瓜设计的本地OCR模块 只需要简单几步操作即可拥有两大通用识别模块 让你在工作中畅通无阻 这套模型是基于 https github com kerlomz captcha trainer 训
  • JSP注释(4种)

    说到注释 相信大家肯定都不陌生 它是对程序代码的解释和说明 注释可以提高代码的可读性 让他人能够更加轻松地了解代码 从而提高团队合作开发的效率 在 JSP 中可以使用以下 4 种注释 HTML 注释 带有 JSP 表达式的注释 隐藏注释 脚
  • 登录和注册的基本实现,超简单!

    前序 相信有很多的人在刚刚做项目的实现 登录与注册功能的实现是基本的要求 要是刚刚开始写的小伙伴肯定会有很多的困惑 这里我介绍一下自己的写法 希望能帮到你 也希望能免费点个小 这里就以之前我写的一个为例 大家可以根据自己的规则来更改 一 登
  • python 短路法提高二叉堆插入效率

    在学习 problem solving with algorithms and data structure using python 中的二叉堆时 其插入数据方法是将这个数据放在列表的尾部 然后通过一次次与父节点进行比较 并且交换 实现顺
  • 用Log4j 2记录日志

    说明 maven工程中增加对Log4j 2的依赖 下面代码示例的maven工程中的pom xml文件中需要增加对Log4j 2的依赖
  • -moz-transform:rotate()

    目前越来越多的浏览器兼容CSS3标准了 就连IE浏览器老大哥也开始向CSS3低头 微软宣布IE9浏览器支持更多的CSS3属性 IE9更注重HTML5标准 不过CSS3里有一个使对象旋转的属性transform rotate 号称兼容CSS3
  • 2023高教社杯 国赛数学建模B题思路 - 多波束测线问题

    1 赛题 B 题 多波束测线问题 单波束测深是利用声波在水中的传播特性来测量水体深度的技术 声波在均匀介质中作匀 速直线传播 在不同界面上产生反射 利用这一原理 从测量船换能器垂直向海底发射声波信 号 并记录从声波发射到信号接收的传播时间
  • springboot定时任务

    1 配置 在主函数加 EnableScheduling 定时任务 package com biubiu import org springframework boot SpringApplication import org springf
  • golang的web框架Gin(一)---Gin的安装与初体验

    简介 1 1 介绍 Go世界里最流行的Web框架 Github上有32K star 基于httprouter开发的Web框架 中文文档齐全 简单易用的轻量级框架 Gin是一个golang的微框架 封装比较优雅 API友好 源码注释比较明确
  • [已解决]运行 ‘tomcat8‘ 出错: 无法打开调试器端口 (127.0.0.1:6672): java.net.SocketException

    解决 运行 tomcat8 出错 无法打开调试器端口 127 0 0 1 6672 java net SocketException 修改HTTP port端口号 没占用的端口号都可以 建议8000以上的数字 只要不是现在的端口号就可以 修
  • ARM(IMX6U)裸机按键输入实验(BSP+SDK、GPIO输入与输出、按键消抖)

    参考 Linux之ARM IMX6U 裸机按键输入实验 GPIO的输出与输入 作者 一只青木呀 发布时间 2020 08 17 21 43 37 网址 https blog csdn net weixin 45309916 article