STM32学习之EXTI外部中断(以对外式红外传感器 / 旋转编码器为例)

news2025/3/1 9:19:26

中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序处理完成后又返回原来被暂停的位置继续运行

中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源

中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回

在这里插入图片描述

STM32中断:
68个可屏蔽中断通道包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设;
使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级

中断由于硬件限制,只能跳到固定的地址去执行程序,所以要一个存地址的表,就叫中断向量表

NVIC(嵌套中断向量控制器)基本结构:
在这里插入图片描述
统一分配中断优先级和管理中断,是一个内核外设,是CPU的一个小助手。n代表一个外设可能会占用多个中断通道,但 CPU某时只看一个,想象成CPU是医生,左侧的中断是排队的病人,NVIC是叫号系统,分配看病优先级并负责管理谁去见医生(后来的更紧急也可以抢占优先)

每个中断有16个优先级,为了把这个优先级再区分抢占优先级响应优先级,就需要对这16个优先级进行分组。NVIC的中断优先级由优先级寄存器的4位(四位二进制可以表示0~15的数,对应16个优先级,这个优先级的数是值越小,优先级越高,0就是最高优先级)决定,这4位可以进行切分,分为高n位的抢占优先级低4-n位的响应优先级

抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队。

当两个中断同时响应时,抢占优先级谁高谁先中断; 当抢占优先级相同时,谁的响应优先级高谁先响应;
当抢占优先级相同时,低响应优先级已经进入中断函数,高响应优先级不可打断低优先级)
抢占优先级和响应优先级均相同的,按中断号排队

STM32的中断不存在先来后到的排队方式,在任何时候都是优先级高的先响应

//
EXTI 学习
EXTI(Extern Interrupt)外部中断
EXTI可以监测指定GPI0口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序

支持的触发方式: 上升沿/下降沿/双边沿/软件触发
支持的GPIO口: 所有GPIO口都可以触发中断,但相同的Pin不能同时触发中断
通道数: 16个GPIO Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
触发响应方式: 中断响应/事件响应

EXTI基本结构:
在这里插入图片描述
AFIO主要用于引脚复用功能的选择和重定义;
在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择
(此处应结合点路结构深入学习,暂且先到这,插个眼,先学会用再杀回来)

一点补充:
AFIO中断引脚选择
我们刚才这里说了EXTI模块只有16个GPIO的通道。但这里每个GPIO外设都有16个引脚,如果每个引脚占用一个通道,EXTI的16个通道显然就不够用了。所以在这里会有一个AFIO中断引脚选择的电路模块。

这个AFIO就是一个数据选择器,它可以在这前面3个GPIO外设各自的16个引脚里选择其中一个连接到后面的EXTI的通道里,所以这前面说相同的Pin不能同时触发中断。因为对于PA0、PB0、PC0这些通过AFIO选择之后,只有其中一个能接到EXTI的通道0上。同理,PA1、PB1、PC1这些也只能有一个接到通道1上。这就是所有GPIO口都能触发中断,但相同的pin不能同时触发中断的原因

///
对外式红外传感器
在这里插入图片描述
DO数字输出端接到B14端口,当挡光片或者编码盘在这个对射式红外传感器中间经过时,DO就会输出电平跳变的信号,然后这个电平跳变的信号触发STM32 PB14号口的中断,我们在中断函数里执行变量++的程序,然后主循环里调用OLED显示这个变量

记住上面提到的EXIT结构图,从左往右一条路

具体步骤就是:

第一步,配置RCC,把我们这里涉及的外设的时钟都打开,不打开时钟外设是没法工作的。

第二步,配置GPIO ,选择我们的端口为输入模式。

第三步,配置AFIO ,选择我们用的这一路GPIO ,连接到后面的EXTI。

第四步,配置EXTI,选择边沿触发方式,比如上升沿、下降沿或者双边沿,还有选择触发响应方式,可以选择中断响应和事件响应。当然我们一般都是中断响应。

第五步,配置NVIC,给这个中断选择一个合适的优先级。通过NVIC,外部中断信号就能进入CPU。了。这样CPU才能收到中断信号,才能跳转到中断函数里执行中断程序。

这五步就是外部中断的配置流程,这里涉及的外设比较多

要点强调:
GPIO_EXTILineConfig就是我们本节外部中断需要用的函数,调用这个函数就可以配置AFIO 的数据选择器来选择我们想要的中断引脚,这个函数虽然是GPIO 开头,但实际上里面操作的是AFIO 的寄存器
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
//将外部中断的14号线映射到GPIOB,即选择PB14为外部中断引脚
第一个参数GPIO_PortSource,选择某个GPIO外设作为外部中断源,这个参数可以是GPIO_PortSourceGPIOx,其中x可以是A到G。
第二个参数是GPIO_PinSource,指定配置的外设中断线。这个参数可以是GPIO_PinSourcex,其中x可以是0到15。

当执行完这个函数后,AFIO 的第14个数据选择器就拨好了。其中输入端被拨到了GPIOB 外设上,对应的就是PB14号引脚,输出端固定连接的是EXTI的第14个中断线路

在这里插入图片描述


直接复制上节OLED工程
在Hardware目录下添加CountSensor.c/.h

#ifndef __COUNT_SENSOR_H
#define __COUNT_SENSOR_H

void CountSensor_Init(void);
uint16_t CountSensor_Get(void);

#endif

#include "stm32f10x.h"                  // Device header

uint16_t CountSensor_Count;				//全局变量,用于计数

/**
  * 函    数:计数传感器初始化
  * 参    数:无
  * 返 回 值:无
  */
void CountSensor_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启GPIOB的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//开启AFIO的时钟,外部中断必须开启AFIO的时钟
		
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);	//将PB14引脚初始化为上拉输入
	
	/*AFIO选择中断引脚*/
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
	//将外部中断的14号线映射到GPIOB,即选择PB14为外部中断引脚
	//AFIO外设中断引脚选择配置就完成了
	
	/*EXTI初始化*/
	EXTI_InitTypeDef EXTI_InitStructure;//定义结构体变量
	EXTI_InitStructure.EXTI_Line = EXTI_Line14;					
	//选择配置外部中断的14号线
	
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;					
	//指定外部中断线使能
	
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;			
	//指定外部中断线为中断模式
	
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;		
	//指定外部中断线为下降沿触发
	
	EXTI_Init(&EXTI_InitStructure);								
	//将结构体变量交给EXTI_Init,配置EXTI外设
	
	/*NVIC中断分组*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置NVIC为分组2
	//即抢占优先级范围:0~3,响应优先级范围:0~3
	//此分组配置在整个工程中仅需调用一次
	//若有多个中断,可以把此代码放在main函数内,while循环之前
	//若调用多次配置分组的代码,则后执行的配置会覆盖先执行的配置
	
	/*NVIC配置*/
	NVIC_InitTypeDef NVIC_InitStructure;//定义结构体变量
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	//选择配置NVIC的EXTI15_10线
	
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//指定NVIC线路使能
	
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	//指定NVIC线路的抢占优先级为1
	
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	//指定NVIC线路的响应优先级为1
	
	NVIC_Init(&NVIC_InitStructure);
	//将结构体变量交给NVIC_Init,配置NVIC外设
}

/**
  * 函    数:获取计数传感器的计数值
  * 参    数:无
  * 返 回 值:计数值,范围:0~65535
  */
uint16_t CountSensor_Get(void)
{
	return CountSensor_Count;
}

/**
  * 函    数:EXTI15_10外部中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void EXTI15_10_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line14) == SET)		//判断是否是外部中断14号线触发的中断
	{
		/*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
		if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)
		{
			CountSensor_Count ++;					//计数值自增一次
		}
		EXTI_ClearITPendingBit(EXTI_Line14);		//清除外部中断14号线的中断标志位
													//中断标志位必须清除
													//否则中断将连续不断地触发,导致主程序卡死
	}
}


int main(void)
{
	/*模块初始化*/
	OLED_Init();			//OLED初始化
	CountSensor_Init();		//计数传感器初始化
	
	/*显示静态字符串*/
	OLED_ShowString(1, 1, "Count:");	//1行1列显示字符串Count:
	
	while (1)
	{
		OLED_ShowNum(1, 7, CountSensor_Get(), 5);		//OLED不断刷新显示CountSensor_Get的返回值
	}
}

我们用的是下降沿触方法,在移开挡光片的时候触发中断,数值加1;
改下这里变为上升沿出发,遮挡的时候数字加1;
如果这里改成上升沿下降沿都触发,就是遮挡和移开的时候都加1。

/
旋转编码器

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

#ifndef __ENCODER_H
#define __ENCODER_H

void Encoder_Init(void);
int16_t Encoder_Get(void);

#endif

#include "stm32f10x.h"                  // Device header

int16_t Encoder_Count;					//全局变量,用于计数旋转编码器的增量值

/**
  * 函    数:旋转编码器初始化
  * 参    数:无
  * 返 回 值:无
  */
void Encoder_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);		//开启GPIOB的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);		//开启AFIO的时钟,外部中断必须开启AFIO的时钟
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);						//将PB0和PB1引脚初始化为上拉输入
	
	/*AFIO选择中断引脚*/
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);//将外部中断的0号线映射到GPIOB,即选择PB0为外部中断引脚
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);//将外部中断的1号线映射到GPIOB,即选择PB1为外部中断引脚
	
	/*EXTI初始化*/
	EXTI_InitTypeDef EXTI_InitStructure;						//定义结构体变量
	EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;		//选择配置外部中断的0号线和1号线
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;					//指定外部中断线使能
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;			//指定外部中断线为中断模式
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;		//指定外部中断线为下降沿触发
	EXTI_Init(&EXTI_InitStructure);								//将结构体变量交给EXTI_Init,配置EXTI外设
	
	/*NVIC中断分组*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);				//配置NVIC为分组2
																//即抢占优先级范围:0~3,响应优先级范围:0~3
																//此分组配置在整个工程中仅需调用一次
																//若有多个中断,可以把此代码放在main函数内,while循环之前
																//若调用多次配置分组的代码,则后执行的配置会覆盖先执行的配置
	
	/*NVIC配置*/
	NVIC_InitTypeDef NVIC_InitStructure;						//定义结构体变量
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;			//选择配置NVIC的EXTI0线
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				//指定NVIC线路使能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	//指定NVIC线路的抢占优先级为1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;			//指定NVIC线路的响应优先级为1
	NVIC_Init(&NVIC_InitStructure);								//将结构体变量交给NVIC_Init,配置NVIC外设

	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;			//选择配置NVIC的EXTI1线
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				//指定NVIC线路使能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	//指定NVIC线路的抢占优先级为1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;			//指定NVIC线路的响应优先级为2
	NVIC_Init(&NVIC_InitStructure);								//将结构体变量交给NVIC_Init,配置NVIC外设
}

/**
  * 函    数:旋转编码器获取增量值
  * 参    数:无
  * 返 回 值:自上此调用此函数后,旋转编码器的增量值
  */
int16_t Encoder_Get(void)
{
	/*使用Temp变量作为中继,目的是返回Encoder_Count后将其清零*/
	/*在这里,也可以直接返回Encoder_Count
	  但这样就不是获取增量值的操作方法了
	  也可以实现功能,只是思路不一样*/
	int16_t Temp;
	Temp = Encoder_Count;
	Encoder_Count = 0;
	return Temp;
}

/**
  * 函    数:EXTI0外部中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void EXTI0_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line0) == SET)		//判断是否是外部中断0号线触发的中断
	{
		/*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
		if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
		{
			if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)		//PB0的下降沿触发中断,此时检测另一相PB1的电平,目的是判断旋转方向
			{
				Encoder_Count --;					//此方向定义为反转,计数变量自减
			}
		}
		EXTI_ClearITPendingBit(EXTI_Line0);			//清除外部中断0号线的中断标志位
													//中断标志位必须清除
													//否则中断将连续不断地触发,导致主程序卡死
	}
}

/**
  * 函    数:EXTI1外部中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void EXTI1_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line1) == SET)		//判断是否是外部中断1号线触发的中断
	{
		/*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
		if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
		{
			if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)		//PB1的下降沿触发中断,此时检测另一相PB0的电平,目的是判断旋转方向
			{
				Encoder_Count ++;					//此方向定义为正转,计数变量自增
			}
		}
		EXTI_ClearITPendingBit(EXTI_Line1);			//清除外部中断1号线的中断标志位
													//中断标志位必须清除
													//否则中断将连续不断地触发,导致主程序卡死
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何使用 ChatGPT Prompts 写学术论文?

第 1 部分:学术写作之旅:使用 ChatGPT Prompts 进行学术写作的结构化指南 踏上学术写作过程的结构化旅程,每个 ChatGPT 提示都旨在解决特定方面,确保对您的主题进行全面探索。 制定研究问题: “制定一个关于量子计算的社会影响的研究问题,确保清晰并与您的研究目标保持一…

HuatuoGPT-o1:基于40K可验证医学问题的两阶段复杂推理增强框架,通过验证器引导和强化学习提升医学模型的推理能力

HuatuoGPT-o1:基于40K可验证医学问题的两阶段复杂推理增强框架,通过验证器引导和强化学习提升医学模型的推理能力 论文大纲理解1. 确认目标2. 分析过程3. 实现步骤4. 效果展示 解法拆解全流程提问俩阶段详细分析 论文:HuatuoGPT-o1, Towards …

07-计算机网络面试实战

07-计算机网络面试实战 计算机网络面试实战 为什么要学习网络相关知识? 对于好一些的公司,计算机基础的内容是肯定要面的,尤其是 30k 以内的工程师,因为目前处于的这个级别肯定是要去写项目的,还没上升到去设计架构的高…

Github - 如何提交一个带有“verified”标识的commit

Github - 如何提交一个带有“verified”标识的commit 前言(Why) 今天在Github上浏览某项目的commit记录的时候发现,有的commit记录带有verified绿色标识,有的带有橘色的Unverified标识,还有的什么都不显示。 既然我是根正苗红的作者(bushi)…

中式美学|中国红电商展台咒语分享

使用工具:千鹿AI 咒语:geometric shape podium,Red background, and rose gold elements on the right side, Chinese New Year atmosphere, simple and clean light luxury scene, minimalist style, minimalist stage design, studio lighting, minim…

中断系统 | 高优先级抢占原理

参考视频 入坑单片机 – [12_2]中断系统 [12_3]底层解析 51内核中断抢占性 如果我们把51单片机的5个中断都打开的话,CPU对与中断的响应是从上到下的。 如果INT0 和TIM0 的中断同时发生,CPU会有执行INT0的服务函数,然后再执行TIM0的函数。…

探寻AI Agent:开启知识图谱自动生成新篇章(17/30)

一、AI Agent 与知识图谱:智能时代的双雄 在当今科技飞速发展的时代,人工智能如同一股汹涌澎湃的浪潮,正以前所未有的力量重塑着我们的世界。而在这股浪潮中,AI Agent 与知识图谱无疑是两颗最为璀璨的明珠,它们各自发挥…

CA系统的设计(CA证书生成,吊销,数字签名生成)

CA系统概述 CA认证系统是一种基于公钥密码基础设施(PKI)的信息安全技术,它可以为网络通信双方提供身份认证、数据加密、数字签名等功能。CA认证系统的核心是证书授权机构(CA),它负责为用户(节点…

phpstudy2018问题(技巧)总结

目录 安装介绍注意操作 问题phpstudy待续、更新中...... 安装 软件下载(新人推荐2018 版本phpstudy ) 官网下载 https://www.xp.cn/download.html 介绍 系统服务------开机自启 非服务模式------开机不自启 搭建好环境, 此时服务器与客户端同时存在 …

USB2.0之描述符(Descriptors)

文章目录 描述符(Descriptors)设备描述符(Device Descriptors)配置描述符(Configuration Descriptors)接口描述符(Interface Descriptors)端点描述符(Endpoint Descriptors)字符串描述符(String Descriptors) 参考资料 描述符(Descriptors) 描述符是设备本身各项信息的集合&…

从授权校验看SpringBoot自动装配

背景 最近需要实现一个对于系统的授权检测功能,即当SpringBoot应用被启动时,需要当前设备是否具有有效的的授权许可信息,若无则直接退出应用。具体的实现方案请继续看下文。 环境 Ruoyi-Vue SpringBoot3 RuoYi-Vue: 🎉 基于Spr…

jmeter分布式启动

https://www.cnblogs.com/qtclm/p/11082081.html 1、代理机:输入“ipconfig”,找到IP地址,在Jmeter/bin/jmeter.properties设置remote host 启动jmeter server 1、控制机:输入“ipconfig”,找到IP地址,在J…

SpringCloud源码-Ribbon

一、Spring定制化RestTemplate,预留出RestTemplate定制化扩展点 org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration 二、Ribbon定义RestTemplate Ribbon扩展点功能 org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguratio…

目标检测,语义分割标注工具--labelimg labelme

1 labelimg labelimg可以用来标注目标检测的数据集, 提供多种格式的输出, 如Pascal Voc, YOLO等。 1.1 安装 pip install labelimg1.2 使用 命令行直接输入labelimg即可打开软件主界面进行操作。 使用非常简单, 不做过细的介绍&#xff0…

pd虚拟机 [po] Parallels Desktop 20 激活 for Mac [jie] 安装教程【支持M芯片】

文章目录 效果图一、下载软件二、安装运行⚠️注意事项:1、前往 系统设置–> 隐私与安全性 –> 完整磁盘访问权限,中允许终端:2、安装运行【ParallelsDesktop-20.1.2-55742.dmg】,运行【安装.app】3、将【Patch】文件夹拖到…

windows11安装软件时选择文件路径只有桌面及子文件夹怎么解决方法

现象:当桌面文件夹、文件总数超过一定数量时(具体个数不详,个人猜测可能跟系统架构或内存有关)点击应用程序中“浏览”按钮时,只能看到桌面文件夹,其他盘符看不到。一个巨硬愚蠢的bug。定期清理下桌面吧,习惯下载到桌面…

SpringCloud源码-openFeign

LoadBalancer默认只有nacos服务发现器 openFeign与springcloud loadbalancer的结合点 openFeign通过spring cloud loadbalancer进行负载均衡,spring cloud loadbalancer通过discovery client获取nacos的机器列表,然后底层进行负载均衡。

开源架构中的数据库选择优化版

上一篇文章推荐: 开源架构学习指南:文档与资源的智慧锦囊(New) 我管理的社区推荐:【青云交社区】和【架构师社区】 推荐技术圈福利社群:点击快速加入 开源架构中的数据库选择优化版 一、引言二、关系型开源…

Listwise 排序之 LambdaRank:最大化 NDCG 的秘诀

Listwise系列相关文章(置顶) 1.Listwise 模型时间线梳理 2.Listwise 排序之 LambdaRank:最大化 NDCG 的秘诀 引言 LambdaRank 是一种用于排序学习(Learning to Rank, LTR)的模型,特别适用于推荐系统和信息…

汉化SecureCRT9.1

我个人觉得,SecureCRT是最好用的ssh远程工具软件,但是这个软件没有中文版本,我这种英文水平糟糕的人用起来,略有不便,因为一直没有在网上找到合适的汉化版本,于是有自己做一个汉化版本的计划。 前几日&…