基于STM32F429移植UCOSIII

news2024/9/22 19:28:22

μC/OS-III(Micro C OS Three)是一个可升级的、可固化的、基于优先级的实时内核,它是Micrium公司出品的RTOS(实时操作系统)类实时操作系统的一个版本。以下是对μC/OS-III的详细描述:

1. 基本特性

  • 多任务管理:μC/OS-III是一个支持多任务抢占的内核,总是优先执行任务优先级高的任务。它支持时间片调度,允许系统中有多个相同任务优先级的任务,通过时间片的方式轮流调度这些任务。
  • 任务数量不限:μC/OS-III理论上支持不受限制的任务数量,但实际上,系统中任务的最大数量受处理器内存空间的限制。
  • 任务优先级数量不限:μC/OS-III支持的任务优先级数量不受限制,但对于大多数应用场景而言,使用32~256个任务优先级就绰绰有余了。
  • 内核对象数量不限:μC/OS-III提供了多种内核对象,如任务、信号量、事件标志、消息队列、软件定时器和内存区等,用户可以在不考虑处理器内存限制的情况下无限制地创建这些内核对象。

2. 任务管理

  • 任务创建、删除、挂起和恢复:μC/OS-III支持任务的创建、删除、挂起和恢复等操作,以及任务调度和切换。
  • 时间片轮转调度:当多个相同优先级的任务就绪时,μC/OS-III将以时间片的方式调度这些任务,即根据用户指定的时间(时间片)轮流调度这些任务。

3. 中断处理

  • 极短的中断禁用时间:μC/OS-III通过锁定任务调度器代替禁用中断来保护一些关键区域(临界区),这确保了μC/OS-III能够快速地响应中断。

4. 信号量和消息队列

  • 信号量机制:μC/OS-III提供了二值信号量、计数型信号量和互斥信号量,用于任务同步和资源管理。
  • 任务内嵌信号量和消息队列:μC/OS-III允许任务直接获取来自其他任务或中断的信号和消息,而不需要任何的中间内核对象,这大大提高了系统的运行效率。

5. 其他特性

  • 时间戳:μC/OS-III提供了时间戳功能,用户可以方便地测量系统在运行过程中处理器处理某些事件所消耗的时间。
  • 自定义钩子函数:μC/OS-III提供了一些在内核执行操作之前、之后或过程中的钩子函数,以便用户扩展μC/OS-III的功能。
  • 防死锁:μC/OS-III允许任务在等待某些内核对象前,设置一个等待的最大超时时间,以有效地防止死锁的发生。
  • 软件定时器:用户可以创建任意数量的“单次”和“周期”软件定时器,并且每个软件定时器都可以有独立的超时回调函数。

6.在STM32F429移植UCOSIII

6.1 移植环境

单片机:STM32F429IGT6

固件库:HAL库

编程软件:Keil 5.38

操作系统:UCOSIII 3.04

6.2 UCOSIII源码

下载好的UCOSIII 3.04 源码如下图所示,如果找不到源码下载渠道的朋友可以评论获取。

(1)EvalBoards文件夹是关于STM32F429的工程文件

(2)uC-CPU文件夹是与CPU相关的代码。

(3)uC-LIB文件夹是一些可移植的但是和编译器没有关系的函数组成的,UCOSIII用不到,但移植的时候需要复制过去。

(4)uCOS-III文件夹里面包含CPU平台的文件和UCOSIII的源码。

6.3 开始移植

(1)本次移植以跑马灯项目为基础,在项目中创建UCOSIII文件夹,然后将源码uC-CPU、uC-LIB、uCOS-III三个文件夹复制过去。

(2)在项目中的UCOSIII文件夹中创建UCOS_BSP、UCOS_CONFIG两个文件夹。

(3)将 源码目录 EvalBoards\ST\STM32F429II-SK\BSP 文件夹下面的 bsp.c、bsp.h两个文件复制到项目UCOS_BSP文件夹下。

(4)将源码目录 EvalBoards\ST\STM32F429II-SK\uCOS-III 文件夹中的下面这些文件复制到项目的UCOS_CONFIG文件夹下。

(5)在项目工程中创建以下分组:

(6)将源码文件导入到项目中。

(7)给项目添加头文件配置信息。

(8)此时编译一下有个报错,修改 bsp.h下面的 stm32f4xx_conf.h 为 stm32f4xx_hal.h ,再编译一下报错更多了,还是因为bsp文件的问题,下面对其进行修改。

修改过程比较复杂,改完后代码如下:

bsp.c

#define   BSP_MODULE
#include  <bsp.h>


/*
*********************************************************************************************************
*                                             REGISTERS
*********************************************************************************************************
*/

#define  BSP_REG_DEM_CR                           (*(CPU_REG32 *)0xE000EDFC)
#define  BSP_REG_DWT_CR                           (*(CPU_REG32 *)0xE0001000)
#define  BSP_REG_DWT_CYCCNT                       (*(CPU_REG32 *)0xE0001004)
#define  BSP_REG_DBGMCU_CR                        (*(CPU_REG32 *)0xE0042004)

/*
*********************************************************************************************************
*                                            REGISTER BITS
*********************************************************************************************************
*/

#define  BSP_BIT_DEM_CR_TRCENA                    DEF_BIT_24
#define  BSP_BIT_DWT_CR_CYCCNTENA                 DEF_BIT_00


CPU_INT32U  BSP_CPU_ClkFreq (void)
{
    CPU_INT32U  hclk_freq;

    hclk_freq = HAL_RCC_GetHCLKFreq();
    return (hclk_freq);
}




#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
void  CPU_TS_TmrInit (void)
{
    CPU_INT32U  fclk_freq;


    fclk_freq = BSP_CPU_ClkFreq();

    BSP_REG_DEM_CR     |= (CPU_INT32U)BSP_BIT_DEM_CR_TRCENA;    /* Enable Cortex-M4's DWT CYCCNT reg.                   */
    BSP_REG_DWT_CYCCNT  = (CPU_INT32U)0u;
    BSP_REG_DWT_CR     |= (CPU_INT32U)BSP_BIT_DWT_CR_CYCCNTENA;

    CPU_TS_TmrFreqSet((CPU_TS_TMR_FREQ)fclk_freq);
}
#endif



#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
CPU_TS_TMR  CPU_TS_TmrRd (void)
{
    CPU_TS_TMR  ts_tmr_cnts;


    ts_tmr_cnts = (CPU_TS_TMR)BSP_REG_DWT_CYCCNT;

    return (ts_tmr_cnts);
}
#endif




#if (CPU_CFG_TS_32_EN == DEF_ENABLED)
CPU_INT64U  CPU_TS32_to_uSec (CPU_TS32  ts_cnts)
{
    CPU_INT64U  ts_us;
    CPU_INT64U  fclk_freq;


    fclk_freq = BSP_CPU_ClkFreq();
    ts_us     = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);

    return (ts_us);
}
#endif


#if (CPU_CFG_TS_64_EN == DEF_ENABLED)
CPU_INT64U  CPU_TS64_to_uSec (CPU_TS64  ts_cnts)
{
    CPU_INT64U  ts_us;
    CPU_INT64U  fclk_freq;


    fclk_freq = BSP_CPU_ClkFreq();
    ts_us     = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);

    return (ts_us);
}
#endif

bsp.h

#ifndef  BSP_PRESENT
#define  BSP_PRESENT


/*
*********************************************************************************************************
*                                                 EXTERNS
*********************************************************************************************************
*/

#ifdef   BSP_MODULE
#define  BSP_EXT
#else
#define  BSP_EXT  extern
#endif


/*
*********************************************************************************************************
*                                              INCLUDE FILES
*********************************************************************************************************
*/

#include  <stdio.h>
#include  <stdarg.h>
#include  <cpu.h>
#include  <cpu_core.h>
#include  <lib_def.h>
#include  <lib_ascii.h>
#include  <stm32f4xx_hal.h>

#endif                                                          /* End of module include.                               */

(9)将 cpu_a.asm 里面的  OS_CPU_PendSVHandler 全部替换为 PendSV_Handler,然后将stm32f4xx_it.c里面的PendSV_Handler注释掉。

(10)修改 os_cfg_app.h 中的参数如下:

#ifndef OS_CFG_APP_H
#define OS_CFG_APP_H

/*
************************************************************************************************************************
*                                                      CONSTANTS
************************************************************************************************************************
*/

                                                            /* --------------------- MISCELLANEOUS ------------------ */
#define  OS_CFG_MSG_POOL_SIZE            100u               /* Maximum number of messages                             */

#define  OS_CFG_ISR_STK_SIZE             100u               /* Stack size of ISR stack (number of CPU_STK elements)   */

#define  OS_CFG_TASK_STK_LIMIT_PCT_EMPTY  10u               /* Stack limit position in percentage to empty            */


                                                            /* ---------------------- IDLE TASK --------------------- */
#define  OS_CFG_IDLE_TASK_STK_SIZE       128u               /* Stack size (number of CPU_STK elements)                */


                                                            /* ------------------ ISR HANDLER TASK ------------------ */
#define  OS_CFG_INT_Q_SIZE                10u               /* Size of ISR handler task queue                         */
#define  OS_CFG_INT_Q_TASK_STK_SIZE      100u               /* Stack size (number of CPU_STK elements)                */


                                                            /* ------------------- STATISTIC TASK ------------------- */
#define  OS_CFG_STAT_TASK_PRIO     (OS_CFG_PRIO_MAX - 2u)   /* Priority                                               */
#define  OS_CFG_STAT_TASK_RATE_HZ         10u               /* Rate of execution (1 to 10 Hz)                         */
#define  OS_CFG_STAT_TASK_STK_SIZE       100u               /* Stack size (number of CPU_STK elements)                */


                                                            /* ------------------------ TICKS ----------------------- */
#define  OS_CFG_TICK_RATE_HZ            1000u               /* Tick rate in Hertz (10 to 1000 Hz)                     */
#define  OS_CFG_TICK_TASK_PRIO             1u               /* Priority                                               */
#define  OS_CFG_TICK_TASK_STK_SIZE       128u               /* Stack size (number of CPU_STK elements)                */


                                                            /* ----------------------- TIMERS ----------------------- */
#define  OS_CFG_TMR_TASK_PRIO             2u               /* Priority of 'Timer Task'                               */
#define  OS_CFG_TMR_TASK_RATE_HZ         100u               /* Rate for timers (100 Hz Typ.)                           */
#define  OS_CFG_TMR_TASK_STK_SIZE        128u               /* Stack size (number of CPU_STK elements)                */

#endif

(11)修改 sys.h 文件  SYSTEM_SUPPORT_OS  改成1 支持操作系统,然后 将stm32f4xx_it.c 里面的 SysTick_Handler 函数注释掉。

#define SYSTEM_SUPPORT_OS        1        //定义系统文件夹是否支持OS

6.4 测试代码

在main函数加一个开始任务和两个灯闪动的任务,灯根据配置的时间运转即为移植成功,代码如下:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "includes.h"

//任务优先级
#define START_TASK_PRIO		3
//任务堆栈大小	
#define START_STK_SIZE 		512
//任务控制块
OS_TCB StartTaskTCB;
//任务堆栈	
CPU_STK START_TASK_STK[START_STK_SIZE];
//任务函数
void start_task(void *p_arg);

//任务优先级
#define LED0_TASK_PRIO		4
//任务堆栈大小	
#define LED0_STK_SIZE 		128
//任务控制块
OS_TCB Led0TaskTCB;
//任务堆栈	
CPU_STK LED0_TASK_STK[LED0_STK_SIZE];
void led0_task(void *p_arg);

//任务优先级
#define LED1_TASK_PRIO		5
//任务堆栈大小	
#define LED1_STK_SIZE       128
//任务控制块
OS_TCB Led1TaskTCB;
//任务堆栈	
CPU_STK LED1_TASK_STK[LED1_STK_SIZE];
//任务函数
void led1_task(void *p_arg);


int main(void)
{
    OS_ERR err;
	CPU_SR_ALLOC();
    
    Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz   
    HAL_Init();                     //初始化HAL库
    delay_init(180);                //初始化延时函数
    uart_init(115200);              //初始化USART
    LED_Init();                     //初始化LED 
	OSInit(&err);		//初始化UCOSIII
	OS_CRITICAL_ENTER();//进入临界区
	//创建开始任务
	OSTaskCreate((OS_TCB 	* )&StartTaskTCB,		//任务控制块
				 (CPU_CHAR	* )"start task", 		//任务名字
                 (OS_TASK_PTR )start_task, 			//任务函数
                 (void		* )0,					//传递给任务函数的参数
                 (OS_PRIO	  )START_TASK_PRIO,     //任务优先级
                 (CPU_STK   * )&START_TASK_STK[0],	//任务堆栈基地址
                 (CPU_STK_SIZE)START_STK_SIZE/10,	//任务堆栈深度限位
                 (CPU_STK_SIZE)START_STK_SIZE,		//任务堆栈大小
                 (OS_MSG_QTY  )0,					//任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
                 (OS_TICK	  )0,					//当使能时间片轮转时的时间片长度,为0时为默认长度,
                 (void   	* )0,					//用户补充的存储区
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, //任务选项,为了保险起见,所有任务都保存浮点寄存器的值
                 (OS_ERR 	* )&err);				//存放该函数错误时的返回值
	OS_CRITICAL_EXIT();	//退出临界区	 
	OSStart(&err);      //开启UCOSIII
    while(1)
    {
	} 
}

//开始任务函数
void start_task(void *p_arg)
{
	OS_ERR err;
	CPU_SR_ALLOC();
	p_arg = p_arg;

	CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
   OSStatTaskCPUUsageInit(&err);  	//统计任务                
#endif
	
#ifdef CPU_CFG_INT_DIS_MEAS_EN		//如果使能了测量中断关闭时间
    CPU_IntDisMeasMaxCurReset();	
#endif

#if	OS_CFG_SCHED_ROUND_ROBIN_EN  //当使用时间片轮转的时候
	 //使能时间片轮转调度功能,设置默认的时间片长度s
	OSSchedRoundRobinCfg(DEF_ENABLED,10,&err);  
#endif		
	
	OS_CRITICAL_ENTER();	//进入临界区
	//创建LED0任务
	OSTaskCreate((OS_TCB 	* )&Led0TaskTCB,		
				 (CPU_CHAR	* )"led0 task", 		
                 (OS_TASK_PTR )led0_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )LED0_TASK_PRIO,     
                 (CPU_STK   * )&LED0_TASK_STK[0],	
                 (CPU_STK_SIZE)LED0_STK_SIZE/10,	
                 (CPU_STK_SIZE)LED0_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
                 (OS_ERR 	* )&err);				
				 
	//创建LED1任务
	OSTaskCreate((OS_TCB 	* )&Led1TaskTCB,		
				 (CPU_CHAR	* )"led1 task", 		
                 (OS_TASK_PTR )led1_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )LED1_TASK_PRIO,     	
                 (CPU_STK   * )&LED1_TASK_STK[0],	
                 (CPU_STK_SIZE)LED1_STK_SIZE/10,	
                 (CPU_STK_SIZE)LED1_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,				
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, 
                 (OS_ERR 	* )&err);
				 
	OS_CRITICAL_EXIT();	//进入临界区				 
	OS_TaskSuspend((OS_TCB*)&StartTaskTCB,&err);		//挂起开始任务			 
}

//led0任务函数
void led0_task(void *p_arg)
{
	OS_ERR err;
	p_arg = p_arg;
	while(1)
	{
		LED0=0;    //LED0打开
		OSTimeDlyHMSM(0,0,0,200,OS_OPT_TIME_HMSM_STRICT,&err); //延时200ms
		LED0=1;    //LED0关闭
		OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms
	}
}

//led1任务函数
void led1_task(void *p_arg)
{
	p_arg = p_arg;
	while(1)
	{
		LED1=!LED1;
        delay_ms(500);//延时500ms
	}
}

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

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

相关文章

智能制造与工业互联网有何关联?工业互联网如何推进智能制造?

随着信息技术的飞速发展&#xff0c;智能制造和工业互联网已经成为当今产业变革的核心。智能制造&#xff0c;以其深度融合的设计、生产、管理、营销和售后服务等环节&#xff0c;代表了先进制造模式的典范。而工业互联网则作为智能制造的神经中枢&#xff0c;通过连接机器、人…

【初阶数据结构题目】17.用栈实现队列

用栈实现队列 点击链接答题 思路&#xff1a; 定义两个栈&#xff1a;pushST&#xff08;入数据&#xff09;和popST&#xff08;出数据&#xff09; 假设我们要在队列里放123&#xff0c;出队列123 我们先在pushST里面放进去1 2 3 然后把pushST里面的数据拿到popST里面&#…

会务要闻|向绿提质:上市企业ESG评级提升

在全球市场对环境、社会和治理&#xff08;ESG&#xff09;指标的关注与日俱增的大背景下&#xff0c;中国正积极拥抱ESG理念&#xff0c;将其作为推动经济与社会全面绿色转型的催化剂&#xff0c;更被企业视为长期主义投资策略的基石。面对日益严格的国际ESG尽职调查要求&…

信息论在机器学习中的实际应用

目录 一、说明 二、什么是信息论&#xff1f; 2.1 信息论中的关键概念 2.2 熵与信息 2.3 相互信息 2.4 Kullback-Leibler 背离 三、信息论在机器学习中的应用 3.1 功能选择&#xff1a; 3.2 计算边际概率分布 3.3 决策树&#xff1a;Information 增益 3.4 评估具有 KL 背…

FastAPI+Vue3工程项目管理系统项目实战私教课 上课笔记20240808 课程和学习计划制定

学习目标 将Word和Excel做的东西放到数据库里面去工程类公司&#xff0c;甲方&#xff0c;劳务存到数据库存储的信息主要是人员的信息 基本信息&#xff1a; 人员信息&#xff0c;资料库&#xff0c;甲方的人出现在哪些项目上&#xff0c;考勤材料信息&#xff0c;进货记录&…

yolov5更换主干网络shufflent

目录 1.网络结构解析 1.1创建yolov5s_shufflent_v2_X0_5.yaml文件 2.对common.py末尾进行添加 3.修改yolo.py 1.网络结构解析 1.可以先看看shufflenet_v2的网络结构 import torch from torch import nn from torchvision import models from torchinfo import summaryclas…

利用vscode-icons-js在Vue3项目中实现文件图标展示

背景&#xff1a; 在开发文件管理系统或类似的项目时&#xff0c;我们常常需要根据文件类型展示对应的文件图标&#xff0c;这样可以提高用户体验。本文将介绍如何在Vue3项目中利用vscode-icons-js库&#xff0c;实现类似VSCode的文件图标展示效果。 先看效果&#xff1a; 一…

Flink任务提交流程和运行模式

任务提交流程 Flink 的提交流程随着部署模式、资源管理平台的不同&#xff0c;会有不同的变化。这里做进一步的抽象&#xff0c;形成一个大概高视角的任务执行流程图&#xff0c;如下&#xff1a; Flink按照集群和资源管理的划分运行模式有&#xff1a;Standalone、Flink On…

你是否陷入了惯性思维的陷阱?

如何突破惯性思维&#xff1f; 文 / 周妙錥&#xff08;MEOW EE CHEW&#xff09;13-02-2024 什么是惯性思维&#xff1f; 惯性思维&#xff08;Inertial Thinking&#xff09;是指我们在面对问题、决策或行为选择时&#xff0c;倾向于依赖过去的经验、习惯或想法&#xff0…

SubtitleEdit:一个基于.Net开发的开源字幕编辑器

现在是短视频的时代&#xff0c;对视频的字幕编辑需求非常多&#xff0c;今天介绍一个功能强大的开源视频字幕编辑器。 01 项目简介 Subtitle Edit 是基于.Net开发的开源项目&#xff0c;支持跨平台使用&#xff0c;包括Windows、Linux 和 macOS。这个软件不仅支持多种字幕格…

打开 Mac 触控板的三指拖移功能

对于支持力度触控的触控板&#xff0c;可以选择使用三指手势来拖移项目。 相应的设置名称会因你使用的 macOS 版本而有所不同&#xff1a; 选取苹果菜单  >“系统设置”&#xff08;或“系统偏好设置”&#xff09;。 点按“辅助功能”。 点按“指针控制”&#xff08;…

cms框架cookice注入漏洞

目录 一、环境 二、开始分析 2.1代码审计&#xff08;未授权访问&#xff09; 一、环境 环境私聊获取 二、开始分析 2.1代码审计&#xff08;未授权访问&#xff09; 我们可以看到构造函数ip是通过X_FORWARDED_FOR来获取的&#xff0c;而这个刚好可以伪造&#xff0c;那我…

理解张量拼接(torch.cat)

拼接 维度顺序&#xff1a;对于 3D 张量&#xff0c;通常可以理解为 (深度, 行, 列) 或 (批次, 行, 列)。 选择一个dim进行拼接的时候其他两个维度大小要相等 对于三维张量&#xff0c;理解 torch.cat 的 dim 参数确实变得更加抽象&#xff0c;但原理是相同的。让我们通过一…

【ow365】java对接使用第三方ow365预览pdf,word等office文档

ow365官网 文档在线预览 OfficeWeb365 速度更快的Office在线预览服务提供office在线预览及PDF在线预览服务&#xff0c;支持Word文档在线预览、Excel在线预览、PowerPoint在线预览、WPS等Office文件在线预览&#xff0c;支持所有浏览器及移动设备Mobile预览&#xff0c;无需安…

一款免费开源快速启动工具,提高工作效率!

这是一款可以帮助我们快速启动windows电脑上的程序的工具&#xff0c;可以添加分组&#xff0c;设置网站&#xff0c;程序&#xff0c;系统工具快速一键打开&#xff0c;让桌面变的更简洁&#xff0c;打开程序更方便。小编提醒&#xff0c;直接拖动程序快捷方式到程序框内&…

游戏直播、教学录制两不误:2024年Win适用录屏软件推荐

回顾一下你是去线下看活动的次数多还是在线上参与活动的次数多。线下活动的时候我们一般是举着相机或者手机进行录制&#xff0c;那线上呢&#xff1f;只要找到适合win10录屏的工具你线上活动记录起来就更方便了。 1.FOXIT录屏大师 链接直达&#xff1a;https://www.foxitsof…

隐藏WindTerm左边的时间戳

文章目录 1、快捷键操作隐藏时间戳2、鼠标方式操作隐藏 1、快捷键操作隐藏时间戳 按住 alt 键不动&#xff0c;连续按 t 两下 即可隐藏时间戳 2、鼠标方式操作隐藏 取消勾选时间戳即可隐藏时间戳

NRBO-XGBoost分类 基于牛顿-拉夫逊优化算法[24年最新算法]-XGBoost多特征分类预测+交叉验证

NRBO-XGBoost分类 基于牛顿-拉夫逊优化算法[24年最新算法]-XGBoost多特征分类预测交叉验证 多输入单输出&#xff09; matlab代码 程序已调试好&#xff0c;无需更改代码替换数据直接使用&#xff01;&#xff01;&#xff01;数据格式为excel格式&#xff01;需要定制可私&a…

CTF — 图像隐写三板斧

这几天做CTF比赛相关的题目,每天总结一篇与大家分享,本人对CTF也算是个初学者,通过一些学习感觉收获还是很多的。学会了一些工具软件的使用和相关知识的原理。今天继续分享图片隐写,图像隐写类题目的特点:考法多样,思路清奇,工具众多。先分享“第一板斧”的解题套路。 …

Spark轨迹大数据高效处理_计算两经纬度点间的距离_使用Haversine formula公式

开发背景 接上文我求的两经纬度点之间的方位角&#xff0c;我的需求里还提到了要计算距离&#xff0c;当然这个距离也是为后面的需求做铺垫的&#xff0c;因此需要求两个经纬度电之间的距离。 不要妄想用勾股定理求出来&#xff0c;实际上距离的计算还是稍微复杂些。这里使用的…