物联网——TIM定时器、PWM驱动呼吸灯、舵机和直流电机

定时器概念(常用于输出PWM波形,驱动电机)

在这里插入图片描述

时间=脉冲数时钟周期; 这里的脉冲数=6553665536,支持定时器级联,从而延长定时

定时器类型

在这里插入图片描述

基本定时器原理图(UI:更新中断, U:更新事件,仅支持向上计时模式)

在这里插入图片描述

(stm32主模式)可以通过映射U(事件)至到触发器(TRGO)来控制DAC的输出,这样就不用CPU花费大量的中断时间输出DAC

通用定时器原理图(支持向上/下计时模式,中央对齐计时模式)

中央对齐计时模式(计数器的值和重装值相等时产生一次中断,计数器值再减为零再产生一次中断)

在这里插入图片描述

高级定时器

在这里插入图片描述

DTG(Dead Time Generate): 死区生成电路,用于防止直通

BKIN:刹车输入

定时中断基本结构

在这里插入图片描述

预分频器时序

在这里插入图片描述

计数器时序图

在这里插入图片描述
在这里插入图片描述
影子寄存器的作用:让值的更改与更新事件保持同步,防止在运行途中更改造成错误
在这里插入图片描述

MyClock.c

#include "stm32f10x.h"
extern uint16_t Num;
//定时器初始化
void Timer_Init(void){
  // Enables or disables the Low Speed APB (APB1) peripheral clock.(外部时钟)
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
   //(内部时钟)
   TIM_InternalClockConfig(TIM2);
   //基本定时器配置
  TIM_TimeBaseInitTypeDef BaseTI;
  BaseTI.TIM_ClockDivision = TIM_CKD_DIV1;
  BaseTI.TIM_CounterMode =   TIM_CounterMode_Up; //向上计数法
  BaseTI.TIM_Prescaler = 7200-1;   //PSC,计数器(PSC大,ARR小,则定时器频率低,OV=C_PSC/PSC+1/ARR+1)
  BaseTI.TIM_Period = 1000-1;   //ARR,重定位值 ,(PSC小,ARR大,则定时器频率高) 
  BaseTI.TIM_RepetitionCounter = 0;    //Specifies the repetition counter value. Each time the RCR downcounterreaches zero, an update event is generated and counting restarts from the RCR value
  TIM_TimeBaseInit(TIM2,&BaseTI);   
  //由于时钟在初始化的时候,触发了一次更新事件使预分频器的值有效,所以要清除掉更新事件,避免后续计时器数值从一开始
  TIM_ClearFlag(TIM2,TIM_FLAG_Update);  
   //中断配置,由更新事件触发中断
  TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
  //中断控制器
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  NVIC_InitTypeDef NI;
  NI.NVIC_IRQChannel = TIM2_IRQn;
  NI.NVIC_IRQChannelCmd = ENABLE;
  NI.NVIC_IRQChannelPreemptionPriority = 2;
  NI.NVIC_IRQChannelSubPriority = 1;  
  NVIC_Init(&NI);
  //启动定时器
  TIM_Cmd(TIM2,ENABLE);
}
//对射式定时器初始化
void MappintTimer_Init(void){
   // Enables or disables the Low Speed APB (APB1) peripheral clock.(外部时钟)
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);   //红外射线引脚
  GPIO_InitTypeDef GI;
  GI.GPIO_Mode = GPIO_Mode_IPU;
  GI.GPIO_Pin = GPIO_Pin_0;
  GI.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA,&GI);
  
   //(外部时钟)
  TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x00); //时钟模式,外部触发计数器,外部触发极性(这里是不反转,低电平有效),滤波器(采样n个点都相同,才输出滤波器)
   //基本定时器配置
  TIM_TimeBaseInitTypeDef BaseTI;
  BaseTI.TIM_ClockDivision = TIM_CKD_DIV1;
  BaseTI.TIM_CounterMode =   TIM_CounterMode_Up; //向上计数法
  BaseTI.TIM_Prescaler = 1-1;   //PSC,计数器(PSC大,ARR小,则定时器频率低,OV=C_PSC/PSC+1/ARR+1),这里从0~9
  BaseTI.TIM_Period = 10-1;   //ARR,重定位值 ,(PSC小,ARR大,则定时器频率高),这里不需要分频 
  BaseTI.TIM_RepetitionCounter = 0;    //Specifies the repetition counter value. Each time the RCR downcounterreaches zero, an update event is generated and counting restarts from the RCR value
  TIM_TimeBaseInit(TIM2,&BaseTI);   
  //由于时钟在初始化的时候,触发了一次更新事件使预分频器的值有效,所以要清除掉更新事件,避免后续计时器数值从一开始
  TIM_ClearFlag(TIM2,TIM_FLAG_Update);  
   //中断配置,由更新事件触发中断
  TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
  //中断控制器
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  NVIC_InitTypeDef NI;
  NI.NVIC_IRQChannel = TIM2_IRQn;
  NI.NVIC_IRQChannelCmd = ENABLE;
  NI.NVIC_IRQChannelPreemptionPriority = 2;
  NI.NVIC_IRQChannelSubPriority = 1;  
  NVIC_Init(&NI);
  //启动定时器
  TIM_Cmd(TIM2,ENABLE);
}
//时钟中断控制,这个函数可以定义在主函数外面,这样就不用使用extern修饰变量
void TIM2_IRQHandler(void){
   if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET){
       Num++;
       TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
   } 
}

PWM波形

PWM(Pulse Width Modulation)波形,即脉冲宽度调制波形,是一种通过调整一系列等幅脉冲的宽度来对输出进行编码和控制的技术。在PWM信号中,每个脉冲的幅度保持恒定,但是脉冲的持续时间(宽度)变化,从而改变脉冲的占空比,即高电平时间与整个脉冲周期的比例。这种调制方式使得PWM信号能够等效地模拟出不同强度的模拟信号,常用于控制电机转速、LED亮度调节、电源转换等领域。
PWM波形的关键特性包括:
-脉冲序列:PWM波由一系列矩形波(方波)组成。
-固定周期:每个PWM周期的时间长度是固定的。
-可变宽度:每个脉冲的高电平时间(即“开启时间”)可以改变,低电平时间相应调整以保持周期不变,这样就改变了占空比。
-占空比:占空比是指一个周期内高电平时间与整个周期时间的比例,通常以百分比表示,用于控制输出的有效功率或模拟信号的强度。
-等效模拟信号:通过调整占空比,PWM可以近似模拟连续的模拟信号,如正弦波,用于驱动如电机或LED等设备,实现平滑的控制效果。
在逆变电路和电源管理应用中,常用的PWM调制方法之一是SPWM(Sinusoidal PWM),它通过使脉冲宽度按照正弦波的形状变化,使得输出的PWM波形在一定意义上等效于期望的正弦波形,从而控制输出电压或电流的大小和频率。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

PWM基本结构

在这里插入图片描述

PWM频率

CK_PSC

在PWM(Pulse Width Modulation,脉冲宽度调制)控制中,CK_PSC通常指的是时钟预分频系数(Prescaler value for Clock)。这是微控制器(如STM32系列)中的定时器模块中的一个配置参数,用于调整定时器的时钟频率。
具体来说,CK_PSC是定时器输入时钟(CK_INT,来自系统时钟或者外部时钟源)在进入定时器计数器之前经过的一个分频器。通过设置不同的CK_PSC值,可以减慢定时器的计数速度,使得计数器能以较低的频率进行计数,这对于生成各种不同频率的PWM信号非常关键。预分频的计算公式通常是 Timer Clock Frequency = (Input Clock Frequency) / (PSC + 1)。
例如,如果你有一个基于STM32的系统,其系统时钟频率为72MHz,而你需要一个较慢的PWM频率输出,你可以通过设置合适的CK_PSC值来实现这一点。增加PSC值会降低到达计数器的时钟频率,从而允许更精细地控制PWM信号的频率和占空比。
在编程时,通常会通过设置定时器的相关寄存器(如STM32中的TIMx_PSC寄存器)来配置CK_PSC的值,以满足特定应用的需求。

CCR 和 ARR

自动重装载寄存器(ARR)用于确定波形的频率(即周期)、捕获比较寄存器(CCRx)(用于确定占空比的)
PWM的工作过程如下:首先ARR寄存器里面的值确定了一个PWM周期(注意这个周期是在PWM系统初始化的时候写入ARR寄存器的,写入以后一般就不再改动了)。然后CCR寄存器里面的值是PWM工作过程中确定的,它可以为一个定值,也可以是一个变化的值。
在这里插入图片描述

PWM分辨率

PWM分辨率是指在PWM一个周期内能够实现的占空比调整的最小单位,它是衡量PWM信号精细程度的一个重要指标。PWM通过调整脉冲信号高电平时间的长短来模拟输出不同的平均电压值,而这个调整的细腻程度就是由分辨率决定的。
具体来说,PWM分辨率可以用比特数表示,常见的有8位、10位、12位等。一个8位的PWM控制器可以提供2^8=256个不同的占空比等级,这意味着在一个PWM周期内,高电平时间可以有256种不同的设置。相应地,10位分辨率则可以提供1024个不同的占空比等级,12位则有4096个等级,依此类推。分辨率越高,能够实现的控制精度就越高,输出的模拟信号就越接近真实连续的模拟信号。
PWM分辨率的计算也可以关联到具体的时钟频率上,比如一个PWM的时钟频率确定时,提高分辨率会导致每个脉冲宽度的可调步进减小,从而使得控制更为精确。反之,分辨率较低意味着调整的步长较大,占空比的变化相对粗糙。

呼吸灯电路图

在这里插入图片描述

注意事项

在这里插入图片描述

占空比为10%的PWM波形(示波器显示)

在这里插入图片描述

呼吸灯核心代码

//主函数
#include "stm32f10x.h"                  // Device header
#include "MyDelay.h"   //自定义延时函数
#include "Delay.h"     //官方延迟函数
#include "Button.h"   //按键Led驱动
#include "stdio.h"
#include "PWM.h"
#include "OLED.h"

int main(void){
  //环境配置
   OLED_Init();
   PWM_Init();
   while(1){
     for(int i=1;i<=100;i+=2){
       OLED_ShowNum(1,1,666,3);
       PWM_SetCompare1(i);
       Delay_ms(20);
     }
     for(int i=100;i>=1;i-=2){
       OLED_ShowNum(1,1,666,3);
       PWM_SetCompare1(i);
       Delay_ms(20);
     }       
   }
   return 0;
}

//PWM.h
#ifndef PWM_H
#define PWM_H
//初始化PWM
void PWM_Init(void);
//用于动态改变CCR,调节LED灯的亮度,PWM使用的PA0端口
void PWM_SetCompare1(uint16_t Compare); 
#endif



//PWM.c
#include "stm32f10x.h"                  // Device header
//初始化PWM
void PWM_Init(void){
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);   //时钟中断
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  //为呼吸灯指定引脚PA0
  
  GPIO_InitTypeDef GI;
  GI.GPIO_Mode = GPIO_Mode_AF_PP;   //定时器(外设)控制引脚,要用复用推挽输出
  GI.GPIO_Pin = GPIO_Pin_0;
  GI.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA,&GI);
  
  TIM_InternalClockConfig(TIM2);     //内部时钟
 
  TIM_TimeBaseInitTypeDef TI;     //时钟中断配置
  TI.TIM_ClockDivision = TIM_CKD_DIV2 ;
  TI.TIM_CounterMode = TIM_CounterMode_Up;
  TI.TIM_Period = 100-1;    // ARR
  TI.TIM_Prescaler = 720-1;      // PSC ,CK_PSC=72MHZ
  TI.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM2,&TI);
  
  TIM_Cmd(TIM2,ENABLE);  //时钟中断使能
  
  //时钟中断的输出比较模块定义: PWM波形,频率1KHZ,占空比50%,分辨率为 1%,
  TIM_OCInitTypeDef OCI;
  TIM_OCStructInit(&OCI); //先初始化输出比较模块,后续修改某个属性
  OCI.TIM_OCMode = TIM_OCMode_PWM1;
  OCI.TIM_OCPolarity = TIM_OCPolarity_High;   //极性,高电平有效电平
  OCI.TIM_OutputState = ENABLE;
  OCI.TIM_Pulse = 0;    //CCR捕获寄存器,可以通过改变CCR的值,调制PWM波形的占空比,从而改变LED灯的亮度    
  TIM_OC1Init(TIM2,&OCI);  //pwm波形初始化 
}

//用于动态改变CCR,调节LED灯的亮度,PWM使用的PA0端口
void PWM_SetCompare1(uint16_t Compare){
   
   TIM_SetCompare1(TIM2,Compare); //该函数用于设置CRR的值

}



//重映射端口PA15
#include "stm32f10x.h"                  // Device header

//初始化PWM
void PWM_Init(void){
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);   //时钟中断
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  //为呼吸灯指定引脚PA0
  //法二:为了提高引脚使用率,重映射端口,打开AFIO,重映射引脚,解除调试端口
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
  GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);
  GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //禁用JTAG调试,这里用的是ST-Link
  
  GPIO_InitTypeDef GI;
  GI.GPIO_Mode = GPIO_Mode_AF_PP;   //定时器(外设)控制引脚,要用复用推挽输出
  GI.GPIO_Pin = GPIO_Pin_15;
  GI.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA,&GI);
  
  TIM_InternalClockConfig(TIM2);     //内部时钟
 
  TIM_TimeBaseInitTypeDef TI;     //时钟中断配置
  TI.TIM_ClockDivision = TIM_CKD_DIV2 ;
  TI.TIM_CounterMode = TIM_CounterMode_Up;
  TI.TIM_Period = 100-1;    // ARR
  TI.TIM_Prescaler = 720-1;      // PSC ,CK_PSC=72MHZ
  TI.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM2,&TI);
  
  TIM_Cmd(TIM2,ENABLE);  //时钟中断使能
  
  //时钟中断的输出比较模块定义: PWM波形,频率1KHZ,占空比50%,分辨率为 1%,
  TIM_OCInitTypeDef OCI;
  TIM_OCStructInit(&OCI); //先初始化输出比较模块,后续修改某个属性
  OCI.TIM_OCMode = TIM_OCMode_PWM1;
  OCI.TIM_OCPolarity = TIM_OCPolarity_High;   //极性,高电平有效电平
  OCI.TIM_OutputState = ENABLE;
  OCI.TIM_Pulse = 0;    //CCR捕获寄存器,可以通过改变CCR的值,调制PWM波形的占空比,从而改变LED灯的亮度    
  TIM_OC1Init(TIM2,&OCI);  //pwm波形初始化 
}

//用于动态改变CCR,调节LED灯的亮度,PWM使用的PA0端口
void PWM_SetCompare1(uint16_t Compare){
   
   TIM_SetCompare1(TIM2,Compare); //该函数用于设置CRR的值

}

舵机

在这里插入图片描述
在这里插入图片描述

按键控制舵机旋转

#include "stm32f10x.h"                  // Device header
#include "MyDelay.h"   //自定义延时函数
#include "Delay.h"     //官方延迟函数
#include "Button.h"   //按键Led驱动
#include "stdio.h"
#include "PWM.h"
#include "OLED.h"
#include "Servos.h"
float Angle;
int KeyNum;
int main(void){
  //环境配置
   OLED_Init();
   Servos_PWM_Init();
   Button_Init();
   //显示角度
  OLED_ShowString(1,1,"Angle:");
  
   while(1){
    KeyNum = Key_GetNum();
    if(KeyNum == 1){
        Angle += 25;
      if(Angle>=180) Angle = 180;
        OLED_ShowNum(1,7,Angle,5);
        Servos_SetAngle(Angle);
    } 
     if(Angle>=180){
       Angle = 0; 
       OLED_ShowNum(1,7,Angle,5);
       Servos_SetAngle(0);
     }    
   }
   return 0;
}





#ifndef Servos_h
#define Servos_h
//舵机PWM波形初始化
void Servos_PWM_Init(void);
//动态改变PWM通道2的波形
void PWM_SetCompare2(uint16_t Compare);
//设置舵机旋转角度
void Servos_SetAngle(float Angle);
#endif




#include "stm32f10x.h"
//舵机PWM波形初始化
void Servos_PWM_Init(void){
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);   //时钟中断
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  //为呼吸灯指定引脚PA0

  GPIO_InitTypeDef GI;
  GI.GPIO_Mode = GPIO_Mode_AF_PP;   //定时器(外设)控制引脚,要用复用推挽输出
  GI.GPIO_Pin = GPIO_Pin_1;
  GI.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA,&GI);
  
  TIM_InternalClockConfig(TIM2);     //内部时钟
 
  TIM_TimeBaseInitTypeDef TI;     //时钟中断配置
  TI.TIM_ClockDivision = TIM_CKD_DIV2;
  TI.TIM_CounterMode = TIM_CounterMode_Up;
  TI.TIM_Period = 20000;    // ARR
  TI.TIM_Prescaler = 72;      // PSC ,CK_PSC=72MHZ
  TI.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM2,&TI);
  
  TIM_Cmd(TIM2,ENABLE);  //时钟中断使能
  
  //时钟中断的输出比较模块定义: PWM波形,舵机要求时钟20ms,频率50HZ,占空比动态变化,分辨率动态变化,
  TIM_OCInitTypeDef OCI;
  TIM_OCStructInit(&OCI); //先初始化输出比较模块,后续修改某个属性
  OCI.TIM_OCMode = TIM_OCMode_PWM1;
  OCI.TIM_OCPolarity = TIM_OCPolarity_High;   //极性,高电平有效电平
  OCI.TIM_OutputState = ENABLE;
  OCI.TIM_Pulse = 0;    //调制PWM波形的占空比,从而控制舵机,舵机CCR取值范围:500 ~ 2500    
  TIM_OC1Init(TIM2,&OCI);  //pwm通道1初始化 
  TIM_OC2Init(TIM2,&OCI);  //pwm通道2
  
}

//动态改变PWM通道2的CCR
void PWM_SetCompare2(uint16_t Compare){
    TIM_SetCompare2(TIM2,Compare);
}

//设置舵机旋转角度
void Servos_SetAngle(float Angle){
    float sum = 500 + (Angle/180*2000);   //CCR:500~2500 与 角度:0~180 计算得出
    PWM_SetCompare2(sum);
}

直流电机

   在这里插入图片描述
在这里插入图片描述

//电机驱动代码
#include "stm32f10x.h"                  // Device header
#include "MyDelay.h"   //自定义延时函数
#include "Delay.h"     //官方延迟函数
#include "Button.h"   //按键Led驱动
#include "stdio.h"
#include "OLED.h"
#include "Servos.h"
#include "DCmotors.h"

int Speed,KeyNum;
int main(void){
  //环境配置
   OLED_Init();
   DCmotors_Init();
   Button_Init();
   Motor_SetSpeed(-50);
  OLED_ShowString(1,1,"Circle Speed:");
   while(1){
    	KeyNum = Key_GetNum();				//获取按键键码
		if (KeyNum == 1)					//按键1按下
		{
			Speed += 20;					//速度变量自增20
			if (Speed > 100)				//速度变量超过100后
			{
				Speed = -100;				//速度变量变为-100
											//此操作会让电机旋转方向突然改变,可能会因供电不足而导致单片机复位
											//若出现了此现象,则应避免使用这样的操作
			}
		}
		Motor_SetSpeed(Speed);				//设置直流电机的速度为速度变量
		OLED_ShowSignedNum(2, 1, Speed, 3);	//OLED显示速度变量
   }
   return 0;
}



#ifndef DCmotors_h
#define DCmotors_h
//直流电机驱动
void DCmotors_Init(void);
//设置电机旋转速度以及旋转方向(电流方向决定旋转方向)
void Motor_SetSpeed(int8_t Speed);
#endif


#include "stm32f10x.h"
#include "OLED.h"
#include "PWM.h"
//直流电机驱动
void DCmotors_Init(void){
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  
  GPIO_InitTypeDef GI;
  GI.GPIO_Mode = GPIO_Mode_Out_PP;   //要用推挽输出(不由片上外设控制,无需复用推挽输出)
  GI.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
  GI.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA,&GI);
  
  PWM_Init();  //PWM波形初始化
}
//设置电机旋转速度以及旋转方向(电流方向决定旋转方向)
void Motor_SetSpeed(int8_t Speed){
    if (Speed >= 0)							//如果设置正转的速度值
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_4);	//PA4置高电平
		GPIO_ResetBits(GPIOA, GPIO_Pin_5);	//PA5置低电平,设置方向为正转
		PWM_SetCompare3(Speed);				//PWM设置为速度值
	}
	else									//否则,即设置反转的速度值
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_4);	//PA4置低电平
		GPIO_SetBits(GPIOA, GPIO_Pin_5);	//PA5置高电平,设置方向为反转
		PWM_SetCompare3(-Speed);			//PWM设置为负的速度值,因为此时速度值为负数,而PWM只能给正数
	}
}


//封装好的PWM模块
#ifndef PWM_H
#define PWM_H
//初始化PWM
void PWM_Init(void);
//用于动态改变CCR,调节LED灯的亮度,PWM使用的PA0端口
void PWM_SetCompare3(uint16_t Compare); 
#endif




#include "stm32f10x.h"                  // Device header
//初始化PWM
void PWM_Init(void){
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);   //时钟中断
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  //为呼吸灯指定引脚PA0
  //法二:为了提高引脚使用率,重映射端口,打开AFIO,重映射引脚,解除调试端口
//  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//  GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);
//  GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //禁用JTAG调试,这里用的是ST-Link
  
  GPIO_InitTypeDef GI;
  GI.GPIO_Mode = GPIO_Mode_AF_PP;   //(外设)控制引脚,PA2要用复用推挽输出
  GI.GPIO_Pin = GPIO_Pin_2;
  GI.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA,&GI);
  
  TIM_InternalClockConfig(TIM2);     //内部时钟
 
  TIM_TimeBaseInitTypeDef TI;     //时钟中断配置
  TI.TIM_ClockDivision = TIM_CKD_DIV2 ;
  TI.TIM_CounterMode = TIM_CounterMode_Up;
  TI.TIM_Period = 100-1;    // ARR
  TI.TIM_Prescaler = 36-1;      // PSC ,CK_PSC=72MHZ
  TI.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM2,&TI);
  
  TIM_Cmd(TIM2,ENABLE);  //时钟中断使能
  
  //时钟中断的输出比较模块定义: PWM波形,频率1KHZ,占空比50%,分辨率为 1%,
  TIM_OCInitTypeDef OCI;
  TIM_OCStructInit(&OCI); //先初始化输出比较模块,后续修改某个属性
  OCI.TIM_OCMode = TIM_OCMode_PWM1;
  OCI.TIM_OCPolarity = TIM_OCPolarity_High;   //极性,高电平有效电平
  OCI.TIM_OutputState = ENABLE;
  OCI.TIM_Pulse = 0;    //CCR捕获寄存器,可以通过改变CCR的值,调制PWM波形的占空比,从而改变LED灯的亮度    
  TIM_OC3Init(TIM2,&OCI);  //pwm波形初始化 
  
}

//用于动态改变CCR,调节LED灯的亮度,PWM使用的PA0端口
void PWM_SetCompare3(uint16_t Compare){
   
   TIM_SetCompare3(TIM2,Compare); //该函数用于设置CRR的值

}


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

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

相关文章

Jmeter的线程组之间传递参数

使用jemter做接口测试&#xff0c;有时候需要会遇到不同线程组之间调用相同变量的情况&#xff0c;最多见的就是token的传递&#xff0c;网上有很多处理方法&#xff0c;这里只记录setProperty的办法&#xff0c;一招鲜走遍天&#xff01; 首先我有两个线程组&#xff1a; 线程…

一种最大重叠离散小波包特征提取和支持向量机的ECG心电信号分类方法(MATLAB 2018)

目前小波分析算法常采用Mallat快速算法。该算法由与滤波器卷积、隔点采样和隔点插零等三个环节组成。由于实际使用的滤波器并不具有理想频域特性&#xff0c;使得在标准二进小波算法中存在着频率混叠和小波系数失真等缺点&#xff0c;在标准二进小波包算法中还存在频带错乱现象…

基于 Spring Boot 博客系统开发(十二)

基于 Spring Boot 博客系统开发&#xff08;十二&#xff09; 本系统是简易的个人博客系统开发&#xff0c;为了更加熟练地掌握 SprIng Boot 框架及相关技术的使用。&#x1f33f;&#x1f33f;&#x1f33f; 基于 Spring Boot 博客系统开发&#xff08;十一&#xff09;&…

热门新游 2024 植物大战僵尸杂交版 Mac 版本下载安装详细教程

最近植物大战僵尸杂交版可谓是非常的火&#xff0c;好多主播都在播这款游戏&#xff0c;我一个 Mac 党也想玩&#xff0c;可奈何该游戏目前只有 PC 版本&#xff0c;经过一番折腾终于在我的 Mac 上安装上了该游戏&#xff0c;分享给大家 其实安装过程也很简单&#xff0c;只需…

深度学习 --- stanford cs231 编程作业(如何在chrome中安装Google colab)

stanford cs231 编程作业(如何开始你的colab编程&#xff09; 斯坦福231n的所有作业都要求在colab里面做&#xff0c;colab可以为你提供免费的云计算。实际上在他的官网中也有关于如何安装colab的详细说明视频。 https://youtu.be/DsGd2e9JNH4https://youtu.be/DsGd2e9JNH4 我这…

GPU学习(1)

一、为什么要GPU 我们先看一个基本的神经网络计算 YF(x)AxB 这就是一次乘法一次加法 &#xff0c;也叫FMA&#xff0c;(fused multiply-add) 如果矩阵乘&#xff0c;就是上面的那个式子扩展一下&#xff0c;所以又用了这张老图 比如你要多执行好几个yAxB&#xff0c;可能比较简…

AI图书推荐:使用GitHub Copilot和ChatGPT辅助的Python编程

使用Python编写计算机程序变得更加简单了&#xff01;使用像GitHub Copilot和ChatGPT这样的AI辅助编码工具&#xff0c;将你的想法快速转化为应用程序。人工智能已经改变了我们编写计算机程序的方式。有了像Copilot和ChatGPT这样的工具&#xff0c;你可以用简单的英语描述你想要…

【docker】Docker的基本指令和HTML/PYTHON/C++的简单创建示例

目录 &#x1f30a;1. 什么是 Docker&#xff1f; &#x1f30a;2. Docker 安装 &#x1f30a;3. Docker基本指令 &#x1f30a;4. Docker 创建示例【联网情况】 &#x1f30d;4.1 示例&#xff1a;HTML &#x1f30d;4.2 示例&#xff1a;Python 脚本 &#x1f30d;4.3…

四信云-设备维保管理系统上线,实现设备全生命周期管理

在当今的制造业中&#xff0c;设备是企业生产的核心要素&#xff0c;是企业竞争力的基石。 随着企业发展规模不断扩大&#xff0c;设备数量急速增长&#xff0c;传统的手工管理方式已经无法满足企业需求&#xff0c;设备管理系统的出现则填补了市场需求空白&#xff0c;其目标…

5-21作业

流式域套接字 服务器端实现 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> #include <semaphore.h> #include <…

【运维项目经历|015】:Nginx Web服务性能提升与优化项目

目录 项目名称 项目背景 项目目标 项目成果 我的角色与职责 我主要完成的工作内容 本次项目涉及的技术 本次项目遇到的问题与解决方法 本次项目中可能被面试官问到的技术性问题 问题1&#xff1a;本次项目的人员配置&#xff1f; 问题2&#xff1a;本次项目的周期&am…

PX4使用yolo仿真环境搭建

文章目录 前言一、修改机架sdf文件二、安装yolo三、运行 前言 ubuntu20.04 PX4 1.13.3 已配置好PX4 ROS gazebo环境 一、修改机架sdf文件 将双目相机加到仿真的iris机架上 修改下图文件 添加如下&#xff1a; <include><uri>model://stereo_camera</uri>…

tensorrt输出结果为nan的解决方案

系统环境&#xff1a; ubuntu20.04 python3.9 cuda11.8 cudnn8.9.7.29 torch1.13.1cu117&#xff08;pip install torch1.13.1&#xff09; 1.针对cuda版本查了一下trt支持版本&#xff0c;发现V10和V8版本都支持 本着用新不用旧标准&#xff0c;果断下载了8.6&#xff0c…

iptables+SNAT+DNAT

一、Linux包过滤防火墙概述 主要工作在网络层&#xff0c;针对IP数据包&#xff0c;体现在对包内的IP地址、端口、协议等信息的处理上 以下两种称呼都可以表示Linux防火墙 netfilter 位于Linux内核中的包过滤功能体系 成为Linux防火墙的“内核态” 是内核的一部分&#xff0…

誉天Linux云计算架构师就业班要学习哪些内容?

课程设计思路&#xff1a; 根据十多年来毕业学员的就业和反馈&#xff0c;对数百名学员的就业回访;Linux运维&#xff0c;云计算&#xff0c;高并发&#xff0c;分布式&#xff0c;容器&#xff0c;云原生&#xff0c;自动化等是目前市场上就业情况最好&#xff0c;需求量最大&…

SQL查询-电商数据案例

假设我们现在需要是某电商平台数据分析&#xff0c;由于业务需要&#xff0c;需要用sql取数 包括&#xff0c;Python连接数据库到模拟电商数据库&#xff0c;到sql场景查询 1,Python连接SQL数据库 以下是使用Python连接MySQL数据库并进行操作的示例代码&#xff1a; import…

【python】python 全国5A级景区数据采集与pyecharts可视化(源码+数据+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

Liunx上安装MySQL

该文章是介绍的是 Ubuntu 操作系统&#xff0c;如果有使用 CentOS 的小伙伴不会的话可以私信我~ 1. 查找安装包 apt list |grep "mysql-server" 2. 安装mysql sudo apt install mysql-server 注意&#xff1a;安装的到最后一步会问你是否继续&#xff0c;输入y / Y就…

python内存马学习

python内存马学习 python内存马学习 python内存马学习环境搭建和复现分析payloadFlask 请求上下文管理机制bypass高版本flask内存马的利用before_request**after_request** teardown_requesterrorhandler相关例题H&NCTF 2024 ezFlask python内存马 环境搭建和复现 from fl…

SQL问题的常用信息收集命令及解决思路 |OceanBase应用实践

面对SQL问题&#xff0c;大家的常用的分析思路是&#xff1a; 一、问题是否源于SQL本身&#xff1f;是的话需进行SQL调优。 二、SQL语句本身无误&#xff0c;但执行效果并未达到我们的预期效果。 检查当前的服务器负载状况&#xff0c;例如CPU利用率、内存占用、IO读写等关键…