PH47代码框架软件二次开发极简教程
1. 教程说明
本教程适用于对飞控及Stm32程序设计比较熟悉的二次开发者快速掌握PH47框架的使用要点。本教程仅对PH47框架中最主要的二次开发特性进行简要说明,建议与框架中\DevStudio\Algorithms\Controller_Demo.cpp(.h)示例代码配合学习。关于二次开发特性中的详细或高级内容,请参见《PH47框架二次开发教程》。
对于飞控或是Stm32编程不是太熟练的开发者,建议先了解学习Stm32程序设计相关内容,以及《PH47框架二次开发教程》。
1.1 基本概念
- 时间相关、循环控制、调试功能大部分基本功能由框架层全局函数实现。
- 整个PH47框架内,数据读取、写入、交换等操作均依托框架层的数据总线系统(frm.bus),以frm.bus.Function()方式使用。
- 机载调参参数(控制参数)的读取、写入存储均通过框架层的参数系统(core.para)实现,以core.para.Function()方式使用。
- 用户代码一般位于应用层Application当中实现。应用层为用户提供了初始化、快速循环,普通循环、慢速循环函数,以及GCS上行指令响应函数、控制台指令响应函数等重要函数框架供用户扩充使用。
2. 基本全局功能函数使用
2.1 常用全局时间函数
函 数 | 功 能 描 述 |
HAL_Delay() | 用于ms 级延时,执行时独占系统资源 |
osDelay() | 用于ms 级延时。osDelay() 依赖于 FreeRTOS 启动完成,延时期间可以将系统资源轮换给其他线程使用 |
gDelay_us() | 用于 us 级别延时。延时时间不要超过 1000us |
gGetMills() | 获取调用时刻距离 mcu 加电启动时刻的ms时间间隔, 获取数据范围为 4294967296ms,即1193 hour |
gGetMills_f() | 获取精确到小数点后3位的ms时间, 即精确到us。 gGetMills_f()在运行时间超过4800s后会溢出重置为 0 后重新开始计时 |
gGetMicros() | 获取mcu加电以来的us时间。 注意: us计时器溢出时间为600s |
2.2 调试功能使用
函 数 | 功 能 描 述 |
TRACE() | 使用邮件队列方式显示格式化字符串。 具有线程安全性,且连续调用能够确保顺序正确。依赖于 PH47 框架的启动完成, 框架启动前不能正常工作。显示时刻会晚于函数调用时刻(滞后不高于 10ms 级别) 。 TRACE("\r\ndemo> 1. TRACE at %.3fms", gGetMills_f()); |
gPrintf() | 使用中断方式显示格式化字符串。 不依赖于框架的启动完成。连续密集调用时显示的先后顺序可能会发生改变 gPrintf("\r\ndemo> 2. gPrintf at %.3fms", gGetMills_f()); |
ASSERT(f) | 表达式f真值确认。 若表示式f为false,则核心板状态指示LED连续快速闪烁,当前线程执行停止在ASSERT()语句处,同时在调试串口输出ASSERT语句所在的文件名及代码行号。 |
bus.arDbg_1[10] bus.arDbg_2[10] | 调试专用总线数据项。只需将调试数据赋值给总线数据项即可。 PH47框架已经预置了调试数据的下行发送机制,用户无需自己实现。 调试数据默认下行发送频率为25hz,运行过程中可调整。 |
3 使用CFreqDiv类进行循环频率控制
- 1/3: 在.h文件中定义一个CFreqDiv类对象_FreqDemo_1Hz。
CFreqDiv _FreqDemo_1Hz;
- 2/3: 适当位置对_FreqDemo_1Hz对象进行初始化,如在.cpp文件初始化函数中,设定循环间隔。
_FreqDemo_1Hz.SetRunInv_ms(1000); // 循环控制间隔为 1000ms, 即 1Hz
- 3/3: 在需要进行循环频率控制的位置通过IsSetRunInv_ms()函数判断是否达到循环控制条件。此处注意:_FreqDemo_1Hz对象的IsSetRunInv_ms()函数调用在同一循环中只能在一个位置出现一次,不能在多个不同位置多次调用。
if(_FreqDemo_1Hz.IsSetRunInv_ms())
{// do something…
}
4. 数据总线基本操作
数据总线系统为整个PH47代码框架提供了设置、获取、交换数据的方法和途径。以及获取诸如设置获取数据时间戳,数据设置时间间隔,数据权限控制等功能。
数据总线系统由一系列总线数据项(Bus item)构成,总线数据项既可以是包含了一个数据简单类型(如 uint8_t,int32,float等)的数据项,也可以是多个具有相关性的数据构成的复杂类型数据项,如结构变量。
4.1 数据总线系统文件包含
用户要在自己的代码文件中使用数据总线功能,只需在自己的.cpp文件开始出加入如下文件包含:
#include"../../Frame/UseGlobalObject.h" //文件包含路径根据实际情况确定
数据总线中数据项的声明位于如下文件中:
\DevStudio\BoardConfig\Board_BBDB\DataBus_BBDB.h
数据总线中复杂类型数据项(框架内置)的结构声明位于如下文件中:
\DevStudio\Frame\Core\BusItemFormatDef.h
4.2 数据总线功能函数使用
函 数 | 功 能 描 述 |
Get() | 读取数据总线数值 Vector3f vAcc = bus.sImu.AccRaw.Get(); // 获取总线数据项数值 TRACE("\r\n> Acc %.2f %.2f %.2f", vAcc.x, vAcc.y, vAcc.z); |
Set() | 设置数据总线数值。 本函数在设置总线数值的同时,对当前总线数据的时间戳进行了设置。 // demo 1 bus.arDbg_2[0].Set(2.234); // demo 2 MICOLINK_PAYLOAD_RANGE_SENSOR_t payload; payload.distance = 10.5f; payload.strength = 1.0f; bus.OptiFlowTof_MTF01.Set(&payload); // 设置总线数据项数值 |
GetTimeStamp_ms() | 获取 AccRaw 以 ms 为单位时间戳的整数部分,示例见下。 |
GetTmStampDec_us() | 获取 AccRaw 以 ms 为单位时间戳的 3 位小数部分(即精确到 us),示例见下。 |
GetDt2Prev_us() | 获取总线数据项最近两次被设置(Set)之间的时间间隔(us) // 上述三个函数综合示例 TRACE("\r\n> AccRaw timeTag:%d.%dms dt:%dus", bus.sImu.AccRaw.GetTimeStamp_ms(), // 时间戳整数部分(ms) bus.sImu.AccRaw.GetTmStampDec_us(), // 时间戳小数部分(us) bus.sImu.AccRaw.GetDt2Prev_us()); // 最近两次设置时间间隔(us) |
4.3 全局变量
全局变量变量是一种特殊的总线数据,用于在整个PH47代码框架内表示系统状态,分为bool型和uint8_t型两种类型。整个框架共有48个bool型,8个uint8_t类型全局变量。
PH47代码框架以及CSS插件已经预置了全局变量的发送及解析机制,以5Hz频率下行发送更新。用户在PH47框架中只需对其进行设置或读取即可。
函 数 | 功 能 描 述 |
gGetStatus() GetStatus() | 读取全局变量数值。 gGetStatus()等同于GetStatus(),只是前者为全局函数形式,后者需要通过core对象进行引用。 gGetStatus(S_IMU_STILL); // bool 类型 core.GetStatus(S_RC_ALIVE); uint8_t uTmp = gGetStatus(S_SYSTEM_STATUS_TAG); // uint8_t 类型 |
gSetStatus() SetStatus() | 设置全局状态变量。 参数blForceUpdate为true表示无论当前全局状态变量数值如何都进行设置。 false表示若待设置数值与当前数值相同就不进行设置 gSetStatus(S_WATCH_DOG_MODE, true, true); |
4.4 自定义简单类型总线数据项
在\DevStudio\BoardConfig\Board_BBDB\DataBus_BBDB.h文件中注释为"用户自定义设置区域"内加入自有总线数据的定义(注意!不要对该区域以外的总线数据声明进行任何修改或删除!):
// <=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>
// 用户自定义参数设置区域, 不得对该区域之外的任何内容进行修改
CBusItem<float> fAspdDiffPress; // float类型的bus item
// <=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>
之后就可以使用总线相关函数实现各种功能了
4.5 自定义复杂类型总线数据项目
- 1/3:在需要使用总线的.cpp文件头部加入对数据总线的文件包含:
#include"../../Frame/UseGlobalObject.h"
- 2/3:在如下文件中加入对复杂类型的结构声明(用户自定义):
\DevStudio\BoardConfig\Board_BBDB\BusItemDef4User.h
struct BUS_ITEM_DEMO
{CBusItem<uint8_t> Item_A;CBusItem<float> Item_B;
};
- 3/3:在\DevStudio\BoardConfig\Board_BBDB\DataBus_BBDB.h文件的“用户自定义参数设置区域”加入总线数据的定义:
// <=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>
// 用户自定义参数设置区域, 不得对该区域之外的任何内容进行修改
BUS_ITEM_DEMO sBusItemDemo;
// <=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>
4.6 自定义全局状态变量
文件DevStudio\BoardConfig\Board_BBP\StateVarDef_BBP.h对全局状态变量的ID进行了定义,此文件中的enum STATUS_BOOL及enumSTATUS_UINT枚举分别定义了bool及uint8_t类型的全局状态变量ID。
与自定义总线数据类似,自定义全局状态变量必须位于标注“用户自定义参数设置区域”的区域内。二次开发者不能对该区域意外的任何内容进行删除或修改。
- 1/2:在DevStudio\BoardConfig\Board_BBDB\StateVarDef_BBDB.h文件的enum STATUS_BOOL声明的用户自定义部分加入S_STATUS_VAR_DEMO声明
// <=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>
// 用户自定义 全局状态变量 设置区域, 不得对该区域之外的任何内容进行修改
S_STATUS_VAR_DEMO, // 直接定义 id 即可
// <=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>
- 2/2:之后在程序中需要的地方就可以通过下述函数设置或是获取状态;
gSetStatus(S_STATUS_VAR_DEMO, true);
bool blStatus = gGetStatus(S_STATUS_VAR_DEMO);
5. 机载参数系统基本操作
机载控制参数系统为整个PH47代码框架提供了控制参数的读取、写入、空地间传输等功能的全套使用解决方案。
机载参数数据存储于控制板外置 flash 或 eeprom 存储器中。可通过 CSS控制站以单个或批量的方式下载及上传设定。
5.1 参数系统文件包含
用户要在自己的代码文件中使用参数系统功能,只需在自己的.cpp文件开始处加入如下文件包含:
#include"../../Frame/UseGlobalObject.h" //文件包含路径根据实际情况确定
参数系统的参数id定义,以及参数默认属性设置(参数字典),分别位于如下文件中:
\DevStudio\BoardConfig\Firmware_BBDB\ParamDict_BBDB.h
\DevStudio\BoardConfig\Firmware_BBDB\ParamDict_BBDB.cpp
5.2 参数系统功能使用
函 数 | 功 能 描 述 |
Get() | 读取记载参数数值。 Get() 函数获取的参数存储于RAM中,若存储器(flash/e2prom)中参数被CSS上传设定所更新,或被程序中其他参数设定函数所改变,则RAM中参数数值也自动更新,用户无需手动刷新。 // 获取当前设定的遥测通讯波特率 uint32_t uBaudRate = (uint32_t)(core.para.Get(P_BAUD_RATE)); // 获取加速度计x轴偏移量 float fVal = frm.para.Get(P_SENSOR_ACC_OFST_X); |
Set() | 设置机载调参参数数值。 blForcesave决定是否对存储介质(Flash或EEprom)存储数据进行强制更新。 为 ture时不能进行高速率(>50hz)密集调用,否则有可能造成存储器密集写入超时而导致数据存储失败 // 设置参数数值强制更新存储 core.para.Set(P_SENSOR_ACC_OFST_X, _cal_acc_offset.x, true); // 仅对RAM当中的参数数值进行更新,控制板重启后丢失 frm.para.Set(P_SENSOR_ACC_OFST_X, blSave) |
5.3 自定义参数的实现
- 1/3:在ParaDict_BBDB.h文件enum PARAID枚举定义的用户区域当中加入新参数P_TEST_USER_1的 id 的定义,无需为id指定特定数值,顺序排列即可。在 CSS 参数下载列表中的顺序以enum PARAID当中的顺序为准。
// <=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>// 用户自定义参数设置区域, 不得对该区域之外的任何内容进行修改P_TEST_USER_1, // 自定义参数 id// <=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>
- 2/3:在ParaDict_BBDB.cpp文件全局数组g_arParaDictMCU[]参数字典的用户区域中加入新参数的属性数据。enum PARAID中参数id的数值及顺序与g_arParaDictMCU[]各元素均无关系,可根据实际需要组织。
// <=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>// 用户自定义参数设置区域, 不得对该区域之外的任何内容进行修改// 自定义参数 P_TEST_USER_1 的默认属性进行设置//{"TestUser_1", P_TEST_USER_1, 0x0000, 256.0f, 0.0f, 500.0f}, // <=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>
- 3/3;修改参数字典并编译下载至控制板后,必须通过控制板的调试串口运行一次 "initfstrun;"命令以初始化存储器数据。
6. 遥测通讯系统使用
PH7 代码框架通过 mavlink plus 协议与地面控制站 GCS,或其他无人控制目标进行双向通讯。mavlink plus 协议在mavlink 1.0基础上增加修改了message 设置,并对 GCS 上行控制命令实施真伪性动态甄别。
6.1 遥测通讯系统文件包含
若在用户二次开发代码中使用mavlink通讯功能,那么就需要在自己的代码中加入如下文件包含:
#include "/DevStudio/Frame/Core/MavlinkInterface.h"#include "/DevStudio/Frame/Core/MavlinkWrap.h"
6.2 遥测通讯系统功能使用
在整个 PH7 代码框架内对 GCS 的数据通讯以core.mavlink.FunName()的形式来使用 mavlink 协议相关功能函数。
对其他控制目标的数据通讯以core.consolelink.FunName()的形式来使用 mavlink 通讯相关功能函数。
PH47代码框架已对Message的下行发送进行了完善的封装,为不同类型的Message设定了不同的发送速率,发送速率在运行过程中可重新设定调整。整个Message的下行发送机制为全自动执行,用户在仅需在发送message时以core.mavlink.AddMsg_xxx()形式调用对应函数,即可将待发送消息加入下行消息发送队列随即自动发送。二次开发用户常用消息发送函数如下:
函 数 | 功 能 描 述 |
AddMsg_Ctrl_Base() | 下行发送飞控控制器相关数据 |
AddMsg_Atms_Data() | 下行发送大气相关数据 |
AddMsg_GpsRawInt() | 下行发送GPS相关数据 |
AddMsg_Raw_Imu() | 下行发送IMU相关数据 |
AddMsg_Attitude() | 下行发送姿态相关数据 |
AddMsg_Debug_1() | 下行发送调试数据 1 |
AddMsg_Debug_2() | 下行发送调试数据 2 |
AddMsg_StatusText() | 下行发送状态信息 |
mavlink message 发送示例:
// demo 1: 下行发送心跳包
mavlink_heartbeat_t packet;
memset(&packet, 0x00, sizeof(packet));packet.base_mode = (uint8_t) 6;
packet.system_status = 0xA5;
packet.autopilot = BOARD_PH7;
packet.custom_mode = 0xEE;
packet.mavlink_version = MAVLINK_VERSION;uRet = core.mavlink.AddMsg_HeartBeat(&packet); // 加入发送队列,随后自动发送
demo 2: 下行发送状态信息
char szTmp[32] = {""};
gFormat(szTmp, "Log %d HIL sim start.", uFlightNum);
core.mavlink.AddMsg_StatusText(szTmp, MAV_SEVERITY_WARNING);// 更多Message发送使用方法可见文件:\DevStudio\Frame\Frame.cpp 当中的
// void MavMsgSnd2GCS_Slow() 函数
7. 应用层框架预制功能函数的使用
PH47框架在应用层\DevStudio\Application\App_BBP.cpp(.h)文件,即应用层类CAppBBDB中预置了多个供二次开发用户使用的功能函数,用户根据上述函数的功能特性,有针对性的在其中加入自己的代码即可方便的进行二次开发。
函数名称 CAppBBDB类成员函数 | 功 能 描 述 |
Init() | PH47框架完全启动后调用该初始化函数 在本函数中可安全使用 ASSERT, TRACE 等依赖于框架启动的函数 |
FastThread_1000Hz() | 快速线程函数,调用频率在400—500hz之间波动。 |
NormalThread_250Hz() | 普通线程函数,调用频率固定为250hz |
SlowThread_50Hz() | 慢速线程函数,调用频率固定为50hz |
HandleRevMavlinkMsg() | mavlink 用户自定义上行控制指令处理函数 |
HandleConsoleCmd() | 调试控制台用户自定义命令处理函数 |
7.1 程序示例:
普通线程函数示例
void CAppBBDB::NormalThread_250Hz()
{// 获取循环间隔时间float fDt = 0.0f;if(_NormalLoopDt.GetLocalDt_ms(fDt) == false)return;// Controller_Common 示例代码algo._pController_Common->Update(fDt);
}
接收 mavlink message 用户自定义上行指令处理示例
void CAppBBDB::HandleRevMavlinkMsg(mavlink_command_long_sa_t *pPacket)
{//解析及响应 GCS 上行控制命令if(pRevMsg ->msgid == MAVLINK_MSG_ID_COMMAND_LONG_SA ){mavlink_command_long_sa_t packet;mavlink_msg_command_long_sa_decode(pRevMsg, &packet);if(packet.command == MAV_CMD_USER_DEFINE){ if(packet.param1 == fValue){// User code ...}}}
}
用户自定义调试控制台命令处理函数示例
void CAppBBDB::HandleConsoleCmd(uint8_t *pBuff)
{// pBuff 为用户命令字符串,命令字符串最长不能超过 32 byteif(strcmp((char *) pBuff, "User CMD") == 0){// User code ...}
}
更多内容见CSDN博客专栏:无人机飞控https://blog.csdn.net/ss15/category_9690939.html?spm=1001.2014.3001.5482相关资源:PH47: PH47运动控制代码框架.
https://gitee.com/ss15/ph47
相关文章:

PH47代码框架软件二次开发极简教程
1. 教程说明 本教程适用于对飞控及Stm32程序设计比较熟悉的二次开发者快速掌握PH47框架的使用要点。本教程仅对PH47框架中最主要的二次开发特性进行简要说明,建议与框架中\DevStudio\Algorithms\Controller_Demo.cpp(.h)示例代码配合学习。关于二次开发特性中的详细…...

SQL Server-导入和导出excel数据-注意事项
环境: win10,SQL Server 2008 R2 之前写过的放在这里: SqlServer_陆沙的博客-CSDN博客 https://blog.csdn.net/pxy7896/category_12704205.html 最近重启ASP.NET项目,在使用sql server导出和导入数据时遇到一些问题,特…...

Linux系统:配置Apache支持CGI(Ubuntu)
配置Apache支持CGI 根据以下步骤配置,实现Apache支持CGI 安装Apache: 可参照文章: Ubuntu安装Apache教程。执行以下命令,修改Apache2配置文件000-default.conf: sudo vim /etc/apache2/sites-enabled/000-default.con…...

qt 序列化和反序列化
序列化:QByteArray buffer; QBuffer bufferDevice(&buffer); bufferDevice.open(QIODevice::WriteOnly); QDataStream out(&bufferDevice); out.setVersion(QDataStream::Qt_5_13); 反序列化: void deserialize(const QByteArray &buffer) {…...

java实现文件变动监听
在文件的内容发生变动时,应用可以感知这种变种,并重新加载文件内容,更新应用内部缓存 实现 轮询:定时器Timer,ScheduledExecutorService 判断文件修改:根据java.io.File#lastModified获取文件的上次修改时…...

Maven的使用
1. Maven 简介 https://maven.apache.org/ Maven 是一个强大的项目管理和构建工具,广泛应用于 Java 项目中,旨在简化项目的依赖管理、构建、测试、部署等工作。Maven 主要通过定义 pom.xml(Project Object Model 文件)来管理项…...

C++开发进阶1:C++编程命名规范
进行C开发时最基础且最重要的是命名规范,掌握良好的命名规范能增加代码的可读性。 认识文件: .cpp:C 源文件. .h或.hpp:C 头文件 .tpp模板实现文件(如果模板定义和实现分开) .inl内联文件,…...

Android 图片相识度比较(pHash)
概述 在 Android 中,要比对两张 Bitmap 图片的相似度,常见的方法有基于像素差异、直方图比较、或者使用一些更高级的算法如 SSIM(结构相似性)和感知哈希(pHash)。 1. 基于像素的差异比较 可以逐像素比较…...

Gitlab 完全卸载–亲测可行
1、停止gitlab gitlab-ctl stop2.卸载gitlab(注意这里写的是gitlab-ce) rpm -e gitlab-ce 3、查看gitlab进程 ps aux | grep gitlab 4、杀掉第一个进程(就是带有好多.............的进程) 5、删除所有包含gitlab文件 find / …...

gitlab操作和管理
详细的说明下这几条指令: Git global setup git config --global user.name “” git config --global user.email “” Create a new repository git clone ssh://git12/letect.git cd vlm-event-secondary-detect git switch -c main touch README.md git add RE…...

ctfshow-web入门-反序列化(web254-web258)
目录 1、web254 2、web255 3、web256 4、web257 5、web258 1、web254 传入符合要求的用户名和密码即可: ?usernamexxxxxx&passwordxxxxxx 拿到 flag:ctfshow{e4795ccd-6bff-44b6-a15c-6c679d802e61} 2、web255 整体逻辑代码和上一道差不多 新…...

repo 命令大全详解(第十一篇 repo init)
repo forall 命令用于在指定的项目上执行给定的命令,非常适合批量操作。 参数分类及解释 基本参数 [<project>...]: 可选,指定要操作的项目。如果不指定,则对所有项目执行命令。 示例: repo forall my_project -c "git status&q…...

ComfyUI | 全新ComfyUI前端操作指南:提升你的工作速度!
随着WebUI基本停更,越来越多的AI创作者转向了ComfyUI。 ComfyUI最大的优势是简洁、高效、占用显存低,工作流模式虽然有一点入门难度,但一旦上手,操作非常舒适。 由于原Stable Diffusion团队的参与,ComfyUI的易用度也…...

nginx解决非人类使用http打开的443,解决网安漏扫时误扫443端口带来的问题
一、问题描述 正常访问https的站点时,使用网址https://www.baidu.com,但会有一种错误的访问请求http://www.baidu.com:443,一般都是非人类所为,如漏洞扫描工具,那么请求以后带来的后果是个错误页面 400 Bad Request T…...

黑马 | Reids | 基础篇
黑马reids基础篇 文章目录 黑马reids基础篇一.初始Redis1.1SQL 和 NoSql的区别1.1.1结构化和非结构化1.1.2关联和非关联1.1.3查询方式1.1.4 事务1.1.5总结 1.2 认识Redis1.3 Redis安装启动默认启动:后台启动:开机自启 1.4 Redis客户端1.4.1.Redis命令行客…...

SAP-换登录界面图片
SMW0 二、SM30 (将value值删除,登录图片恢复默认) 重新登录,更改成功。...

移动 Web核心笔记(二)
空间转换 空间:是从坐标轴角度定义的 X 、Y 和 Z 三条坐标轴构成了一个立体空间,Z 轴位置与视线方向相同。 空间转换也叫 3D转换 属性:transform 平移 /*单独设置 z轴效果不明显*/ transform: translate3d(x, y, z); transform: translateX(…...

MySQL创建和管理表
1. 基础知识 存储数据是处理数据的第一步,只有正确地把数据存储起来,才能进行有效的处理和分析。 在 MySQL 中,一个完整的数据存储过程总共有 4 步,分别是创建数据库、确认字段、创建数据表、插入数据。 从系统架构的层次上看…...

【从零开始的LeetCode-算法】910. 最小差值 II
给你一个整数数组 nums,和一个整数 k 。 对于每个下标 i(0 < i < nums.length),将 nums[i] 变成 nums[i] k 或 nums[i] - k 。 nums 的 分数 是 nums 中最大元素和最小元素的差值。 在更改每个下标对应的值之后…...

周报 | 24.10.14-24.10.20文章汇总
为了更好地整理文章和发表接下来的文章,以后每周都汇总一份周报。 周报 | 24.10.7-24.10.13文章汇总-CSDN博客 OpenCV与AI深度学习 | T-Rex Label !超震撼 AI 自动标注工具,开箱即用、检测一切-CSDN博客 计算机视觉与机器学习 | 目标检测 …...

Codeforce 980 Div2 A-D 题解
A. Profitable Interest Rate 原题 A. Profitable Interest Rate 思路 易推出公式 2 * a - b 代码 #include <bits/stdc.h> //#define int long long#define F(i, a, b) for (int i (a); i < (b); i) #define dF(i, a, b) for (int i (a); i > (b); i--)usi…...

一次代码优化的过程
场景说明: wpf项目,有4个不同的页面,共用一个next按钮,实现点击后跳转到下一个页面。 第一个页面是导入文件,当有2个及以上文件时,会弹窗提示。如下图所示: 之前和之后的代码对比: 之…...

多线程的学习(1)
线程的创建方式 1.继承Thread类 package duoXianCheng;public class MyThread extends Thread{public void run(){System.out.println("hoh");}public static void main(String[] args) {MyThread m1 new MyThread();m1.start();//start启动线程,调用重…...

PyCharm借助MobaXterm跳板机连接服务器
服务器信息: Step 1 MovaXterm→Session→SSH输入服务器信息 Step 2 MovaXterm→Session→SSH→Network setting→SSG gateway(jump host) 输入跳板机信息 键入密码即可 Step 3 MovaXterm→Tunneling→New SSH tunnel 依次输入:A本机端口,…...

计算机毕业论文基于Android 的签到系统设计与实现
计算机专业本科毕业设计(论文)开题报告 毕业设计(论文)题目:基于Android的签到系统设计与实现 文章目录 毕业设计论文开题报告一、课题的目的及意义(含国内外的研究现状分析):二、课题任务、重点研究内容、实现途径、条件:摘 要1. 绪论1.1. 研究背景1.2. 研究现状1.3.…...

量化学习-02
1、宏观经济学基础概念 宏观经济简单背景 宏观经济,就是在宏观范畴以全局视角观察经济现象,分析其中的经济总量。该宏观范畴所包含的范围可以指一个国家或地区,是由众多微观个体组成的一个经济体,而这里面的微观个体可以指一个家…...

SAP_MM模块-设置业务合作伙伴类型字段必输(多种方案)
一、业务背景 公司需要把供应商增加一个细分的维度,并且要求该字段设置为必输,防止用户新增供应商时忘记维护。这里给用户找了一个分类的字段:业务合作伙伴类型,本文主要讲解如何设置该字段设置为必填; 注意ÿ…...

STM32平台上实现串口接收不定长数据-实际项目中应用
文章目录 一、中断串口监听方式初始化中断处理串口监听 二、空闲中断方式三、空闲中断DMA方式四、总结 本文将详细介绍在STM32平台上实现串口接收不定长数据的几种方法 一、中断串口监听方式 这种方式也是我早期使用的方式,直接使用寄存器来操作,这种方…...

AWD入门
一、简介 AWD(Attack With Defense,攻防兼备)模式。你需要在一场比赛里要扮演攻击方和防守方,攻者得分,失守者会被扣分。也就是说攻击别人的靶机可以获取 Flag 分数时,别人会被扣分,同时你也要保护自己的主机不被别人…...

T3矩阵看功率
每个像素的T3矩阵,功率等于特征值的和。 不同的像素的T3矩阵相加,可不能用特征分解的相加,因为两个T矩阵的特征向量不同...