【STM32RT-Thread零基础入门】 3. PIN设备(GPIO)的使用

硬件:STM32F103ZET6、ST-LINK、usb转串口工具、4个LED灯、1个蜂鸣器、4个1k电阻、2个按键、面包板、杜邦线

文章目录

  • 前言
  • 一、PIN设备介绍
    • 1. 引脚编号获取
    • 2. 设置引脚的输入/输出模式
    • 3. 设置引脚的电平值
    • 4. 读取引脚的电平值
    • 5. 绑定引脚中断回调函数
    • 6. 脱离引脚中断回调函数
    • 7. 使能中断
  • 二、任务1:LED灯双闪控制
    • 1. 任务描述
    • 2. 代码编写
  • 三、任务2:蜂鸣器控制(查询法)
    • 1. 任务描述
    • 2. 代码编写
    • 3. 测试
  • 四、任务3:蜂鸣器控制(中断回调法)
    • 1. 任务描述
    • 2. 代码编写
    • 3. 测试
  • 五、任务4:同时实现LED闪烁和按键控制喇叭
    • 1. 任务描述
    • 2. 代码编写
    • 3. 测试
  • 总结


前言

在嵌入式系统中,GPIO是最常用的一种设备,在RT-Thread操作系统中,把GPIO命名为PIN设备。


一、PIN设备介绍

RT-Thread通过PIN设备对芯片的GPIO引脚进行管理,应用程序可以通过其提供的一组PIN设备管理接口来操作GPIO,PIN设备管理接口如表所示

接口描述
rt_pin_get()获取引脚编号
rt_pin_mode()设置引脚模式
rt_pin_write()设置引脚电平
rt_pin_read()读取引脚电平
rt_pin_attach_irq()绑定引脚中断回调函数
rt_pin_irq_enable()使能引脚中断
rt_pin_detach_irq()脱离引脚中断回调函数

1. 引脚编号获取

引脚变化和芯片的引脚号不是同一概念。RT-Thread的PIN设备驱动程序把芯片的不同引脚赋予不同的编号,操作PIN设备时,需要使用引脚编号来指定对哪个引脚进行操作。
可通过三种方法获得引脚编号:
(1)API法
利用rt_pin_get() 函数来获取引脚编号,例如获取PD9的引脚编号,则可以使用
pin_number = rt_pin_get("PD.9")
(2)宏定义法
对于STM32芯片,可以使用GET_PIN(PORTx,PIN)获取引脚编号,如硬件的PD9用于驱动LED_R_PIN,则可以把宏LED_R_PIN定义为相应的引脚编号,如下:
#define LED_R_PIN GET_PIN(D, 9)
(3)查看驱动文件
在drivers/drv_gpio.c中,pin[]数组定义了硬件平台的GPIO引脚编号,通过查看该数组,得到引脚PD9的编号为57。
具体数组代码如下:

static const struct pin_index pins[] = 
{
#if defined(GPIOA)
   __STM32_PIN(0 ,  A, 0 ),
   __STM32_PIN(1 ,  A, 1 ),
   __STM32_PIN(2 ,  A, 2 ),
   __STM32_PIN(3 ,  A, 3 ),
   __STM32_PIN(4 ,  A, 4 ),
   __STM32_PIN(5 ,  A, 5 ),
   __STM32_PIN(6 ,  A, 6 ),
   __STM32_PIN(7 ,  A, 7 ),
   __STM32_PIN(8 ,  A, 8 ),
   __STM32_PIN(9 ,  A, 9 ),
   __STM32_PIN(10,  A, 10),
   __STM32_PIN(11,  A, 11),
   __STM32_PIN(12,  A, 12),
   __STM32_PIN(13,  A, 13),
   __STM32_PIN(14,  A, 14),
   __STM32_PIN(15,  A, 15),
#if defined(GPIOB)
   __STM32_PIN(16,  B, 0),
   __STM32_PIN(17,  B, 1),
   __STM32_PIN(18,  B, 2),
   __STM32_PIN(19,  B, 3),
   __STM32_PIN(20,  B, 4),
   __STM32_PIN(21,  B, 5),
   __STM32_PIN(22,  B, 6),
   __STM32_PIN(23,  B, 7),
   __STM32_PIN(24,  B, 8),
   __STM32_PIN(25,  B, 9),
   __STM32_PIN(26,  B, 10),
   __STM32_PIN(27,  B, 11),
   __STM32_PIN(28,  B, 12),
   __STM32_PIN(29,  B, 13),
   __STM32_PIN(30,  B, 14),
   __STM32_PIN(31,  B, 15),
#if defined(GPIOC)
   __STM32_PIN(32,  C, 0),
   __STM32_PIN(33,  C, 1),
   __STM32_PIN(34,  C, 2),
   __STM32_PIN(35,  C, 3),
   __STM32_PIN(36,  C, 4),
   __STM32_PIN(37,  C, 5),
   __STM32_PIN(38,  C, 6),
   __STM32_PIN(39,  C, 7),
   __STM32_PIN(40,  C, 8),
   __STM32_PIN(41,  C, 9),
   __STM32_PIN(42,  C, 10),
   __STM32_PIN(43,  C, 11),
   __STM32_PIN(44,  C, 12),
   __STM32_PIN(45,  C, 13),
   __STM32_PIN(46,  C, 14),
   __STM32_PIN(47,  C, 15),
#if defined(GPIOD)
   __STM32_PIN(48,  D, 0),
   __STM32_PIN(49,  D, 1),
   __STM32_PIN(50,  D, 2),
   __STM32_PIN(51,  D, 3),
   __STM32_PIN(52,  D, 4),
   __STM32_PIN(53,  D, 5),
   __STM32_PIN(54,  D, 6),
   __STM32_PIN(55,  D, 7),
   __STM32_PIN(56,  D, 8),
   __STM32_PIN(57,  D, 9),
   __STM32_PIN(58,  D, 10),
   __STM32_PIN(59,  D, 11),
   __STM32_PIN(60,  D, 12),
   __STM32_PIN(61,  D, 13),
   __STM32_PIN(62,  D, 14),
   __STM32_PIN(63,  D, 15),

2. 设置引脚的输入/输出模式

宏定义描述
PIN_MODE_OUTPUT推挽输出
PIN_MODE_OUTPUT_OD开漏输出,硬件需要外接上拉电阻
PIN_MODE_INPUT输入
PIN_MODE_INPUT_PULLUP上拉输入,引脚悬空时为高电平
PIN_MODE_INPUT_PULLDOWN下拉输入,引脚悬空时为低电平
引脚可通过以下函数设置输入/输出模式:

void rt_pin_mode(rt_base_t pin, rt_base_t mode)

pin:引脚编号
mode:输入/输出模式所对应的宏

#define LED_R_PIN GET_PIN(D, 9)
rt_pin_mode(LED_R_PIN, PIN_MODE_OUTPUT);

3. 设置引脚的电平值

设置函数如下:
void rt_pin_write(rt_base_t pin, rt_base_t value)
pin:引脚编号
value:高电平为PIN_HIGH;低电平为PIN_LOW

4. 读取引脚的电平值

设置函数如下:
int rt_pin_read(rt_base_t pin)
pin:引脚编号
返回值:高电平为PIN_HIGH;低电平为PIN_LOW

5. 绑定引脚中断回调函数

引脚作为中断输入时,需要设置引脚的中断触发方式,引脚的中断触发模式有5种,RT-Thread中分别有5个宏与之对应,具体如下:

宏定义描述
PIN_IQR_MODE_RISING上升沿触发
PIN_IQR_MODE_FALLING下降沿触发
PIN_IQR_MODE_RISING_FALLING双边沿触发
PIN_IQR_MODE_HIGH_LEVEL高电平触发
PIN_IQR_MODE_LOW_LEVEL低电平触发

当引脚产生中断时,通过中断回调函数响应中断。绑定中断回调函数到引脚后,引脚有中断发生,就会执行对应的中断回调函数。

具体函数如下:
rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args)
pin:引脚编号
mode:中断触发模式
hdr:中断回调函数指针,用户需要自定义这个函数
args:中断回调函数的参数,不需要设置时为RT_NULL
返回:绑定成功为RT_EOK;失败产生错误码

6. 脱离引脚中断回调函数

如不希望响应中断,或者想更换中断响应函数,则可以使用如下脱离引脚中断回调函数:
rt_err_t rt_pin_detach_irq(rt_int32_t pin)
pin:引脚编号
返回:脱离成功为RT_EOK;失败产生错误码

7. 使能中断

rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled)
pin:引脚编号
enable:PIN_IRQ_ENABLE(开启),PIN_IRQ_DISABLE(关闭)
返回:使能成功为RT_EOK;失败产生错误码

二、任务1:LED灯双闪控制

1. 任务描述

控制LED1、LED2轮流闪烁。通过本任务,学习PIN设备输出功能的设置方法。

在这里插入图片描述

2. 代码编写

在项目的main.c文件中,编写如下代码:

#include <rtthread.h>
#include <rtdevice.h>
#include "drv_common.h"
 
/* 定义左右转向灯的控制引脚 */
#define LED_L_PIN GET_PIN(D, 8)
#define LED_R_PIN GET_PIN(D, 9)

int main(void)
{
    /* 把引脚设置为推拉输出模式 */
    rt_pin_mode(LED_L_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED_R_PIN, PIN_MODE_OUTPUT);

    while (1){
        rt_pin_write(LED_L_PIN, PIN_HIGH);//灭左灯
        rt_pin_write(LED_R_PIN, PIN_LOW);//亮右灯
        rt_thread_mdelay(500);//延迟500毫秒
        rt_pin_write(LED_L_PIN, PIN_LOW);//亮左灯
        rt_pin_write(LED_R_PIN, PIN_HIGH);//灭右灯
        rt_thread_mdelay(500);
    }

    return RT_EOK;
}

三、任务2:蜂鸣器控制(查询法)

1. 任务描述

通过按键控制蜂鸣器的开关。当按键按下时,蜂鸣器响起;当按键松开时,蜂鸣器关闭。通过本任务,学习PIN设备输入功能的使用。
在这里插入图片描述
在这里插入图片描述

2. 代码编写

#include <rtthread.h>
#include <rtdevice.h>
#include "drv_common.h"

/* 定义左右转向灯的控制引脚 */
#define BEEP_PIN GET_PIN(A, 5)
#define KEY1_PIN GET_PIN(A, 0)

int main(void)
{
    /* 把蜂鸣器引脚设置为推拉模式 */
    rt_pin_mode(BEEP_PIN, PIN_MODE_OUTPUT);
    /* 把按键引脚设置为上拉输入模式 */
    rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP);

    while (1)
    {
        if(PIN_LOW==rt_pin_read(KEY1_PIN)){//按键按下
            rt_thread_mdelay(20);//延时去抖
            if(PIN_LOW==rt_pin_read(KEY1_PIN))
                rt_pin_write(BEEP_PIN, PIN_LOW);//蜂鸣器响
        }
        else
            rt_pin_write(BEEP_PIN, PIN_HIGH);//否则,蜂鸣器不响

        rt_thread_mdelay(300);//每0.3秒进行一次按键扫描
    }

    return RT_EOK;
}

3. 测试

按下按键,蜂鸣器发声,松开按键,停止发声,但是经过多次尝试发现,按键检测成功率较低,所以需要利用中断进行改进。

四、任务3:蜂鸣器控制(中断回调法)

1. 任务描述

通过按键控制蜂鸣器的开关。当按键按下时,蜂鸣器响起;当按键松开时,蜂鸣器关闭。通过本任务,掌握PIN设备中断回调函数的使用方法。

2. 代码编写

#include <rtthread.h>
#include <rtdevice.h>
#include "drv_common.h"

#define BEEP_PIN GET_PIN(A, 5)  //定义蜂鸣器的控制引脚
#define KEY1_PIN GET_PIN(A, 0)  //定义按键的控制引脚

/* 定义中断回调函数实现 */
void beep_on(void *args)
{
    /* 判断按键是否按下 */
    if(PIN_LOW==rt_pin_read(KEY1_PIN))
    {
        /* 按键按下,驱动蜂鸣器响  */
        rt_pin_write(BEEP_PIN, PIN_LOW);
        /* 等待按键台起  */
        while(PIN_LOW==rt_pin_read(KEY1_PIN));
        /* 关闭蜂鸣器  */
        rt_pin_write(BEEP_PIN, PIN_HIGH);
    }
}
int main(void)
{
    rt_pin_mode(BEEP_PIN, PIN_MODE_OUTPUT); //把蜂鸣器引脚设置为推拉模式
    rt_pin_write(BEEP_PIN, PIN_HIGH); //初始化蜂鸣器默认状态为不响

    /* 把按键引脚设置为上拉输入模式 */
    rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP);
    /* 绑定中断,下降沿触发模式,回调函数名为beep_on */
    rt_pin_attach_irq(KEY1_PIN, PIN_IRQ_MODE_FALLING, beep_on, RT_NULL);
    rt_pin_irq_enable(KEY1_PIN, PIN_IRQ_ENABLE); //使能中断

    return RT_EOK;
}

3. 测试

按下按键,蜂鸣器发声,松开按键,停止发声,经过多次尝试发现,按键检测成功率较高,所以中断法比查询法更具优势。

五、任务4:同时实现LED闪烁和按键控制喇叭

1. 任务描述

本任务功能为同时实现LED灯双闪功能和按键控制蜂鸣器的功能,要求两个功能不能相互影响,按键检测灵敏度要高,即每次发生按键按下的事件,程序都能成功检测该事件并开启蜂鸣器。

2. 代码编写

#include <rtthread.h>
#include <rtdevice.h>
#include "drv_common.h"

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

/* 定义左右转向灯的控制引脚 */
#define LED_L_PIN GET_PIN(D, 8)
#define LED_R_PIN GET_PIN(D, 9)
/* 定义蜂鸣器的控制引脚 */
#define BEEP_PIN GET_PIN(A, 5)
/* 定义按键的控制引脚 */
#define KEY1_PIN GET_PIN(A, 0)

/* 定义中断回调函数 */
void beep_on(void *args)
{
    /* 判断按键是否按下 */
    if(PIN_LOW==rt_pin_read(KEY1_PIN))
    {
        rt_pin_write(BEEP_PIN, PIN_LOW); //按按键下,驱动蜂鸣器响 
        while(PIN_LOW==rt_pin_read(KEY1_PIN)); //等待按键台起
        rt_pin_write(BEEP_PIN, PIN_HIGH); //关闭蜂鸣器
    }
}

int main(void)
{
    /* 把LED灯引脚设置为输出模式 */
    rt_pin_mode(LED_L_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED_R_PIN, PIN_MODE_OUTPUT);

    /* 把蜂鸣器引脚设置为推拉模式 */
    rt_pin_mode(BEEP_PIN, PIN_MODE_OUTPUT);
    /* 初始化蜂鸣器默认状态为不响 */
    rt_pin_write(BEEP_PIN, PIN_HIGH);

    /* 把按键引脚设置为上拉输入模式 */
    rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP);
    /* 绑定中断,下降沿触发模式,回调函数名为beep_on */
    rt_pin_attach_irq(KEY1_PIN, PIN_IRQ_MODE_FALLING, beep_on, RT_NULL);
    rt_pin_irq_enable(KEY1_PIN, PIN_IRQ_ENABLE); // 使能中断 

    while(1){
        rt_pin_write(LED_L_PIN, PIN_HIGH);//亮左灯
        rt_pin_write(LED_R_PIN, PIN_LOW);//灭右灯
        rt_thread_mdelay(500);//延迟500毫秒
        rt_pin_write(LED_L_PIN, PIN_LOW);//灭左灯
        rt_pin_write(LED_R_PIN, PIN_HIGH);//亮右灯
        rt_thread_mdelay(500);
    }

    return RT_EOK;
}

3. 测试

测试过程如下:
(1)系统启动后,观察左右转向灯是否轮流闪烁;
(2)当按下按键时,喇叭是否发出响声;
(3)当松开按键时,喇叭是否停止发出响声;
(4)一直按住按键不松开,观察灯的闪烁情况。
测试结果:
(1)系统启动后,左右转向灯轮流闪烁;
(2)当按下按键时,喇叭发出响声;
(3)当松开按键时,喇叭停止发出响声;
(4)一直按住按键不松开,喇叭发出响声,灯停止闪烁。


总结

从任务4测试结果中,我们可以发现,按键功能影响了闪灯的功能,说明两个功能还是没有很好地解耦,依然存在相互影响的情况。
出现这种情况,主要是由于中断回调函数中存在需要长时间等待的代码,当按键一直按住不松开的时候,中断回调函数由于一直停留在等待按键松开的地方而无法退出中断处理。而中断的优先级又高于main()线程的优先级,从而导致main()线程无法得到执行。
通常,我们不应该在中断回调函数中进行长时间的处理,中断回调函数应该只做一些必要的快速处理操作,而把长时间的处理操作放到线程中实现。
关于线程和优先级的概念,我们在下一节讲述。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/75853.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【算法题】螺旋矩阵IV (求解n阶折线蛇形矩阵)

一、问题的提出 n阶折线蛇形矩阵的特点是按照图1所示的方式排列元素。n阶蛇形矩阵是指矩阵的大小为nn&#xff0c;其中n为正整数。 题目背景 一个 n 行 n 列的螺旋矩阵可由如图1所示的方法生成&#xff0c;观察图片&#xff0c;找出填数规律。填数规则为从 1 开始填到 nn。 …

hive-无法启动hiveserver2

启动hiveserver2没有反应&#xff0c;客户端也无法连接( beeline -u jdbc:hive2://node01:10000 -n root) 报错如下 查看hive的Log日志&#xff0c;发现如下报错 如何解决 在hive的hive_site.xml中添加如下代码 <property><name>hive.server2.active.passive…

UDS (Unified Diagnostic Services)汽车诊断标准协议

作者博客主页 作者 : Eterlove 一笔一画&#xff0c;记录我的学习生活&#xff01;站在巨人的肩上Standing on Shoulders of Giants! 该文章为原创&#xff0c;转载请注明出处和作者 参考文献&#xff1a; 《道路车辆统一诊断服务(UDS) Road vehicles - Unified diagnostic s…

__ob__: Observer 后缀的数组的取值方式

开发中&#xff0c;经常从接口、父组件中&#xff0c;拿到数组然后给新的数组使用&#xff0c; 但是&#xff0c;有时候会发现带有 __ob__: Observer 后缀的数组&#xff0c;对这种数组来说&#xff0c;你是无法取到这个数组的值的&#xff0c; 而且&#xff0c;离谱的是consol…

【Rust】Rust学习 第十章泛型、trait 和生命周期

泛型是具体类型或其他属性的抽象替代。我们可以表达泛型的属性&#xff0c;比如他们的行为或如何与其他泛型相关联&#xff0c;而不需要在编写和编译代码时知道他们在这里实际上代表什么。 之后&#xff0c;我们讨论 trait&#xff0c;这是一个定义泛型行为的方法。trait 可以…

MAC环境,在IDEA执行报错java: -source 1.5 中不支持 diamond 运算符

Error:(41, 51) java: -source 1.5 中不支持 diamond 运算符 (请使用 -source 7 或更高版本以启用 diamond 运算符) 进入设置 修改java版本 pom文件中加入 <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin&l…

matlab使用教程(16)—图论中图的定义与修改

1.修改现有图的节点和边 此示例演示如何使用 addedge 、 rmedge 、 addnode 、 rmnode 、 findedge 、 findnode 及 subgraph 函数访问和修改 graph 或 digraph 对象中的节点和/或边。 1.1 添加节点 创建一个包含四个节点和四条边的图。s 和 t 中的对应元素用于指定每条…

什么是前端框架?怎么学习? - 易智编译EaseEditing

前端框架是一种用于开发Web应用程序界面的工具集合&#xff0c;它提供了一系列预定义的代码和结构&#xff0c;以简化开发过程并提高效率。 前端框架通常包括HTML、CSS和JavaScript的库和工具&#xff0c;用于构建交互式、动态和响应式的用户界面。 学习前端框架可以让您更高效…

Android 组件

TextView 文本框 用于显示文本的一个控件。文本的字体尺寸单位为 sp 。sp: scaled pixels(放大像素). 主要用于字体显示。 文本常用属性 属性名说明id为TextView设置一个组件id&#xff0c;根据id&#xff0c;我们可以在Java代码中通过 findViewById()的方法获取到该对象&…

vue实现a组件中数据变化b组件实时更新(ab组件无关联)

需求&#xff1a;A组件新增、编辑或者删除数据时&#xff0c;B组件实时更新数据 // src/utils/bus.js// bus.$emit(bridge-updated) 是在事件总线实例 bus 上触发了一个自定义事件 // data-updated&#xff0c;相当于发布了一个事件。// bus.$on(bridge-update…

面试热题(合并K个升序链表)

给定一个链表数组&#xff0c;每个链表都已经按升序排列。 请将所有链表合并到一个升序链表中&#xff0c;返回合并后的链表。 输入&#xff1a;lists [[1,4,5],[1,3,4],[2,6]] 输出&#xff1a;[1,1,2,3,4,4,5,6] 解释&#xff1a;链表数组如下&#xff1a; [1->4->5,1…

ssh做端口转发

问题 主机1能访问外网&#xff0c;主机2 不能访问外网外部主机想要访问主机2 解决 在主机1和主机2之间建隧道。 在主机1上做本地端口转发。可以用ssh来做本地端口转发(转发到远端)。 方法&#xff1a; 在&#xff08;本地&#xff09;主机1上执行 ssh -C -f -N -g -L 10.…

分类预测 | MATLAB实现GAPSO-BP遗传算法组合粒子群算法优化BP神经网络多输入分类预测

分类预测 | MATLAB实现GAPSO-BP遗传算法组合粒子群算法优化BP神经网络多输入分类预测 目录 分类预测 | MATLAB实现GAPSO-BP遗传算法组合粒子群算法优化BP神经网络多输入分类预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.分类预测 | MATLAB实现GAPSO-BP遗…

HTTP--Request详解

请求消息数据格式 请求行 请求方式 请求url 请求协议/版本 GET /login.html HTTP/1.1 请求头 客户端浏览器告诉服务器一些信息 请求头名称: 请求头值 常见的请求头&#xff1a; User-Agent&#xff1a;浏览器告诉服务器&#xff0c;我访问你使用的浏览器版本信息 可…

视频云存储平台EasyCVR视频汇聚接入AI算法接口,如何在检测中对视频流画框?

视频集中存储EasyCVR安防监控视频汇聚平台基于云边端智能协同架构&#xff0c;具有强大的数据接入、处理及分发能力&#xff0c;平台可支持多协议接入&#xff0c;包括市场主流标准协议与厂家私有协议及SDK&#xff0c;如&#xff1a;国标GB28181、RTMP、RTSP/Onvif、海康Ehome…

C++面向对象编程

C面向对象编程 面向对象基础 实体&#xff08;属性&#xff0c;行为&#xff09; ADT(abstract data type) 面向对象语言的四大特征&#xff1a;抽象&#xff0c;封装&#xff08;隐藏&#xff09;&#xff0c;继承&#xff0c;多态。 访问限定符&#xff1a;public 共有的…

el-tree通过default-expand-all动态控制展开/折叠

1、如下图通过勾选框动态控制展开/折叠&#xff0c;全选/清空 2、实现方式如下&#xff1a;定义key&#xff0c;监听checked2修改treeKey&#xff0c;重新渲染tere&#xff1b;附加全选和清空。 <div class"tree"><el-checkbox v-model"checked1"…

一场大火烧毁了印度的芯片梦 | 百能云芯

谈起印度的半导体发展史&#xff0c;鲜为人知的是&#xff0c;该国曾有可能成为全球半导体制造业的重要中心。然而&#xff0c;一个意外的事件彻底改变了历史进程&#xff0c;让印度错失了超越台积电的机会。 01半导体制造潜力 在高科技行业&#xff0c;也许很多人都不看好印度…

数据结构-栈和队列

目录 栈的概念 栈的使用 ​编辑 模拟实现栈 中缀表达式转后缀表达式 括号匹配 出栈入栈次序匹配 队列概念 队列的使用 栈的概念 栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素的操作.进行数据插入和删除操作的一端称为栈顶,;另一端称为栈底.栈中的数据…

vue 获取设备指纹

import Fingerprint2 from fingerprintjs2 // async 异步请求 async getFingerprint () {return new Promise((resolve, reject) > {Fingerprint2.getV18({}, (result, components) > {resolve(result)})})}, // 获取用户sessionasync getSession () {/* 等待获取设备指纹…