基于STM32智能小车

一、前置准备

前置知识:需要学习stm32,建议去b站看江科大的视频,讲的很详细,学完串口那一块就可以制作了,软件用的是Keil5,开发语言C语言,手机连接蓝牙模块软件是蓝牙调试器。

需要准备的器件:小车底盘,面包板,stm32f103c8t6,电机驱动模块(tb6612)、蓝牙模块(hc06)、超声波测距模块(HC-SR04)、红外寻迹模块(TCRT5000)、舵机(sg90)、杜邦线若干、电源模块(可以换成充电宝,用5伏那一口)、黑色胶布(用于制作轨迹)、超声波测距模块云台。

二、演示

寻迹演示

基于STM32制作智能小车

自动避障(忘记录了后续补上)

三、功能实现

1、接线图

 2、引脚定义表

3、PWM驱动电机旋转

3.1、让一个轮子转起来

电机旋转就是我们小车轮子旋转了,我们先看看然后让一个轮子转起来。

电机驱动的PWMA接PA1口,AIN2与AIN1接PA5与PA4口,根据定义表中,我们要使用定时器(TIM) 2的通道(Channel) 2,所以初始化代码是。

3.2、代码实现 

void PWM_Init(void)
{/*GPIO重映射*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);			//开启TIM2的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);			//开启GPIOA的时钟GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;TIM_TimeBaseInitStructure.TIM_Prescaler = 36 - 1;TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCStructInit(&TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_Pulse = 0;TIM_OC1Init(TIM2, &TIM_OCInitStructure);TIM_OC2Init(TIM2, &TIM_OCInitStructure);TIM_Cmd(TIM2, ENABLE);
}

设置CCR代码

void PWM_SetCompare(uint8_t Num,uint16_t Compare)
{if(Num == 2){TIM_SetCompare1(TIM2, Compare); // 使用通道2}else if(Num == 3){TIM_SetCompare2(TIM2, Compare); // 使用通道3}else if(Num == 4){TIM_SetCompare4(TIM2, Compare); // 使用通道4}
}

电机驱动代码

思路:使用PA4,与PA5口,对GPIO进行初始化,对于void Motor_SetSpeed(int8_t Speed),当速度大于0正转,小于0反转,对4口5口分别设置高低电平,并且调用PWM_SetCompare3(),修改CCR的值,也就是转速(TIM_OCInitStructure.TIM_Pulse = 0;)。

void Motor_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // GPIO_Mode_Out_PP: GPIO引脚在该模式下可以输出高或低电平,而不会受到其他引脚的影响。GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);PWM_Init();
}void Motor_SetSpeed(int8_t Speed)
{if(Speed >= 0){GPIO_SetBits(GPIOA, GPIO_Pin_4);GPIO_ResetBits(GPIOA, GPIO_Pin_5);PWM_SetCompare3(Speed);}else{GPIO_ResetBits(GPIOA, GPIO_Pin_4);GPIO_SetBits(GPIOA, GPIO_Pin_5);PWM_SetCompare3(-Speed);}
}

主函数

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Motor.h"
#include "Key.h"int main(void)
{Motor_Init();		//直流电机初始化Motor_SetSpeed(30);	while (1){}
}

3.2、让四个轮子转起来

这时,电机就转起来了。

提问:这样就能让一个轮子转起来,那我cv 4份,就能都转起来,即简单又方便,我太聪明了,hhh~

答:这样做肯定不对的,如何实现请看思路。

思路:我们可以使用PWMA控制左边两个轮子,PWMB控制右边两个轮子,当然下图知识作为参考,可以自行脑补。

可以仔细看看下面四图。我们让PWMA控制左边的轮子,可以看看第二张图的接线,将左边的电机正负极接到AO1、AO2上面;PWMB控制右边的轮子,将右边的电机正负极接到BO1、BO2上面。

注意:当正负极接反时,电机会反转,当按下前进按钮,三个轮子前进,一个轮子后退,这个肯定不是我们想要的,所以,这里接线的时候注意下!

这时我们的线就接好了,我们来看看代码是如何实现的。

3.4、代码实现

思路:这里使用pa4、pa5、pa6、pa7 做控制四个电机,根据Aspet的值控制左边与右边的轮子

void Motor_SetSpeed(unsigned char Aspet,int8_t Speed)
{if(Aspet == 1){if(Speed > 0){GPIO_SetBits(GPIOA, GPIO_Pin_6);GPIO_ResetBits(GPIOA, GPIO_Pin_7);PWM_SetCompare(3,Speed);}else{GPIO_ResetBits(GPIOA, GPIO_Pin_6);GPIO_SetBits(GPIOA, GPIO_Pin_7);PWM_SetCompare(3,-Speed);}}else if(Aspet == 2){if(Speed > 0){GPIO_SetBits(GPIOA, GPIO_Pin_4);GPIO_ResetBits(GPIOA, GPIO_Pin_5);PWM_SetCompare(2,Speed);}else{GPIO_ResetBits(GPIOA, GPIO_Pin_4);GPIO_SetBits(GPIOA, GPIO_Pin_5);PWM_SetCompare(2,-Speed);}}
}

3.5、前进后退等功能

根据Motor_SetSpeed的Speed参数正负值控制前进与后退、Aspet控制左轮与右轮,新建一个车模块,封装前进、后退、左拐、右拐、后左拐、后右拐等功能。

void Car_Init(void){Motor_Init();
}
void Go_Ahead(void){Motor_SetSpeed(1,50);Motor_SetSpeed(2,50);
}
void Go_Back(void){Motor_SetSpeed(1,-50);Motor_SetSpeed(2,-50);
}
void Turn_Left(void){Motor_SetSpeed(1,0);Motor_SetSpeed(2,90);
}
void Turn_Right(void){Motor_SetSpeed(2,0);Motor_SetSpeed(1,90);}
void Self_Left(void){Motor_SetSpeed(1,-90);Motor_SetSpeed(2,90);
}
void Self_Right(void){Motor_SetSpeed(1,90);Motor_SetSpeed(2,-90);
}
void Car_Stop(void){Motor_SetSpeed(1,0);Motor_SetSpeed(2,0);
}

4、蓝牙模块

串口通信里面,tx发送信息,rx接受信息,这里我使用了pa9口作为tx,pa10作为rx,

注:在蓝牙模块的tx与rx中,要记得反插,也就是蓝牙的tx接pa10,蓝牙的rx接pa9。

4.1、代码实现

uint8_t Serial_RxData;
uint8_t Serial_RxFlag;void Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // txGPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // rxGPIO_Init(GPIOA, &GPIO_InitStructure);USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 9600;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStructure);// 下面是用中断的方法实现串口发送// 使能 USART1 的接收中断,以便在接收到新的数据时触发中断处理程序。USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 开启串口接收数据的中断NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 配置NVIC为分组2NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;  // 选择配置NVIC的USART1线NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  // 指定NVIC线路使能NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 指定NVIC线路的抢占优先级为1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  // 将结构体变量交给NVIC_Init,配置NVIC外设NVIC_Init(&NVIC_InitStructure);USART_Cmd(USART1, ENABLE);	}
// 串口发送一个字节
void Serial_SendByte(uint8_t Byte)
{USART_SendData(USART1, Byte);while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}// 串口发送一个数组
void Serial_SendArray(uint8_t *Array, uint16_t Length)
{uint16_t i;for (i = 0; i < Length; i ++)		//遍历数组{Serial_SendByte(Array[i]);		//依次调用Serial_SendByte发送每个字节数据}
}// 串口发送一个字符串
void Serial_SendString(char *String)
{uint8_t i;for (i = 0; String[i] != '\0'; i ++)//遍历字符数组(字符串),遇到字符串结束标志位后停止{Serial_SendByte(String[i]);		//依次调用Serial_SendByte发送每个字节数据}
}// 次方函数(内部使用)
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{uint32_t Result = 1;	//设置结果初值为1while (Y --)			//执行Y次{Result *= X;		//将X累乘到结果}return Result;
}// 串口发送数字
void Serial_SendNumber(uint32_t Number, uint8_t Length)
{uint8_t i;for (i = 0; i < Length; i ++)		//根据数字长度遍历数字的每一位{Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');	//依次调用Serial_SendByte发送每位数字}
}// 使用printf需要重定向的底层函数
int fputc(int ch, FILE *f)
{Serial_SendByte(ch);			//将printf的底层重定向到自己的发送字节函数return ch;
}// 自己封装的prinf函数
void Serial_Printf(char *format, ...)
{char String[100];				//定义字符数组va_list arg;					//定义可变参数列表数据类型的变量argva_start(arg, format);			//从format开始,接收参数列表到arg变量vsprintf(String, format, arg);	//使用vsprintf打印格式化字符串和参数列表到字符数组中va_end(arg);					//结束变量argSerial_SendString(String);		//串口发送字符数组(字符串)
}// 获取串口接收标志位
uint8_t Serial_GetRxFlag(void)
{if(Serial_RxFlag == 1){Serial_RxFlag = 0;return 1;}return 0;
}// 获取串口接收的数据
uint8_t Serial_GetRxData(void)
{return Serial_RxData;
}

4.2、中断函数

// USART1中断函数
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET) // 判断是否是USART1的接收事件触发的中断{// USART_ReceiveData: 将接收到的数据从 USART1 的接收数据寄存器中读取Serial_RxData1 = USART_ReceiveData(USART1);OLED_ShowHexNum(1,1, Serial_RxData1, 10);if(Serial_RxData1 == 0x30) Car_Stop();if(Serial_RxData1 == 0x31) Go_Ahead();if(Serial_RxData1 == 0x32) Go_Back();if(Serial_RxData1 == 0x33) Turn_Left();if(Serial_RxData1 == 0x34) Turn_Right();if(Serial_RxData1 == 0x35) Self_Left();if(Serial_RxData1 == 0x36) Self_Right();if(Serial_RxData1 == 0x37){Car_Stop(); Servo_SetAngle(0);}if(Serial_RxData1 == 0x38){Car_Stop(); Servo_SetAngle(90);}if(Serial_RxData1 == 0x39){Car_Stop(); Servo_SetAngle(180);}USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}

5、自动避障功能

舵机与超声波模块联合使用,实现检查前面是否有障碍物,如有,左拐或右拐,如果遇到死胡同(前左右都有障碍物)停下来。

4.1、舵机模块

舵机使用的PB0口,根据引脚定义表进行定时器与通道的初始化,前面有讲,这里就不过多进行复述了。

代码实现
void PWMServo_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);TIM_InternalClockConfig(TIM3);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1;  TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCStructInit(&TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_Pulse = 0;TIM_OC3Init(TIM3, &TIM_OCInitStructure);TIM_Cmd(TIM3, ENABLE);
}void PWMServo_SetCompare3(uint16_t Compare)
{TIM_SetCompare3(TIM3, Compare); }

对舵机初始化封装与转弯角度。

void Servo_Init(void)
{PWMServo_Init();
}void Servo_SetAngle(float Angle)
{PWMServo_SetCompare3(Angle / 180 * 2000 + 500);
}

主函数调用,就可以使用了。

4.2、超声波模块

使用的是pb12口,原理可以看看这位大佬的。

uint16_t Cnt;
uint16_t OverCnt;
void Ultrasound_Init(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // trigGPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // echoGPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);TIM_InternalClockConfig(TIM4);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 60000 - 1; // arrTIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; // pscTIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStructure);}
float Test_Distance()
{GPIO_SetBits(GPIOB, GPIO_Pin_12);Delay_us(20);GPIO_ResetBits(GPIOB, GPIO_Pin_12);while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13) == RESET){};TIM_Cmd(TIM4, ENABLE);while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13) == SET){};TIM_Cmd(TIM4, DISABLE);Cnt = TIM_GetCounter(TIM4);float distance = (Cnt * 1.0 / 10 * 0.34) / 2;TIM4->CNT = 0;Delay_us(100);return distance;}

我们来看看自动寻迹的代码,先让他一直前进,当检测的具体小于15cm时,停下来,舵机左转或右转,然后再进行检测,前进或停下来操作。

void Obstacle_Avoidance()
{Go_Ahead();uint16_t Distance = Test_Distance();if(Distance < 15){Car_Stop();Servo_SetAngle(0);	Delay_ms(1000);Distance= Test_Distance();if(Distance > 15){Delay_ms(1000);Turn_Right();Delay_ms(1300);Servo_SetAngle(90);Go_Ahead();}else {Servo_SetAngle(180);Delay_ms(1000);Distance = Test_Distance();if(Distance > 15){	Delay_ms(1000);Turn_Left();Delay_ms(1300);Servo_SetAngle(90);Go_Ahead();}else{Servo_SetAngle(90);while(1){};}}}Delay_ms(100);}

这里代码后续进行优化

4.3、主函数调用

int main(void)
{Car_Init();Serial_Init();Servo_Init();Servo_SetAngle(90);Ultrasound_Init();//Go_Ahead();while (1){Obstacle_Avoidance(); // 自动规避障碍//Auto_Tracing(); // 自动寻迹}
}

6、自动寻迹功能

寻迹模块使用的红外,这个原理自行搜索,使用的PB5到PB8口,然后使用GPIO_ReadInputDataBit 读取信号,也就是0或1 ,0代表没有检测到黑线,1代表检测到黑线,下面的代码待优化

6.1、代码实现

// 寻迹模块
void Track_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);
}
// b6,b5在左边   b7 b8在右边
void Auto_Tracing()
{// 没有黑线往前走if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)==0&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)==0&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)==0&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8)==0){Go_Ahead();}// 有黑线往后走else if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)==1&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)==1&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)==1&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8)==1){Car_Stop();}// 后右拐else if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)==0&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)==0&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)==1&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8)==1){Turn_Left();}// 右拐else if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)==0&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)==0&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)==1&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8)==0){Turn_Left();}// 右拐else if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)==0&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)==0&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)==0&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8)==1){Turn_Left();}// 左拐else if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)==0&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)==1&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)==0&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8)==0){Turn_Right();}// 后左拐else if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)==1&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)==1&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)==0&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8)==0){Turn_Right();}// 左拐else if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)==1&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)==0&&
//			GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)==0&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8)==0){Turn_Right();}
}

这样,自动寻迹就完成了,主函数调用就可以跑了。

四、总结

代码待优化,后续来总结。

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

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

相关文章

数学+思维,CF1056B - Divide Candies

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - 1056B - Codeforces 二、解题报告 1、思路分析 考虑i^2 j^2 | m 而m的余数有限&#xff0c;且m很小 我们枚举两重循环&#xff0c;都枚举m的余数&#xff0c;分别记为x&#xff0c;y 如果x ^ …

Linux☞进程控制

在终端执行命令时&#xff0c;Linux会建立进程&#xff0c;程序执行完&#xff0c;进程会被终止&#xff1b;Linux是一个多任务的OS,允许多个进程并发运行&#xff1b; Linxu中启动进程的两种途径&#xff1a; ①手动启动(前台进程(命令gedit)...后台进程(命令‘&’)) ②…

数据库安全加固与API防护策略

在数字化时代&#xff0c;数据库作为企业核心资产的安全性至关重要。然而&#xff0c;随着网络攻击手段的不断演进&#xff0c;数据库和API接口成为了黑客的主要攻击目标。本文将探讨数据库被攻击、API接口被滥用的情况&#xff0c;并提供一系列实用的防护措施&#xff0c;旨在…

【玩转C语言】第三讲---> scanf 和 printf 函数详解(非常重要)!

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 引言&#xff1a; 大家好&#xff0c;我是坊钰&#xff0c;为了让大家深入了解C语言&#xff0c;我开创了【玩转C语言系列】&#xff0c;将为大家介绍C语言相关知识…

C++ ─── STL 以及string

前言&#xff1a;什么是STL STL(standard template libaray-标准模板库)&#xff1a;是C标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&#xff0c;而且 是一个包罗数据结构与算法的软件框架 STL的六大组件 1. 为什么学习string类&#xff1f; 1.1 C语言中的字符…

Ambari集成Apache Kyuubi实践

目前还有很多公司基于HDP来构建自己的大数据平台&#xff0c;随着Apache Kyuubi的持续热度&#xff0c;如何基于原有的HDP产品来集成Apache Kyuubi&#xff0c;很多人都迫切的需求。集成Apache Kyuubi到HDP中&#xff0c;主要涉及Ambari的二次开发。本文详细叙述了集成Apache K…

分享一个用python的本地WIFI密码查看器

本章教程&#xff0c;主要分享一个本地wifi密码查看器&#xff0c;用python实现的&#xff0c;感兴趣的可以试一试。 具体代码 import subprocess # 导入 subprocess 模块&#xff0c;用于执行系统命令 import tkinter as tk # 导入 tkinter 模块&#xff0c;用于创建图形用…

实现Ingress-Nginx Controller高可用方案

文章目录 前提准备1.修改Ingress-Controller 运行模式为hostNetwork并生效2.给部署ingress-controller的节点打标签3.查看ingress-controller的部署情况 方式一&#xff1a;LVSKeepalivedNginxIngress一、部署ipvsadm和keepalived二、配置keepalived1.配置lvs01(keepalived mas…

Java Web学习笔记27——对话框、表单组件

常见组件对话框&#xff1a; Dialog对话框&#xff1a;在保留当前页面状态下&#xff0c;告知用户并承载相关操作。 dialogTableVisible: false 默认是不可见的。 在按钮属性中设置为true的意思&#xff0c;点击按钮的时候&#xff0c;才会true&#xff0c;对话框才会显示。 …

python Tk 获取输入框内容,分割内容

创建输入框、一个按钮和一个标签的GUI。 用户可以在输入框中输入文本&#xff0c;点击按钮后&#xff0c;程序将在控制台打印输入的文本&#xff08;已经分割为列表&#xff09;&#xff0c;并在GUI中的标签上显示一些静态文本。 import tkinter as tk# 创建主窗口 root tk.…

基于SpringBoot+Vue学生请假管理系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝1W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;还…

linux指令--sed

sed 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。 语法解析 sed [选项] 编辑命令 文件 选项&#xff1a; -n&#xff1a;只显示匹配处理的行-e&#xff1a;执行多个编辑命令时-i&#xff1a;在原文件中进行修改&#xff0c;不输出到屏幕-…

qsort函数

学习c语言的过程中少不了的就是排序&#xff0c;例如冒泡排序&#xff08;不清楚的同学可以翻找一下之前的文章&#xff09;&#xff0c; 我们这里将冒泡排序作为一个自定义函数来呈现一下 #include<stdio.h>void bubble_sort(int arr[], int len) {for (int i 0; i &…

【Vue】mutations

文章目录 一、定义mutations二、组件中提交 mutations三、带参数的 mutations 一、定义mutations mutations是vuex中的对象&#xff0c;这个对象可以定义在当前store的配置项中 const store new Vuex.Store({state: {count: 0},// 定义mutations// mutations是一个对象&#x…

Progressive Feature Fusion Framework Based on Graph Convolutional Network

以Resnet50作为主干网络&#xff0c;然后使用GCN逐层聚合多级特征&#xff0c;逐级聚合这种模型架构早已不新鲜&#xff0c;这篇文章使用GCN的方式对特征进行聚合&#xff0c;没有代码。这篇文章没有过多的介绍如何构造的节点特征和邻接矩阵&#xff0c;我觉得对于图卷积来说&a…

自动化Reddit图片收集:Python爬虫技巧

引言 Reddit&#xff0c;作为一个全球性的社交平台&#xff0c;拥有海量的用户生成内容&#xff0c;其中包括大量的图片资源。对于数据科学家、市场研究人员或任何需要大量图片资源的人来说&#xff0c;自动化地从Reddit收集图片是一个极具价值的技能。本文将详细介绍如何使用…

多个p标签一行展示,溢出隐藏

一开始&#xff0c;我是让div包裹多个p标签&#xff0c;并让div“flex”布局&#xff0c;且单行溢出隐藏&#xff0c;可是发现当父元素或当前元素有flex时&#xff0c;text-overflow: ellipsis;是不生效的 大多数解决办法都是&#xff0c;不要flex&#xff0c;或者给div下的每个…

【启程Golang之旅】网络编程与反射

欢迎来到Golang的世界&#xff01;在当今快节奏的软件开发领域&#xff0c;选择一种高效、简洁的编程语言至关重要。而在这方面&#xff0c;Golang&#xff08;又称Go&#xff09;无疑是一个备受瞩目的选择。在本文中&#xff0c;带领您探索Golang的世界&#xff0c;一步步地了…

Java进阶_多态特性

生活中的多态 多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口&#xff0c;使用不同的实例而执行不同操作&#xff0c;如图所示&#xff1a; 现实中&#xff0c;比如我们按下 F1 键这个动作&#xff0c;同一个事件发生在不同的对象上会产生不同的结果。…

达梦8 探寻达梦排序机制之一:传统排序机制(SORT_FLAG=0)

测试版本&#xff1a;--03134283938-20221019-172201-20018 达梦的排序机制由四个dm.ini参数控制&#xff1a; SORT_BUF_SIZE 100 #maximum sort buffer size in MegabytesSORT_BLK_SIZE 1 #ma…