STM32F4系列单片机的定时器讲解和计数器,PWM信号输出,PWM信号捕获的实现对电机进行控制和监测功能

news2024/11/26 10:48:21

1.定时器功能介绍:

在控制领域里面,我们可以用信号输出定时器,进行PWM的控制,从而达到控制电机的目的,通过输入捕获功能可以用来接收外部的数字信号,用于测量脉冲宽度、频率或周期等。在这里给大家介绍下,具体用定时器做计数,输出和捕获的功能实现。

STM32F4一共有三种14个定时器。(12个16位的,2个32位的),STM32F1系列只有8个16位的。

高级定时器:TIM1、TIM8。通常用于特定领域和专业需求用户使用的精密计时工具,通常适用于需要精度更高的领域。通常可以精确到毫秒或更小的时间单位,并具有更复杂的逻辑和算法。

通用定时器:TIM2、TIM5、TIM3、TIM4,TIM9~TIM14。 

基本定时器:TIM6、TIM7,没有捕获等通道,用作简单定时。

STM32通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)等。

2.计数定时器配置

在STM32F429上实现TIM6的计时,可以通过以下步骤进行:

  1. 使能TIM6时钟。

  2. 初始化TIM6时基单元,设置时钟分频系数和计数周期。

  3. 使能更新中断(如果需要)。

  4. 使能TIM6。

  5. 等待中断处理(如果使能了中断)。

以下是一个简单的示例代码,展示如何使用HAL库函数来配置TIM6作为一个简单的计时器:

/* 注意:1. 中断相关名称。注意基本定时器TIM6 的中断名为 TIM6_DAC_IRQn,< TIM6 global and DAC1&2 underrun error  interrupts>,其他一些定时器为 TIMx_IRQn(x=2,3,4,7 etc)	*/
/* 中断函数名为 TIM6_DAC_IRQHandler(),而不是 TIM6_IRQHandler()		*/
/* 3. 基本定时器(TIM6, TIM7),通用定时器,高级定时器(TIM1, TIM8),功能越来越多,此处只做个简单计时,基本定时器足够了	*/

#include "timer.h"

uint32_t tim = 0;						// 全局变量,每0.1ms加1
TIM_HandleTypeDef TIM6_Handler;      	//定时器句柄 

/* 基本定时器6初始化						*/
/* 实现 0.1ms 计时中断					*/
/* 90M/90=1M,1M/100 = 10kHz = 0.1ms	*/
void TIM6_Init(void)
{  

    TIM_MasterConfigTypeDef sMasterConfig = {0};
    TIM6_Handler.Instance			= TIM6;                  		// 基本定时器
    TIM6_Handler.Init.Prescaler		= 180-1;                 		// 分频系数 180MHz,得到 180M/180=1M 时钟
    TIM6_Handler.Init.CounterMode	= TIM_COUNTERMODE_UP;    		// 向上计数器
    TIM6_Handler.Init.Period		= 100-1;                  		// 自动装载值 100,每 100/1M = 100us=0.1ms中断一次
    htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    HAL_TIM_Base_Init(&TIM6_Handler);
	
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
    HAL_TIM_Base_Start_IT(&TIM6_Handler); //使能定时器3和定时器3更新中断:TIM_IT_UPDATE   
}
/* 定时器底册驱动,开启时钟,设置中断优先级	*/
/* 此函数会被HAL_TIM_Base_Init()函数调用		*/
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
    if(htim->Instance==TIM6)
	{
        __HAL_RCC_TIM6_CLK_DISABLE();    						// 使能TIM6时钟,
		HAL_NVIC_SetPriority(TIM6_IRQn,1,3);    					// 中断优先级:抢占优先级1,子优先级3。
        HAL_NVIC_EnableIRQ(TIM6_IRQn);        					// 开启ITM6中断  
	}
}

/**
  * @brief  定时器比较中断
  * @param  htim:定时器句柄指针
	*	@note 		无
  * @retval 无
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(__HAL_TIM_GET_IT_SOURCE(&TIM6_Handler, TIM_IT_UPDATE) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(&TIM6_Handler, TIM_IT_UPDATE);				// 清除中断标志位
    }
    tim ++; 														// 又是0.1ms,全局时间计数加1
}

3.TIM3输出4路PWM波

与定时不同,配置输出PWM波需要配置I/O口,相应地需要配置相应通道;输出PWM波时可不配置中断。步骤如下:

初始化配置。选择时钟、配置分频系数、计数模式、自动重装值、分频因子。
通道配置。配置PWM模式、默认占空比、输出比较极性并且开启对应的通道。
底层配置。开启时钟、配置相关引脚。
此处,航模电机驱动频率选择常用的 400Hz,定时器重装值选择 5000-1。为了方便实际中调节各个电机的占空比,编写设置于获取占空比的函数,占空比调节精度为 1/1000。

对于I/O选择,使用了TIM3 CH1~CH3,对应引脚参考核心板原理图:

#define PWM_PIN			GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_0 | GPIO_PIN_1
#define PWM_GPIO		GPIOB
#define PWM_ENCLK()		__HAL_RCC_TIM3_CLK_ENABLE();	\
						__HAL_RCC_GPIOB_CLK_ENABLE();	// 使能定时器3,开启GPIOB时钟						

/* 四个电机枚举	*/
typedef enum
{
	MOTOR1 = 0,
	MOTOR2 = 1,
	MOTOR3 = 2,
	MOTOR4 = 3
};
	 
/* TIM3 4路 PWM波输出初始化 		*/
void TIM3_PWM_Init(void)
{ 
    TIM3_Handler.Instance			= TIM3;            		//定时器3
    TIM3_Handler.Init.Prescaler		= 45-1;       			//定时器分频 45,得到 90M/45=2M 时钟
    TIM3_Handler.Init.CounterMode	= TIM_COUNTERMODE_UP;	//向上计数模式
    TIM3_Handler.Init.Period		= 5000-1;          		//自动重装载值 5000,得到PWM频率 2M/5k=400Hz
    TIM3_Handler.Init.ClockDivision	= TIM_CLOCKDIVISION_DIV1;
    HAL_TIM_PWM_Init(&TIM3_Handler);       					//初始化PWM
    
    TIM3_CHxHandler.OCMode			= TIM_OCMODE_PWM1; 		//模式选择PWM1
    TIM3_CHxHandler.Pulse			= 0;           			//设置比较值,此值用来确定占空比,默认为0
    TIM3_CHxHandler.OCPolarity		= TIM_OCPOLARITY_HIGH; 	//输出比较极性为高
	
	HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CHxHandler,TIM_CHANNEL_1);	//配置TIM3通道1
    HAL_TIM_PWM_Start(&TIM3_Handler, TIM_CHANNEL_1);		//开启PWM通道1
	HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CHxHandler,TIM_CHANNEL_2);	//配置TIM3通道2
    HAL_TIM_PWM_Start(&TIM3_Handler, TIM_CHANNEL_2);		//开启PWM通道2
	HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CHxHandler,TIM_CHANNEL_3);	//配置TIM3通道3
    HAL_TIM_PWM_Start(&TIM3_Handler, TIM_CHANNEL_3);		//开启PWM通道3
	HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CHxHandler,TIM_CHANNEL_4);	//配置TIM3通道4
    HAL_TIM_PWM_Start(&TIM3_Handler, TIM_CHANNEL_4);		//开启PWM通道4
	
}

/* 定时器底层驱动,时钟使能,引脚配置	*/
/* 此函数会被HAL_TIM_PWM_Init()调用	*/
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
    GPIO_InitTypeDef GPIO_Initure;
	
	PWM_ENCLK();
	
    GPIO_Initure.Pin		= PWM_PIN; 
    GPIO_Initure.Mode		= GPIO_MODE_AF_PP;  			// 复用推完输出
    GPIO_Initure.Pull		= GPIO_PULLUP;          		// 上拉
    GPIO_Initure.Speed		= GPIO_SPEED_HIGH;     			// 高速
	GPIO_Initure.Alternate	= GPIO_AF2_TIM3;				// 引脚复用
    HAL_GPIO_Init(PWM_GPIO, &GPIO_Initure);
}

/* 设置电机占空比										*/
/* motor: 选择电机,可填MOTOR1, MOTOR2, MOTOR3, MOTOR4	*/
/* duty: 占空比为千分之 duty								*/
void SetMotorDuty(uint8_t motor, uint16_t duty)
{
	if (duty > 1000)
		duty = 1000;
	else if (duty < 0)
		duty = 0;
	
	if (motor == MOTOR1)
		TIM3->CCR1 = duty * 5 - 1;	// 由于计数器重装值ARR为 5000,精度为千分之一,故此处乘以5,减一是因为从0开始计数
	else if (motor == MOTOR2)
		TIM3->CCR2 = duty * 5 - 1;
	else if (motor == MOTOR3)
		TIM3->CCR3 = duty * 5 - 1;
	else if (motor == MOTOR4) 
		TIM3->CCR4 = duty * 5 - 1;
}

/* 获取电机占空比														*/
/* motor选择电机,可填MOTOR1, MOTOR2, MOTOR3, MOTOR4,占空比为千分之返回值	*/
uint16_t GetMotorDuty(uint8_t motor)
{
	uint32_t cap_value;
	if (motor == MOTOR1)
		cap_value = HAL_TIM_ReadCapturedValue(&TIM3_Handler,TIM_CHANNEL_1);		// 读取比较寄存器的值
	else if (motor == MOTOR2)
		cap_value = HAL_TIM_ReadCapturedValue(&TIM3_Handler,TIM_CHANNEL_1);
	else if (motor == MOTOR3)
		cap_value = HAL_TIM_ReadCapturedValue(&TIM3_Handler,TIM_CHANNEL_1);
	else if (motor == MOTOR4) 
		cap_value = HAL_TIM_ReadCapturedValue(&TIM3_Handler,TIM_CHANNEL_1);
	
	return (cap_value+1) / 5;
}				

4.TIM5输入捕获

输入捕获也需要配置对应的 I/O 口于通道,而且需要在中断服务函数里实现定时中断、高/低电平时间的测量。步骤如下:

1.初始化配置:选择时钟、配置分配系数、计数模式、自动重装值、时钟分频因子。
2.通道配置:配置上升/下降沿捕获、引脚对应寄存器、分频因子、滤波效果。
3.底层配置:配置引脚、使能时钟、中断优先级与是能。
4.中断服务函数:思想很简单,分别读取下降沿、上升沿、下降沿时寄存器数据,计算得到正脉宽、周期等参数。

#define CAP_PIN			GPIO_PIN_0
#define CAP_GPIO		GPIOA
#define CAP_ENCLK()		__HAL_RCC_TIM5_CLK_ENABLE();	\
						__HAL_RCC_GPIOA_CLK_ENABLE(); 	//使能TIM5时钟,开启GPIOA时钟

TIM_HandleTypeDef TIM5_Handler;         							//定时器5句柄

uint32_t cap_value1 = 0;			// 检测到上升沿时的计数
uint32_t cap_value2 = 0;			// 检测到下降沿时的计数, cap_value2 - cap_value1 即为正脉冲时间
uint32_t cap_value3 = 0;			// 再次检测到上升沿时的计数, cap_value3 - cap_value1 即为周期

uint8_t cap_sta = 0;				// 输入捕获状态, 0:没有完成捕获,去捕获边沿吧  1:捕获边沿完成,去计算周期吧
uint8_t cap_times = 0;				// 捕获次数

/* 定时器5通道1输入捕获配置 	*/
/* 频率:90M/90/1 = 1MHz		*/
void TIM5_CH1_Cap_Init(void)
{  
    TIM_IC_InitTypeDef TIM5_CH1Config;  
    
    TIM5_Handler.Instance			= TIM5;                         // 通用定时器5
    TIM5_Handler.Init.Prescaler		= 90-1;                     	// 分频系数
    TIM5_Handler.Init.CounterMode	= TIM_COUNTERMODE_UP;    		// 向上计数器
    TIM5_Handler.Init.Period		= 0XFFFFFFFF;                   // 自动装载值
    TIM5_Handler.Init.ClockDivision	= TIM_CLOCKDIVISION_DIV1;		// 时钟分频银子
    HAL_TIM_IC_Init(&TIM5_Handler);									// 初始化输入捕获时基参数
    
    TIM5_CH1Config.ICPolarity		= TIM_ICPOLARITY_RISING;    	// 上升沿捕获
    TIM5_CH1Config.ICSelection		= TIM_ICSELECTION_DIRECTTI;		// 设置引脚与寄存器关系。CH1、CH2用TI1,CH3、CH4用TI2
    TIM5_CH1Config.ICPrescaler		= TIM_ICPSC_DIV1;          		// 配置输入分频,不分频
    TIM5_CH1Config.ICFilter=0;                          			// 配置输入滤波器,不滤波
    HAL_TIM_IC_ConfigChannel(&TIM5_Handler,&TIM5_CH1Config,TIM_CHANNEL_1);//配置TIM5通道1
	
    HAL_TIM_IC_Start_IT(&TIM5_Handler,TIM_CHANNEL_1);   			// 开启TIM5的捕获通道1,并且开启捕获中断
    __HAL_TIM_ENABLE_IT(&TIM5_Handler,TIM_IT_UPDATE);   			// 使能更新中断
}

/* 定时器5底层驱动,时钟使能,引脚配置	*/
/* 此函数会被HAL_TIM_IC_Init()调用	*/
void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
{
    GPIO_InitTypeDef GPIO_Initure;
	
	CAP_ENCLK();
	
    GPIO_Initure.Pin		= CAP_PIN;            					// 引脚
    GPIO_Initure.Mode		= GPIO_MODE_AF_PP;      				// 复用推挽输出
    GPIO_Initure.Pull		= GPIO_PULLDOWN;        				// 下拉
    GPIO_Initure.Speed		= GPIO_SPEED_HIGH;     					// 高速
    GPIO_Initure.Alternate	= GPIO_AF2_TIM5;   						// PA0复用为TIM5通道1
    HAL_GPIO_Init(CAP_GPIO,&GPIO_Initure);

    HAL_NVIC_SetPriority(TIM5_IRQn,2,0);    						// 设置中断优先级,抢占优先级2,子优先级0
    HAL_NVIC_EnableIRQ(TIM5_IRQn);          						// 开启ITM5中断通道  
}

/* 定时器5中断服务函数			*/
void TIM5_IRQHandler(void)
{
	HAL_TIM_IRQHandler(&TIM5_Handler);								//定时器共用处理函数
}

/* 定时器输入捕获中断处理回调函数,该函数在HAL_TIM_IRQHandler中会被调用	*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)			//更新中断(溢出)发生时执行
{
	if (cap_sta == 0)
	{
		switch (cap_times)
		{
			case 0: 				// 清空一切,准备捕获
				cap_value1 = 0;
				cap_value2  = 0;
				cap_value3  = 0;
				__HAL_TIM_DISABLE(&TIM5_Handler);        									//关闭定时器5
				__HAL_TIM_SET_COUNTER(&TIM5_Handler,0);		
				TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);   					//一定要先清除原来的设置!!
				TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//定时器5通道1设置为下降沿捕获
				__HAL_TIM_ENABLE(&TIM5_Handler);
				cap_times = 1;
				break;
			case 1:					// 捕获了一次
				cap_value1 = HAL_TIM_ReadCapturedValue(&TIM5_Handler,TIM_CHANNEL_1);		// 读数一次
				TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);   					//一定要先清除原来的设置!!
				TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);//定时器5通道1设置为上升沿捕获		
				cap_times = 2;
				break;
			case 2:					// 捕获了两次
				cap_value2 = HAL_TIM_ReadCapturedValue(&TIM5_Handler,TIM_CHANNEL_1);		// 读数一次
				TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);   					//一定要先清除原来的设置!!
				TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//定时器5通道1设置为下降沿捕获		
				cap_times = 3;
				break;
			case 3:					// 捕获了三次
				cap_value3 = HAL_TIM_ReadCapturedValue(&TIM5_Handler,TIM_CHANNEL_1);		// 读数一次
				TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);   					//一定要先清除原来的设置!!
				TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);	//定时器5通道1设置为上升沿捕获
				cap_times = 0;			
				cap_sta = 1;		// 所有捕获完成,可以去计算了
				break;
		}
	}
}

测试捕获和输出:

void TestPwmTask(void *arg)
{
	const uint16_t test_postime = 100;	// 正常时间为 test_postime / 1000 * 2500 = test_postime * 2.5
	
	uint32_t pos_time;				// 高电平时间
	uint32_t cycle;					// 周期
	uint32_t freq;					// 频率
	float pos_duty;					// 正占空比
	
	SetMotorDuty(MOTOR1, test_postime);						// 电机PWM 400Hz = 2500 us,占空比 100/1000,高电平时间 250us		
	SetMotorDuty(MOTOR2, test_postime);
	SetMotorDuty(MOTOR3, test_postime);
	SetMotorDuty(MOTOR4, test_postime);
		
	while(1)
	{
        if (cap_sta == 1)      		//成功捕获到了一次高电平
		{
			pos_time = cap_value3 - cap_value2;
			cycle = cap_value3 - cap_value1;
			freq = (uint32_t)1000000 / cycle;
			pos_duty = (float) pos_time / (float) cycle;
			
			printf("周期:%d us\t  正脉冲宽:%d us  \r\n", cycle, pos_time);
			printf("频率:%d Hz\t  正占空比:%.2f %%\r\n\r\n", freq, pos_duty*100);

			cap_sta = 0;          		// 搞完事情,开启下一次捕获
		}
		delay_ms(200);
	}
}

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

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

相关文章

二维相位解包理论算法和软件【全文翻译-将相位分解为 “非旋转 “和 “旋转 “(2.4)】

2.4 将相位分解为 "非旋转 "和 "旋转 "部分 借用电磁场理论,可以用发散和卷曲来指定矢量场[9][10]。当且仅当矢量函数 F(r)(以及由其描述的场)在整个域 D 中不旋转或无旋转时,我们称之为矢量函数 F(r)、 因此,如果等式 2.30(也是第 2.2 节关于路径…

面对汽车充电桩隐私泄露威胁,应该怎么做?

想必各位车主在第一次扫码或刷卡使用汽车充电桩时&#xff0c;都会出现类似于上图的请求&#xff0c;除了上述的定位权限外&#xff0c;运营商还会索要你的网络权限、相机权限、通知权限、设备信息权限、存储权限、电话权限等。 那么你知道这些权限充电桩获取后到底用于什么吗&…

DELL服务器使用iDRAC升级BIOS等固件版本

前言 正值DELL推出DELL R730XD服务器最新的BIOS固件&#xff08;2.19.0 2024/3/18&#xff09;之际&#xff0c;本人也有合适的时间将手头的服务器BIOS固件进行升级操作。 本文博将DELL R730xd 的iDRAC8版本为例&#xff0c;介绍整个升级过程。其他DELL类型的服务器操作类似&…

黄金票据攻击

黄金票据攻击——域内横向移动技术 一、黄金票据攻击介绍&#xff1a; 黄金票据攻击是一种滥用Kerberos身份认证协议的攻击方式&#xff0c;它允许攻击者伪造域控krbtgt用户的TGT&#xff08;Ticket-Granting Ticket&#xff09;。通过这种方法&#xff0c;攻击者可以生成有效…

【C语言】2048小游戏【附源码】

一、游戏描述&#xff1a; 2048是一款数字益智类游戏&#xff0c;玩家需要使用键盘控制数字方块的移动&#xff0c;合并相同数字的方块&#xff0c;最终达到数字方块上出现“2048”的目标。 每次移动操作&#xff0c;所有数字方块会朝着指定方向同时滑动&#xff0c;并在靠近边…

supersqli-攻防世界

题目 加个报错 1 and 11 #没报错判断为单引号字符注入 爆显位 1 order by 2#回显正常 1 order by 3#报错 说明列数是2 尝试联合查询 -1 union select 1,2# 被过滤了 return preg_match("/select|update|delete|drop|insert|where|\./i",$inject); select|update|d…

vCenter Server出现no healthy upstream的解决方法

https://blog.51cto.com/wangchunhai/4907250 访问vCenter 7.0 地址后&#xff0c;页面出现“no healthy upstream”,无法正常登录vCenter&#xff0c;重启后依旧如此&#xff0c;该故障的前提是没有对vCenter做过任何配置&#xff0c;如下图所示。 尝试登录"VMware vCen…

快速排渣器与矿用快速除渣器

你不想虚度光阴&#xff0c;你想用自己的努力&#xff0c;书写自己人生的精彩&#xff0c;那么&#xff0c;你脚下的路不能回头&#xff0c;铺满掌声和鲜花的人生路上&#xff0c;脚下没有那么平坦&#xff0c;或是泥泞&#xff0c;或是陷阱&#xff0c;别管多么艰难的路程&…

前端跨页面通信方案介绍

在浏览器中&#xff0c;我们可以同时打开多个Tab页&#xff0c;每个Tab页可以粗略理解为一个“独立”的运行环境&#xff0c;即使是全局对象也不会在多个Tab间共享。然而有些时候&#xff0c;我们希望能在这些“独立”的Tab页面之间同步页面的数据、信息或状态。这就是本文说说…

ubuntu20.04 运行 lio-sam 流程记录

ubuntu20.04 运行 lio-sam 一、安装和编译1.1、安装 ROS11.2、安装 gtsam1.3、安装依赖1.4、下载源码1.5、修改文件1.6、编译和运行 二、官方数据集的运行2.1、casual_walk_2.bag2.2、outdoor.bag、west.bag2.3、park.bag 三、一些比较好的参考链接 记录流程&#xff0c;方便自…

新质生产力崛起,运营商前端运营如何跃升

“新质生产力”一个当前的热搜高频词&#xff0c;今年还被首次写进政府工作报告&#xff0c;是2024年十大工作任务的首位。那么什么是“新质生产力”&#xff1f;它对于我们的生活、学习、工作及未来发展有什么影响呢&#xff1f;今天小宝就抛砖引玉来讲一讲“新质生产力”对于…

数字化服务升级:数字乡村改善农民生活质量

随着信息技术的迅猛发展&#xff0c;数字化浪潮已经深入社会的各个角落&#xff0c;为人们的生活带来了翻天覆地的变化。在乡村地区&#xff0c;数字化服务的升级正在逐步改变农民的生活方式&#xff0c;提高他们的生活质量。本文将围绕数字化服务升级&#xff0c;探讨数字乡村…

【精心整理】2024最新Web安全攻防教程资料PPT大合集

以下是学习资料目录&#xff0c;如需要下载&#xff0c;请您前往星球查阅和获取&#xff1a;https://t.zsxq.com/18YLzWtDI 1、Sqlmap Tamper脚本编写介绍-01.pptx 2、Tamper脚本分析&#xff08;支持所有类型数据库的Tamper脚本&#xff09;-01.pptx 3 、Sqlmap Tamper脚本分析…

一款强大的逆向分析工具-Ghidra

工具介绍 Ghidra 是由美国国家安全局&#xff08;NSA&#xff09;研究部门开发的软件逆向工程&#xff08;SRE&#xff09;套件&#xff0c;用于支持网络安全任务。包括一套功能齐全的高端软件分析工具&#xff0c;使用户能够在各种平台(Windows、Mac OS和Linux)分析编译后的代…

Flutter应用发布流程详解:从开发到上架一站式指南

引言 Flutter是一款由Google推出的跨平台移动应用开发框架&#xff0c;其强大的性能和流畅的用户体验使其备受开发者青睐。然而&#xff0c;开发一款应用只是第一步&#xff0c;将其成功上架到苹果商店才是实现商业目标的关键一步。本文将详细介绍如何使用Flutter将应用程序上…

Qt使用opencv打开摄像头

1.效果图 2.代码 #include "widget.h"#include <QApplication>#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp>#include <QImage> #include <QLabel> #incl…

为什么蓝牙信道探测将引领高精度定位服务?

从蓝牙耳机到智能家居设备&#xff0c;蓝牙技术因其成熟的音频流和数据传输功能已成为我们生活中的一部分。一项新技术——蓝牙信道探测&#xff08;Bluetooth Channel Sounding&#xff09;正向高精度定位服务市场迈进。 本文信驰达&#xff08;RF-star&#xff09;将介绍蓝牙…

java学习之路-数组定义与使用

目录 ​编辑 1.什么是数组 2.数组的创建及其初始化 2.1数组的创建 2.2数组的初始化 3.数组的使用 3.1数组元素访问 3.2遍历数组 4.数组是引用类型 4.1jvm的内存分布 4.2基本类型变量与引用类型变量的区别 4.3引用变量详解 4.4 null 5.数组的使用场景 5.1存储数据 5…

基于SpringBoot+微信小程序的图书借阅管理系统(包运行调试)

介绍 系统介绍 是一套图书借阅管理系统&#xff0c;包括用户小程序以及后台管理系统。 前台商城系统包含用户注册登录、首页门户、图书查询、在线借阅、个人中心、我的信息、我的借阅、押金充值。 后台管理系统包含统计分析、用户管理、分类管理、图书管理、借阅管理、管理员…

硬件了解 笔记

motherboard的高低端区别在哪里&#xff1f; 核心&#xff1a;从单核变成双核&#xff0c;多核&#xff08;几核就是几个打工人&#xff09; 多线程&#xff1a;6核本来对应6个线程&#xff0c;但是多线程就是说6核对应12个线程 频率 主频&#xff1a;平时打工的速度 睿频&…