艾思控AQMD6008BLS-TE无刷电机驱动使用笔记(配合STM32)

一、介绍

本驱动器使用的电机电流精确检测技术、有感无刷电机自测速、有感无刷电机转动位置检测、再生电流恒电流制动(或称刹车)技术和强大的PID调节技术可地控制电机平稳正反转、换向及制动,输出电流实时调控防止过流,精准控制电机转速和转动位置,电机响应时间短且反冲力小。

二、使用方法

该款无刷电机驱动有多种使用方法,就stm32而言,可以通过输出PWM信号对电机进行调速,也可通过485通讯或CAN通讯与电机驱动进行通讯(电机驱动内部应该也是另外一块32)。项目使用过程中,经导师建议,优先采用485通讯方式。在使用此种通讯方式时,注意设备地址和通讯参数(波特率、奇偶校验等)的设置。

在通过速度控制寄存器进行速度控制时,可以通过0x0042寄存器设定占空比,也可通过0x0043寄存器设定换向频率。另外,在正确配置电机极个数和减速比之后,可以通过0x0034寄存器读取电机的转速。

三、代码

在编写代码的过程中,有参考硬件家园刘工的工程代码,在此表示感谢。

Motor.h

#ifndef __MOTOR_H__
#define __MOTOR_H__

#include "MyApplication.h"

//定义枚举类型
typedef enum
{
	M1 = (uint8_t)0x01,
	M2 = (uint8_t)0x02,
}Motor_Num_t;

//定义结构体类型
typedef struct
{
	uint8_t M1_Addr;
	uint8_t M2_Addr;
	FlagStatus_t Motor_Move_State;
	uint16_t M1_Read_Value;
	uint16_t M2_Read_Value;
	void (*Motor_Set_PWM)(uint8_t, float, UART_t*); 
	void (*Motor_Read_Value)(uint8_t, UART_t*);
	void (*Protocol_Read_Speed)(uint8_t, UART_t*);
	void (*Motor_PWM_Acc_Buffer)(uint8_t, float, UART_t*);
	void (*Motor_PWM_Rv_Buffer)(uint8_t, float, UART_t*);
	void (*Motor_Brake)(uint8_t, UART_t*);
} Motor_t;



/* extern variables-----------------------------------------------------------*/
extern Motor_t  Motor;
/* extern function prototypes-------------------------------------------------*/

#endif
/********************************************************
  End Of File
********************************************************/

Motor.c

/* Includes ------------------------------------------------------------------*/
#include "MyApplication.h"

/* Private define-------------------------------------------------------------*/
#define FunctionCode_Read_Motor 		(uint8_t)0x03
#define FunctionCode_Write_Motor 	(uint8_t)0x06
#define UART3_Read_Speed_LENGTH		(uint8_t)7

/* Private variables----------------------------------------------------------*/
static void Motor_Set_PWM(uint8_t, float, UART_t*); 
static void Motor_Read_Value(uint8_t, UART_t*);
static void Protocol_Read_Speed(uint8_t, UART_t*);
static void Motor_PWM_Acc_Buffer(uint8_t, float, UART_t*);
static void Motor_PWM_Rv_Buffer(uint8_t, float, UART_t*);
static void Motor_Brake(uint8_t, UART_t*); 

/* Public variables-----------------------------------------------------------*/
Motor_t Motor = 
{
	0x01, 
	0x02,
	FALSE,
	0,
	0,
	Motor_Set_PWM,
	Motor_Read_Value,
	Protocol_Read_Speed,
	Motor_PWM_Acc_Buffer,
	Motor_PWM_Rv_Buffer,
	Motor_Brake
};

/* Private function prototypes------------------------------------------------*/      

/*
	* @name   Motor_Set_PWM
	* @brief  设置驱动PWM占空比
	* @param  Motor_Num -> 编号, pwm -> 占空比, UART -> 串口
	* @retval None      
*/
static void Motor_Set_PWM(uint8_t Motor_Num, float pwm, UART_t* UART)
{
	UART_t* const COM = UART;
	uint16_t SpeedTemp = (uint16_t)(pwm * 10);
	
	//条件选择语句
	switch(Motor_Num)
	{	
		case M1: 
		{
			*(COM->pucSend_Buffer + 0) = Motor.M1_Addr;
			*(COM->pucSend_Buffer + 1) = FunctionCode_Write_Motor;
			
			*(COM->pucSend_Buffer + 2) = 0x00;
			*(COM->pucSend_Buffer + 3) = 0x42;

			*(COM->pucSend_Buffer + 4) = (uint8_t)(SpeedTemp >> 8);
			*(COM->pucSend_Buffer + 5) = (uint8_t)SpeedTemp;

			CRC_16.CRC_Value = CRC_16.CRC_Check(COM->pucSend_Buffer, 6);
			CRC_16.CRC_H     = (uint8_t)(CRC_16.CRC_Value >> 8);
			CRC_16.CRC_L     = (uint8_t)CRC_16.CRC_Value;

			*(COM->pucSend_Buffer + 6) = CRC_16.CRC_H;
			*(COM->pucSend_Buffer + 7) = CRC_16.CRC_L;

			UART3.SendArray(COM->pucSend_Buffer, 8);
			
			break;
		}
		case M2:
		{
			*(COM->pucSend_Buffer + 0) = Motor.M2_Addr;
			*(COM->pucSend_Buffer + 1) = FunctionCode_Write_Motor;
			
			*(COM->pucSend_Buffer + 2) = 0x00;
			*(COM->pucSend_Buffer + 3) = 0x42;

			*(COM->pucSend_Buffer + 4) = (uint8_t)(SpeedTemp >> 8);
			*(COM->pucSend_Buffer + 5) = (uint8_t)SpeedTemp;

			CRC_16.CRC_Value = CRC_16.CRC_Check(COM->pucSend_Buffer, 6);
			CRC_16.CRC_H     = (uint8_t)(CRC_16.CRC_Value >> 8);
			CRC_16.CRC_L     = (uint8_t)CRC_16.CRC_Value;

			*(COM->pucSend_Buffer + 6) = CRC_16.CRC_H;
			*(COM->pucSend_Buffer + 7) = CRC_16.CRC_L;

			UART3.SendArray(COM->pucSend_Buffer, 8);
			
			break;
		}
		default: System.Assert_Failed();
	}
	HAL_Delay(30);
}

/*
	* @name   Motor_Read_Speed
	* @brief  通过驱动读取转速
	* @param  UART -> 串口
	* @retval None      
*/
static void Motor_Read_Value(uint8_t Motor_Num, UART_t* UART)
{
	UART_t* const  COM = UART;
	
	//条件选择语句
	switch(Motor_Num)
	{
		case M1: 
		{
			*(COM->pucSend_Buffer + 0) = Motor.M1_Addr;
			*(COM->pucSend_Buffer + 1) = FunctionCode_Read_Motor;
			
			*(COM->pucSend_Buffer + 2) = 0x00;
			*(COM->pucSend_Buffer + 3) = 0x34;
			
			*(COM->pucSend_Buffer + 4) = 0x00;
			*(COM->pucSend_Buffer + 5) = 0x01;
			
			CRC_16.CRC_Value = CRC_16.CRC_Check(COM->pucSend_Buffer, 6);
			CRC_16.CRC_H     = (uint8_t)(CRC_16.CRC_Value >> 8);
			CRC_16.CRC_L     = (uint8_t)CRC_16.CRC_Value;

			*(COM->pucSend_Buffer + 6) = CRC_16.CRC_H;
			*(COM->pucSend_Buffer + 7) = CRC_16.CRC_L;

			Modbus.Sensor_To_Read_Flag = 1;
			UART3.SendArray(COM->pucSend_Buffer, 8);
			break;			
		}
		
		case M2: 
		{
			*(COM->pucSend_Buffer + 0) = Motor.M2_Addr;
			*(COM->pucSend_Buffer + 1) = FunctionCode_Read_Motor;
			
			*(COM->pucSend_Buffer + 2) = 0x00;
			*(COM->pucSend_Buffer + 3) = 0x34;
			
			*(COM->pucSend_Buffer + 4) = 0x00;
			*(COM->pucSend_Buffer + 5) = 0x01;
			
			CRC_16.CRC_Value = CRC_16.CRC_Check(COM->pucSend_Buffer, 6);
			CRC_16.CRC_H     = (uint8_t)(CRC_16.CRC_Value >> 8);
			CRC_16.CRC_L     = (uint8_t)CRC_16.CRC_Value;

			*(COM->pucSend_Buffer + 6) = CRC_16.CRC_H;
			*(COM->pucSend_Buffer + 7) = CRC_16.CRC_L;

			Modbus.Sensor_To_Read_Flag = 2;
			UART3.SendArray(COM->pucSend_Buffer, 8);
			break;			
		}	
		default: System.Assert_Failed();
	}
	
	HAL_Delay(30);
}

/*
	* @name   Protocol_Read_Speed
	* @brief  分析串口值
	* @param  UART_t* -> 串口
	* @retval None      
*/
static void Protocol_Read_Speed(uint8_t Motor_Num, UART_t* UART)
{
	UART_t* const  COM = UART;
	uint8_t i = 0, Index = 0;

	//串口3停止DMA接收
	HAL_UART_DMAStop(&huart3);

	switch(Motor_Num)
	{
		case M1:
		{
			//过滤干扰数据,首字节为modbus地址,共8字节
			for(i = 0; i < UART3_Rec_LENGTH; i++)
			{
				//检测键值起始数据Modbus.Addr
				if(Index == 0)
				{
					if(*(COM->pucRec_Buffer+i) != Motor.M1_Addr)
						continue;
				}
				
				*(COM->pucRec_Buffer + Index) = *(COM->pucRec_Buffer + i);

				//已读取7个字节
				if(Index == UART3_Read_Speed_LENGTH - 1)
					break;
				
				Index++;
			}
			
			//计算CRC-16
			CRC_16.CRC_Value   = CRC_16.CRC_Check(COM->pucRec_Buffer, 5); //计算CRC值
			CRC_16.CRC_H       = (uint8_t)(CRC_16.CRC_Value >> 8);
			CRC_16.CRC_L       = (uint8_t)CRC_16.CRC_Value;	

			//校验CRC-16
			if(((*(COM->pucRec_Buffer + 5) == CRC_16.CRC_L) && (*(COM->pucRec_Buffer + 6) == CRC_16.CRC_H))
																										||
				 ((*(COM->pucRec_Buffer + 5) == CRC_16.CRC_H) && (*(COM->pucRec_Buffer + 6) == CRC_16.CRC_L)))
			{
				//校验地址
				
				if(((*(COM->pucRec_Buffer + 0)) == Motor.M1_Addr) && ((*(COM->pucRec_Buffer + 1)) == FunctionCode_Read_Motor) && ((*(COM->pucRec_Buffer + 2)) == 0x02))
				{
					
					Motor.M1_Read_Value = ((*(COM->pucRec_Buffer + 3)) << 8) | ((*(COM->pucRec_Buffer + 4)));
				}
			}	
			break;
		}
		case M2:
		{
			//过滤干扰数据,首字节为modbus地址,共8字节
			for(i = 0; i < UART3_Rec_LENGTH; i++)
			{
				//检测键值起始数据Modbus.Addr
				if(Index == 0)
				{
					if(*(COM->pucRec_Buffer+i) != Motor.M2_Addr)
						continue;
				}
				
				*(COM->pucRec_Buffer + Index) = *(COM->pucRec_Buffer + i);

				//已读取7个字节
				if(Index == UART3_Read_Speed_LENGTH - 1)
					break;
				
				Index++;
			}
			
			//计算CRC-16
			CRC_16.CRC_Value   = CRC_16.CRC_Check(COM->pucRec_Buffer, 5); //计算CRC值
			CRC_16.CRC_H       = (uint8_t)(CRC_16.CRC_Value >> 8);
			CRC_16.CRC_L       = (uint8_t)CRC_16.CRC_Value;	

			//校验CRC-16
			if(((*(COM->pucRec_Buffer + 5) == CRC_16.CRC_L) && (*(COM->pucRec_Buffer + 6) == CRC_16.CRC_H))
																										||
				 ((*(COM->pucRec_Buffer + 5) == CRC_16.CRC_H) && (*(COM->pucRec_Buffer + 6) == CRC_16.CRC_L)))
			{
				//校验地址
				if(((*(COM->pucRec_Buffer + 0)) == Motor.M2_Addr) && ((*(COM->pucRec_Buffer + 1)) == FunctionCode_Read_Motor) && ((*(COM->pucRec_Buffer + 2)) == 0x02))
				{
					Motor.M2_Read_Value = ((*(COM->pucRec_Buffer + 3)) << 8) | ((*(COM->pucRec_Buffer + 4)));
				}
			}				
			break;
		}
		default: break;
	}
	
	//清缓存
	for(i = 0; i < UART3_Rec_LENGTH; i++)
	{
		*(COM->pucRec_Buffer + i) = 0x00;
	}

}

/*
	* @name   Motor_PWM_Acc_Buffer
	* @brief  电机PWM加速缓冲
	* @param  Motor_Num -> 编号, time -> 时间, UART -> 串口
	* @retval None      
*/
static void Motor_PWM_Acc_Buffer(uint8_t Motor_Num, float time, UART_t* UART)
{
	UART_t* const  COM = UART;
	uint8_t SpeedTemp = (uint8_t)(time * 10);
	

	//条件选择语句
	switch(Motor_Num)
	{	
		case M1: 
		{
			*(COM->pucSend_Buffer + 0) = Motor.M1_Addr;
			*(COM->pucSend_Buffer + 1) = FunctionCode_Write_Motor;
			
			*(COM->pucSend_Buffer + 2) = 0x00;
			*(COM->pucSend_Buffer + 3) = 0x60;

			*(COM->pucSend_Buffer + 4) = 0x00;
			*(COM->pucSend_Buffer + 5) = SpeedTemp;

			CRC_16.CRC_Value = CRC_16.CRC_Check(COM->pucSend_Buffer, 6);
			CRC_16.CRC_H     = (uint8_t)(CRC_16.CRC_Value >> 8);
			CRC_16.CRC_L     = (uint8_t)CRC_16.CRC_Value;

			*(COM->pucSend_Buffer + 6) = CRC_16.CRC_H;
			*(COM->pucSend_Buffer + 7) = CRC_16.CRC_L;

			UART3.SendArray(COM->pucSend_Buffer, 8);
			
			break;
		}
		case M2:
		{
			*(COM->pucSend_Buffer + 0) = Motor.M2_Addr;
			*(COM->pucSend_Buffer + 1) = FunctionCode_Write_Motor;
			
			*(COM->pucSend_Buffer + 2) = 0x00;
			*(COM->pucSend_Buffer + 3) = 0x60;

			*(COM->pucSend_Buffer + 4) = 0x00;
			*(COM->pucSend_Buffer + 5) = SpeedTemp;

			CRC_16.CRC_Value = CRC_16.CRC_Check(COM->pucSend_Buffer, 6);
			CRC_16.CRC_H     = (uint8_t)(CRC_16.CRC_Value >> 8);
			CRC_16.CRC_L     = (uint8_t)CRC_16.CRC_Value;

			*(COM->pucSend_Buffer + 6) = CRC_16.CRC_H;
			*(COM->pucSend_Buffer + 7) = CRC_16.CRC_L;

			UART3.SendArray(COM->pucSend_Buffer, 8);
			
			break;
		}
		default: System.Assert_Failed();
	}
	HAL_Delay(30);	
}

/*
	* @name   Motor_PWM_Rv_Buffer
	* @brief  电机PWM减速缓冲
	* @param  Motor_Num -> 编号, time -> 时间, UART -> 串口
	* @retval None      
*/
static void Motor_PWM_Rv_Buffer(uint8_t Motor_Num, float time, UART_t* UART)
{
	UART_t* const  COM = UART;
	uint8_t SpeedTemp = (uint8_t)(time * 10);
	

	//条件选择语句
	switch(Motor_Num)
	{	
		case M1: 
		{
			*(COM->pucSend_Buffer + 0) = Motor.M1_Addr;
			*(COM->pucSend_Buffer + 1) = FunctionCode_Write_Motor;
			
			*(COM->pucSend_Buffer + 2) = 0x00;
			*(COM->pucSend_Buffer + 3) = 0x51;

			*(COM->pucSend_Buffer + 4) = 0x00;
			*(COM->pucSend_Buffer + 5) = SpeedTemp;

			CRC_16.CRC_Value = CRC_16.CRC_Check(COM->pucSend_Buffer, 6);
			CRC_16.CRC_H     = (uint8_t)(CRC_16.CRC_Value >> 8);
			CRC_16.CRC_L     = (uint8_t)CRC_16.CRC_Value;

			*(COM->pucSend_Buffer + 6) = CRC_16.CRC_H;
			*(COM->pucSend_Buffer + 7) = CRC_16.CRC_L;

			UART3.SendArray(COM->pucSend_Buffer, 8);
			
			break;
		}
		case M2:
		{
			*(COM->pucSend_Buffer + 0) = Motor.M2_Addr;
			*(COM->pucSend_Buffer + 1) = FunctionCode_Write_Motor;
			
			*(COM->pucSend_Buffer + 2) = 0x00;
			*(COM->pucSend_Buffer + 3) = 0x51;

			*(COM->pucSend_Buffer + 4) = 0x00;
			*(COM->pucSend_Buffer + 5) = SpeedTemp;

			CRC_16.CRC_Value = CRC_16.CRC_Check(COM->pucSend_Buffer, 6);
			CRC_16.CRC_H     = (uint8_t)(CRC_16.CRC_Value >> 8);
			CRC_16.CRC_L     = (uint8_t)CRC_16.CRC_Value;

			*(COM->pucSend_Buffer + 6) = CRC_16.CRC_H;
			*(COM->pucSend_Buffer + 7) = CRC_16.CRC_L;

			UART3.SendArray(COM->pucSend_Buffer, 8);
			
			break;
		}
		default: System.Assert_Failed();
	}
	HAL_Delay(30);	
}

/*
	* @name   Motor_Brake
	* @brief  电机刹车
	* @param  Motor_Num -> 编号, UART -> 串口
	* @retval None      
*/
static void Motor_Brake(uint8_t Motor_Num, UART_t* UART)
{
	UART_t* const  COM = UART;

	//条件选择语句
	switch(Motor_Num)
	{	
		case M1: 
		{
			*(COM->pucSend_Buffer + 0) = Motor.M1_Addr;
			*(COM->pucSend_Buffer + 1) = FunctionCode_Write_Motor;
			
			*(COM->pucSend_Buffer + 2) = 0x00;
			*(COM->pucSend_Buffer + 3) = 0x40;

			*(COM->pucSend_Buffer + 4) = 0x00;
			*(COM->pucSend_Buffer + 5) = 0x01;

			CRC_16.CRC_Value = CRC_16.CRC_Check(COM->pucSend_Buffer, 6);
			CRC_16.CRC_H     = (uint8_t)(CRC_16.CRC_Value >> 8);
			CRC_16.CRC_L     = (uint8_t)CRC_16.CRC_Value;

			*(COM->pucSend_Buffer + 6) = CRC_16.CRC_H;
			*(COM->pucSend_Buffer + 7) = CRC_16.CRC_L;

			UART3.SendArray(COM->pucSend_Buffer, 8);
			
			break;
		}
		case M2:
		{
			*(COM->pucSend_Buffer + 0) = Motor.M2_Addr;
			*(COM->pucSend_Buffer + 1) = FunctionCode_Write_Motor;
			
			*(COM->pucSend_Buffer + 2) = 0x00;
			*(COM->pucSend_Buffer + 3) = 0x40;

			*(COM->pucSend_Buffer + 4) = 0x00;
			*(COM->pucSend_Buffer + 5) = 0x01;

			CRC_16.CRC_Value = CRC_16.CRC_Check(COM->pucSend_Buffer, 6);
			CRC_16.CRC_H     = (uint8_t)(CRC_16.CRC_Value >> 8);
			CRC_16.CRC_L     = (uint8_t)CRC_16.CRC_Value;

			*(COM->pucSend_Buffer + 6) = CRC_16.CRC_H;
			*(COM->pucSend_Buffer + 7) = CRC_16.CRC_L;

			UART3.SendArray(COM->pucSend_Buffer, 8);
			
			break;
		}
		default: System.Assert_Failed();
	}
	HAL_Delay(30);	
}



/********************************************************
  End Of File
********************************************************/

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

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

相关文章

答应我,大学生一定要试试这个啊

我要看看&#xff01;还有谁不知道这个工具的一定要试试啊&#xff01;只需要输入需求&#xff0c;一键生成&#xff0c;几秒就给我写出来一篇&#xff0c;不满意可以重新写&#xff0c;关键每次内容都不一样&#xff0c;完全不用担心会撞啊&#xff01; 写个论文&#xff0c;…

一文解释Linux的内存分页管理

内存是计算机的主存储器。内存为进程开辟出进程空间&#xff0c;让进程在其中保存数据。我将从内存的物理特性出发&#xff0c;深入到内存管理的细节&#xff0c;特别是了解虚拟内存和内存分页的概念。 内存 简单地说&#xff0c;内存就是一个数据货架。内存有一个最小的存储…

vue下载阿里OSS上的图片与视频,纯前端实现,以及纯JS下载图片案例

vue下载阿里OSS上的图片与视频&#xff0c;以及纯JS下载图片案例 1. 简介与日常使用2. Vue下载阿里OSS上的图片与视频3. 调用&#xff08;单个与批量下载均可使用&#xff09;4. 纯JS下载图片案例&#xff0c;Vue里面也可以用 1. 简介与日常使用 参考这篇文章即可&#xff1a;…

pandas.DataFrame() 数据自动写入Excel

DataFrame 表格数据格式 &#xff1b; to_excel 写入Excel数据&#xff1b; read_excel 阅读 Excel数据函数 import pandas as pd#df2 pd.DataFrame({neme: [zhangsan, lisi, 3]}) df1 pd.DataFrame({One: [1, 2, 3],name: [zhangsan, lisi, 3]})#One是列明&#xff0c;123是…

PHP 基础编程 2

文章目录 时间函数dategetdatetime 使用数组实现登录注册和修改密码简单数组增加元素方法修改元素方法删除元素方法 具体实现方法数组序列化数组写入文件判断元素是否在关联数组中&#xff08;登录功能实现&#xff09;实现注册功能实现修改admin用户密码功能 时间函数 时区&am…

ChatGPT论文指南|ChatGPT助力论文论点提炼详细流程!【建议收藏】

点击下方▼▼▼▼链接直达AIPaperPass &#xff01; AIPaperPass - AI论文写作指导平台 公众号原文▼▼▼▼&#xff1a; ChatGPT论文指南|ChatGPT助力论文论点提炼详细流程&#xff01;【建议收藏】 上一篇文章中我们了解到如何使用ChatGPT查阅选题相关文献&#xff0c;并进…

离线Vscode 安装完成后 添加到右键菜单

复制下面代码&#xff0c;修改文件后缀名为&#xff1a;reg Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\*\shell\VSCode] "Open with Code" "Icon""D:\\_Porgram_IT\\VsCode\\Code.exe"[HKEY_CLASSES_ROOT\*\shell\VSCode\comman…

多商家多坐席客服系统的创建与智能分配

系统本身是属于多商家多坐席SaaS客服系统&#xff0c;每个商家账号之间是独立的互相不可见&#xff0c;商户下可创建商户子账号。 系统存在三种角色&#xff1a;管理员&#xff0c;商户主账号&#xff0c;商户子账号 管理员权限可以查看系统中的所有账号&#xff0c;以及查看所…

【Storm实战】1.1 图解Storm的抽象概念

文章目录 0. 前言1. Storm 中的抽象概念1.1 流 (Stream)1.2 拓扑 (Topology)1.3 Spout1.4 Bolt1.5 任务 (Task)1.6 工作者 (Worker) 2. 形象的理解Storm的抽象概念2.1 流 (Stream)2.2 拓扑 (Topology)2.3 Spout2.4 Bolt2.5 任务 (Task)2.6 工作者 (Worker)场景1场景2 3.参考文档…

突破技术边界:R与jsonlite库探秘www.snapchat.com的数据之旅

概述 Snapchat是一款流行的社交媒体应用&#xff0c;它允许用户发送和接收带有滤镜和贴纸的照片和视频&#xff0c;以及创建和观看故事和发现内容。Snapchat的数据是非常有价值的&#xff0c;因为它可以反映用户的行为、偏好和趋势。然而&#xff0c;Snapchat的数据并不容易获…

微信小程序中获取用户当前位置的解决方案

微信小程序中获取用户当前位置的解决方案 1 概述 微信小程序有时需要获取用户当前位置&#xff0c;以便为用户提供基于位置信息的服务&#xff08;附近美食、出行方案等&#xff09;。 获取用户当前位置的前提是用户手机需要打开 GPS 定位开关&#xff1b;其次&#xff0c;微…

el-cascader隐藏某一级的勾选框及vue报错Error in callback for watcher “options“的解决办法

今天用到饿了么的级联选择器时出现了这个报错Error in callback for watcher “options“: “TypeError: Cannot read propertie ‘level‘ of null,因为需求是在不同类型 el-cascader多选的时候默认是可以勾选所有级的选项的,如下图: 包含级联cascader的options、select的…

旋转图像(LeetCode 48)

文章目录 1.问题描述2.难度等级3.热门指数4.解题思路参考文献 1.问题描述 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在「原地」旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。 示…

文件管理方法:利用文件大小进行筛选,高效移动文件至目标文件夹

在日常工作中&#xff0c;文件管理是一项至关重要的任务。为了更高效地管理文件&#xff0c;可以利用文件大小进行筛选&#xff0c;并将文件快速移动至目标文件夹。接下来一起来看看云炫文件管理器如何利用文件大小进行筛选&#xff0c;以及如何高效移动文件至目标文件夹的方法…

树莓派外设开发综述及WiringPi库安装

树莓派常用的接口 IO&#xff1a; input&#xff1a; output&#xff1a; PWM&#xff1a; IIC spi uart WiringPi库 树莓派一个非常重要的 WiringPi库&#xff08;Linux下 动态库 ”.so“ 静态库”.a"&#xff09; &#xff08;是一个特定平台&#xff0c;特…

Linux第8步_USB设置

学习完设置“虚拟机的电源”后&#xff0c;接着学习通过鼠标点击操作U盘&#xff0c;目的是了解USB设置。 1、在桌面&#xff0c;双击“VMware Workstation Pro”图标&#xff0c;得到下图&#xff1a; 2、点击“编辑虚拟机”&#xff0c;得到下图&#xff1a; 只要点击编辑虚…

私域营销,让你的生意从线下到线上都火爆!

一、提高流量 获取流量的五个关键要素&#xff1a;目标受众、传播渠道、内容策略、短期利益和长期价值 在当今竞争激烈的市场环境中&#xff0c;获取流量是每个企业和个人都必须面对的挑战。为了有效地吸引潜在客户&#xff0c;我们需要关注五个关键要素&#xff1a;目标受众…

DVenom:一款功能强大的Shellcode加密封装和加载工具

关于DVenom DVenom是一款功能强大的Shellcode加密封装和加载工具&#xff0c;该工具专为红队研究人员设计&#xff0c;可以帮助红队成员通过对Shellcode执行加密封装和加载实现反病毒产品的安全检测绕过。 功能介绍 1、支持绕过某些热门反病毒产品&#xff1b; 2、提供了多种…

手把手教你,Selenium 遇见伪元素该如何处理?

Selenium 遇见伪元素该如何处理&#xff1f; 前言 问题发生 在很多前端页面中&#xff0c;大家会见到很多&#xff1a;:before、::after 元素&#xff0c;比如【百度流量研究院】&#xff1a; 比如【百度疫情大数据平台】&#xff1a; 以【百度疫情大数据平台】为例&#xff…

Prometheus-AlertManager 邮件告警

环境,软件准备 本次演示环境&#xff0c;我是在虚拟机上安装 Linux 系统来执行操作&#xff0c;以下是安装的软件及版本&#xff1a; System: CentOS Linux release 7.6Docker: 24.0.5Prometheus: v2.37.6Consul: 1.6.1 docker 安装prometheus,alertmanage,说明一下这里直接将…