单片机软件定时器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个定时器就改为>=10
	 4: 查看底部例程使用方法
	 5: 记得把printf注释掉,如果没有配置printf会停在printf的while循环里面
	*/

#if 1
	typedef unsigned char u8;
	typedef unsigned short int u16;
	typedef unsigned int u32;
#endif
#if 0
	typedef unsigned char uint8_t;
	typedef unsigned short int uint16_t;
	typedef unsigned int uint32_t;
#endif

	typedef enum timer_run_mode
	{
		TIM_INTERUPUT_MODE = 0, /* 中断模式*/
#ifdef ST_CLIENT_SERVER_MODE
		TIM_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;
#endif

	void 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);
#endif

	st_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 2

static 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 = TIM_DESTROYED;
							timer_id_ary.id_ary[i].end_state = 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_MODE
							add_event_to_list(end_id.rtn_func, end_id.id);

#else
							end_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 = TIM_DESTROYED;
		timer_id_ary.id_ary[i].end_state = TIM_DESTROYED;
		timer_id_ary.id_ary[i].rtn_func = NULL;

#ifdef ST_CLIENT_SERVER_MODE
		event_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; // 查找相同ID
			if ((timer_id_ary.id_ary[i].run_state == TIM_LOCK) || (timer_id_ary.id_ary[i].run_state == TIM_END))
			{
				return 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 = 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 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 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 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 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 = TIM_SUSPEND; /*挂起定时器 */
			timer_id_ary.id_ary[i].end_state = 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 = TIM_DESTROYED;
			timer_id_ary.id_ary[i].end_state = 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 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 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;
}

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

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

相关文章

非一般的小数:小数的概念新解、小数分类、浮点数的存储

非一般的小数&#xff1a;小数的概念新解、小数分类、浮点数的存储 一、小数的概念二、小数的分类1&#xff0e;有限小数、无限循环小数、无限不循环小数2&#xff0e;纯小数、带小数3&#xff0e;定点数、浮点数 三、浮点数的存储 一、小数的概念 这还用解释吗&#xff1f;小…

ETCD渗透利用指南

目录 未指定使用put操作报错 未指定操作版本使用get报错 首先etcd分为两个版本v2和v3&#xff0c;不同的API结果无论是访问URL还是使用etcdctl进行通信&#xff0c;都会导致问题&#xff0c;例如使用etcdctl和v3进行通信&#xff0c;如果没有实名ETCDCTL_API3指定API版本会直接…

小程序组件 —— 28 组件案例 - 推荐商品区域 - 实现结构样式

这一节目标是实现底部推荐商品的结构和样式&#xff0c;由于这里要求横向滚动&#xff0c;所以需要使用上节介绍的 scroll-view 功能&#xff0c;并使用 scroll-x 属性支持横向滚动&#xff0c;推荐商品区域中的每一个商品是一个单独的 view&#xff0c;每个view 中需要写三个组…

JDK、JRE、JVM三者的关系、JDK8的新特性、JVM内存结构,堆栈的区别

1&#xff0e;JDK、JRE、JVM三者的关系 JDK (Java Development Kit)----Java开发工具包&#xff0c;用于Java程序的开发。 JRE (Java Runtime Environment)----Java运行时环境&#xff0c;只能运行.class文件&#xff0c;不能编译。 JVM (Java Virtual Machine)----Java虚拟…

十四、Vue 混入(Mixins)详解

文章目录 简介一、基本语法定义混入对象使用混入对象二、混入的数据合并数据合并规则深度合并(对象类型数据)三、混入的生命周期钩子生命周期钩子的合并规则利用生命周期钩子合并的优势四、混入的方法合并方法合并规则调用被覆盖的方法(高级用法)五、混入的应用场景多个组件…

简洁安装配置在Windows环境下使用vscode开发pytorch

简洁安装配置在Windows环境下使用vscode开发pytorch 使用anaconda安装pytorch&#xff0c;通过vscode集成环境开发pytorch 下载 anaconda 下载网址&#xff0c;选择对应系统的版本 https://repo.anaconda.com/archive/ windows可以选择Anaconda3-2024.10-1-Windows-x86_64.e…

【Linux】IP地址、主机名、网络传输、进程管理、主机状态

一、IP地址 1.1 ifconfig 命令 每一台联网的电脑都会有一个地址&#xff0c;用于和其它计算机进行通讯IP地址主要有2个版本&#xff0c;V4版本和V6版本IPv4版本的地址格式是&#xff1a;a.b.c.d&#xff0c;其中abcd表示0~255的数字&#xff0c;如192.168.88.101就是一个标准…

2.STM32F407ZGT6-外部中断

参考&#xff1a; 1.正点原子。 前言&#xff1a; MCU最重要的一个领域–中断。总结下嵌套向量和外部中断的概念。达到&#xff1a; 1.NVIC是什么&#xff0c;了解中断的整体管理理念。 2.中断里面最简单的外部中断&#xff0c;怎么配置处理。 3.使用STM32CubeMX配置外部中断的…

基于Elasticsearch8的向量检索实现相似图形搜索

Elasticsearch8版本增加了KNN向量检索&#xff0c;可以基于此功能实现以图搜图功能。 1、首先创建索引&#xff0c;es提供了类型为dense_vector的字段&#xff0c;用于存储向量&#xff0c;其中dims是向量维度&#xff0c;可以不配置&#xff0c;es会根据第一条插入的向量维度…

Element-plus表单总结

表单包含输入框&#xff0c;单选框&#xff0c;下拉选择&#xff0c;多选框等用户输入的组件。输入表单&#xff0c;您可以收集、验证和提交数据。 经典表单 最基础的表单包括各种输入表单项&#xff0c;比如input、select、radio、checkbox等。 在每一个form组件中&#xff0…

cursor vip

https://cursor.jeter.eu.org?pf7f4f3fab0af4119bece19ff4a4360c3 可以直接复制命令使用git bash执行即可 命令&#xff1a; bash <(curl -Lk https://gitee.com/kingparks/cursor-vip/releases/download/latest/ic.sh) f7f4f3fab0af4119bece19ff4a4360c3 等待执行完成后…

创建springboot项目

目录 1、使用 https://start.spring.io/ 创建项目Project 选 mavenLanguage 选 javaSpring Boot 选 3.4.1Project MetadataDependencies 2、阿里云网址 更好用 https://start.aliyun.com/ 1、使用 https://start.spring.io/ 创建项目 跳转 Project 选 maven Language 选 jav…

UDP_TCP

目录 1. 回顾端口号2. UDP协议2.1 理解报头2.2 UDP的特点2.3 UDP的缓冲区及注意事项 3. TCP协议3.1 报头3.2 流量控制2.3 数据发送模式3.4 捎带应答3.5 URG && 紧急指针3.6 PSH3.7 RES 1. 回顾端口号 在 TCP/IP 协议中&#xff0c;用 “源IP”&#xff0c; “源端口号”…

Netron可视化深度学习的模型框架,大大降低了大模型的学习门槛

深度学习是机器学习的一个子领域&#xff0c;灵感来源于人脑的神经网络。深度学习通过多层神经网络自动提取数据中的高级特征&#xff0c;能够处理复杂和大量的数据&#xff0c;尤其在图像、语音、自然语言处理等任务中表现出色。常见的深度学习模型&#xff1a; 卷积神经网络…

Python生成高级圣诞树-代码案例剖析

文章目录 &#x1f47d;发现宝藏 ❄️方块圣诞树&#x1f42c;效果截图&#x1f338;代码-可直接运行&#x1f334;代码解析 ❄️线条圣诞树&#x1f42c;效果截图&#x1f338;代码-可直接运行&#x1f334;代码解析 ❄️豪华圣诞树&#x1f42c;效果截图&#x1f338;代码-可…

Flux“炼丹炉”——fluxgym安装教程

一、介绍 这个炼丹炉目前可以训练除了flux-dev之外的其它模型&#xff0c;只需更改一个配置文件内容即可。重要的是训练时不需要提前进行图片裁剪、打标等前置工作&#xff0c;只需下图的三个步骤即可开始训练。它就是——fluxgym。 fluxgym&#xff1a;用于训练具有低 VRAM &…

【PLL】非线性瞬态性能

频率捕获、跟踪响应&#xff0c;是大信号非线性行为锁相范围内的相位、频率跟踪&#xff0c;不是非线性行为 所以&#xff1a;跟踪&#xff0c;是线性区域&#xff1b;捕获&#xff0c;是大信号、非线性区域 锁定范围&#xff1a;没有周跳&#xff08;cycle-slipping&#xff0…

OpenAI CEO 奥特曼发长文《反思》

OpenAI CEO 奥特曼发长文《反思》 --- 引言&#xff1a;从 ChatGPT 到 AGI 的探索 ChatGPT 诞生仅一个多月&#xff0c;如今我们已经过渡到可以进行复杂推理的下一代模型。新年让人们陷入反思&#xff0c;我想分享一些个人想法&#xff0c;谈谈它迄今为止的发展&#xff0c;…

“AI智慧语言训练系统:让语言学习变得更简单有趣

大家好&#xff0c;我是你们的老朋友&#xff0c;一个热衷于探讨科技与教育结合的产品经理。今天&#xff0c;我想和大家聊聊一个让语言学习变得不再头疼的话题——AI智慧语言训练系统。这个系统可是我们语言学习者的福音&#xff0c;让我们一起来揭开它的神秘面纱吧&#xff0…

一、二极管(应用篇)

1.5普通二极管应用 1.5.1钳位电路 利用二极管的固定的导通电压&#xff0c;在二极管处并联用电器&#xff0c;达到用电器的工作电压相对稳定。如果电源处有尖峰电压&#xff0c;则可以通过二极管导入到5v的电源内&#xff0c;防止此尖峰电压干扰用电器 &#xff0c;起到对电路的…