12.示例程序(定时器定时中断&定时器外部时钟)

2023-11-01

目录

定时中断和时钟源选择相关库函数使用

1.定时器初始化配置

2.参数(PSC、ARR等)更改函数(在程序运行过程中修改)

3.使用定时器库函数的一些细节

定时器定时中断实例

定时器外部时钟选择


 知识点get:

滤波器工作原理:可以滤掉信号的抖动干扰。在一个固定的时钟频率f下进行采样,如果连续N个采样点都为相同的电平,那就代表输入信号稳定了,就把这个采样值输出出去;如果这N个采样值不全都相同,那就说明信号有抖动,这时就保持上一次的输出,或者直接输出低电平也行,这样就能保证输出信号在一定程度上的滤波;这里的采样频率f和采样点数N都是滤波器的参数,频率越低,采样点数越多,滤波效果越好,不过相应的信号延迟就越大;采样频率f由内部时钟直接而来,也可以是由内部时钟加一个时钟分频而来,这个分频多少是由参数ClockDivision决定的,这个参数其实跟时基单元关系并不大,它的可选值可以选择1分频(也就是不分频),2分频和4分频。


定时中断和时钟源选择相关库函数使用

定时器相关的库函数非常多,本节仅对将要使用的库函数和 亿些使用细节 进行说明(即使这样也还是很多)。

定时中断基本结构如下,便于理解下面的库函数及程序流程

 定时器初始化步骤如下,对应定时中断结构图

第一步,RCC开启时钟,定时器的基准时钟和整个外设的工作时钟就都打开了
第二步,选择时基单元的时钟源,对于定时中断就选择内部时钟源
第三步,配置时基单元,包括预分频器、自动重装载器、计数模式等,参数用结构体配置
第四步,配置输出中断控制,允许更新中断输出到NVIC
第五步,配置NVIC,在NVIC中打开定时器中断通道并分配一个优先级
第六步,运行控制,使能计数器,当定时器使能后,计数器就开始计数了,当计数器更新时,触发中断
最后再写一个中断函数,中断函数每隔一段时间就能自动执行一次


1.定时器TIM的库函数

  • 基本配置、时基单元、中断输出控制、NVIC、运行控制函数
// 恢复定时器缺省配置
void TIM_DeInit(TIM_TypeDef* TIMx);

// 时基单元初始化
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

// 把时基单元初始化函数所用的结构体变量赋一个默认值
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

// 使能计数器(对应定时中断结构图中的“运行控制”功能) 
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

// 使能中断输出信号(对应定时中断结构图中的“中断输出控制”功能)
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
  • 时钟源选择函数
//选择内部时钟
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);

//选择ITRx其它定时器时钟
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);

//选择TIx捕获通道时钟,对于外部引脚的波形一般都会有极性选择和滤波器
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
                                uint16_t TIM_ICPolarity, uint16_t ICFilter);

//选择ETR通过外部时钟模式1输入的时钟
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                             uint16_t ExtTRGFilter);

//选择ETR通过外部时钟模式2输入的时钟,如果不需触发输入功能本函数可与上面函数互换
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, 
                             uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);

//单独用来配置ETR引脚的预分频器、极性、滤波器这些参数
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                   uint16_t ExtTRGFilter);

2.参数(PSC、ARR等)更改函数(在程序运行过程中修改

以下,单独的函数可以方便地更改PSC\ARR等参数

// 预分频值设置,TIM_PSCReloadMode为是否应用输入缓冲功能配置
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);

// 改变计数器的计数模式
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);

// 自动重装寄存器预装功能配置(计数器有无预装功能)
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

// 手动给计数器写入一个值
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);

// 手动给自动重装寄存器写入一个值
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);

// 获取当前计数器的值
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);

// 获取当前的预分频器的值
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);

// 获取定时中断的标志位和清除标志位,使用方法与EXTI相同
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

3.使用定时器库函数的一些细节

* 选择内部时钟函数:定时器上电后默认选择内部时钟,如果要选择内部时钟,这一句可以省略。

TIM_InternalClockConfig(TIM_TypeDef* TIMx);

时基单元初始化函数TIN_TimeBaseInit:在配置结构体变量时,会遇到以下几个细节问题

1.TIM_TimeBaseInitStructure.TIM_ClockDivision (采样)时钟分频频率选择
  在定时器的外部信号输入引脚一般都有一个滤波器来消除信号的抖动干扰,它的工作原理是:在一个固定的时钟频率f下进行采样,如果连续N个采样点都是相同的电平,就代表输入信号稳定了,就将采样值输出到下一级电路;如果N个采样点不全都相同,就说明信号有抖动,这时保持上一次的输出,或直接输出低电平。 这样就能保证输出信号在一定程度上的滤波。这里的采样频率f 和采样点数N,f和N是滤波器的参数,频率越低,采样点数越多,滤波效果就越好,不过相应的信号延迟就越大。
  采样频率f的来源可以是内部时钟直接提供,也可以是内部时钟加一个时钟分频而来。 分频是多少,就由参数TIM_ClockDivision决定。可见 TIM_ClockDivision与时基单元的关系并不大,它的可选值可以选择1分频,2分频和4分频。


2.TIM_TimeBaseInitStructure.TIM_CounterMode  计数器模式

TIM_CounterMode_Up  (向上计数)

TIM_CounterMode_CenterAligned1  (中央对齐计数)

3.TIM_TimeBaseInitStructure.TIM_Period     周期ARR自动重装器的值

4.TIM_TimeBaseInitStructure.TIM_Prescaler  PSC预分频器的值

以上2-3-4参数就是时基单元里面每个关键寄存器的参数,在配置结构体变量时,并没有能直接操作计数器CNT的参数。如果需要,可以采用SetCounter和GetCounter两个函数来操作计数器。

5.TIM_TimeBaseInitStructure.TIM_RepetitionCounter 重复计数寄存器,通过这个参数可以设置重复计数寄存器。但是通用定时器中没有这一个寄存器,故可以直接设置为0。


6.定时时间的计算

决定定时时间的参数,是TIM_Period和TIM_Prescaler
  参考公式:

计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)

                                                   = CK_PSC / (PSC + 1) / (ARR + 1)

* 定时1s也就是定时频率为1Hz,定时频率=72M/ (PSC + 1) / (ARR + 1) = 1s =1Hz,那就可以PSC给7200,ARR给10000(1MHz等于10^6Hz),然后两个参数再减1。

* 注意PSC(TIM_Prescaler)和ARR(TIM_Period)的取值都要在0~65535之间。

* PSC和ARR的取值不是唯一的。可以预分频给少点,自动重装给多点,这样就是以一个比较高的频率计比较多的数;也可以预分配给多点,自动重装给少点,这样就是以一个比较低的频率计比较少的数;两种方法都可以达到目标的定时时间。

* 在这里预分频是对72M进行7200分频,得到的就是10k的计数频率,在10k的频率下,计10000个数,就是1s的时间。


7.在TIM_TimeBaseInit函数的最后,会立刻生成一个更新事件,来重新装载预分频器和重复计数器的值。预分频器有缓冲寄存器,我们写入的PSC和ARR只有在更新事件时才会起作用。但是更新事件和更新中断是同时发生的,更新中断会置更新中断标志位,手动生成一个更新事件,就相当于在初始化时立刻进入更新函数执行一次,在开启中断之前手动清除一次更新中断标志位,就可以避免刚初始化完成就进入中断函数的问题

* 使能中断函数TIM_ITConfig

TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //开启更新中断到NVIC的通道

启动定时器 

TIM_Cmd(TIM2,ENABLE);//当产生更新时,就会触发中断

* 外部时钟配置函数TIM_ETRClockMode2Config

1.TIM_ExtTRGPrescaler外部时钟预分频器:可以选择外部时钟分频关闭(1分频)、2分频、4分频、8分频。


2.TIM_ExtTRGPolarity 外部触发的极性:TIM_ExtTRGPolarity_Inverted为反向极性,即低电平和下降沿有效;TIM_ExtTRGPolarity_NonInverted为不反向,即高电平和上升沿有效。


3.ExtTRGFilter 外部输入滤波器:工作原理与内部时钟的滤波器相似,它的值可以是0x00到0x0F之间的一个值,其决定了采样的f和N,具体的对应关系在手册中有对应表:

4.GPIO配置:因为是使用外部接口输入时钟,故在使用该函数之前还需要配置GPIO端口。对于定时器,手册中给的推荐配置是浮空输入。但是浮空输入会导致引脚的输入电平极易受干扰,所以输入信号的功率不小时一般选择上拉或下拉输入。当外部的输入信号功率很小,内部的上拉/下拉电阻(较大)可能会影响到这个输入信号,这时就需要用浮空输入,防止影响外部输入的电平。


定时器定时中断实例

本次实验要完成的现象是:定义一个 uint16_t 的 Num 变量,使其每秒+1。器件连接图和程序源码如下所示:

  • Timer.c
#include "stm32f10x.h"                  // Device header

/*
定时器初始化
对应定时中断结构图

第一步,RCC开启时钟,定时器的基准时钟和整个外设的工作时钟就都打开了
第二步,选择时基单元的时钟源,对于定时中断就选择内部时钟源
第三步,配置时基单元,包括预分频器、自动重装载器、计数模式等,参数用结构体配置
第四步,配置输出中断控制,允许更新中断输出到NVIC
第五步,配置NVIC,在NVIC中打开定时器中断通道并分配一个优先级
第六步,运行控制,使能计数器,当定时器使能后,计数器就开始计数了,当计数器更新时,触发中断
最后再写一个中断函数,中断函数每隔一段时间就能自动执行一次

*/
void Timer_Init(void)  //定时中断初始化代码
{
	//初始化tim2,也就是通用定时器
	//使用APB1的开启时钟函数,TIM2是APB1总线的外设
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	//选择时基单元的时钟,选择内部时钟;若不调用这个函数,系统上电也是默认是内部时钟
	TIM_InternalClockConfig(TIM2);
	
	//配置时基单元 
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;  //指定时钟分频
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式
	/*定时1s也就是定时频率为1Hz,定时频率=72M/ (PSC + 1) / (ARR + 1) = 1s =1Hz,
	那就可以PSC给7200,ARR给10000(1MHz等于10^6Hz),然后两个参数再减1
	在这里预分频是对72M进行7200分频,得到的就是10k的计数频率,
	在10k的频率下,计10000个数,就是1s的时间*/
	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;  //ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;  //PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;  //重复计数器的值
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	/*在TIM_TimeBaseInit函数的最后,会立刻生成一个更新事件,来重新装载预分频器和重复计数器的值
	预分频器有缓冲寄存器,我们写入的PSC和ARR只有在更新事件时才会起作用
	为了让写入的值立刻起作用,故在函数的最后手动生成了一个更新事件
	但是更新事件和更新中断是同时发生的,更新中断会置更新中断标志位,手动生成一个更新事件,就相当于在初始化时立刻进入更新函数执行一次
	在开启中断之前手动清除一次更新中断标志位,就可以避免刚初始化完成就进入中断函数的问题*/
	TIM_ClearFlag(TIM2,TIM_FLAG_Update);
	
	//使能中断
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //开启更新中断到NVIC的通道
	
	//NVIC中断
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC优先级分组
	NVIC_InitTypeDef NVIC_InitTyStructure;
	NVIC_InitTyStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitTyStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitTyStructure.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级
	NVIC_InitTyStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级
	NVIC_Init(&NVIC_InitTyStructure); 
	
	//启动定时器
	TIM_Cmd(TIM2,ENABLE);//当产生更新时,就会触发中断
}
/*
中断函数模版
void TIM2_IRQHandler(void) //当定时器产生更新中断时,这个函数就会自动被执行
{
	//检查中断标志位
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
	//执行相应的用户代码
		Num ++;
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
	}
}
*/


  • main.c
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"

uint16_t Num;

int main(void)
{
	
	OLED_Init();	//初始化OLED
	Timer_Init();    //初始化定时器
	
	OLED_ShowString(1,1,"Num:");

	while(1)
	{
		OLED_ShowNum(1,5,Num,5);
		OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5);//CNT计数器值的变化情况(变化范围是ARR从0一直到自动重装值(10000-1))
	}

}


//定时器2中断函数放在使用中断的main.c文件中;在startup文件中
void TIM2_IRQHandler(void) //当定时器产生更新中断时,这个函数就会自动被执行
{
	//检查中断标志位
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
	//执行相应的用户代码
		Num ++;//定时器每秒自动加一个Num全局变量
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
	}

}

定时器外部时钟选择

* 可以在引脚定义图里找TIMx的ETR引脚是哪个

* 在上一个定时中断实例程序基础上进行更改;基本任务仍然是定时中断,时钟部分就不使用内部时钟了

本次实验要完成的现象是:用光敏传感器手动模拟一个外部时钟,定义一个 uint16_t 的 Num 变量,当外部时钟触发10次(预分频之后的脉冲)后Num + 1。器件连接图和程序源码如下所示:

  • Timer.c
#include "stm32f10x.h"                  // Device header

/*
定时器初始化
对应定时中断结构图

第一步,RCC开启时钟,定时器的基准时钟和整个外设的工作时钟就都打开了
第二步,选择时基单元的时钟源,对于定时中断就选择内部时钟源
第三步,配置时基单元,包括预分频器、自动重装载器、计数模式等,参数用结构体配置
第四步,配置输出中断控制,允许更新中断输出到NVIC
第五步,配置NVIC,在NVIC中打开定时器中断通道并分配一个优先级
第六步,运行控制,使能计数器,当定时器使能后,计数器就开始计数了,当计数器更新时,触发中断
最后再写一个中断函数,中断函数每隔一段时间就能自动执行一次

*/
void Timer_Init(void)  //定时中断初始化代码
{
	//初始化tim2,也就是通用定时器
	//使用APB1的开启时钟函数,TIM2是APB1总线的外设
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	//外部模式2需要用到gpio,进行GPIOA的时钟配置
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//通过ETR引脚的外部时钟模式2配置
	TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x00);
	
	//配置时基单元 
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;  //指定时钟分频
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式
	/*定时1s也就是定时频率为1Hz,定时频率=72M/ (PSC + 1) / (ARR + 1) = 1s =1Hz,
	那就可以PSC给7200,ARR给10000(1MHz等于10^6Hz),然后两个参数再减1
	在这里预分频是对72M进行7200分频,得到的就是10k的计数频率,
	在10k的频率下,计10000个数,就是1s的时间*/
	TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;  //ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;  //PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;  //重复计数器的值
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	/*在TIM_TimeBaseInit函数的最后,会立刻生成一个更新事件,来重新装载预分频器和重复计数器的值
	预分频器有缓冲寄存器,我们写入的PSC和ARR只有在更新事件时才会起作用
	为了让写入的值立刻起作用,故在函数的最后手动生成了一个更新事件
	但是更新事件和更新中断是同时发生的,更新中断会置更新中断标志位,手动生成一个更新事件,就相当于在初始化时立刻进入更新函数执行一次
	在开启中断之前手动清除一次更新中断标志位,就可以避免刚初始化完成就进入中断函数的问题*/
	TIM_ClearFlag(TIM2,TIM_FLAG_Update);
	
	//使能中断
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //开启更新中断到NVIC的通道
	
	//NVIC中断
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC优先级分组
	NVIC_InitTypeDef NVIC_InitTyStructure;
	NVIC_InitTyStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitTyStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitTyStructure.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级
	NVIC_InitTyStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级
	NVIC_Init(&NVIC_InitTyStructure); 
	
	//启动定时器
	TIM_Cmd(TIM2,ENABLE);//当产生更新时,就会触发中断
}

//函数封装
uint16_t Timer_getcounter(void)
{
	return TIM_GetCounter(TIM2);

}


/*
中断函数模版
void TIM2_IRQHandler(void) //当定时器产生更新中断时,这个函数就会自动被执行
{
	//检查中断标志位
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
	//执行相应的用户代码
		Num ++;
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
	}
}
*/


  • main.c
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"

uint16_t Num;

int main(void)
{
	
	OLED_Init();	//初始化OLED
	Timer_Init();    //初始化定时器
	
	OLED_ShowString(1,1,"Num:");
	OLED_ShowString(2,1,"CNT:");
	
	
	while(1)
	{
		OLED_ShowNum(1,5,Num,5);
		OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5);//CNT计数器值的变化情况(变化范围是ARR从0一直到自动重装值(10000-1))
	}

}





//定时器2中断函数放在使用中断的main.c文件中;在startup文件中
void TIM2_IRQHandler(void) //当定时器产生更新中断时,这个函数就会自动被执行
{
	//检查中断标志位
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
	//执行相应的用户代码
		Num ++;//定时器每秒自动加一个Num全局变量
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
	}

}

 总笔记目录 点击  传送门

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

12.示例程序(定时器定时中断&定时器外部时钟) 的相关文章

随机推荐

  • 前端基础_使用moveTo与lineTo路径绘制火柴人

    使用moveTo与lineTo路径绘制火柴人 接下来看一下除了arc方法以外 其他使用路径绘制图形时会使用到的方法 moveTo x y 不绘制 只是将当前位置移动到新的目标坐标 x y lineTo x y 不仅将当前位置移动到新的目标坐
  • 工控CTF(wp)

    GUET工控CTF 所见非真 异常的流量分析 黑客的攻击 黑客的大意 丢失的数据 凯撒的秘密 工程的秘密 S7协议分析 轻松时刻 打不开的压缩包 失控的遥控 病毒文件分析 OPC协议分析 sign in 随意记录一下这次CTF的解题步骤 比
  • 文章详情页 - 评论功能的实现

    目录 1 准备工作 1 1 创建评论表 1 2 创建评论实体类 1 3 创建 mapper 层评论接口和对应的 xml 实现 1 4 准备评论的 service 层 1 5 准备评论的 controller 层 2 总的初始化详情页 2 1
  • The Open Group 参考卡|《ArchiMate® 3.1 规范》中文版正式发布

    ArchiMate 规范 3 1 版在 3 0 1 版之间做了如下改动 增加了新的策略元素 价值流 为关联关系添加了可选的指示标记 改进了元模型和相关图形的组织结构 进一步完善和规范了关系的推导 除此之外 ArchiMate 规范 3 1
  • 全球及中国微电网市场规模容量及建设运营模式分析报告2021年版

    全球及中国微电网市场规模容量及建设运营模式分析报告2021年版 HS HS HS HS HS HS HS HS HS HS HS HS 修订日期 2021年11月 搜索鸿晟信合研究院查看官网更多内容 第一章 微电网相关概述 1 1 微电网概
  • pandas 取excel 中的某一列_别找了,这是 Pandas 最详细教程了

    点击上方 菜鸟编程大本营 选择 星标 公众号 重磅干货 第一时间送达 来源 机器之心 Python 是开源的 它很棒 但是也无法避免开源的一些固有问题 很多包都在做 或者在尝试做 同样的事情 如果你是 Python 新手 那么你很难知道某个
  • MySQL 如何优化慢查询?

    一 前言 在日常开发中 我们往往会给表加各种索引 来提高 MySQL 的检索效率 但我们有时会遇到明明给字段加了索引 并没有走索引的Case 进而导致 MySQL 产生慢查询 严重场景下 甚至出现主从延迟 数据库拖垮的极端事故 本文梳理出索
  • 用Python采集Notion数据

    使用 Python 采集 Notion 数据的方法 首先 你需要在 Notion 网站上申请一个 API key 具体方法可以参考这篇文章 https developers notion com docs getting started s
  • 驱动开发,stm32mp157a开发板的led灯控制实验(再优化),使用ioctl函数,通过字符设备驱动分步注册方式编写LED驱动,完成设备文件和设备的绑定

    1 实验目的 编写LED灯的驱动 在应用程序中编写控制LED灯亮灭的代码逻辑实现LED灯功能的控制 2 LED灯相关寄存器分析 LED1 gt PE10 LED1亮灭 RCC寄存器 4 gt 1 0X50000A28 GPIOE MODER
  • 采用冒泡排序的方法将数组中的元素从小到大进行排序

    include
  • QT生成动态链接库.so文件

    首先是新建一个工程 选择C 库 打开后是这样的 然后输入新建的名称 下一步 记得勾选Qtcore那个 就是默认的那个 否则编译似乎不能通过 因为后面自动生成的 h文件里还有这个 自动生成的有4个文件一个pro 一个cpp 一个XXX h文件
  • 【darknet yolo】could not open file xx.cfg

    错误图如上 原因 data文件的编码不对 用notepad 打开发现 错误的 正确的 发现错误的比正确的每行换行的时候多了一个cr 解决 ubuntu下安装dos2unix 然后转换下 dos2unix 52 data
  • 面试题:Spring常见的一些面试题与答案

    Spring是Java开发领域中最流行的框架之一 广泛应用于企业级应用的开发 在面试中 面试官经常会问及与Spring相关的问题 以考察面试者对Spring框架的理解和应用能力 本文将介绍一些常见的Spring面试题 并提供详细的解答和实际
  • PID参数解析+调参经验笔记(经验法)

    在最前面推荐一个大佬的讲解 真的很浅显易懂 建议先看了解大概PID 链接 ps 2022 1 2更新pid通俗理解 out speed p err d now speed pid最核心算法 运动员参加100米跑步 假设这个人可以瞬间提速 但
  • 关于==和equals的区别和联系,面试这么回答就可以

    长篇大论的话 我这里就不多写了 相信大家入门java 的时候就知道个大概了 这里想表述的是 如果面试官问你 关于 和equals的区别 该怎么回答完美呢 可以这样说 总结的来说 1 对于 比较的是值是否相等 如果作用于基本数据类型的变量 则
  • vcomp140.dll丢失怎样修复?多种方法教你修复

    vcomp140 dll丢失算是一个比较常见的异常事件 在使用电脑的时候 有时候弹窗出现由于找不到vcomp140 dll 无法继续执行代码等 这种都是属于vcomp140 dll文件丢失 今天我们主要针对这个情况来给大家说说vcomp14
  • 谁在爬我的网站?我要“炸”了他

    如果你曾经搭建过自己的网站 那么你一定对网络爬虫感到无比的烦恼 这些爬虫每天都在大量的访问你的网站 频繁且毫无节制地消耗你的服务器资源 那么 今天我们就来探讨一下 如何 干死 这些爬虫的服务器 注意 本文所讨论的内容仅供技术交流 不涉及任何
  • jquery的layer打开iframe,通过ajax提交iframe表单

    addOption click function thisId var index1 layer open type 2 area 850px 450px maxmin true title 添加项 btn 确定 取消 content In
  • Centos下环境变量

    文章内容如下 1 什么是环境变量 2 如何通过程序获取环境变量 3 常识规律 一 环境变量的定义 环境变量就是指一段路径 定义环境变量主要是为了方便的执行程序 添加环境变量的方法是export PATH PATH A B export PA
  • 12.示例程序(定时器定时中断&定时器外部时钟)

    目录 定时中断和时钟源选择相关库函数使用 1 定时器初始化配置 2 参数 PSC ARR等 更改函数 在程序运行过程中修改 3 使用定时器库函数的一些细节 定时器定时中断实例 定时器外部时钟选择 知识点get 滤波器工作原理 可以滤掉信号的