【STM32】在标准库中使用定时器

1.TIM简介

各个定时器特性

STM32F407系列控制器有2个高级控制定时器、10个通用定时器和2个基本定时器。通常情况下,先看定时器挂在哪个总线上APB1或者APB2,然后定时器时钟需要在此基础上乘以2。

2.标准库实现定时中断

#ifndef __BSP_TIMER_H
#define __BSP_TIMER_H

#ifdef __cplusplus
extern "C"{

#endif

#include "stm32f4xx.h"

#define INT_TIMER_IRQ             TIM3_IRQn
#define INT_TIMER_IRQHandler      TIM3_IRQHandler

//我们使用了通用定时器TIM3来实现计时中断
//注意,并不是所有的TIM在向量表中都定义了中断服务函数,所以你得自己去查一查
//TIM3在APB1总线上
#define INT_TIMER               TIM3
#define INT_TIMER_CLK           RCC_APB1Periph_TIM3

void Init_INT_TIMER(void);
	
#ifdef __cplusplus
}
#endif

#endif


#include "bsp_timer.h"
#include "bsp_led.h"
#include "stdio.h"

void Init_INT_TIMER(void)
{
	//使能定时器时钟
	RCC_APB1PeriphClockCmd(INT_TIMER_CLK,ENABLE);
	
	//初始化定时器,配置ARR,PSC
	TIM_TimeBaseInitTypeDef TIM_InitStruct;
	TIM_InitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_InitStruct.TIM_CounterMode=TIM_CounterMode_Up;//选择向上计数的方式
	
	/* 累计 TIM_Period个后产生一个更新或者中断*/
    //当定时器从0计数到4999,即为5000次,为一个定时周期
	TIM_InitStruct.TIM_Period=5000-1;
	
	//定时器时钟源TIMxCLK = 2 * PCLK1
    //        PCLK1 = HCLK / 4
    //        => TIMxCLK=HCLK/2=SystemCoreClock/2=84MHz
    // 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=10000Hz ==>0.1ms
	TIM_InitStruct.TIM_Prescaler=8400-1;//
	//所以,一个中断产生时间为 0.1ms*5000=500ms
	TIM_InitStruct.TIM_RepetitionCounter=0;//高级定时器才有的参数,这里也无用
	TIM_TimeBaseInit(INT_TIMER,&TIM_InitStruct);
	
	//配置中断控制器并使能中断
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel=INT_TIMER_IRQ;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=3;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
	NVIC_Init(&NVIC_InitStruct);
	TIM_ITConfig(INT_TIMER,TIM_IT_Update,ENABLE);
	
	//使能定时器
	TIM_Cmd(INT_TIMER,ENABLE);
}

void INT_TIMER_IRQHandler(void)
{
	if(SET==TIM_GetITStatus(INT_TIMER,TIM_IT_Update))
	{
		LED_TOGGLE();
		TIM_ClearITPendingBit(INT_TIMER,TIM_IT_Update);
		printf("INT_TIMER_IRQHandler\r\n");
	}
}

int main(void)
{
	Init_USART();
	
	Init_LED();
	
	//设置中断分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
		
	Init_INT_TIMER();
	printf("hello,this is stm32f407\r\n");
  /* Infinite loop */
  while (1)
  {
	  
  }
}

在这里插入图片描述

自动重载寄存器TIMx_ARR用来存放于计数器值比较的数值,如果两个数值相等就生成事件,将相关事件标志位置位,生成DMA和中断输出。 TIMx_ARR有影子寄存器,可以通过TIMx_CR1寄存器的ARPE位控制影子寄存器功能,如果ARPE位置1,影子寄存器有效, 只有在事件更新时才把TIMx_ARR值赋给影子寄存器。如果ARPE位为0,修改TIMx_ARR值马上有效。

void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

就是标准库中的这个函数,其实就是配置TIMx_CR1寄存器的ARPE位。所以,我们也可以意识到,ARR值是可以热更新的。

3.标准库实现PWM输出

PWM输出就是对外输出脉宽(即占空比)可调的方波信号,信号频率由自动重装寄存器ARR的值决定,占空比由比较寄存器CCR的值决定。

PWM模式分为两种,PWM1和PWM2,总得来说是差不多,就看你怎么用而已,具体的区别见表格 PWM1与PWM2模式的区别 。

PWM1与PWM2模式的区别

下面我们以PWM1模式来讲解,以计数器CNT计数的方向不同还分为边沿对齐模式和中心对齐模式。PWM信号主要都是用来控制电机, 一般的电机控制用的都是边沿对齐模式,FOC电机一般用中心对齐模式。我们这里只分析这两种模式在信号感官上(即信号波形)的区别, 具体在电机控制中的区别不做讨论,到了你真正需要使用的时候就会知道了。

在递增计数模式下,计数器从 0 计数到自动重载值( TIMx_ARR寄存器的内容),然后重新从 0 开始计数并生成计数器上溢事件

PWM1模式的边沿对齐波形

在边沿对齐模式下,计数器CNT只工作在一种模式,递增或者递减模式。这里我们以CNT工作在递增模式为例,在中,ARR=8,CCR=4,CNT从0开始计数, 当CNT<CCR的值时,OCxREF为有效的高电平,于此同时,比较中断寄存器CCxIF置位。当CCR=<CNT<=ARR时,OCxREF为无效的低电平。然后CNT又从0开始计数并生成计数器上溢事件,以此循环往复。
在这里插入图片描述

#ifndef __BSP_TIMER_H
#define __BSP_TIMER_H

#ifdef __cplusplus
extern "C"{

#endif

#include "stm32f4xx.h"

//我们使用TIM5来输出PWM波形
//这里我们需要查手册,看看TIM5输出通道复用的引脚(TIM5_CH1--PA0)
#define PWM_OUT_TIMER           TIM5
#define PWM_OUT_TIMER_CLK       RCC_APB1Periph_TIM5
#define PWM_OUT_PIN             GPIO_Pin_0
#define PWM_OUT_GPIO_Port       GPIOA
#define PWM_OUT_GPIO_CLK        RCC_AHB1Periph_GPIOA
#define PWM_OUT_AF_SOURCE       GPIO_PinSource0
#define PWM_OUT_AF              GPIO_AF_TIM5

void Init_PWM_OUT_TIMER(void);
	
#ifdef __cplusplus
}
#endif

#endif
#include "bsp_timer.h"
#include "bsp_led.h"
#include "stdio.h"

void Init_PWM_OUT_TIMER(void)
{
	//使能定时器时钟
	RCC_APB1PeriphClockCmd(PWM_OUT_TIMER_CLK,ENABLE);
	//使能pwm输出引脚使能
	RCC_AHB1PeriphClockCmd(PWM_OUT_GPIO_CLK,ENABLE);
	
	//初始化pwm输出GPIO
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Pin=PWM_OUT_PIN;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;//配置为复用推挽输出
	GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;//默认拉高
	GPIO_InitStruct.GPIO_Speed=GPIO_Fast_Speed;
	GPIO_Init(PWM_OUT_GPIO_Port,&GPIO_InitStruct);
	//并设置复用映射
	GPIO_PinAFConfig(PWM_OUT_GPIO_Port,PWM_OUT_AF_SOURCE,PWM_OUT_AF);
	
	//初始化定时器,配置ARR,PSC
	TIM_TimeBaseInitTypeDef TIM_InitStruct;
	TIM_InitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_InitStruct.TIM_CounterMode=TIM_CounterMode_Up;//选择向上计数的方式
	
	/* 累计 TIM_Period个后产生一个更新或者中断*/
    //当定时器从0计数到4999,即为5000次,为一个定时周期
	TIM_InitStruct.TIM_Period=5000-1;
	
	//定时器时钟源TIMxCLK = 2 * PCLK1
    //        PCLK1 = HCLK / 4
    //        => TIMxCLK=HCLK/2=SystemCoreClock/2=84MHz
    // 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=10000Hz ==>0.1ms
	TIM_InitStruct.TIM_Prescaler=8400-1;//
	//所以,一个中断产生时间为 0.1ms*5000=500ms
	TIM_InitStruct.TIM_RepetitionCounter=0;//高级定时器才有的参数,这里也无用
	TIM_TimeBaseInit(PWM_OUT_TIMER,&TIM_InitStruct);
	
	TIM_OCInitTypeDef TIM_OCInitStruct;
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_Pulse=2500;// 设置PWM占空比
	//其他的参数在高级定时器中才会用到,可以忽视。我们这里使用的通用定时器。
	TIM_OC1Init(PWM_OUT_TIMER, &TIM_OCInitStruct);
	
	//使能定时器
	TIM_Cmd(PWM_OUT_TIMER,ENABLE);
}

在这里插入图片描述

注意:当把CCR设置为5000的时候,就都是高电平了。设置为4999时,才会出现低电平。

和ARR值一样,CCR值同样可以热更新。

void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1);

我们可以简单做个实验,把该定时器溢出中断也打开,然后在溢出中断中改变CCR的值,其实就是改变占空比。然后看看输出波形。

uint32_t ccr=0;
void TIM5_IRQHandler(void)
{
	if(SET==TIM_GetITStatus(PWM_OUT_TIMER,TIM_IT_Update))
	{
		if(ccr>5000)
			ccr=0;
		TIM_SetCompare1(PWM_OUT_TIMER,ccr);
		TIM_ClearITPendingBit(PWM_OUT_TIMER,TIM_IT_Update);
		ccr+=1000;
	}
}

在这里插入图片描述

如果要输出96kHz的PWM波形,则需修改:

	TIM_InitStruct.TIM_Prescaler=8400/96-1;//84MHz/(8400/96)=(10000*96)Hz=960000Hz=960KHz
	TIM_InitStruct.TIM_Period=10-1;

4.标准库实现PWM输入捕获

在说PWM输入捕获之前,我们还是搞清楚输入捕获吧。输入捕获通过检测外部信号在捕获通道上的边沿变化(上升沿或下降沿)来工作。当设定的边沿到达时,当前定时器的计数值(TIMx_CNT)被立即锁定并存储到相应的捕获/比较寄存器(TIMx_CCRx)中。但是如果只是配置捕获上升沿,那么我们只能够测量周期,因为高电平的下降沿我们没有捕获,导致不能够计算占空比。

那我们可以在捕获到第一个上升沿后,配置捕获下降沿,然后再次配置捕获上升沿,理论上这种方式也是可以的,但是太繁琐了,其实定时器是支持直接配置PWM输入捕获的,通用定时器就可以,具体看下文源码。

说说软件基本思路,因为自己使用的硬件设计有限,其他定时器的通道未引出,所以只能使用一个定时器TIM5。使用一块板输出PWM波形,频率是96KHz,占空比是渐变的。使用另外一块板作为PWM输入捕获。定时器复用的通道引脚直接使用杜邦线连接。

#include "bsp_timer.h"
#include "bsp_led.h"
#include "stdio.h"

void Init_PWM_IN_TIMER(void)
{
	//使能定时器时钟
	RCC_APB1PeriphClockCmd(PWM_IN_TIMER_CLK,ENABLE);
	//使能pwm输出引脚使能
	RCC_AHB1PeriphClockCmd(PWM_IN_GPIO_CLK,ENABLE);
	
	//初始化pwm输出GPIO
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Pin=PWM_IN_PIN;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;//配置为复用推挽输出
	GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;//默认拉高
	GPIO_InitStruct.GPIO_Speed=GPIO_Fast_Speed;
	GPIO_Init(PWM_IN_GPIO_Port,&GPIO_InitStruct);
	//并设置复用映射
	GPIO_PinAFConfig(PWM_IN_GPIO_Port,PWM_IN_AF_SOURCE,PWM_IN_AF);
	
	//初始化定时器,配置ARR,PSC
	TIM_TimeBaseInitTypeDef TIM_InitStruct;
	TIM_InitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_InitStruct.TIM_CounterMode=TIM_CounterMode_Up;//选择向上计数的方式
	
	/* 累计 TIM_Period个后产生一个更新或者中断*/
    //当定时器从0计数到4999,即为5000次,为一个定时周期
	TIM_InitStruct.TIM_Period=5000-1;
	
	//定时器时钟源TIMxCLK = 2 * PCLK1
    //        PCLK1 = HCLK / 4
    //        => TIMxCLK=HCLK/2=SystemCoreClock/2=84MHz
    // 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=10000Hz ==>0.1ms
	TIM_InitStruct.TIM_Prescaler=8400-1;
	//所以,一个中断产生时间为 0.1ms*5000=500ms
	
	
	TIM_InitStruct.TIM_Prescaler=8400/96-1;//84MHz/(8400/96)=(10000*96)Hz=960000Hz=960KHz
	TIM_InitStruct.TIM_Period=0xffffffff;
	TIM_InitStruct.TIM_RepetitionCounter=0;//高级定时器才有的参数,这里也无用
	TIM_TimeBaseInit(PWM_IN_TIMER,&TIM_InitStruct);
	
	/*--------------------输入捕获结构体初始化-------------------*/
    // 使用PWM输入模式时,需要占用两个捕获寄存器,一个测周期,另外一个测占空比
    // 捕获通道IC1配置
    // 选择捕获通道
	TIM_ICInitTypeDef  TIM_ICInitStructure;
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
    // 设置捕获的边沿
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
    // 设置捕获通道的信号来自于哪个输入通道,有直连和非直连两种
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    // 1分频,即捕获信号的每个有效边沿都捕获
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    // 不滤波
    TIM_ICInitStructure.TIM_ICFilter = 0x0;
    // 初始化PWM输入模式
    TIM_PWMIConfig(PWM_IN_TIMER, &TIM_ICInitStructure);

    // 当工作做PWM输入模式时,只需要设置触发信号的那一路即可(用于测量周期)
    // 另外一路(用于测量占空比)会由硬件自带设置,不需要再配置

    // 选择输入捕获的触发信号
    TIM_SelectInputTrigger(PWM_IN_TIMER, TIM_TS_TI1FP1);

    // 选择从模式: 复位模式
    // PWM输入模式时,从模式必须工作在复位模式,当捕获开始时,计数器CNT会被复位
    TIM_SelectSlaveMode(PWM_IN_TIMER, TIM_SlaveMode_Reset);
    TIM_SelectMasterSlaveMode(PWM_IN_TIMER,TIM_MasterSlaveMode_Enable);
	
	//配置中断控制器并使能中断
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel=TIM5_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=4;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
	NVIC_Init(&NVIC_InitStruct);
	TIM_ITConfig(PWM_IN_TIMER,TIM_IT_CC1,ENABLE);
	
	//使能定时器
	TIM_Cmd(PWM_IN_TIMER,ENABLE);
}
uint32_t IC1Value,IC2Value;
float DutyCycle,Frequency;

void TIM5_IRQHandler(void)
{
	if(SET==TIM_GetITStatus(PWM_IN_TIMER,TIM_IT_CC1))
	{
		TIM_ClearITPendingBit(PWM_IN_TIMER,TIM_IT_CC1);
		 /* 获取输入捕获值 */
    IC1Value = TIM_GetCapture1(PWM_IN_TIMER);
    IC2Value = TIM_GetCapture2(PWM_IN_TIMER);
    //printf("IC1Value = %d  IC2Value = %d \r\n",IC1Value,IC2Value);

    // 注意:捕获寄存器CCR1和CCR2的值在计算占空比和频率的时候必须加1
    if (IC1Value != 0&&IC2Value != 0) {
		/* 频率计算 */
        Frequency = (960*1000.0)/(float)(IC1Value+1);
		
        /* 占空比计算 */
        DutyCycle = (float)((IC2Value+1)*1.0 / (IC1Value+1)*100.0);
        
        printf("DutyCycle=%0.2f%%   Frequency=%0.2fHz\r\n",DutyCycle,Frequency);
    } else {
        DutyCycle = 0;
        Frequency = 0;
    }
	}
}


因为是PWM输入模式,只能使用通道1和通道2 ,假如我们使用的是通道1,即TI1,输入的PWM信号会被分成两路,分别是TI1FP1和TI1FP2, 两路都可以是触发信号。如果选择TI1FP1为触发信号,那么IC1捕获到的是PWM信号的周期, IC2捕获到的是占空比,这种输入通道TI和捕获通道IC的映射关系叫直连, 输入捕获结构体的TIM_ICSelection要配置为TIM_ICSelection_DirectTI。如果选择TI1FP2为触发信号,则IC2捕获到的是周期,IC1捕获到的是占空比, 这种输入通道TI和捕获通道IC的映射关系叫非直连,输入捕获结构体的TIM_ICSelection要配置为TIM_ICSelection_IndirectTI。 有关输入通道TI和捕获通道IC的具体映射关系见图 输入通道与捕获通道IC的映射图 ,有直连和非直连两种。

输入通道与捕获通道IC的映射图

当捕获到PWM信号的第一个上升沿时,产生中断,计数器被复位,锁存到捕获寄存器IC1和IC2的值都为0。当下降沿到来时,IC2会捕获,对应的是占空比, 但是会产生中断。当捕获到第二个下降沿时,IC1会捕获,对应的是周期,而且会再次进入中断,这个时间就可以根据IC1和IC2的值计算出频率和占空比。 有关PWM输入的时序见图 PWM输入模式时序图 。

PWM输入模式时序图

在这里插入图片描述

还有几点值得注意:

  1. 输入捕获的GPIO复用引脚也是配置为推挽复用功能。
  2. 输入捕获定时器的周期需要比被测PWM周期大,不然捕获定时器计数溢出都还没有捕获到上升沿。

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

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

相关文章

.[emcrypts@tutanota.de].mkp勒索病毒新变种该如何应对?

引言 在数字化时代&#xff0c;随着信息技术的迅猛发展&#xff0c;网络安全问题日益凸显。其中&#xff0c;勒索病毒作为一种极具破坏力的恶意软件&#xff0c;给个人和企业带来了巨大的经济损失和数据安全风险。近期&#xff0c;一种名为“.mkp勒索病毒”的新型威胁开始在网络…

多线程引发的安全问题

前言&#x1f440;~ 上一章我们介绍了线程的一些基础知识点&#xff0c;例如创建线程、查看线程、中断线程、等待线程等知识点&#xff0c;今天我们讲解多线程下引发的安全问题 线程安全&#xff08;最复杂也最重要&#xff09; 产生线程安全问题的原因 锁&#xff08;重要…

在 Python 中创建列表时,应该写 `[]` 还是 `list()`?

在 Python 中&#xff0c;创建列表有两种写法&#xff1a; # 写法一&#xff1a;使用一对方括号 list_1 []# 写法二&#xff1a;调用 list() list_2 list() 那么哪种写法更好呢&#xff1f; 单从写法上来看&#xff0c;[] 要比 list() 简洁&#xff0c;那在性能和功能方面…

江科大笔记—读写内部闪存FLASH读取芯片ID

读写内部闪存FLASH 右下角是OLED&#xff0c;然后左上角在PB1和PB11两个引脚&#xff0c;插上两个按键用于控制。下一个代码读取芯片ID&#xff0c;这个也是接上一个OLED&#xff0c;能显示测试数据就可以了。 STM32-STLINK Utility 本节的代码调试&#xff0c;使用辅助软件…

[机缘参悟-200] - 对自然、人性、人生、人心、人际、企业、社会、宇宙全面系统的感悟 - 全图解

对自然、人性、人生、人心、人际、企业、社会、宇宙进行全面系统的感悟&#xff0c;是一个极其深邃且复杂的主题。以下是对这些领域的简要感悟&#xff1a; 自然&#xff1a; 自然是人类生存的根基&#xff0c;它充满了无尽的奥秘和美丽。自然界的平衡和循环规律&#xff0c;教…

运算符重载之日期类的实现

接上一篇文章&#xff0c;废话不多说&#xff0c;直接上代码 Date.h #pragma once #include<iostream> using namespace std; #include<assert.h>class Date {//友元函数声明friend ostream& operator<<(ostream& out, const Date& d);friend …

学编程容易遇到的误区,请提前规避

随着互联网行业的蓬勃发展和编程技术的普及&#xff0c;越来越多的人开始对编程感兴趣。然而&#xff0c;编程学习并非一蹴而就&#xff0c;新手入门时常常会陷入误区&#xff0c;影响学习状态效率。 今天&#xff0c;我们来一起揭开编程学习常见的五大误区&#xff0c;希望能…

Workbench密码登录登录失败

Workbench密码登录登录失败操作系统禁用了密码登录方式&#xff0c;会导致使用了正确的用户名和密码仍无法登录 sudo vim /etc/ssh/sshd_config 输入O进入编辑 改完后重启 systemctl restart sshd.service 登录报错 有试了几遍登上了 可能是改完还要等一会儿

Python:探索高效、智能的指纹识别技术(简单易懂)

目录 概括 导入库 函数一 参数&#xff1a; 函数二 函数三 主函数 运行结果 src&#xff1a; model_base 7.bmp ​编辑 总结 概括 指纹识别是一种基于人体生物特征的身份验证技术。它通过捕捉和分析手指上的独特纹路和细节特征&#xff0c;实现高准确度的身份识别。…

账做错了怎么办?看完这篇三分钟学会调错账|柯桥职业技能培训

作为会计遇到错账、漏账在所难免。既然错误在所难免&#xff0c;如果纠正错误就十分重要。今天就跟小编一起学下如何调账。 在处理错账之前&#xff0c;我们首先要把会计科目做一下分类&#xff0c;以便于我们找到错账的类型和原因。会计科目可以分为资产负债类科目&#x…

2.SQL注入-字符型

SQL注入-字符型(get) 输入kobe查询出现id和邮箱 猜测语句,字符在数据库中需要用到单引号或者双引号 select 字段1,字段2 from 表名 where usernamekobe;在数据库中查询对应的kobe&#xff0c;根据上图对应上。 select id,email from member where usernamekobe;编写payload语…

Emp.dll文件丢失?理解Emp.dll重要性与处理常见问题

在繁多的动态链接库&#xff08;DLL&#xff09;文件中&#xff0c;emp.dll 可能不是最广为人知的&#xff0c;但在特定软件或环境中&#xff0c;它扮演着关键角色。本文旨在深入探讨 emp.dll 的功能、重要性以及面对常见问题时的解决策略。 什么是 emp.dll&#xff1f; Emp.d…

【Java Gui精美界面】IDEA安装及配置SwingX

SwingX 是一个基于 Swing 的 Java GUI 库&#xff0c;旨在为 Swing 提供额外的功能和丰富的组件 特点描述基于 Swing继承了 Swing 的所有特性和功能。丰富组件SwingX 提供了一组高级 UI 组件&#xff0c;例如 TreeTable仍在发展中不活跃的发展ing。。。支持搜索高亮如 TreeTab…

【单元测试】Controller、Service、Repository 层的单元测试

Controller、Service、Repository 层的单元测试 1.Controller 层的单元测试1.1 创建一个用于测试的控制器1.2 编写测试 2.Service 层的单元测试2.1 创建一个实体类2.2 创建服务类2.3 编写测试 3.Repository 1.Controller 层的单元测试 下面通过实例演示如何在控制器中使用 Moc…

【漏洞复现】飞企互联——SQL注入

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 飞企互联-FE企业运营管理平台是一个基于云计算、智能化、大数据…

JAVA高级进阶13单元测试、反射、注解

第十三天、单元测试、反射、注解 单元测试 介绍 单元测试 就是针对最小的功能单元(方法)&#xff0c;编写测试代码对其进行正确性测试 咱们之前是如何进行单元测试的&#xff1f; 有啥问题 &#xff1f; 只能在main方法编写测试代码&#xff0c;去调用其他方法进行测试。 …

Django 自定义过滤器

1&#xff0c;编写自定义过滤器并注册 创建目录 Test/app5/templatetags 分别创建文件 Test/app5/templatetags/__init__.py Test/app5/templatetags/myfilter.py 添加过滤器脚本 Test/app5/templatetags/myfilter.py from django import template register template.…

shell:处理命令行参数 获取用户输入

1. 命令行参数 1.1 位置参数 bash shell会将一些称为位置参数(positional parameter)的特殊变量分配给输入到命令行中的 所有参数。这也包括shell所执行的脚本名称。位置参数变量是标准的数字:$0是程序名&#xff0c;$1是第 一个参数&#xff0c;$2是第二个参数&#xff0c;依…

基于C语言的Jacobi迭代和Gauss-Seidel迭代的方程组求解实现

文章目录 Jacobi迭代方法介绍Gauss-Seidel迭代方法介绍具体代码实现示例题目实现效果 Jacobi迭代方法介绍 Jacobi迭代法是一种简单的迭代求解方法&#xff0c;适用于严格对角占优矩阵。其基本思想是利用当前迭代步的已知解来更新下一个迭代步的解。在C语言实现中&#xff0c;我…

网格处理库 pmp-library 编译及应用笔记 -- 已全部解决√

多边形网格处理库Polygon Mesh Processing Library&#xff0c;简称pmp-library的 编译及应用笔记 – 已全部解决√ 官网&#xff1a;https://www.pmp-library.org/index.html 代码&#xff1a;https://github.com/pmp-library/pmp-library 平台&#xff1a;Ubuntu1 20.04&…