单片机软件定时器V4.0
单片机软件定时器V4.0
用于单片机定时执行任务等,比如LED GPIO等定时控制,内置前后台工作模式
头文件有使用例子
#ifndef __SORFTIME_APP_H
#define __SORFTIME_APP_H#ifdef __cplusplus
extern "C"
{
#endif#include <stdint.h>// #define ST_CLIENT_SERVER_MODE 1 /*取消注释切换到前后台模式*/#define MAX_TIMER_NUM 16 /* 定时器最大个数(可修改) *//**移植修改步骤**//*1:st_sorft_timer_init(); 初始化2: 把 st_sorft_timer_counter_prosess(); 放入1ms中断回调或1ms的OS任务中3: 修改 MAX_TIMER_NUM 的定义值,比如需要用到10个定时器就改为>=104: 查看底部例程使用方法5: 记得把printf注释掉,如果没有配置printf会停在printf的while循环里面*/#if 1typedef unsigned char u8;typedef unsigned short int u16;typedef unsigned int u32;
#endif
#if 0typedef unsigned char uint8_t;typedef unsigned short int uint16_t;typedef unsigned int uint32_t;
#endiftypedef enum timer_run_mode{TIM_INTERUPUT_MODE = 0, /* 中断模式*/
#ifdef ST_CLIENT_SERVER_MODETIM_CLIENT_SERVER_MODE = 1, /* 前后台模式*/
#endif} st_e_run_mode_t;/***********状态枚举***********/typedef enum timer_init_state{TIM_CRAT_SUCES = 0, /* create succes 创建成功状态 */TIM_CRAT_ERROR = 1, /* create faild 创建失败状态 */} st_e_state_crat_t;typedef enum timer_run_state{TIM_LOCK = 2, /* 锁定计数,不能再次更新计数值,只能等到计数结束 */TIM_UNLOCK = 3, /* 不锁定计数,可以中途手动更新计数值 */TIM_END = 4, /* 计数值到达目标值,停止计数 */} st_e_state_run_t;typedef enum timer_end_state{TIM_ONCE = 5, /* 单次计数模式*/TIM_CYCLE = 6, /* 循环计数模式*/} st_e_state_end_t;typedef enum timer_close_state{TIM_DESTROYED = 7, /* 销毁状态 (擦除这个定时器所占坑位资源)*/TIM_SUSPEND = 8 /* 挂起定时器 (会占用一个定时器坑位,不推荐)*/} st_e_state_close_t;typedef void (*st_rtn_func_t)(uint16_t);/*******单个定时器结构体 *************/typedef struct id_menber{uint16_t id; /* 软件定时器id */uint32_t count; /* 计数运行值 */uint32_t target; /* 计数目标值 */st_e_state_run_t run_state; /* 运行时的状态 */st_e_state_end_t end_state; /* 结束后的状态 */st_rtn_func_t rtn_func; /* 计时结束的回调函数 */} st_id_t;/*******所有定时器结构体 *************/typedef struct timer_id{st_id_t id_ary[MAX_TIMER_NUM]; /*数组*/uint16_t timer_last_index; /*当前定时器最大个数*/} s_timer_id;#ifdef ST_CLIENT_SERVER_MODE/*前后台模式,前台运行在main while模式,后台中断定时器设置标志*/typedef struct timer_event{uint16_t event_id[MAX_TIMER_NUM];st_rtn_func_t event_ary[MAX_TIMER_NUM]; /*数组*/} s_event_id;
#endifvoid st_sorft_timer_init(void); /*初始化软件定时器*/void st_sorft_timer_counter_prosess(void); /*此函数放入定时器中断回调函数*/
#ifdef ST_CLIENT_SERVER_MODE/*这个函数放入main 的while循环*/void st_sorft_timer_event_prosess(void);
#endifst_e_state_crat_t st_start_timer(uint16_t timer_id, uint32_t count, st_e_state_run_t run_state); /*开启一个定时器*/st_e_state_crat_t st_start_once_timer(uint16_t timer_id, uint32_t count, st_e_state_run_t run_state); /*开启一次定时器*/st_e_state_crat_t st_start_cb_timer(uint16_t timer_id, uint32_t count, st_e_state_run_t run_state, st_e_state_end_t end_state, st_rtn_func_t rtn_func); /*计时结束,执行回调函数,函数执行完毕自动销毁该定时器*/st_e_state_close_t st_close_timer(uint16_t timer_id, st_e_state_close_t close_state); /* 关掉或者暂停一个定时器 */st_e_state_run_t st_timer_state(uint16_t timer_id); /* 读取定时器状态 */uint32_t st_timer_count_value(uint16_t timer_id); /*查询定时器计数值 *///**使用例程 start**///*#define EVENT_ID_LED 0x10#define EVENT_ID_GPIO 0x11#define EVENT_ID_SPI 0x12#define EVENT_ID_TIME 0x13#define LOG(...) printf(__VA_ARGS__)void app_main_process(uint16_t id){if (id == EVENT_ID_LED){st_start_cb_timer(EVENT_ID_LED, 30, TIM_LOCK, TIM_ONCE, app_main_process);LOG("LED\n");return;}if (id == EVENT_ID_GPIO){st_start_cb_timer(EVENT_ID_GPIO, 40, TIM_LOCK, TIM_ONCE, app_main_process);LOG("GPIO\n");return;}if (id == EVENT_ID_SPI){LOG("SPI\n");return;}}main(){st_sorft_timer_init();st_start_cb_timer(EVENT_ID_LED, 5, TIM_LOCK, TIM_ONCE, app_main_process);st_start_cb_timer(EVENT_ID_GPIO, 10, TIM_LOCK, TIM_CYCLE, app_main_process);st_start_cb_timer(EVENT_ID_SPI, 20, TIM_UNLOK, TIM_CYCLE, app_main_process);while (1){// st_sorft_timer_event_prosess(); //前后台模式}return 0;}*///**end**//#ifdef __cplusplus
}
#endif
#endif
#include "sorftime_app.h"#include "stdio.h"/***********计数值**************/
#define ST_START_COUNT_VALUE 0
#define ST_END_COUNT_VALUE 0xFFFFFFFE
#define ST_ID_NULL 0
/************ID值****************/
#define ST_NULL_ID 0
#define ST_NEW_ID 1
#define ST_OLD_ID 2static s_timer_id timer_id_ary;static uint8_t OPEN_COUNTER = 0;
static uint8_t MAX_USE_NUMBER = 0;#ifdef ST_CLIENT_SERVER_MODE
static s_event_id event_id_ary;
static void add_event_to_list(st_rtn_func_t event_cb, uint16_t id);
#endif/*** @brief 定时器中断回调,对所有计数值进行减少* 中断触发为 1ms* 根据用户层需要的计时时间,到达就改变状态**/
void st_sorft_timer_counter_prosess(void)
{ /* 此函数放入中断回调*/uint8_t i = 0;st_id_t end_id;if (OPEN_COUNTER){for (i = 0; i < MAX_USE_NUMBER; i++){if ((timer_id_ary.id_ary[i].id) != ST_ID_NULL){if ((timer_id_ary.id_ary[i].run_state != TIM_SUSPEND) && (timer_id_ary.id_ary[i].run_state != TIM_END)){if ((++(timer_id_ary.id_ary[i].count)) >= (timer_id_ary.id_ary[i].target)){timer_id_ary.id_ary[i].count = ST_END_COUNT_VALUE;end_id.id = timer_id_ary.id_ary[i].id;end_id.run_state = timer_id_ary.id_ary[i].run_state;end_id.end_state = timer_id_ary.id_ary[i].end_state;end_id.rtn_func = timer_id_ary.id_ary[i].rtn_func;timer_id_ary.id_ary[i].run_state = TIM_END;/*结束定时*/if (end_id.end_state == TIM_ONCE){timer_id_ary.id_ary[i].id = ST_ID_NULL;timer_id_ary.id_ary[i].count = ST_END_COUNT_VALUE;timer_id_ary.id_ary[i].run_state = (st_e_state_run_t)TIM_DESTROYED;timer_id_ary.id_ary[i].end_state = (st_e_state_end_t)TIM_DESTROYED;timer_id_ary.id_ary[i].target = ST_END_COUNT_VALUE;timer_id_ary.id_ary[i].rtn_func = NULL;}/*循环触发*/if (end_id.end_state == TIM_CYCLE){timer_id_ary.id_ary[i].count = ST_START_COUNT_VALUE;timer_id_ary.id_ary[i].run_state = end_id.run_state;}/*执行回调*/if (end_id.rtn_func != NULL){
#ifdef ST_CLIENT_SERVER_MODEadd_event_to_list(end_id.rtn_func, end_id.id);#elseend_id.rtn_func(end_id.id);
#endif}}}}}}
}#ifdef ST_CLIENT_SERVER_MODE
/*** @brief 前台调用,处理对应id的事件* 后台中断将触发的timer id 标记* 此函数负责处理对应的id事件调用**/
void st_sorft_timer_event_prosess(void)
{uint16_t i = 0;for (i = 0; i < MAX_TIMER_NUM; i++){if (event_id_ary.event_ary[i] != NULL){event_id_ary.event_ary[i](event_id_ary.event_id[i]);event_id_ary.event_id[i] = ST_ID_NULL;event_id_ary.event_ary[i] = NULL;return;}}
}
#endif
#ifdef ST_CLIENT_SERVER_MODE
/*** @brief 添加事件回调到列表**/
static void add_event_to_list(st_rtn_func_t event_cb, uint16_t id)
{uint16_t i = 0;for (i = 0; i < MAX_TIMER_NUM; i++){if (event_id_ary.event_ary[i] == NULL){event_id_ary.event_ary[i] = event_cb;event_id_ary.event_id[i] = id;return;}}
}
#endif
/**@brief 定时器id赋值,使用定时器前先调用一次此接口
**/
void st_sorft_timer_init(void)
{uint16_t i = 0;/* 清空定时器所有 timer_id = 0*/for (i = 0; i < MAX_TIMER_NUM; i++){timer_id_ary.id_ary[i].id = ST_ID_NULL;timer_id_ary.id_ary[i].count = ST_END_COUNT_VALUE;timer_id_ary.id_ary[i].target = ST_END_COUNT_VALUE;timer_id_ary.id_ary[i].run_state = (st_e_state_run_t)TIM_DESTROYED;timer_id_ary.id_ary[i].end_state = (st_e_state_end_t)TIM_DESTROYED;timer_id_ary.id_ary[i].rtn_func = NULL;#ifdef ST_CLIENT_SERVER_MODEevent_id_ary.event_id[i] = ST_ID_NULL;event_id_ary.event_ary[i] = NULL;
#endif}timer_id_ary.timer_last_index = 0; /* 对管理的timer进行计数*/OPEN_COUNTER = 1;
}/**@brief 启动一个定时器
* timer_id 用户自定义ID
* 需要计数时间MS
* 计数状态,LOCK_TIMING(计数时无法刷新计数值,只能等到计数结束)
* 计数状态,TIMING 可以中途重新刷新计数值
**/st_e_state_crat_t st_start_timer(uint16_t timer_id, uint32_t count, st_e_state_run_t run_state)
{uint16_t i = 0;uint8_t first_i = 0;uint8_t flag = ST_NULL_ID;if (timer_id == 0 || count == 0){return TIM_CRAT_ERROR;}if (!OPEN_COUNTER){st_sorft_timer_init();}/*************查找相同ID或者直接创建****************/for (i = 0; i < MAX_TIMER_NUM; i++){if (timer_id_ary.id_ary[i].id == timer_id){first_i = i;flag = ST_OLD_ID; // 查找相同IDif ((timer_id_ary.id_ary[i].run_state == TIM_LOCK) || (timer_id_ary.id_ary[i].run_state == TIM_END)){return (st_e_state_crat_t)TIM_LOCK;}break;}if ((timer_id_ary.id_ary[i].id == ST_ID_NULL) && (!flag)){first_i = i;flag = ST_NEW_ID; /* 查找并记录空闲ID*/}}if (!flag){return TIM_CRAT_ERROR; /* 防止未查找到*/}if ((timer_id_ary.timer_last_index) < MAX_TIMER_NUM){timer_id_ary.id_ary[first_i].id = timer_id;timer_id_ary.id_ary[first_i].count = ST_START_COUNT_VALUE; /* 计数初始值*/timer_id_ary.id_ary[first_i].target = count;timer_id_ary.id_ary[first_i].run_state = run_state;timer_id_ary.id_ary[first_i].end_state = (st_e_state_end_t)TIM_DESTROYED;timer_id_ary.id_ary[first_i].rtn_func = NULL;if (flag == ST_NEW_ID){if (first_i >= MAX_USE_NUMBER){MAX_USE_NUMBER = first_i + 1;}if (++timer_id_ary.timer_last_index >= MAX_USE_NUMBER) /* 新增一个ID ,进行+1计数 */{timer_id_ary.timer_last_index = MAX_USE_NUMBER;}}return TIM_CRAT_SUCES; /* 返回创建成功的状态 */}else{return TIM_CRAT_ERROR;}
}
/***@brief 启动一次定时器* 计时结束自动销毁定时器* **/
st_e_state_crat_t st_start_once_timer(uint16_t timer_id, uint32_t count, st_e_state_run_t run_state)
{uint16_t i = 0;uint8_t first_i = 0;uint8_t flag = ST_NULL_ID;if (timer_id == 0 || count == 0){return (st_e_state_crat_t)TIM_DESTROYED;}if (!OPEN_COUNTER){st_sorft_timer_init();}/*************查找相同ID或者直接创建****************/for (i = 0; i < MAX_TIMER_NUM; i++){if (timer_id_ary.id_ary[i].id == timer_id){first_i = i;flag = ST_OLD_ID; /* 查找相同ID */if (timer_id_ary.id_ary[i].run_state == TIM_LOCK){return (st_e_state_crat_t)TIM_LOCK;}break;}if ((timer_id_ary.id_ary[i].id == ST_ID_NULL) && (!flag)){first_i = i;flag = ST_NEW_ID;}}if (!flag){return TIM_CRAT_ERROR;}if ((timer_id_ary.timer_last_index) < MAX_TIMER_NUM){timer_id_ary.id_ary[first_i].id = timer_id;timer_id_ary.id_ary[first_i].count = ST_START_COUNT_VALUE;timer_id_ary.id_ary[first_i].target = count;timer_id_ary.id_ary[first_i].run_state = run_state;timer_id_ary.id_ary[first_i].end_state = TIM_ONCE;timer_id_ary.id_ary[first_i].rtn_func = NULL;if (flag == ST_NEW_ID){if (first_i >= MAX_USE_NUMBER){MAX_USE_NUMBER = first_i + 1;}if (++timer_id_ary.timer_last_index >= MAX_USE_NUMBER){timer_id_ary.timer_last_index = MAX_USE_NUMBER;}}return TIM_CRAT_SUCES;}else{return TIM_CRAT_ERROR;}
}/*** @brief 启动一次定时器* 计时结束自动销毁定时器**/
st_e_state_crat_t st_start_cb_timer(uint16_t timer_id,uint32_t count,st_e_state_run_t run_state,st_e_state_end_t end_state,st_rtn_func_t rtn_func)
{uint16_t i = 0;uint8_t first_i = 0;uint8_t flag = ST_NULL_ID;if (timer_id == 0 || count == 0 || rtn_func == NULL){return (st_e_state_crat_t)TIM_DESTROYED;}if (!OPEN_COUNTER){st_sorft_timer_init();}/*************查找相同ID或者直接创建****************/for (i = 0; i < MAX_TIMER_NUM; i++){if (timer_id_ary.id_ary[i].id == timer_id){first_i = i;flag = ST_OLD_ID;if (timer_id_ary.id_ary[i].run_state == TIM_LOCK){return (st_e_state_crat_t)TIM_LOCK;}break;}if ((timer_id_ary.id_ary[i].id == ST_ID_NULL) && (!flag)){first_i = i;flag = ST_NEW_ID;}}if (!flag){return TIM_CRAT_ERROR;}if ((timer_id_ary.timer_last_index) < MAX_TIMER_NUM){timer_id_ary.id_ary[first_i].id = timer_id;timer_id_ary.id_ary[first_i].count = ST_START_COUNT_VALUE;timer_id_ary.id_ary[first_i].target = count;timer_id_ary.id_ary[first_i].run_state = run_state;timer_id_ary.id_ary[first_i].end_state = end_state;timer_id_ary.id_ary[first_i].rtn_func = rtn_func;if (flag == ST_NEW_ID){if (first_i >= MAX_USE_NUMBER){MAX_USE_NUMBER = first_i + 1;}if (++timer_id_ary.timer_last_index >= MAX_USE_NUMBER){timer_id_ary.timer_last_index = MAX_USE_NUMBER;}}return TIM_CRAT_SUCES; /*返回创建成功的状态*/}else{return TIM_CRAT_ERROR;}
}/*** @brief 关掉定时器,* TIM_SUSPEND 定时器不销毁,计数暂停* TIM_DESTROYED 销毁定时器,ID将被抹去*/
st_e_state_close_t st_close_timer(uint16_t timer_id, st_e_state_close_t close_state)
{uint16_t i = 0;if (timer_id == 0){return TIM_DESTROYED;}for (i = 0; i < MAX_USE_NUMBER; i++){if (timer_id_ary.id_ary[i].id == timer_id){break;}}if (i >= MAX_USE_NUMBER){return TIM_DESTROYED;}if (close_state == TIM_SUSPEND){ /* 暂停定时器,也就是关掉的意思 *//***暂停定时器**** 查看是否有相同ID ********/if ((timer_id_ary.id_ary[i].id) == timer_id){timer_id_ary.id_ary[i].id = timer_id; /*ID不能抹去 */timer_id_ary.id_ary[i].count = ST_END_COUNT_VALUE;timer_id_ary.id_ary[i].run_state = (st_e_state_run_t)TIM_SUSPEND; /*挂起定时器 */timer_id_ary.id_ary[i].end_state = (st_e_state_end_t)TIM_SUSPEND;timer_id_ary.id_ary[i].target = ST_END_COUNT_VALUE;return TIM_SUSPEND;}}else if (close_state == TIM_DESTROYED){ /* 销毁定时器 *//****销毁定时器*** 查看是否有相同ID ********/if ((timer_id_ary.id_ary[i].id) == timer_id){timer_id_ary.id_ary[i].id = ST_ID_NULL;timer_id_ary.id_ary[i].count = ST_END_COUNT_VALUE;timer_id_ary.id_ary[i].run_state = (st_e_state_run_t)TIM_DESTROYED;timer_id_ary.id_ary[i].end_state = (st_e_state_end_t)TIM_DESTROYED;timer_id_ary.id_ary[i].target = ST_END_COUNT_VALUE;timer_id_ary.id_ary[i].rtn_func = NULL;if (timer_id_ary.timer_last_index > 0){timer_id_ary.timer_last_index--;}if (timer_id_ary.id_ary[MAX_USE_NUMBER - 1].run_state == TIM_DESTROYED){MAX_USE_NUMBER--;}return TIM_DESTROYED; // 返回刚刚创建的状态}}return TIM_DESTROYED;
}/***@bref 返回定时器状态有此ID的定时器就返回当前状态没有就返回DESTROYED* **/
st_e_state_run_t st_timer_state(uint16_t timer_id)
{uint16_t i = 0;if (timer_id == 0){return (st_e_state_run_t)TIM_DESTROYED;}for (i = 0; i < MAX_TIMER_NUM; i++){if ((timer_id_ary.id_ary[i].id) == timer_id){return timer_id_ary.id_ary[i].run_state;}}return (st_e_state_run_t)TIM_DESTROYED;
}/*@bref 查询计数值
*/
uint32_t st_timer_count_value(uint16_t timer_id)
{uint16_t i = 0;if (timer_id == 0){return ST_END_COUNT_VALUE;}for (i = 0; i < MAX_TIMER_NUM; i++){if ((timer_id_ary.id_ary[i].id) == timer_id){return timer_id_ary.id_ary[i].count;}}return ST_END_COUNT_VALUE;
}
相关文章:
单片机软件定时器V4.0
单片机软件定时器V4.0 用于单片机定时执行任务等,比如LED GPIO等定时控制,内置前后台工作模式 头文件有使用例子 #ifndef __SORFTIME_APP_H #define __SORFTIME_APP_H#ifdef __cplusplus extern "C" { #endif#include <stdint.h>// #…...

超完整Docker学习记录,Docker常用命令详解
前言 关于国内拉取不到docker镜像的问题,可以利用Github Action将需要的镜像转存到阿里云私有仓库,然后再通过阿里云私有仓库去拉取就可以了。 参考项目地址:使用Github Action将国外的Docker镜像转存到阿里云私有仓库 一、Docker简介 Do…...
C++ 入门第26天:文件与流操作基础
往期回顾: C 入门第23天:Lambda 表达式与标准库算法入门-CSDN博客 C 入门第24天:C11 多线程基础-CSDN博客 C 入门第25天:线程池(Thread Pool)基础-CSDN博客 C 入门第26天:文件与流操作基础 前言…...
使用python将多个Excel表合并成一个表
import pandas as pd# 定义要合并的Excel文件路径和名称 file_paths [file1.xlsx, file2.xlsx, file3.xlsx, file4.xlsx, file5.xlsx]# 创建一个空的DataFrame来存储合并后的数据 merged_data pd.DataFrame()# 循环遍历每个Excel文件,并读取其中的数据 for file_p…...
halcon三维点云数据处理(七)find_shape_model_3d_recompute_score
目录 一、find_shape_model_3d_recompute_score例程代码二、set_object_model_3d_attrib_mod函数三、prepare_object_model_3d 函数四、create_cube_shape_model_3d函数五、获得CamPose六、project_cube_image函数七、find_shape_model_3d函数八、project_shape_model_3d函数 一…...

vue js实现时钟以及刻度效果
2025.01.08今天我学习如何用js实现时钟样式,效果如下: 一、html代码如下: <template><!--圆圈--><div class"notice_border"><div class"notice_position notice_name_class" v-for"item in …...

unity学习15:预制体prefab
目录 1 创建多个gameobject 2 创建prefab 2.1 创建prefab (类) 2.2 prefab 是一个文件 2.3 prefab可以导出 3 创建prefab variant (子类) 3.1 除了创建多个独立的prefab, 还可以创建 prefab variant 3.2 他…...

基于Thinkphp6+uniapp的陪玩陪聊软件开发方案分析
使用uni-app框架进行前端开发。uni-app是一个使用Vue.js开发所有前端应用的框架,支持一次编写,多端发布,包括APP、小程序、H5等。 使用Thinkphp6框架进行后端开发。Thinkphp6是一个轻量级、高性能、面向对象的PHP开发框架,具有易…...
MySQL - 子查询和相关子查询详解
在SQL中,子查询(Subquery)和相关子查询(Correlated Subquery)是非常强大且灵活的工具,可以用于执行复杂的数据检索和操作。它们允许我们在一个查询中嵌套另一个查询,从而实现更复杂的逻辑和条件…...
Android 系统签名 keytool-importkeypair
要在 Android 项目中使用系统签名并将 APK 打包时与项目一起打包,可以按照以下步骤操作: 步骤 1:准备系统签名文件 从 Android 系统源码中获取系统签名文件,通常位于 build/target/product/security 目录下,包括 pla…...

安卓漏洞学习(十八):Android加固基本原理
APP加固技术发展历程 APK加固整体思路 加固整体思路:先解压apk文件,取出dex文件,对dex文件进行加密,然后组合壳中的dex文件(Android类加载机制),结合之前的apk资源(解压apk除dex以外…...

Docker 使用Dockerfile创建镜像
创建并且生成镜像 在当前目录下创建一个名为Dockerfile文件 vi Dockerfile填入下面配置 # 使用 CentOS 作为基础镜像 FROM centos:7# 设置工作目录 WORKDIR /app# 复制项目文件到容器中 COPY bin/ /app/bin/ COPY config/ /app/config/ COPY lib/ /app/lib/ COPY plugin/ /a…...
【Python运维】利用Python实现高效的持续集成与部署(CI/CD)流程
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 持续集成与部署(CI/CD)是现代软件开发中不可或缺的实践,通过自动化测试、构建和部署流程,显著提高了开发效率与运维质量。本文详细介绍…...

成功!QT 5.15.2编译mysql驱动
首选要说明,5.15与6.7编译驱动是完全不同的。搞错了永远编译不出来。 参考 主要是参考安装QT,安装mysql等。 编译成功!QT/6.7.2/Creator编译Windows64 MySQL驱动(MSVC版)_mingw编译qt6.7-CSDN博客 复制mysql的include和lib到一个方便的目…...

安卓NDK视觉开发——手机拍照文档边缘检测实现方法与库封装
一、项目创建 创建NDK项目有两种方式,一种从新创建整个项目,一个在创建好的项目添加NDK接口。 1.创建NDK项目 创建 一个Native C项目: 选择包名、API版本与算法交互的语言: 选择C版本: 创建完之后,可…...

第二届 Sui 游戏峰会将于 3 月 18 日在旧金山举行
3 月中旬,Sui 基金会和 Mysten Labs 将共同举办第二届 Sui 游戏峰会(Sui Gaming Summit),这是一个专注于 Sui 游戏平台的 GDC 周边活动。此次峰会将与旧金山的年度游戏开发者大会(GDC,Game Developers Conf…...

自动驾驶相关知识学习笔记
一、概要 因为想知道SIL、HIL是什么仿真工具,故而浏览了自动驾驶相关的知识。 资料来源《自动驾驶——人工智能理论与实践》胡波 林青 陈强 著;出版时间:2023年3月 二、图像的分类、分割与检测任务区别 如图所示,这些更高阶的…...

uniapp - 基于uniapp+vue3实现自定义增强版table表格组件体验「兼容H5+小程序+App端」
本文提供增强版table表格组件体验,打造跨端表格的新标杆. uv3-table:一款基于uniappvue3跨端自定义手机端增强版表格组件。支持固定表头/列、边框、斑马纹、单选/多选,自定义表头/表体插槽、左右固定列阴影高亮显示。支持编译兼容H5小程序端App端。 提供…...

新时期下k8s 网络插件calico 安装
1、k8s master节点初始化完毕以后一直处于notreadey状态,一直怀疑是安装有问题或者是初始化有问题(当然,如果真有问题要先解决这些问题),经过不断探索才发现是网络插件没有安装导致的,根据建议安装calico插…...
【SQL】COUNT()函数 用法详解
COUNT()函数 COUNT函数用法:COUNT ( [ALL | DISTINCT] column | expression | *) ALL关键字指示统计所有值,而DISTINCT关键字强制函数仅对不同的值进行操作。 默认情况下,使用ALL选项。条件表达式 COUNT()函数中条件表达式加 OR null。例如…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...