当前位置: 首页 > article >正文

外部中断实验 #STM32F407

外部中断实验

此实验将外部中断配置为按键输入,通过按键输入触发外部中断,在外部中断里面实施相应的处理,具体功能:

  1. 按下KEY0,翻转LED0状态
  2. 按下KEY1,翻转LED1状态
  3. 按下KEY2,同时翻转LED0和LED1状态
  4. 按下KEY_UP,翻转BEEP状态

在中断回调函数里面使用delay进行消抖,导致中断是阻塞的,不符合中断快速执行的原则,linux中的按键处理是实验外部中断+定时器共同实现的,更具普遍性。

弄清楚:

  1. 中断在单片机中是如何实现的
  2. 外部中断处理流程(程序)
  3. 如何配置外部中断

main函数

main函数代码:

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/BEEP/beep.h"
#include "./BSP/EXTI/exti.h"int main(void)
{    HAL_Init();                             /* 初始化HAL库 */sys_stm32_clock_init(336, 8, 2, 7);     /* 设置时钟,168Mhz */delay_init(168);                        /* 延时初始化 */usart_init(115200);                     /* 串口初始化为115200 */led_init();                             /* 初始化LED */beep_init();                            /* 初始化蜂鸣器 */extix_init();                           /* 初始化外部中断输入 */LED0(0);                                /* 先点亮红灯 */while(1){delay_ms(1000);}
}

在main中主要做的是初始化,然后在while(1)里面死循环等待中断的到来,HAL_Init是使用HAL库必须调用的初始化函数;sys_stm32_clock_init、delay_init、usart_init这三个函数是正点原子编写的SYSTEM初始化函数,配置了系统时钟,延时函数,串口配置,实现单片机开发常用基本功能;然后调用led_init、beep_init、extix_init,初始化LED引脚、BEEP引脚、EXTI外部中断,KEY引脚初始化是在extix_init中进行调用的,故未在main中体现,完成所有的硬件初始化后,先将LED0点亮。

本次实验的核心是extix_init以及中断处理函数

exti.h

#ifndef __EXTI_H
#define __EXTI_H#include "./SYSTEM/sys/sys.h"/******************************************************************************************/
/* 引脚 和 中断编号 & 中断服务函数 定义 */ #define KEY0_INT_GPIO_PORT              GPIOE
#define KEY0_INT_GPIO_PIN               GPIO_PIN_4
#define KEY0_INT_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */
#define KEY0_INT_IRQn                   EXTI4_IRQn
#define KEY0_INT_IRQHandler             EXTI4_IRQHandler#define KEY1_INT_GPIO_PORT              GPIOE
#define KEY1_INT_GPIO_PIN               GPIO_PIN_3
#define KEY1_INT_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */
#define KEY1_INT_IRQn                   EXTI3_IRQn
#define KEY1_INT_IRQHandler             EXTI3_IRQHandler#define KEY2_INT_GPIO_PORT              GPIOE
#define KEY2_INT_GPIO_PIN               GPIO_PIN_2
#define KEY2_INT_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */
#define KEY2_INT_IRQn                   EXTI2_IRQn
#define KEY2_INT_IRQHandler             EXTI2_IRQHandler#define WKUP_INT_GPIO_PORT              GPIOA
#define WKUP_INT_GPIO_PIN               GPIO_PIN_0
#define WKUP_INT_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PA口时钟使能 */
#define WKUP_INT_IRQn                   EXTI0_IRQn
#define WKUP_INT_IRQHandler             EXTI0_IRQHandler

.h文件中将引脚相关的量宏定义,方便理解与更改,并且将中断函数重定义,如将EXTI2_IRQHandler定义成KEY2_INT_IRQHandler,方便自己编写维护

exti.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/BEEP/beep.h"
#include "./BSP/KEY/key.h"
#include "./BSP/EXTI/exti.h"/*** @brief       KEY0 外部中断服务程序* @param       无* @retval      无*/
void KEY0_INT_IRQHandler(void)
{HAL_GPIO_EXTI_IRQHandler(KEY0_INT_GPIO_PIN);         /* 调用中断处理公用函数 清除KEY0所在中断线 的中断标志位 */__HAL_GPIO_EXTI_CLEAR_IT(KEY0_INT_GPIO_PIN);         /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}/*** @brief       KEY1 外部中断服务程序* @param       无* @retval      无*/
void KEY1_INT_IRQHandler(void)
{ HAL_GPIO_EXTI_IRQHandler(KEY1_INT_GPIO_PIN);         /* 调用中断处理公用函数 清除KEY1所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */__HAL_GPIO_EXTI_CLEAR_IT(KEY1_INT_GPIO_PIN);         /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}/*** @brief       KEY2 外部中断服务程序* @param       无* @retval      无*/
void KEY2_INT_IRQHandler(void)
{ HAL_GPIO_EXTI_IRQHandler(KEY2_INT_GPIO_PIN);        /* 调用中断处理公用函数 清除KEY2所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */__HAL_GPIO_EXTI_CLEAR_IT(KEY2_INT_GPIO_PIN);        /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}/*** @brief       WK_UP 外部中断服务程序* @param       无* @retval      无*/
void WKUP_INT_IRQHandler(void)
{ HAL_GPIO_EXTI_IRQHandler(WKUP_INT_GPIO_PIN);        /* 调用中断处理公用函数 清除KEY_UP所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */__HAL_GPIO_EXTI_CLEAR_IT(WKUP_INT_GPIO_PIN);        /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}/*** @brief       中断服务程序中需要做的事情*              在HAL库中所有的外部中断服务函数都会调用此函数* @param       GPIO_Pin:中断引脚号* @retval      无*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{delay_ms(20);      /* 消抖 */switch(GPIO_Pin){case KEY0_INT_GPIO_PIN:if (KEY0 == 0){LED0_TOGGLE();  /* LED0 状态取反 */ }break;case KEY1_INT_GPIO_PIN:if (KEY1 == 0){LED1_TOGGLE();  /* LED1 状态取反 */ }break;case KEY2_INT_GPIO_PIN:if (KEY2 == 0){LED1_TOGGLE();  /* LED1 状态取反 */LED0_TOGGLE();  /* LED0 状态取反 */ }break;case WKUP_INT_GPIO_PIN:if (WK_UP == 1){BEEP_TOGGLE();  /* 蜂鸣器状态取反 */ }break;default : break;}
}/*** @brief       外部中断初始化程序* @param       无* @retval      无*/
void extix_init(void)
{GPIO_InitTypeDef gpio_init_struct;key_init();gpio_init_struct.Pin = KEY0_INT_GPIO_PIN;gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;            /* 下降沿触发 */gpio_init_struct.Pull = GPIO_PULLUP;HAL_GPIO_Init(KEY0_INT_GPIO_PORT, &gpio_init_struct);    /* KEY0配置为下降沿触发中断 */gpio_init_struct.Pin = KEY1_INT_GPIO_PIN;gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;            /* 下降沿触发 */gpio_init_struct.Pull = GPIO_PULLUP;HAL_GPIO_Init(KEY1_INT_GPIO_PORT, &gpio_init_struct);    /* KEY1配置为下降沿触发中断 */gpio_init_struct.Pin = KEY2_INT_GPIO_PIN;gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;            /* 下降沿触发 */gpio_init_struct.Pull = GPIO_PULLUP;HAL_GPIO_Init(KEY2_INT_GPIO_PORT, &gpio_init_struct);    /* KEY2配置为下降沿触发中断 */gpio_init_struct.Pin = WKUP_INT_GPIO_PIN;gpio_init_struct.Mode = GPIO_MODE_IT_RISING;             /* 上升沿触发 */gpio_init_struct.Pull = GPIO_PULLDOWN;HAL_GPIO_Init(WKUP_GPIO_PORT, &gpio_init_struct);        /* WKUP配置为上升沿触发中断 */HAL_NVIC_SetPriority(KEY0_INT_IRQn, 0, 2);               /* 抢占0,子优先级2 */HAL_NVIC_EnableIRQ(KEY0_INT_IRQn);                       /* 使能中断线4 */HAL_NVIC_SetPriority(KEY1_INT_IRQn, 1, 2);               /* 抢占1,子优先级2 */HAL_NVIC_EnableIRQ(KEY1_INT_IRQn);                       /* 使能中断线3 */HAL_NVIC_SetPriority(KEY2_INT_IRQn, 2, 2);               /* 抢占2,子优先级2 */HAL_NVIC_EnableIRQ(KEY2_INT_IRQn);                       /* 使能中断线2 */HAL_NVIC_SetPriority(WKUP_INT_IRQn, 3, 2);               /* 抢占3,子优先级2 */HAL_NVIC_EnableIRQ(WKUP_INT_IRQn);                       /* 使能中断线0 */}

extix_init函数,先调用key_init将各按键IO的时钟打开,然后再将按键IO模式配置为中断模式,最后配置各中断优先级及使能。

中断触发流程:(以KEY0为例)

当KEY0变为低电平时,会执行EXTI4_IRQHandler,不过此函数在exit.h里面被重定义成KEY0_INT_IRQHandler。

/*** @brief       KEY0 外部中断服务程序* @param       无* @retval      无*/
void KEY0_INT_IRQHandler(void)
{HAL_GPIO_EXTI_IRQHandler(KEY0_INT_GPIO_PIN);         /* 调用中断处理公用函数 清除KEY0所在中断线 的中断标志位 */__HAL_GPIO_EXTI_CLEAR_IT(KEY0_INT_GPIO_PIN);         /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}

在函数内先调用HAL_GPIO_EXTI_IRQHandler,这是HAL库内的公用处理函数,在其中会先进行一次中断标志位清除,然后调用回调函数(实际的处理函数)。
最后在KEY0_INT_IRQHandler再执行一次中断标志位清除,也就是说一次中断处理内总共执行了两次中断标志位清除,第一次是在HAL库的公用处理函数内,第二层是在自己编写的KEY0_INT_IRQHandler内,HAL库官方推荐这么写:在中断处理首末各执行一次清标志位,以防止误触发。

/*** @brief  This function handles EXTI interrupt request.* @param  GPIO_Pin Specifies the pins connected EXTI line* @retval None*/
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{/* EXTI line interrupt detected */if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET){__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);HAL_GPIO_EXTI_Callback(GPIO_Pin);}
}

先清除中断标志位,这是第一次清中断,然后执行回调函数HAL_GPIO_EXTI_Callback,这个回调函数是HAL库内的虚函数,需要自己重写,具体如下,正式开始执行逻辑处理

/*** @brief       中断服务程序中需要做的事情*              在HAL库中所有的外部中断服务函数都会调用此函数* @param       GPIO_Pin:中断引脚号* @retval      无*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{delay_ms(20);      /* 消抖 */switch(GPIO_Pin){case KEY0_INT_GPIO_PIN:if (KEY0 == 0){LED0_TOGGLE();  /* LED0 状态取反 */ }break;case KEY1_INT_GPIO_PIN:if (KEY1 == 0){LED1_TOGGLE();  /* LED1 状态取反 */ }break;case KEY2_INT_GPIO_PIN:if (KEY2 == 0){LED1_TOGGLE();  /* LED1 状态取反 */LED0_TOGGLE();  /* LED0 状态取反 */ }break;case WKUP_INT_GPIO_PIN:if (WK_UP == 1){BEEP_TOGGLE();  /* 蜂鸣器状态取反 */ }break;default : break;}
}

在回调函数中先延时20毫秒以消抖,根据不同的触发引脚在switch中执行相应的操作。

执行完这个回调函数后,就回到了KEY0_INT_IRQHandler内,然后执行第二次清中断标志位,一次外部中断处理就完成了。

实际上外部中断处理并不复杂,硬件初始化后,程序就等待中断的到来,IO电平变低,中断寄存器中的标志位被置高,程序会立刻跳转到EXTI4_IRQHandler这个函数中,这个函数其实就是一个地址,其在启动文件内定义,是一个固定的地址,用户需要在自己的代码中重写这个函数,在里面加上业务处理函数,若最后加上一个清中断标志位的函数,那该中断可以被重复触发,反之则只能触发一次,这个函数被执行完后,程序又立即跳转到触发中断前执行的位置,这就是STM32的外部中断处理。
HAL库对EXTI4_IRQHandler这个函数进行多次封装,所以变得复杂
在这里插入图片描述

在STM32中,几乎每个引脚都可以被配置为外部中断,那么问题来了,我怎么哪个引脚会执行哪个中断处理函数?这需要去查询单片机的参考手册
在这里插入图片描述

原来STM32是依靠引脚位来分割中断处理函数的,在启动汇编文件里面也一一对应
在这里插入图片描述
在这里插入图片描述

当中断引脚为0~4时,就使用:
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
当中断引脚为5~9时,就使用:
EXTI9_5_IRQHandler
当中断引脚为10~15时,就使用:
EXTI15_10_IRQHandler

在HAL库中如何编写外部中断

  1. 初始化IO引脚,将其配置为中断上升沿触发或下降沿触发
  2. 使用HAL_NVIC_SetPriority配置中断优先级并使用HAL_NVIC_EnableIRQ使能其中断号
  3. 重写EXTIx_IRQHandler,在内部加上HAL_GPIO_EXTI_IRQHandler和__HAL_GPIO_EXTI_CLEAR_IT
  4. 重写回调函数HAL_GPIO_EXTI_Callback,在内部编写具体业务处理代码

Linux中的外部中断+定时器实现按键大概处理思路

当按键按下,触发该按键对应的中断,在其中断处理函数内启动一个10ms的定时器中断,当10ms结束,定时器中断内再判断该按键电平是否按下,如按下,则将事件标志位置高,在正常程序内查询事件标志位以做出响应,如判断为 没按下,则说明可能是抖动电平,忽略此次中断触发。

中断会打断单片机当前执行的程序,因此不应在中断内过多耗费时间,使用中断来置各种标志位是常用的做法。

相关文章:

外部中断实验 #STM32F407

外部中断实验 此实验将外部中断配置为按键输入,通过按键输入触发外部中断,在外部中断里面实施相应的处理,具体功能: 按下KEY0,翻转LED0状态按下KEY1,翻转LED1状态按下KEY2,同时翻转LED0和LED1…...

kafka了解-笔记

文章目录 kafka快速上手Kafka介绍Kafka快速上手理解Kafka的集群工作机制Kafka集群的消息流转模型 Kafka客户端小型流转流程客户端工作机制 kafka快速上手 Kafka介绍 MQ的作用 MQ:MessageQueue,消息队列,是一种FIFO先进先出的数据结构&#…...

渗透利器:Burp Suite 联动 XRAY 图形化工具.(主动扫描+被动扫描)

Burp Suite 联动 XRAY 图形化工具.(主动扫描被动扫描) Burp Suite 和 Xray 联合使用,能够将 Burp 的强大流量拦截与修改功能,与 Xray 的高效漏洞检测能力相结合,实现更全面、高效的网络安全测试,同时提升漏…...

解决QTimer报“Timers cannot be started from another thread“错误

今天在Qt编程时,将QTimer在子线程里执行start()函数,遇到“Timers cannot be started from another thread”问题,使用了如下AI工具,进行查询:     提示词A:“C QTimer 如何跨线程”     提示词B&#…...

vant4 van-list组件的使用

<van-listv-if"joblist && joblist.length > 0"v-model:loading"loading":finished"finished":immediate-check"false"finished-text"没有更多了"load"onLoad">// 加载 const loading ref(fals…...

C++11新特性之weak_ptr智能指针

本节介绍最后一个智能指针——weak_ptr智能指针。 1.介绍 weak_ptr智能指针也是以模板类的方式实现的。同样定义在<memory>头文件&#xff0c;并位于std命名空间中。在使用前需包含这两条语句。 C11虽然将weak_ptr当做智能指针&#xff0c;但该类型通常不单独使用&#…...

LM Studio无设置代理,更改镜像源方法(MAC)

在macbook上使用LM Studio时发现总是加载失败&#xff0c;App也没有设置代理的地方&#xff0c;搜索了挺多解决方案&#xff0c;貌似官网再可以封补很多解决方案已经过时&#xff0c;最终找到一种替换镜像源的方法共享出来。 方便大家都能使用&#xff0c;不介绍命令行修改方式…...

js中的== 和 ===运算符的比较和区别(面试题)

和 运算符用于比较 JavaScript 值是否相等。 自动转换数据类型&#xff0c;允许不同类型值的比较。 进行严格相等比较&#xff0c;仅在值和数据类型都相同的情况下返回 true。NaN 仅在 比较中与自身相等&#xff0c;而在 比较中不相等。null 和 undefined 仅在 比较中相等。…...

通过客户端Chatbox或OpenwebUI访问识别不到本地ollama中的模型等问题的解决

Chatbox和Open WebUI 等无法获取到 Ollama里的模型&#xff0c;主要是由以下原因导致&#xff1a; Ollama 服务未正确暴露给 Docker 容器或客户端模型未正确下载或名称不匹配网络配置或权限问题 排查以上问题的思路首先排查ollama服务是否启动&#xff0c;然后再看端口号 使…...

C# 上位机--变量

C# 上位机--变量 在 C# 上位机开发领域&#xff0c;变量是构建程序逻辑的基础元素之一。它就像是一个容器&#xff0c;用于存储各种类型的数据&#xff0c;从简单的数值到复杂的对象。正确理解和使用变量&#xff0c;对于开发出高效、稳定且易于维护的上位机程序至关重要。本文…...

【Mastering Vim 2_01】开篇词:在 AI 时代持续深耕底层技术,做长期主义的坚定捍卫者

【最新版《Mastering Vim》封面&#xff0c;涵盖 Vim 9.0 版特性】 文章目录 1 背景&#xff1a;AI 时代的底层技术觉醒2 Vim&#xff1a;一款被严重低估的文本编辑神器3 聊聊 IT 人士的职业病4 进阶之道&#xff1a;构建完整的知识体系5 从 AI 时代的深耕与精进再谈长期主义 1…...

【JVM详解二】常量池

一、常量池概述 JVM的常量池主要有以下几种&#xff1a; class文件常量池运行时常量池字符串常量池基本类型包装类常量池 它们相互之间关系大致如下图所示&#xff1a; 每个 class 的字节码文件中都有一个常量池&#xff0c;里面是编译后即知的该 class 会用到的字面量与符号引…...

Leetcode - 149双周赛

目录 一、3438. 找到字符串中合法的相邻数字二、3439. 重新安排会议得到最多空余时间 I三、3440. 重新安排会议得到最多空余时间 II四、3441. 变成好标题的最少代价 一、3438. 找到字符串中合法的相邻数字 题目链接 本题有两个条件&#xff1a; 相邻数字互不相同两个数字的的…...

Java爬虫:打造高效的数据抓取利器——详解详情接口设计与实现

在当今数字化时代&#xff0c;数据如同黄金般珍贵。无论是企业进行市场调研、竞争对手分析&#xff0c;还是研究人员收集信息&#xff0c;数据的需求无处不在。而爬虫技术&#xff0c;作为一种高效的数据抓取手段&#xff0c;成为了众多开发者手中的利器。本文将深入探讨如何使…...

蓝桥杯K倍区间(前缀和与差分,取模化简)

输入 5 2 1 2 3 4 5 输出 6 思路&#xff1a;首先由连续子串和可以想用前缀和&#xff0c;由于加减法总和取模和分别取模结果不受影响&#xff0c;所以我们前缀和之后直接取模方便观察性质&#xff0c;本题前缀和&#xff1a;1&#xff0c;3&#xff0c;6&#xff0c;10&#…...

CEF132 编译指南 MacOS 篇 - depot_tools 安装与配置 (四)

1. 引言 在 CEF132&#xff08;Chromium Embedded Framework&#xff09;的编译过程中&#xff0c;depot_tools 扮演着举足轻重的角色。这套由 Chromium 项目精心打造的脚本和工具集&#xff0c;专门用于获取、管理和更新 Chromium 及其相关项目&#xff08;包括 CEF&#xff…...

Ubuntu 20.04 上安装 qBittorrent

qBittorrent 通过终端安装 系统更新系统升级在 Ubuntu 20.04 上添加 Qbittorent PPA系统更新Qbittorent 安装 Qbittorent 是一个开源且可免费使用的点对点比特流客户端。它体积小&#xff0c;不加载内存盘。众所周知&#xff0c;此应用程序可以在许多操作系统&#xff08;例如…...

iPhone 在华销量大幅下挫

iPhone在乔布斯时代缔造的神话在中国正逐渐走向没落&#xff0c;挤牙膏式的升级方式类似于诺基亚的N70系列&#xff0c;毫无新意的创新能力&#xff0c;求稳着陆的经营理念&#xff0c;工艺和美学不再独领风骚&#xff0c;甚至拍照领域和AI增强计算&#xff0c;折叠屏等技术领域…...

【Ubuntu VScode Remote SSH 问题解决】Resolver error: Error: XHR failed

1. 问题描述 VScode使用remote ssh 远程服务器&#xff0c;报错类似&#xff1a; [12:06:01.219] Downloading VS Code server locally... [12:06:01.310] Resolver error: Error: XHR failedat k.onerror (vscode-file://vscode-app/private/var/folders/g1/cvs2rnpx60qc3b4…...

在JVM的栈(虚拟机栈)中,除了栈帧(Stack Frame)还有什么?

在JVM的栈&#xff08;虚拟机栈&#xff09;中&#xff0c;除了栈帧&#xff08;Stack Frame&#xff09;&#xff0c;还有其他一些与方法调用相关的重要信息。栈的主要作用是存储方法调用的执行过程中的上下文信息&#xff0c;栈帧是其中最关键的组成部分。 栈的组成 栈帧&am…...

docker发布自己的镜像

官方node-red镜像&#xff1a; nodered/node-red - Docker Image 拉取v3版本&#xff1a; docker pull nodered/node-red:3.1.14 运行镜像&#xff1a; docker run --restartalways --privilegedtrue -d -p 1880:1880 -v node_red_data:/data --name mynodered nodered/n…...

【人工智能】解码语言之谜:使用Python构建神经机器翻译系统

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 神经机器翻译(NMT)是近年来机器翻译领域的一项重大突破。它利用深度学习模型,特别是循环神经网络(RNN)和Transformer网络,以端到端的…...

JavaScript数组类型详解

目录 一、数组的基本概念 二、数组的类型 1. 基本数组类型&#xff1a; 2. 数字数组&#xff1a; 3. 字符串数组&#xff1a; 4. 对象数组&#xff1a; 5. 类型数组&#xff08;TypedArray&#xff09;&#xff1a; 6. ArrayBuffer数组&#xff1a; 7. 类数组&#xff…...

【实战AI】利用deepseek 在mac本地部署搭建个人知识库

之前的文章中实现了本地通过ollma 部署deepseek R1&#xff1a;14b 模型&#xff0c;这里我想继续实现个人知识库&#xff0c;方便自己文档&#xff0c;数据的检索&#xff1b; 下载anythingLLM 地址&#xff1a; https://anythingllm.com/desktop 下载安装即可&#xff1b…...

Spring Boot 3.4 中 MockMvcTester 的新特性解析

引言 在 Spring Boot 3.4 版本中&#xff0c;引入了一个全新的 MockMvcTester 类&#xff0c;使 MockMvc 测试可以直接支持 AssertJ 断言。本文将深入探讨这一新特性&#xff0c;分析它如何优化 MockMvc 测试并提升测试的可读性。 Spring MVC 示例 为了演示 MockMvcTester 的…...

Express 中间件

在构建 Web 应用程序时&#xff0c;中间件&#xff08;Middleware&#xff09;扮演着至关重要的角色。它允许你定义一系列的函数来处理 HTTP 请求和响应过程中的各种任务。Express.js 是 Node.js 上最流行的框架之一&#xff0c;以其简洁且强大的中间件机制著称。本文将深入探讨…...

PyCharm结合DeepSeek-R1

PyCharm结合DeepSeek-R1&#xff0c;打造专属 AI 编程助手 在程序员的日常工作中&#xff0c;提高编程效率、快速解决代码问题是重中之重。今天给大家分享一个强强联合的组合 ——PyCharm 插件 Continue 与 DeepSeek-R1&#xff0c;它们能帮你打造出强大的个人 AI 编程助手。 …...

AJAX XML技术详解

AJAX XML技术详解 引言 随着互联网技术的不断发展,前端与后端之间的交互需求日益增长。AJAX(Asynchronous JavaScript and XML)技术应运而生,成为实现前后端分离、提高页面响应速度的关键技术之一。本文将详细介绍AJAX XML技术,包括其原理、应用场景、优缺点等内容。 A…...

【openresty服务器】:源码编译openresty支持ssl,增加service系统服务,开机启动,自己本地签名证书,配置https访问

1&#xff0c;openresty 源码安装&#xff0c;带ssl模块 https://openresty.org/cn/download.html &#xff08;1&#xff09;PCRE库 PCRE库支持正则表达式。如果我们在配置文件nginx.conf中使用了正则表达式&#xff0c;那么在编译Nginx时就必须把PCRE库编译进Nginx&#xf…...

Java+vue前后端分离项目集群部署

一、项目概述 假设我们有一个前后端分离的项目&#xff0c;前端使用React或Vue框架&#xff0c;后端使用Spring Boot或Node.js。我们将分别部署前端和后端到集群环境中。 二、准备工作 1. 代码准备&#xff1a;确保前端和后端代码已经开发完成&#xff0c;并通过本地测试。 2…...