stm32四种方式精密控制步进电机
在搭建完clion的开发环境后,我决定重写之前的项目并优化完善,争取做出完全可落地的东西,也结合要写的论文内容一同学习下去。
因此,首当其冲的就是回到步进电机控制领域,把之前使用中断溢出进行步进电机控制的方案进行进一步优化。
目前使用中断溢出控制步进电机,有如下几个问题:
1.有时电压不稳定/电压太低,电机转不起来。
2.电机频率太高有响声,频率太低有气声,需要设置一个合理的范围值,同时不会因为数值的事情用很长时间去调试电机。
3.电机转向会出问题,或是反应不过来,或是接线有问题。
4.只能通过改变psc预分频器和arr自动重装载值去改变电机速度,无法通过改变占空比的方式控制电机,且驱动器上合适的细分数需要自己调节。
因此我这次使用了四种方式控制电机
1.模拟io控制
2.中断溢出控制
3.定时器比较通道控制
4.定时器pwm控制
芯片选用的是stm32f103zet6,全程未使用编码器/PID,电机驱动器用的是最简单常见的TB6612,主打一个好复现且好上手。电机控制比较稳定,可以根据自己需要选择控制方式。本篇文章使用的硬件和这两篇文章里介绍的一致:
stm32精密控制步进电机(基础篇)_stm32 步进电机-CSDN博客
stm32精密控制步进电机(升级篇)_stm32微机控制-CSDN博客
与之前不同的是我把使能引脚也加上了(PA7控制ENA-;ENA+,PUL+和DIR+接到5v或3.3v引脚),这里可以用万用表验证一下。
四种方式的详细代码我放在了github上,都使用了freertos系统,欢迎移步下载,可以试着点个star,谢谢:
https://github.com/Re-restart/four_ways_to_control_stepper
怎么完成电机接线
Aout1与Aout2(A+与A-)是同相,Bout1与Bout2(B+与B-)是同相。把同相的两条线拧在一起,会发现难以拧动电机;或是直接测试电阻,两个引脚之间电阻极大,那这两个电机引脚就是同相的。
如果驱动器是9v的,建议接12v电源+DCDC,这样电流会更加稳定,电机抖动现象就可以减轻很多。如果外部不是稳定的开关电源,只靠板子和12v电池供电,最好不要设置板子的脉冲和方向引脚为推挽上拉,设置推挽会抢占一些电压,可能给驱动器分配的电压就变少了。
进行电机微秒级延时
众所周知,HAL_Delay和Osdelay都是毫秒延时。这种情况下需要一个定时器去负责微秒的延时,我使用的方式是把TIM4里的预分频器psc设为71,定时器时钟源频率是72MHZ,定时器输入时钟频率就是:
把arr值设置为65535,这样读取出来的寄存器值就是1微秒增加一次,最后比较出的值小于要执行的微秒数就可以。
void delay_us(uint16_t us)
{__HAL_TIM_SET_COUNTER(&htim4, 0); // 清零了 TIM4 的计数器,因此不再需要 start_time 变量来记录初始时间while (__HAL_TIM_GET_COUNTER(&htim4) < us); // 等待计数达到 us
}
另外还有一种做法是设置一个volatile变量(代表这个变量不要被编译器优化,可能在外设或中断中改变它的值,每次访问该变量时需要从内存中读取),start_time是用来读取中断的初始值的,和清零函数__HAL_TIM_SET_COUNTER(&htim4, 0)的作用一致。
为了处理溢出问题,可以利用无符号整数的特性,即(uint16_t)(delay_time-start_time)。
volatile uint16_t start_time=0;
volatile uint16_t delay_time=0;void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{/* USER CODE BEGIN Callback 0 *//* USER CODE END Callback 0 */if (htim->Instance == TIM4) {delay_time++;}/* USER CODE BEGIN Callback 1 *//* USER CODE END Callback 1 */
}void delay_us(uint16_t us)
{start_time=delay_time;while((uint16_t)(delay_time-start_time)<us);
}
按键进行外部中断控制
先新建系统任务控制函数,利用两个板子自带的按钮做外部中断,控制电机左转/右转。这个按键逻辑是默认flag=1,flag_key=1。按下按键后,防抖10s,并把flag和flag_key全置为0。
按键松开后,按键引脚恢复到之前的电平,因为也不会同时摁,就用flag,flag_key和按键引脚松开后的状态共同判断,区分电机状态并执行stepper_turn函数。
void StartDefaultTask(void *argument)
{/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */for(;;) {if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) {osDelay(10);flag = 0;}if(flag == 0 && flag_key == 1) {if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) {stepper_turn(120,360,32,CW);}flag = 1;}
/if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4) == GPIO_PIN_RESET) {osDelay(10);flag_key = 0;}if(flag_key == 0 && flag == 1) {if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4) == GPIO_PIN_SET) {stepper_turn(120,360,32,CCW);}}flag_key = 1;}
电机引脚初始设置
中断和模拟io控制电机都是PA5为PUL-控制引脚,PA6为DIR-控制引脚,PA7为ENA-控制引脚。输入捕获和pwm用的都是TIM3-Channel1,也就是PC6。不是不能设置推挽引脚哈,这个主要看外界的电压状态,如果外界供电稳定,引脚电压也够,那全设置推挽上拉也没什么问题。但是我需要大多数情况下都没问题的引脚配置,所以会设置开漏不上拉,只有PA7是推挽上拉。
/*Configure GPIO pins : PA5 PA6 */GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/*Configure GPIO pin : PA7 */GPIO_InitStruct.Pin = GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5|GPIO_PIN_6, GPIO_PIN_RESET);/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);//void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(timHandle->Instance==TIM3){/* USER CODE BEGIN TIM3_MspPostInit 0 *//* USER CODE END TIM3_MspPostInit 0 */__HAL_RCC_GPIOC_CLK_ENABLE();/**TIM3 GPIO ConfigurationPC6 ------> TIM3_CH1*/GPIO_InitStruct.Pin = GPIO_PIN_6;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);__HAL_AFIO_REMAP_TIM3_ENABLE();/* USER CODE BEGIN TIM3_MspPostInit 1 *//* USER CODE END TIM3_MspPostInit 1 */}}
模拟IO控制步进电机
通过编写stepper_turn函数控制模拟IO。这里面注意一下,ENA-引脚是推挽上拉状态,初始为SET,此时ENA-引脚电平为0v。
已知ENA+引脚电平是3.3v或5v,构成使能信号有效,电机pulse引脚开始翻转,电机转动。电机停止转动时,使能引脚恢复到reset状态。
电机转动的时候,使能引脚PA7其实是有电压的,2v~3v的样子。可以看作这个引脚是来激活驱动器的。如果讨厌这个使能引脚/板子引脚资源比较少,可以不接使能+和使能-引脚,PUL+和DIR+接到5v或3.3v引脚,PUL-和DIR-用于控制电机即可。
tim是周期,angle是角度,subdivide是电机驱动器的细分数,dir是电机旋转方向。
void stepper_turn(int tim,float angle,float subdivide,uint8_t dir)
{int n,i;/*根据细分数求得步距角被分成多少个方波*/n=(int)(angle/(1.8/subdivide));if(dir==CW) //顺时针{HAL_GPIO_WritePin(MOTOR_DIR_GPIO_PORT,MOTOR_DIR_PIN,HIGH);}else if(dir==CCW)//逆时针{HAL_GPIO_WritePin(MOTOR_DIR_GPIO_PORT,MOTOR_DIR_PIN,LOW);}/*开使能*/HAL_GPIO_WritePin(MOTOR_EN_GPIO_PORT,MOTOR_EN_PIN,GPIO_PIN_SET);/*模拟方波*/for(i=0;i<n;i++){HAL_GPIO_WritePin(MOTOR_PUL_GPIO_PORT,MOTOR_PUL_PIN,LOW);delay_us(tim/2);HAL_GPIO_WritePin(MOTOR_PUL_GPIO_PORT,MOTOR_PUL_PIN,HIGH);delay_us(tim/2);}/*关使能*/HAL_GPIO_WritePin(MOTOR_EN_GPIO_PORT,MOTOR_EN_PIN,GPIO_PIN_RESET);
}
中断溢出控制步进电机
和之前文章里的类似,这里不再详细讲解。逻辑稍微改良了一下,不再通过读取引脚状态计数,而是每溢出两次,脉冲引脚翻转一次。这是因为中断需要保持实时性,需要尽量处理简单的逻辑。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{/* USER CODE BEGIN Callback 0 *//* USER CODE END Callback 0 */if (htim->Instance == TIM2) {HAL_IncTick();}/* USER CODE BEGIN Callback 1 */if(htim->Instance==TIM5){pulse=pulse+1;if(pulse%2==0){Pulse_Toggle();}__HAL_TIM_CLEAR_IT(&htim5, TIM_IT_UPDATE);}/* USER CODE END Callback 1 */
}
中断跟其他方式相比,比较容易出现失控,所以启动之前需要先关闭中断,停止电机运行,然后再打开电机驱动和使能。
for(;;) {if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) {osDelay(10);flag = 0;}if(flag == 0 && flag_key == 1) {if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) {StopMotor();Dir_CW();StartMotor();HAL_GPIO_WritePin(MOTOR_EN_GPIO_PORT,MOTOR_EN_PIN,GPIO_PIN_SET);}flag = 1;}if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4) == GPIO_PIN_RESET) {osDelay(10);flag_key = 0;}if(flag_key == 0 && flag == 1) {if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4) == GPIO_PIN_SET) {StopMotor();Dir_CC();StartMotor();HAL_GPIO_WritePin(MOTOR_EN_GPIO_PORT,MOTOR_EN_PIN,GPIO_PIN_SET);//打开使能}flag_key = 1;}if(pulse > 3200) {pulse = 0;StopMotor();BlinkLEDs();}}
然后我把比较重要的操作都封装成函数,这样便于调用。HAL_TIM_Base_MspDeInit用于关闭定时器中断,HAL_TIM_Base_MspInit打开定时器中断。
void StopMotor(void) {HAL_TIM_Base_MspDeInit(&htim5);HAL_GPIO_WritePin(MOTOR_EN_GPIO_PORT,MOTOR_EN_PIN,GPIO_PIN_RESET);
}void StartMotor(void) {HAL_TIM_Base_MspInit(&htim5);
}
定时器比较通道控制步进电机
在这里通过PC6引脚控制步进电机,不需要考虑什么引脚推挽还是开漏的问题,直接设置通道就可以了。如果这里不加延时,电机会一直转。我设置过像HAL_TIM_OC_DelayElapsedCallback一样的回调函数去按照比较通道执行顺序计数,但是并不好用,会发现初始的库文件并没有弱定义这个函数,遂放弃这种方式。
void stepper_turn(uint8_t dir)
{if(dir==CW) //顺时针{HAL_GPIO_WritePin(MOTOR_DIR_GPIO_PORT,MOTOR_DIR_PIN,HIGH);}else if(dir==CCW)//逆时针{HAL_GPIO_WritePin(MOTOR_DIR_GPIO_PORT,MOTOR_DIR_PIN,LOW);}/*开使能*/HAL_GPIO_WritePin(MOTOR_EN_GPIO_PORT,MOTOR_EN_PIN,GPIO_PIN_SET);/* 启动比较输出并使能中断 */HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_1);for(uint16_t i=0;i<2000;i++) {delay_us(1000);}stepper_stop();
}void stepper_stop(void) {HAL_TIM_OC_Stop_IT(&htim3,TIM_CHANNEL_1);HAL_GPIO_WritePin(MOTOR_EN_GPIO_PORT,MOTOR_EN_PIN,GPIO_PIN_RESET);
}
在定时器内设置速度,使能比较通道后关闭中断,需要中断时再去调用并打开中断。这里面电机速度计算过程如下,可算得电机速度周期是1.375ms。
void MX_TIM3_Init(void)
{/* USER CODE BEGIN TIM3_Init 0 *//* USER CODE END TIM3_Init 0 */TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};TIM_OC_InitTypeDef sConfigOC = {0};/* USER CODE BEGIN TIM3_Init 1 *//* USER CODE END TIM3_Init 1 */htim3.Instance = TIM3;htim3.Init.Prescaler = 899;htim3.Init.CounterMode = TIM_COUNTERMODE_UP;htim3.Init.Period = 109;htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;if (HAL_TIM_Base_Init(&htim3) != HAL_OK){Error_Handler();}sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK){Error_Handler();}if (HAL_TIM_OC_Init(&htim3) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK){Error_Handler();}sConfigOC.OCMode = TIM_OCMODE_TOGGLE;sConfigOC.Pulse = 0;sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN TIM3_Init 2 *//*使能比较通道*/TIM_CCxChannelCmd(TIM3,TIM_CHANNEL_1,TIM_CCx_ENABLE);HAL_TIM_OC_Stop_IT(&htim3,TIM_CHANNEL_1);/* USER CODE END TIM3_Init 2 */HAL_TIM_MspPostInit(&htim3);}
定时器PWM方式控制步进电机
其实就是把使能比较通道方式换成pwm通道。 sConfigOC.Pulse/(arr+1)这个值是占空比,可以把它设置在tim周期的50%到80% 之间。
但其实这种方式个人认为并不利于电机控制,因为如果想旋转需要的角度,需要设置主从定时器和输入触发源,而且cubeide会初始化很多配置,其中就包括psc,arr和pulse占空比,不利于程序本身的赋值。而且开启PWM时,必须同时开启AFIO时钟!!必须配置对应引脚为复用输出!HAL_TIM_MspPostInit(&htim3);就是这个定时器引脚定义函数,所以下面的定时器配置里是HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);,假如设置HAL_TIM_PWM_Stop,在freertos里再打开,是驱动不了步进电机的。。。。。这件事情卡了我很久。
好处是它和输出比较方式都随时转换方向,而且不需要考虑推挽还是开漏引脚,控制是真的很稳。
void MX_TIM3_Init(void)
{/* USER CODE BEGIN TIM3_Init 0 *//* USER CODE END TIM3_Init 0 */TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};TIM_OC_InitTypeDef sConfigOC = {0};/* USER CODE BEGIN TIM3_Init 1 *//* USER CODE END TIM3_Init 1 */htim3.Instance = TIM3;htim3.Init.Prescaler = 719;htim3.Init.CounterMode = TIM_COUNTERMODE_UP;htim3.Init.Period = tim_per-1;htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;if (HAL_TIM_Base_Init(&htim3) != HAL_OK){Error_Handler();}sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK){Error_Handler();}if (HAL_TIM_PWM_Init(&htim3) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK){Error_Handler();}sConfigOC.OCMode = TIM_OCMODE_PWM1;sConfigOC.Pulse = tim_per/2;sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN TIM3_Init 2 */HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);/* USER CODE END TIM3_Init 2 */HAL_TIM_MspPostInit(&htim3);}
几种方式的优缺点总结
个人认为这里面设置最简单,相对来说最可控,占用单片机内部资源最少的还是模拟io方式,延时的问题通过定时器TIM4解决后,大大增加了可控的精度。而且实际测试时,12v供电它的引脚电压基本能稳到10v,且电机发热时一样可运行,也不需要特定的gpio驱动,是和模拟i2c一样的,比较好的方式,之后做项目可能会多用这种电机控制方式。
如果特定项目需要快速切换电机方向,建议选择定时器比较通道控制,或以PWM方式控制电机。
另外,发现TIM1是没有办法设置TIM_OCMODE_TOGGLE方式的,只能设置TIM_OCMODE_TIMING,也查了相关手册,并没介绍这个地方,之后可能会继续完善看看这是怎么回事。

相关文章:
stm32四种方式精密控制步进电机
在搭建完clion的开发环境后,我决定重写之前的项目并优化完善,争取做出完全可落地的东西,也结合要写的论文内容一同学习下去。 因此,首当其冲的就是回到步进电机控制领域,把之前使用中断溢出进行步进电机控制的方案进行…...
C++11 智能指针:unique_ptr、shared_ptr和weak_ptr 功能特性 模拟实现
文章目录 unique_ptr功能和特性使用场景make_unique模拟实现 shared_ptr功能和特性使用场景make_shared模拟实现 weak_ptr C 中智能指针都是 RAII(Resource Acquisition Is Initialization)机制的典型应用,在构造时获取资源,在析构…...
Spring Boot启动过程?
目录 1. 启动入口 2. SpringApplication 初始化 3. 准备环境 4. 创建应用上下文(ApplicationContext) 5. 准备应用上下文 6. 刷新应用上下文 7. 启动 Web 服务器(若为 Web 应用) 8. 发布 ApplicationStartedEvent 事件 9. 执行 Runner 10. 发布 ApplicationReady…...
2025年软考报名费用是多少?全国费用汇总!
软考报名时间终于确定了!想要参加2025年软考的同学们注意啦!特别是那些一年只有一次考试机会的科目,千万不要错过哦!这里为大家整理了各地的报名时间、科目、费用等信息,快来看看吧! 一、2025年软考时间安…...
算法-二叉树篇06-二叉树的最大深度
二叉树的最大深度 力扣题目链接 题目描述 给定一个二叉树 root ,返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 解题思路 一样可以使用递归的思想,代码也十分简洁,计算出两个子树的深度取最大加…...
git merge -s ours ...的使用方法
当我们在自己的feature branch上开发时,并且已经commit,push了好几次 同时develop分支也commit , push了好几次, 如下图所示 这个时候就不能直接将feature branch上的改动 pull request到develop上面,因为develop基线已经不一样了…...
面试之《react hooks在源码中是怎么实现的?》
要深入理解 React Hooks 在源码中的实现,可以从以下几个关键方面来剖析: 核心数据结构 在 React 内部,使用链表来管理每个函数组件的 Hooks。每个 Hook 对应一个节点,这些节点通过 next 指针相连。以下是简化后的 Hook 节点结构…...
数字可调控开关电源设计(论文+源码)
1 设计要求 在本次数字可调控开关电源设计过程中,对关键参数设定如下: (1)输入电压:DC24-26V,输出电压:12-24(可调); (2)输出电压误差…...
【DeepSeek】【GPT-Academic】:DeepSeek集成到GPT-Academic(官方+第三方)
目录 1 官方deepseek 1.1 拉取学术GPT项目 1.2 安装依赖 1.3 修改配置文件中的DEEPSEEK_API_KEY 2 第三方API 2.1 修改DEEPSEEK_API_KEY 2.2 修改CUSTOM_API_KEY_PATTERM 2.3 地址重定向 2.4 修改模型参数 2.5 成功调用 2.6 尝试添加一个deepseek-r1参数 3 使用千帆…...
DeepSeek R1 + 飞书机器人实现AI智能助手
效果 TFChat项目地址 https://github.com/fish2018/TFChat 腾讯大模型知识引擎用的是DeepSeek R1,项目为sanic和redis实现,利用httpx异步处理流式响应,同时使用buffer来避免频繁调用飞书接口更新卡片的网络耗时。为了进一步减少网络IO消耗&…...
Android移动应用开发实践-1-下载安装和简单使用Android Studio 3.5.2版本(频频出错)
一、下载安装 1.Android Studio3.5.2下载地址:Android Studio3.5.2下载地址 其他版本下载地址:其他版本下载地址 2.安装教程(可以多找几个看看) 安装 | 手把手教你Android studio 3.5.2安装(安装教程)_a…...
Rk3568驱动开发_驱动编写和挂载_2
1.字符驱动介绍: 字符驱动:按照字节流镜像读写操作的设备,读写数据分先后顺序,例如:点灯、按键、IIC、SPI、等等都是字符设备,这些设备的驱动叫字符驱动设备 Linux应用层如何调用驱动: 字符设…...
验证码识别:使用OCR技术识别图形验证码详解
文章目录 一、基本原理二、所需工具2.1 Python环境2.2 图像处理库2.3 OCR引擎2.4 Python接口 三、实现步骤3.1 获取验证码图像3.2 图像预处理3.3 使用OCR进行字符识别3.4 基本 OCR 识别样例 四、提高识别准确率的方法4.1 字符分割4.2 使用深度学习模型4.3 数据增强4.4 集成多个…...
剑指 Offer II 033. 变位词组
comments: true edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%20Offer%20II%20033.%20%E5%8F%98%E4%BD%8D%E8%AF%8D%E7%BB%84/README.md 剑指 Offer II 033. 变位词组 题目描述 给定一个字符串数组 strs ,将 变位词 组合在一起…...
【苍穹外卖】问题笔记
【DAY1 】 1.VCS找不到 好吧,发现没安git 接着发现安全模式有问题,点开代码信任此项目 2.导入初始文件,全员爆红 好像没maven,配一个 并在设置里设置好maven 3.启用注解,见新手苍穹 pom.xml改lombok版本为1.1…...
微信小程序 - 自定义实现分页功能
概述 在微信小程序项目中,没有现成的分页器组件,所以需要自定义实现分页功能 自定义实现分页功能 1、index.json {"usingComponents": {"van-button": "vant/weapp/button/index"} }这里使用 Vant Weapp 中的 van-butt…...
1.1部署es:9200
安装es:root用户: 1.布署java环境 - 所有节点 wget https://d6.injdk.cn/oraclejdk/8/jdk-8u341-linux-x64.rpm yum localinstall jdk-8u341-linux-x64.rpm -y java -version 2.下载安装elasticsearch - 所有节点 wget ftp://10.3.148.254/Note/Elk/…...
《模拟器过检测教程:Nox、雷电、Mumu、逍遥模拟器 Magisk、LSposed 框架安装与隐藏应用配置》
一、夜神模拟器 (Nox) 过检测 使用版本:7.0.6.2(20250209) 1. 准备工作 将需要用到的应用放入文件夹: C:\Users\Administrator.DESKTOP-I5V50SS\Nox_share\Download 2. 安装面具鸭(Magisk) 在模拟器下…...
人工智能、机器学习、深度学习和大语言模型之间的关系
人工智能(AI)、机器学习(ML)、深度学习(DL)和大语言模型(LLM)之间是逐层包含且技术递进的关系,具体如下: 1. 层级关系 人工智能(AI)…...
上传securecmd失败
上传securecmd失败 问题描述:KES V8R6部署工具中,节点管理里新建节点下一步提示上传securecmd失败,如下: 解决办法: [rootlocalhost ~]# yum install -y unzip 上传的过程中会解压,如果未安装unzip依赖包…...
C++:dfs,bfs各两则
1.木棒 167. 木棒 - AcWing题库 乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过 5050 个长度单位。 然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。 请你设计一个程序…...
Python在实际工作中的运用-通用格式CSV文件自动转换XLSX
继续上篇《Python在实际工作中的运用-CSV无损转XLSX的几个方法》我们虽然对特定格式的CSV实现了快速转换XLSX的目标,但是在运行Py脚本前,还是需要编辑表格创建脚本和数据插入脚本,自动化程度很低,实用性不强,为减少人工提高效率,实现输入CSV文件路径即可自动适配完成转换…...
P9420 [蓝桥杯 2023 国 B] 子 2023
P9420 [蓝桥杯 2023 国 B] 子 2023 题目 分析代码 题目 分析 刚拿到这道题,我大脑简单算了一下,这个值太大了,直观感觉就很难!! 但是,你仔仔细细的一看,先从最简单的第一步入手,再…...
2025-02-26 学习记录--C/C++-C语言 判断字符串S2是否在字符串S1中
合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。💪🏻 C语言 判断字符串S2是否在字符串S1中 #include <stdio.h> // 引入标准输入输出库,用于使用 printf 等函数 #…...
004 Kafka异常处理
6.异常处理 文章目录 6.异常处理1.异常分类与处理原则2.生产者异常处理1. 同步发送捕获异常2. 异步发送回调处理 3.消费者异常处理1.全局异常处理器2.方法级处理3.重试yml配置 4.死信队列(DLQ)配置1. 启用死信队列2. 手动发送到DLQ 5.事务场景异常处理1.…...
创建第一个 Maven 项目(二)
六、添加依赖 在 Maven 项目开发过程中,添加依赖是一项常见且关键的操作。通过添加依赖,我们可以引入项目所需的各种库和框架,极大地扩展项目的功能。接下来,我们将以 JUnit 依赖为例,详细介绍如何在 Maven 项目中添加…...
游戏引擎学习第124天
仓库:https://gitee.com/mrxiao_com/2d_game_3 回顾/复习 今天是继续完善和调试多线程的任务队列。之前的几天,我们已经介绍了多线程的一些基础知识,包括如何创建工作队列以及如何在线程中处理任务。今天,重点是解决那些我们之前没有注意到…...
组件的组成和组件的嵌套关系
组件的组成 首先建一个.vue文件,在里面写一个内容: <template> <div><div class"container">{{ message }}</div> </div> </template> <script> export default{data(){return{message:"组件…...
2025 PHP授权系统网站源码
2025 PHP授权系统网站源码 安装教程: PHP7.0以上 先上传源码到服务器,然后再配置伪静态, 访问域名根据操作完成安装, 然后配置伪静态规则。 Ngix伪静态规则: location / { if (!-e $request_filename) { rewrite …...
KIMI K1.5:大规模强化学习在大语言模型中的应用与工程实践
目录 1、核心技术创新:长上下文强化学习 2、策略优化的技术细节 2.1、在线镜像下降变体 2.2、长度惩罚机制 2.3、智能采样策略 3、工程架构创新 3.1、混合部署框架 3.2、代码沙箱与奖励模型 3.3、分布式系统架构 4、实验成果与性能提升 5、结论与未来展望 大语言模…...
