PY32F003F18之PWM互补输出

news2024/11/27 13:51:50

PY32F003F18中有一个“数字比较器”,这是我的叫法,为了便于和模拟比较器区分。它用作PWM输出功能。

一、比较通道1电路图

 二、PWM工作模式

PWM的工作模式:
1、PWM边沿对齐模式
计数器工作在"边沿对齐模式"
设置"TIMx控制寄存器1(TIMx_CR1)"的DIR和"TIMx控制寄存器1(TIMx_CR1)"的CMS[1:0];
CMS[1:0]=00,配置TIMx为边沿对齐模式,当DIR=0时,计数器向上计数;当DIR=1时,计数器向下计数;

2、PWM中央对齐模式1
3、PWM中央对齐模式2
4、PWM中央对齐模式3
在PWM中央对齐模式中,计数器从0开始计数到自动加载的值(TIMx_ARR 寄存器),会产生一个计数器溢出事件;然后向下计数,当计数器计数到1时,也会产生一个计数器下溢事件;然后再从0开始重新计数,这样循环往复开始计数。所以计数器中断时间不变。

计数器工作在"PWM中央对齐模式":
设置"TIMx控制寄存器1(TIMx_CR1)"的CMS[1:0];计数器工作在"中央对齐模式"
1)、CMS[1:0]=01,配置TIMx为中央对齐模式1,计数器交替地向上和向下计数;若配置为输出通道的,则在计数器向下计数时,"OCx的输出比较中断标志位"被置1;
2)、CMS[1:0]=10,配置TIMx为中央对齐模式2,计数器交替地向上和向下计数;若配置为输出通道的,则在计数器向上计数时,"OCx的输出比较中断标志位"被置1;
3)、CMS[1:0]=11,配置TIMx为中央对齐模式3,计数器交替地向上和向下计数;若配置为输出通道的,则在计数器向上/向下计数时,"OCx的输出比较中断标志位"被置1;

在"TIMx为中央对齐模式"时,向上计数时会出现一次TIMx_CNT<=TIMx_CCR1,向下计数时也会出现一次TIMx_CNT<=TIMx_CCR1,因此PWM输出脉宽为向上计数的2倍,周期也为原来周期的2倍

计数器使用"内部时钟源"
如果从模式控制器被禁止,则CEN、DIR(TIMx_CR1 寄存器)和UG 位(TIMx_EGR 寄存器)是事实上
的控制位,并且只能被软件修改。只要CEN 位被写成1,预分频器的时钟就由内部时钟CK_INT 提供。

三、测试程序

#include "TIM1_PWM_ComplementaryOutput.h"

/*
计数器工作在"边沿对齐模式"
//将"TIMx控制寄存器1(TIMx_CR1)"的DIR=0
//将"TIMx控制寄存器1(TIMx_CR1)"的CMS[1:0]=00B
//CMS[1:0]=00,配置TIMx为边沿对齐模式,当DIR=0时,计数器向上计数;当DIR=1时,计数器向下计数;

计数器使用"内部时钟源"
如果从模式控制器被禁止,则CEN、DIR(TIMx_CR1 寄存器)和UG 位(TIMx_EGR 寄存器)是事实上
的控制位,并且只能被软件修改。只要CEN 位被写成1,预分频器的时钟就由内部时钟CK_INT 提供。
*/

void TIM1_PWM_ComplementaryOutput(void);

#define  PERIOD_VALUE       (uint32_t)(8000 )                   //PWM输出周期值
#define  PULSE1_VALUE       (uint32_t)(PERIOD_VALUE*50/100)     //输出比较1的值,这里使用50%的占空比
#define  PULSE2_VALUE       (uint32_t)(PERIOD_VALUE*25/100)     //输出比较1的值,这里使用25%的占空比
#define  PULSE3_VALUE       (uint32_t)(PERIOD_VALUE*12.5/100)   //输出比较1的值,这里使用12.5%的占空比

//函数功能:
//将PA3初始化为TIM1_CH1功能,用作OC1输出
//将PA0初始化为TIM1_CH1N功能,用作OC1N输出
void TIM1_OC1_GPIO_Config(void)
{
	GPIO_InitTypeDef  GPIO_InitStructureure;

	__HAL_RCC_TIM1_CLK_ENABLE(); //使能TIM1时钟
	__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟

  GPIO_InitStructureure.Pin = GPIO_PIN_3;     //选择第3脚,PA3是为TIM1_CH1
  GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP;            //复用功能推挽模式
  GPIO_InitStructureure.Pull = GPIO_PULLUP;                //引脚上拉被激活
  GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
  GPIO_InitStructureure.Alternate = GPIO_AF13_TIM1;        //选择AF13,将PA3引脚复用为TIM1_CH1
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
	//根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
	//将PA3初始化为TIM1_CH1功能,用作OC1输出

  GPIO_InitStructureure.Pin = GPIO_PIN_0;     //选择第0脚,PA0是为TIM1_CH1N
  GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP;            //复用功能推挽模式
  GPIO_InitStructureure.Pull = GPIO_PULLUP;                //引脚上拉被激活
  GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
  GPIO_InitStructureure.Alternate = GPIO_AF14_TIM1;        //选择AF14,将PA0引脚复用为TIM1_CH1N
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
	//根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
	//将PA0初始化为TIM1_CH1N功能,用作OC1N输出
}

//函数功能:配置TIM1 OC1的输出周期
//TIM1计数器在溢出时会重装ARR值
//arr:自动重装值。
//psc:时钟预分频数
//TIM1_OC1_Period_Config(20000,240);//若使用HSE,当arr=20000,psc=240时,则为200ms,误差为10us;
//TIM1_OC1_Period_Config(20000,80);//若使用HSI,当arr=20000,psc=80时,则为200ms,误差为10us;
void TIM1_OC1_Period_Config(uint16_t arr,uint16_t psc)
{
	TIM_HandleTypeDef  TIM1_HandleStructure;

  TIM1_HandleStructure.Instance = TIM1; //选择TIM1
  TIM1_HandleStructure.Init.Period = arr - 1;
	//自动重装载值
	//将TIM1_HandleStructure.Init.Period写入"TIMx自动重载入寄存器TIMx_ARR",设置自动重装载值;

  TIM1_HandleStructure.Init.Prescaler = psc - 1;
	//预分频为240-1
	//将TIM1_HandleStructure.Init.Prescaler写入"预装载寄存器TIMx_PSC",设置预分频值

  TIM1_HandleStructure.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
	//时钟不分频
	//将TIM1_HandleStructure.Init.ClockDivision写入TIM1控制寄存器1(TIM1_CR1)的CKD[1:0],则tDTS=tCK_INT
	//若使用HSE,计算公式:arr*psc/24000000/1,当arr=20000,psc=240时,则为200ms,误差为10us;
	//若使用HSI,计算公式:arr*psc/8000000/1,当arr=20000,psc=80时,则为200ms,误差为100us;

  TIM1_HandleStructure.Init.CounterMode = TIM_COUNTERMODE_UP;
	//向上计数
	//将"TIMx控制寄存器1(TIMx_CR1)"的DIR=0
	//将"TIMx控制寄存器1(TIMx_CR1)"的CMS[1:0]=00B
	//CMS[1:0]=00,配置TIMx为边沿对齐模式,当DIR=0时,计数器向上计数;当DIR=1时,计数器向下计数;

  TIM1_HandleStructure.Init.RepetitionCounter = 1 - 1;
	//不重复计数
	//将TIM1_HandleStructure.Init.RepetitionCounter写入"重复计数寄存器TIMx_RCR"中的REP[7:0],设置"重复计数器值"

  TIM1_HandleStructure.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
	//自动重装载寄存器没有缓冲
	//根据TIM1_HandleStructure.Init.AutoReloadPreload,修改"TIMx控制寄存器1(TIM1_CR1)"的"自动重装载预装载允许位ARPE"
  //TIM1_HandleStructure.Init.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_DISABLE,不允许将"TIMx自动重新加载寄存器TIMx_ARR"的值被装入缓冲区;

   HAL_TIM_PWM_Init(&TIM1_HandleStructure);
   //选择计数器模式:Structure->CounterMode=TIM_COUNTERMODE_UP,计数器向上计数
   //设置时钟分频因子:Structure->ClockDivision=TIM_CLOCKDIVISION_DIV1,则tDTS=tCK_INT
   //设置自动重装载:Structure->AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_DISABLE,不允许将"TIMx自动重新加载寄存器TIMx_ARR"的值被装入缓冲区;
   //设置自动重装载值:将Structure->Period写入"TIMx自动重载入寄存器TIMx_ARR",设置自动重装载值;
   //设置预分频值:将Structure->Prescaler写入"预装载寄存器TIMx_PSC",的PSC[15:0],设置预分频值
   //计数器的时钟频率CK_CNT=fCK_PSC/(PSC[15:0]+1)
   //设置"重复计数器值":将Structure->RepetitionCounter写入"重复计数寄存器TIMx_RCR"中的REP[7:0],设置"重复计数器值"

   //启动更新事件:
   //将TIMx_EGR中的UG位置1,由软件产生更新事件
   //若TIM1或TIM3在边沿对齐模式下,Structure->CounterMode=TIM_COUNTERMODE_UP,计数器向上计数,则将0被装入计数器
   //若TIM1或TIM3在边沿对齐模式下,Structure->CounterMode=TIM_COUNTERMODE_DOWN,计数器向下计数,则将"TIMx自动重载入寄存器TIMx_ARR"的值被装入计数器
   //若TIM1或TIM3在中央对齐模式下,Structure->CounterMode=TIM_COUNTERMODE_CENTERALIGNED1,交替地向上和向下计数,则将0被装入计数器
   //若TIM1或TIM3在中央对齐模式下,Structure->CounterMode=TIM_COUNTERMODE_CENTERALIGNED2,交替地向上和向下计数,则将0被装入计数器
   //若TIM1或TIM3在中央对齐模式下,Structure->CounterMode=TIM_COUNTERMODE_CENTERALIGNED3,交替地向上和向下计数,则将0被装入计数器
   //TIM1或TIM3或TIM14或TIM16或TIM17将"预装载寄存器TIMx_PSC"装入"预分频器的缓存器"
   //TIM1或TIM3或TIM14或TIM16或TIM17将"重复计数寄存器TIMx_RCR"中的内容装载到其影子寄存器"重复计数器缓存器"
}

//函数功能:
//配置"输出比较器1(通道1)"为PWM1模式,使能"TIM1_CH1和TIM1_CH1N输出",计数器不是触发模式,计数器使能,开始计数
void TIM1_OC1_PWM_Mode_Config(uint32_t pulseWidth)
{
	TIM_HandleTypeDef  TIM1_HandleStructure;
	TIM_OC_InitTypeDef TIM_OC_InitStructure;

  TIM1_HandleStructure.Instance = TIM1; //选择TIM1

  TIM_OC_InitStructure.OCMode       = TIM_OCMODE_PWM1;       //配置为PWM1模式
  TIM_OC_InitStructure.OCPolarity   = TIM_OCPOLARITY_HIGH;   //高电平有效,选择OC1REF直接输出(TIM1_CH1引脚输出,PA3)
  TIM_OC_InitStructure.OCIdleState  = TIM_OCIDLESTATE_SET;   //OC1输出空闲状态为1,(TIM1_CH1引脚输出,PA3)
	TIM_OC_InitStructure.OCNPolarity  = TIM_OCNPOLARITY_HIGH;  //高电平有效,选择OC1NREF直接输出(TIM1_CH1N引脚输出,PA0)
	TIM_OC_InitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET;//OC1N输出空闲状态为0,(TIM1_CH1N引脚输出,PA0)
  TIM_OC_InitStructure.OCFastMode   = TIM_OCFAST_DISABLE;    //关闭快速使能
	TIM_OC_InitStructure.Pulse        = pulseWidth;
	//设置输出脉冲宽度,通道1占空比,将pulseWidth写入TIMx_CCR1
	//当TIMx_CNT<=TIMx_CCR1时,OC1端口上输出设置的有效信号,本程序是"高电平有效"
	HAL_TIM_PWM_ConfigChannel(&TIM1_HandleStructure,&TIM_OC_InitStructure, TIM_CHANNEL_1);
	//配置"输出比较器1(通道1)"为PWM模式
	//使能"输出比较器1"预装载
	//sConfig->OCFastMode=1表示设置"输出比较器1"为快速模式

	HAL_TIM_PWM_Start(&TIM1_HandleStructure, TIM_CHANNEL_1);
	//Channel=TIM_CHANNEL_1,使能"TIM1_CH1输出",计数器不是触发模式,计数器使能,开始计数

	HAL_TIMEx_PWMN_Start(&TIM1_HandleStructure, TIM_CHANNEL_1);
	//Channel=TIM_CHANNEL_1,使能"TIM1_CH1N输出",计数器不是触发模式,计数器使能,开始计数
}

//函数功能:配置"输出比较器1(通道1)"为PWM1模式,使能"TIM1_CH1和TIM1_CH1N输出"
void TIM1_PWM_ComplementaryOutput(void)
{
	TIM1_OC1_GPIO_Config();
  //将PA3初始化为TIM1_CH1功能,用作OC1输出
  //将PA0初始化为TIM1_CH1N功能,用作OC1N输出

  TIM1_OC1_Period_Config(PERIOD_VALUE,240);//配置TIM1 OC1的输出周期

	TIM1_OC1_PWM_Mode_Config(PULSE2_VALUE);
	//配置"输出比较器1(通道1)"为PWM模式,使能"TIM1_CH1和TIM1_CH1N输出",计数器不是触发模式,计数器使能,开始计数
}
#include "TIM1_Up_PWM_ComplementaryOutput.h"

/*
计数器工作在"边沿对齐模式"
//将"TIMx控制寄存器1(TIMx_CR1)"的DIR=0
//将"TIMx控制寄存器1(TIMx_CR1)"的CMS[1:0]=00B
//CMS[1:0]=00,配置TIMx为边沿对齐模式,当DIR=0时,计数器向上计数;当DIR=1时,计数器向下计数;

计数器使用"内部时钟源"
如果从模式控制器被禁止,则CEN、DIR(TIMx_CR1 寄存器)和UG 位(TIMx_EGR 寄存器)是事实上
的控制位,并且只能被软件修改。只要CEN 位被写成1,预分频器的时钟就由内部时钟CK_INT 提供。
*/

void TIM1_Up_PWM_ComplementaryOutput(void);

#define  PERIOD_VALUE       (uint32_t)(8000 )                   //PWM输出周期值
#define  PULSE1_VALUE       (uint32_t)(PERIOD_VALUE*50/100)     //输出比较1的值,这里使用50%的占空比
#define  PULSE2_VALUE       (uint32_t)(PERIOD_VALUE*25/100)     //输出比较1的值,这里使用25%的占空比
#define  PULSE3_VALUE       (uint32_t)(PERIOD_VALUE*12.5/100)   //输出比较1的值,这里使用12.5%的占空比

//函数功能:
//将PA3初始化为TIM1_CH1功能,用作OC1输出
//将PA0初始化为TIM1_CH1N功能,用作OC1N输出
void TIM1_OC1_GPIO_Config(void)
{
	GPIO_InitTypeDef  GPIO_InitStructureure;

	__HAL_RCC_TIM1_CLK_ENABLE(); //使能TIM1时钟
	__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟

  GPIO_InitStructureure.Pin = GPIO_PIN_3;     //选择第3脚,PA3是为TIM1_CH1
  GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP;            //复用功能推挽模式
  GPIO_InitStructureure.Pull = GPIO_PULLUP;                //引脚上拉被激活
  GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
  GPIO_InitStructureure.Alternate = GPIO_AF13_TIM1;        //选择AF13,将PA3引脚复用为TIM1_CH1
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
	//根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
	//将PA3初始化为TIM1_CH1功能,用作OC1输出

  GPIO_InitStructureure.Pin = GPIO_PIN_0;     //选择第0脚,PA0是为TIM1_CH1N
  GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP;            //复用功能推挽模式
  GPIO_InitStructureure.Pull = GPIO_PULLUP;                //引脚上拉被激活
  GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
  GPIO_InitStructureure.Alternate = GPIO_AF14_TIM1;        //选择AF14,将PA0引脚复用为TIM1_CH1N
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
	//根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
	//将PA0初始化为TIM1_CH1N功能,用作OC1N输出
}

//函数功能:配置TIM1 OC1的输出周期
//TIM1计数器在溢出时会重装ARR值
//arr:自动重装值。
//psc:时钟预分频数
//TIM1_OC1_Period_Config(20000,240);//若使用HSE,当arr=20000,psc=240时,则为200ms,误差为10us;
//TIM1_OC1_Period_Config(20000,80);//若使用HSI,当arr=20000,psc=80时,则为200ms,误差为10us;
void TIM1_OC1_Period_Config(uint16_t arr,uint16_t psc)
{
	TIM_HandleTypeDef  TIM1_HandleStructure;

  TIM1_HandleStructure.Instance = TIM1; //选择TIM1
  TIM1_HandleStructure.Init.Period = arr - 1;
	//自动重装载值
	//将TIM1_HandleStructure.Init.Period写入"TIMx自动重载入寄存器TIMx_ARR",设置自动重装载值;

  TIM1_HandleStructure.Init.Prescaler = psc - 1;
	//预分频为240-1
	//将TIM1_HandleStructure.Init.Prescaler写入"预装载寄存器TIMx_PSC",设置预分频值

  TIM1_HandleStructure.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
	//时钟不分频
	//将TIM1_HandleStructure.Init.ClockDivision写入TIM1控制寄存器1(TIM1_CR1)的CKD[1:0],则tDTS=tCK_INT
	//若使用HSE,计算公式:arr*psc/24000000/1,当arr=20000,psc=240时,则为200ms,误差为10us;
	//若使用HSI,计算公式:arr*psc/8000000/1,当arr=20000,psc=80时,则为200ms,误差为100us;

  TIM1_HandleStructure.Init.CounterMode = TIM_COUNTERMODE_UP;
	//向上计数
	//将"TIMx控制寄存器1(TIMx_CR1)"的DIR=0
	//将"TIMx控制寄存器1(TIMx_CR1)"的CMS[1:0]=00B
	//CMS[1:0]=00,配置TIMx为边沿对齐模式,当DIR=0时,计数器向上计数;当DIR=1时,计数器向下计数;

  TIM1_HandleStructure.Init.RepetitionCounter = 1 - 1;
	//不重复计数
	//将TIM1_HandleStructure.Init.RepetitionCounter写入"重复计数寄存器TIMx_RCR"中的REP[7:0],设置"重复计数器值"

  TIM1_HandleStructure.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
	//自动重装载寄存器没有缓冲
	//根据TIM1_HandleStructure.Init.AutoReloadPreload,修改"TIMx控制寄存器1(TIM1_CR1)"的"自动重装载预装载允许位ARPE"
  //TIM1_HandleStructure.Init.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_DISABLE,不允许将"TIMx自动重新加载寄存器TIMx_ARR"的值被装入缓冲区;

   HAL_TIM_PWM_Init(&TIM1_HandleStructure);
   //选择计数器模式:Structure->CounterMode=TIM_COUNTERMODE_UP,计数器向上计数
   //设置时钟分频因子:Structure->ClockDivision=TIM_CLOCKDIVISION_DIV1,则tDTS=tCK_INT
   //设置自动重装载:Structure->AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_DISABLE,不允许将"TIMx自动重新加载寄存器TIMx_ARR"的值被装入缓冲区;
   //设置自动重装载值:将Structure->Period写入"TIMx自动重载入寄存器TIMx_ARR",设置自动重装载值;
   //设置预分频值:将Structure->Prescaler写入"预装载寄存器TIMx_PSC",的PSC[15:0],设置预分频值
   //计数器的时钟频率CK_CNT=fCK_PSC/(PSC[15:0]+1)
   //设置"重复计数器值":将Structure->RepetitionCounter写入"重复计数寄存器TIMx_RCR"中的REP[7:0],设置"重复计数器值"

   //启动更新事件:
   //将TIMx_EGR中的UG位置1,由软件产生更新事件
   //若TIM1或TIM3在边沿对齐模式下,Structure->CounterMode=TIM_COUNTERMODE_UP,计数器向上计数,则将0被装入计数器
   //若TIM1或TIM3在边沿对齐模式下,Structure->CounterMode=TIM_COUNTERMODE_DOWN,计数器向下计数,则将"TIMx自动重载入寄存器TIMx_ARR"的值被装入计数器
   //若TIM1或TIM3在中央对齐模式下,Structure->CounterMode=TIM_COUNTERMODE_CENTERALIGNED1,交替地向上和向下计数,则将0被装入计数器
   //若TIM1或TIM3在中央对齐模式下,Structure->CounterMode=TIM_COUNTERMODE_CENTERALIGNED2,交替地向上和向下计数,则将0被装入计数器
   //若TIM1或TIM3在中央对齐模式下,Structure->CounterMode=TIM_COUNTERMODE_CENTERALIGNED3,交替地向上和向下计数,则将0被装入计数器
   //TIM1或TIM3或TIM14或TIM16或TIM17将"预装载寄存器TIMx_PSC"装入"预分频器的缓存器"
   //TIM1或TIM3或TIM14或TIM16或TIM17将"重复计数寄存器TIMx_RCR"中的内容装载到其影子寄存器"重复计数器缓存器"
}

//函数功能:
//配置"输出比较器1(通道1)"为PWM1模式,使能"TIM1_CH1和TIM1_CH1N输出",计数器不是触发模式,计数器使能,开始计数
void TIM1_OC1_PWM_Mode_Config(uint32_t pulseWidth)
{
	TIM_HandleTypeDef  TIM1_HandleStructure;
	TIM_OC_InitTypeDef TIM_OC_InitStructure;

  TIM1_HandleStructure.Instance = TIM1; //选择TIM1

  TIM_OC_InitStructure.OCMode       = TIM_OCMODE_PWM1;       //配置为PWM1模式
  TIM_OC_InitStructure.OCPolarity   = TIM_OCPOLARITY_HIGH;   //高电平有效,选择OC1REF直接输出(TIM1_CH1引脚输出,PA3)
  TIM_OC_InitStructure.OCIdleState  = TIM_OCIDLESTATE_SET;   //OC1输出空闲状态为1,(TIM1_CH1引脚输出,PA3)
	TIM_OC_InitStructure.OCNPolarity  = TIM_OCNPOLARITY_HIGH;  //高电平有效,选择OC1NREF直接输出(TIM1_CH1N引脚输出,PA0)
	TIM_OC_InitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET;//OC1N输出空闲状态为0,(TIM1_CH1N引脚输出,PA0)
  TIM_OC_InitStructure.OCFastMode   = TIM_OCFAST_DISABLE;    //关闭快速使能
	TIM_OC_InitStructure.Pulse        = pulseWidth;
	//设置输出脉冲宽度,通道1占空比,将pulseWidth写入TIMx_CCR1
	//当TIMx_CNT<=TIMx_CCR1时,OC1端口上输出设置的有效信号,本程序是"高电平有效"
	HAL_TIM_PWM_ConfigChannel(&TIM1_HandleStructure,&TIM_OC_InitStructure, TIM_CHANNEL_1);
	//配置"输出比较器1(通道1)"为PWM模式
	//使能"输出比较器1"预装载
	//sConfig->OCFastMode=1表示设置"输出比较器1"为快速模式

	HAL_TIM_PWM_Start(&TIM1_HandleStructure, TIM_CHANNEL_1);
	//Channel=TIM_CHANNEL_1,使能"TIM1_CH1输出",计数器不是触发模式,计数器使能,开始计数

	HAL_TIMEx_PWMN_Start(&TIM1_HandleStructure, TIM_CHANNEL_1);
	//Channel=TIM_CHANNEL_1,使能"TIM1_CH1N输出",计数器不是触发模式,计数器使能,开始计数
}

//函数功能:配置"输出比较器1(通道1)"为PWM1模式,使能"TIM1_CH1和TIM1_CH1N输出"
void TIM1_Up_PWM_ComplementaryOutput(void)
{
	TIM1_OC1_GPIO_Config();
  //将PA3初始化为TIM1_CH1功能,用作OC1输出
  //将PA0初始化为TIM1_CH1N功能,用作OC1N输出

  TIM1_OC1_Period_Config(PERIOD_VALUE,240);//配置TIM1 OC1的输出周期

	TIM1_OC1_PWM_Mode_Config(PULSE2_VALUE);
	//配置"输出比较器1(通道1)"为PWM模式,使能"TIM1_CH1和TIM1_CH1N输出",计数器不是触发模式,计数器使能,开始计数
}

四、测试结果

五、PWM1"捕获/比较1中断"测试

添加下面的代码,就可以测试"捕获/比较1中断"

//函数功能:允许"捕获/比较1中断"
void TIM1_Up_Down_PWM_Interrupt(void)
{
  HAL_NVIC_SetPriority(TIM1_CC_IRQn, 0, 0); //设置中断优先级
  HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);         //允许"捕获/比较1中断"
  _HAL_TIM_ENABLE_IT(TIM1, TIM_IT_CC1);
	//将"TIMx DMA/中断使能寄存器TIM3_DIER"的CC1IE=1,允许"捕获/比较1中断"
}

//函数功能:配置"输出比较器1(通道1)"为PWM1模式,使能"TIM1_CH1和TIM1_CH1N输出"
void TIM1_Up_Down_PWM_ComplementaryOutput(void)
{
	TIM1_OC1_GPIO_Config();
  //将PA3初始化为TIM1_CH1功能,用作OC1输出
  //将PA0初始化为TIM1_CH1N功能,用作OC1N输出

  TIM1_OC1_Period_Config(PERIOD_VALUE,240);//配置TIM1 OC1的输出周期

	TIM1_Up_Down_PWM_Interrupt();//允许"捕获/比较1中断"
	TIM1_OC1_PWM_Mode_Config(PULSE2_VALUE);
	//配置"输出比较器1(通道1)"为PWM模式,使能"TIM1_CH1和TIM1_CH1N输出",计数器不是触发模式,计数器使能,开始计数
}

 

#ifndef __MyTimer_H
#define __MyTimer_H

#include "py32f0xx_hal.h"

#define _HAL_TIM_ENABLE(__INSTANCE__)                 ((__INSTANCE__)->CR1|=(TIM_CR1_CEN))
//计数器使能,开始计数

#define _HAL_TIM_DISABLE(__INSTANCE__) \
  do { \
    if (((__INSTANCE__)->CCER & TIM_CCER_CCxE_MASK) == 0UL) \
    { \
      if(((__INSTANCE__)->CCER & TIM_CCER_CCxNE_MASK) == 0UL) \
      { \
        (__INSTANCE__)->CR1 &= ~(TIM_CR1_CEN); \
      } \
    } \
  } while(0)
//计数器不使能,停止计数

#define _HAL_TIM_MOE_ENABLE(__INSTANCE__)             ((__INSTANCE__)->BDTR|=(TIM_BDTR_MOE))
//将"TIMx刹车和死区寄存器(TIMx_BDTR)"中的MOE=1,开启OCx和OCxN输出,即使能"TIMx_CH1和TIMx_CH1N"输出

#define _HAL_TIM_MOE_DISABLE_UNCONDITIONALLY(__INSTANCE__)  (__INSTANCE__)->BDTR &= ~(TIM_BDTR_MOE)
//将"TIMx刹车和死区寄存器(TIMx_BDTR)"中的MOE=0,关闭OCx和OCxN输出,即不使能"TIMx_CH1和TIMx_CH1N"输出

#define _HAL_TIM_MOE_DISABLE(__INSTANCE__) \
  do { \
    if (((__INSTANCE__)->CCER & TIM_CCER_CCxE_MASK) == 0UL) \
    { \
      if(((__INSTANCE__)->CCER & TIM_CCER_CCxNE_MASK) == 0UL) \
      { \
        (__INSTANCE__)->BDTR &= ~(TIM_BDTR_MOE); \
      } \
    } \
  } while(0)
//在"TIMx捕获/比较使能寄存器TIMx_CCER"中,如果"OCx禁止输出或捕获禁止",且"OCxNE禁止输出"
//则将"TIMx刹车和死区寄存器(TIMx_BDTR)"中的MOE=0,关闭OCx和OCxN输出,即不使能"TIMx_CH1和TIMx_CH1N"输出

#define _HAL_TIM_ENABLE_IT(__INSTANCE__, __INTERRUPT__)    ((__INSTANCE__)->DIER |= (__INTERRUPT__))
//根据__INTERRUPT__,将TIMx DMA/中断使能寄存器(TIM3_DIER)的对应位置1,使能相应的中断
//TIM_IT_UPDATE,允许定时器更新中断,UIE=1
//TIM_IT_CC1,允许捕获/比较1中断,CC1IE=1
//TIM_IT_CC2,允许捕获/比较2中断,CC2IE=1
//TIM_IT_CC3,允许捕获/比较3中断,CC3IE=1
//TIM_IT_CC4,允许捕获/比较4中断,CC4IE=1
//TIM_IT_COM,允许COM事件中断,COMIE=1
//TIM_IT_TRIGGER,允许触发中断,TIE=1
//TIM_IT_BREAK,允许刹车中断,BIE=1

#define _HAL_TIM_DISABLE_IT(__INSTANCE__, __INTERRUPT__)   ((__INSTANCE__)->DIER &= ~(__INTERRUPT__))
//根据__INTERRUPT__,将TIMx DMA/中断使能寄存器(TIM3_DIER)的对应位清除,不使能相应的中断
//TIM_IT_UPDATE,禁止定时器更新中断,UIE=0
//TIM_IT_CC1,禁止捕获/比较1中断,CC1IE=0
//TIM_IT_CC2,禁止捕获/比较2中断,CC2IE=0
//TIM_IT_CC3,禁止捕获/比较3中断,CC3IE=0
//TIM_IT_CC4,禁止捕获/比较4中断,CC4IE=0
//TIM_IT_COM,禁止COM事件中断,COMIE=0
//TIM_IT_TRIGGER,禁止触发中断,TIE=0
//TIM_IT_BREAK,禁止刹车中断,BIE=0

#define _HAL_TIM_ENABLE_DMA(__INSTANCE__, __DMA__)         ((__INSTANCE__)->DIER |= (__DMA__))
//根据__INTERRUPT__,将TIMx DMA/中断使能寄存器(TIMx_DIER)的对应位置1,使能相应的DMA请求
//TIM_DMA_UPDATE,允许更新的DMA请求,UDE=1
//TIM_DMA_CC1,允许捕获/比较1的DMA请求,CC1DE=1
//TIM_DMA_CC2,允许捕获/比较2的DMA请求,CC2DE=1
//TIM_DMA_CC3,允许捕获/比较3的DMA请求,CC3DE=1
//TIM_DMA_CC4,允许捕获/比较4的DMA请求,CC4DE=1
//TIM_DMA_COM,允许COM的DMA请求,COMDE=1
//TIM_DMA_TRIGGER,允许触发DMA请求,TDE=1

#define _HAL_TIM_DISABLE_DMA(__INSTANCE__, __DMA__)        ((__INSTANCE__)->DIER &= ~(__DMA__))
//根据__INTERRUPT__,将TIMx DMA/中断使能寄存器(TIMx_DIER)的对应位置1,不使能相应的DMA请求
//TIM_DMA_UPDATE,禁止更新的DMA请求,UDE=0
//TIM_DMA_CC1,禁止捕获/比较1的DMA请求,CC1DE=0
//TIM_DMA_CC2,禁止捕获/比较2的DMA请求,CC2DE=0
//TIM_DMA_CC3,禁止捕获/比较3的DMA请求,CC3DE=0
//TIM_DMA_CC4,禁止捕获/比较4的DMA请求,CC4DE=0
//TIM_DMA_COM,禁止COM的DMA请求,COMDE=0
//TIM_DMA_TRIGGER,禁止触发DMA请求,TDE=0

#define _HAL_TIM_GET_FLAG(__INSTANCE__, __FLAG__)          (((__INSTANCE__)->SR &(__FLAG__)) == (__FLAG__))
//根据__FLAG__,若"TIMx状态寄存器(TIMx_SR)"中相应的位置1,则返回1
//TIM_FLAG_UPDATE,若UIF=1,建立"更新事件"
//TIM_FLAG_CC1,若CC1IF=1,如果通道CC1配置为输出模式,则建立"CC1输出事件";
//TIM_FLAG_CC1,若CC1IF=1,如果通道CC1配置为输入模式,则建立"CC1捕获事件"
//TIM_FLAG_CC2,若CC2IF=1,如果通道CC2配置为输出模式,则建立"CC2输出事件";
//TIM_FLAG_CC2,若CC2IF=1,如果通道CC2配置为输入模式,则建立"CC2捕获事件"
//TIM_FLAG_CC3,若CC3IF=1,如果通道CC3配置为输出模式,则建立"CC3输出事件";
//TIM_FLAG_CC3,若CC3IF=1,如果通道CC3配置为输入模式,则建立"CC3捕获事件"
//TIM_FLAG_CC4,若CC4IF=1,如果通道CC4配置为输出模式,则建立"CC4输出事件";
//TIM_FLAG_CC4,若CC4IF=1,如果通道CC4配置为输入模式,则建立"CC4捕获事件";
//TIM_FLAG_COM,若COMIF=1,则建立"COM事件"
//TIM_FLAG_TRIGGER,若TIF=1,则建立"触发事件"
//TIM_FLAG_BREAK,若BIF=1,则建立"刹车事件"
//TIM_FLAG_CC1OF,若CC1OF=1,则表示"计数器x的值被捕获到TIMx_CCR1寄存器"
//TIM_FLAG_CC2OF,若CC2OF=1,则表示"计数器x的值被捕获到TIMx_CCR2寄存器"
//TIM_FLAG_CC3OF,若CC3OF=1,则表示"计数器x的值被捕获到TIMx_CCR3寄存器"
//TIM_FLAG_CC4OF,若CC4OF=1,则表示"计数器x的值被捕获到TIMx_CCR4寄存器"

#define _HAL_TIM_CLEAR_FLAG(__INSTANCE__, __FLAG__)        ((__INSTANCE__)->SR = ~(__FLAG__))
//这么写的原因,因为定时器只能做某一种功能,不能同时实现多种功能
//根据__FLAG__,若"TIMx状态寄存器(TIMx_SR)"中相应的位置0,则返回1
//TIM_FLAG_UPDATE,若UIF=1,建立"更新事件"
//TIM_FLAG_CC1,令CC1IF=0,如果通道CC1配置为输出模式,则清除"CC1输出事件";
//TIM_FLAG_CC1,令CC1IF=0,如果通道CC1配置为输入模式,则清除"CC1捕获事件"
//TIM_FLAG_CC2,令CC2IF=0,如果通道CC2配置为输出模式,则清除"CC2输出事件";
//TIM_FLAG_CC2,令CC2IF=0,如果通道CC2配置为输入模式,则清除"CC2捕获事件"
//TIM_FLAG_CC3,令CC3IF=0,如果通道CC3配置为输出模式,则清除"CC3输出事件";
//TIM_FLAG_CC3,令CC3IF=0,如果通道CC3配置为输入模式,则清除"CC3捕获事件"
//TIM_FLAG_CC4,令CC4IF=0,如果通道CC4配置为输出模式,则清除"CC4输出事件";
//TIM_FLAG_CC4,令CC4IF=0,如果通道CC4配置为输入模式,则清除"CC4捕获事件";
//TIM_FLAG_COM,令COMIF=0,则清除"COM事件"
//TIM_FLAG_TRIGGER,令TIF=0,则清除"触发事件"
//TIM_FLAG_BREAK,令BIF=0,则清除"刹车事件"
//TIM_FLAG_CC1OF,令CC1OF=0,则清除建立的事件(计数器x的值被捕获到TIMx_CCR1寄存器)
//TIM_FLAG_CC2OF,令CC2OF=0,则清除建立的事件(计数器x的值被捕获到TIMx_CCR2寄存器)
//TIM_FLAG_CC3OF,令CC3OF=0,则清除建立的事件(计数器x的值被捕获到TIMx_CCR3寄存器)
//TIM_FLAG_CC4OF,令CC4OF=0,则清除建立的事件(计数器x的值被捕获到TIMx_CCR4寄存器)

#define _HAL_TIM_GET_IT_SOURCE(__INSTANCE__, __INTERRUPT__) ((((__INSTANCE__)->DIER & (__INTERRUPT__)) \
                                                             == (__INTERRUPT__)) ? SET : RESET)
//根据__INTERRUPT__,若"TIMx DMA/中断使能寄存器(TIM3_DIER)的对应位置1,则返回1
//TIM_IT_UPDATE,若UIE=1,返回1,当前允许定时器更新中断
//TIM_IT_CC1,若CC1IE=1,返回1,当前允许捕获/比较1中断
//TIM_IT_CC2,若CC2IE=1,返回1,当前允许捕获/比较2中断
//TIM_IT_CC3,若CC3IE=1,返回1,当前允许捕获/比较3中断
//TIM_IT_CC4,若CC4IE=1,返回1,当前允许捕获/比较4中断
//TIM_IT_COM,若COMIE=1,返回1,当前允许COM事件中断
//TIM_IT_TRIGGER,若TIE=1,返回1,当前允许触发中断
//TIM_IT_BREAK,若BIE=1,返回1,当前允许刹车中断

#define _HAL_TIM_CLEAR_IT(__INSTANCE__, __INTERRUPT__)      ((__INSTANCE__)->SR = ~(__INTERRUPT__))
//根据__INTERRUPT__,将"TIMx状态寄存器(TIMx_SR)"中相应的位置0,取消中断标志位
//TIM_IT_UPDATE,令UIE=0,不允许定时器更新中断
//TIM_IT_CC1,令CC1IE=0,不允许捕获/比较1中断
//TIM_IT_CC2,令CC2IE=0,不允许捕获/比较2中断
//TIM_IT_CC3,令CC3IE=0,不允许捕获/比较3中断
//TIM_IT_CC4,令CC4IE=0,不允许捕获/比较4中断
//TIM_IT_COM,令COMIE=0,不允许COM事件中断
//TIM_IT_TRIGGER,令TIE=0,不允许触发中断
//TIM_IT_BREAK,令BIE=0,不允许刹车中断

#define _HAL_TIM_IS_TIM_COUNTING_DOWN(__INSTANCE__)    (((__INSTANCE__)->CR1 &(TIM_CR1_DIR)) == (TIM_CR1_DIR))
//读"TIMx控制寄存器1(TIMx_CR1)"的DIR位,若返回值为1,则表示该计数器为向下计数;否则为向上计数

#define _HAL_TIM_SET_PRESCALER(__INSTANCE__, __PRESC__)       ((__INSTANCE__)->PSC = (__PRESC__))
//将(__PRESC__)写入"预装载寄存器TIMx_PSC",的PSC[15:0],设置预分频值
//计数器的时钟频率CK_CNT=fCK_PSC/(PSC[15:0]+1)

#define _HAL_TIM_SET_COUNTER(__INSTANCE__, __COUNTER__)  ((__INSTANCE__)->CNT = (__COUNTER__))
//将(__COUNTER__)的值写入"TIMx计数器(TIMx_CNT)"

#define _HAL_TIM_GET_COUNTER(__INSTANCE__)  ((__INSTANCE__)->CNT)
//读"TIMx计数器(TIMx_CNT)"的值

#define _HAL_TIM_SET_AUTORELOAD(__INSTANCE__, __AUTORELOAD__) \
  do{                                                    \
    (__INSTANCE__)->ARR = (__AUTORELOAD__);  \
  } while(0)
//将(__AUTORELOAD__)写入"自动重载入寄存器TIMx_ARR",设置自动重装载值

#define _HAL_TIM_GET_AUTORELOAD(__INSTANCE__)  ((__INSTANCE__)->ARR)
//从"自动重载入寄存器TIMx_ARR"中,读取"自动重装载值"

#define _HAL_TIM_SET_CLOCKDIVISION(__INSTANCE__, __CKD__) \
  do{                                                   \
    (__INSTANCE__)->CR1 &= (~TIM_CR1_CKD);  \
    (__INSTANCE__)->CR1 |= (__CKD__);       \
  } while(0)
//设置"时钟分频因子"
//将TIM1控制寄存器1(TIM1_CR1)的CKD[1:0]置00B
//TIM_CLOCKDIVISION_DIV1,则(__CKD__)=00B:时钟分频因子tDTS=tCK_INT
//TIM_CLOCKDIVISION_DIV2,则((__CKD__)=01B:时钟分频因子tDTS=2*tCK_INT
//TIM_CLOCKDIVISION_DIV4,则((__CKD__)=10B:时钟分频因子tDTS=4*tCK_INT

#define _HAL_TIM_GET_CLOCKDIVISION(__INSTANCE__)  ((__INSTANCE__)->CR1 & TIM_CR1_CKD)
//从"TIMx控制寄存器1(TIM1_CR1)"中,读取CKD[1:0]位值,就是"时钟分频因子"
//将TIM1控制寄存器1(TIM1_CR1)的CKD[1:0]置00B
//返回值为TIM_CLOCKDIVISION_DIV1,表示时钟分频因子tDTS=tCK_INT
//返回值为TIM_CLOCKDIVISION_DIV2,表示时钟分频因子tDTS=2*tCK_INT
//返回值为TIM_CLOCKDIVISION_DIV4,表示时钟分频因子tDTS=4*tCK_INT

#define TIMx_RESET_ICPRESCALERVALUE(__INSTANCE__, __CHANNEL__) \
  ( ( (__CHANNEL__) == TIM_CHANNEL_1) ? ( (__INSTANCE__)->CCMR1 &= ~TIM_CCMR1_IC1PSC ) :\
    ( (__CHANNEL__) == TIM_CHANNEL_2) ? ( (__INSTANCE__)->CCMR1 &= ~TIM_CCMR1_IC2PSC ) :\
    ( (__CHANNEL__) == TIM_CHANNEL_3) ? ( (__INSTANCE__)->CCMR2 &= ~TIM_CCMR2_IC3PSC ) :\
    ( (__INSTANCE__)->CCMR2 &= ~TIM_CCMR2_IC4PSC ) )
//设置"输入捕获模式,Input Capture mode"
//如果(__CHANNEL__)为TIM_CHANNEL_1,则清除"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的输入/捕获1预分频器C1PSC[1:0]
//如果(__CHANNEL__)为TIM_CHANNEL_2,则清除"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的输入/捕获2预分频器C2PSC[1:0]
//如果(__CHANNEL__)为TIM_CHANNEL_3,则清除"TIMx捕获/比较模式寄存器1(TIMx_CCMR2)"中的输入/捕获3预分频器C3PSC[1:0]

#define TIMx_SET_ICPRESCALERVALUE(__INSTANCE__, __CHANNEL__, __ICPSC__) \
  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__INSTANCE__)->CCMR1 |= (__ICPSC__)) :\
   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__INSTANCE__)->CCMR1 |= ((__ICPSC__) << 8U)) :\
   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__INSTANCE__)->CCMR2 |= (__ICPSC__)) :\
   ((__INSTANCE__)->CCMR2 |= ((__ICPSC__) << 8U)))
//设置"输入捕获模式,Input Capture mode"
//若(__CHANNEL__)=TIM_CHANNEL_1,则用(__ICPSC__)设置"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的输入/捕获1预分频器C1PSC[1:0]
//若(__CHANNEL__)=TIM_CHANNEL_2,则(__ICPSC__)设置"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的输入/捕获2预分频器C2PSC[1:0]
//若(__CHANNEL__)=TIM_CHANNEL_3,则(__ICPSC__)设置"TIMx捕获/比较模式寄存器2(TIMx_CCMR2)"中的输入/捕获3预分频器C3PSC[1:0]

#define _HAL_TIM_GET_ICPRESCALER(__INSTANCE__, __CHANNEL__)  \
  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__INSTANCE__)->CCMR1 & TIM_CCMR1_IC1PSC) :\
   ((__CHANNEL__) == TIM_CHANNEL_2) ? (((__INSTANCE__)->CCMR1 & TIM_CCMR1_IC2PSC) >> 8U) :\
   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__INSTANCE__)->CCMR2 & TIM_CCMR2_IC3PSC) :\
   (((__INSTANCE__)->CCMR2 & TIM_CCMR2_IC4PSC)) >> 8U)
//在"输入捕获模式"中,
//若(__CHANNEL__)=TIM_CHANNEL_1,则读取"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的输入/捕获1预分频器C1PSC[1:0]
//若(__CHANNEL__)=TIM_CHANNEL_2,则读取"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的输入/捕获2预分频器C2PSC[1:0]
//若(__CHANNEL__)=TIM_CHANNEL_3,则读取"TIMx捕获/比较模式寄存器2(TIMx_CCMR2)"中的输入/捕获3预分频器C3PSC[1:0]

#define _HAL_TIM_SET_COMPARE(__INSTANCE__, __CHANNEL__, __COMPARE__) \
  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__INSTANCE__)->CCR1 = (__COMPARE__)) :\
   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__INSTANCE__)->CCR2 = (__COMPARE__)) :\
   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__INSTANCE__)->CCR3 = (__COMPARE__)) :\
   ((__INSTANCE__)->CCR4 = (__COMPARE__)))
//设置"CCx的预装载值":
//若(__CHANNEL__)=TIM_CHANNEL_1,则将(__COMPARE__)写入TIMx捕获/比较寄存器1(TIMx_CCR1)中的CCR1[15:0],表示预装载值
//若(__CHANNEL__)=TIM_CHANNEL_2,则将(__COMPARE__)写入TIMx捕获/比较寄存器2(TIMx_CCR2)中的CCR2[15:0],表示预装载值
//若(__CHANNEL__)=TIM_CHANNEL_3,则将(__COMPARE__)写入TIMx捕获/比较寄存器3(TIMx_CCR3)中的CCR3[15:0],表示预装载值
//若(__CHANNEL__)=TIM_CHANNEL_4,则将(__COMPARE__)写入TIMx捕获/比较寄存器4(TIMx_CCR4)中的CCR3[15:0],表示预装载值

#define _HAL_TIM_GET_COMPARE(__INSTANCE__, __CHANNEL__) \
  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__INSTANCE__)->CCR1) :\
   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__INSTANCE__)->CCR2) :\
   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__INSTANCE__)->CCR3) :\
   ((__INSTANCE__)->CCR4))
//读取"CCx的预装载值":
//若(__CHANNEL__)=TIM_CHANNEL_1,则从TIMx捕获/比较寄存器1(TIMx_CCR1)中的CCR1[15:0]读取预装载值
//若(__CHANNEL__)=TIM_CHANNEL_2,则从TIMx捕获/比较寄存器2(TIMx_CCR2)中的CCR2[15:0]读取预装载值
//若(__CHANNEL__)=TIM_CHANNEL_3,则从TIMx捕获/比较寄存器3(TIMx_CCR3)中的CCR3[15:0]读取预装载值
//若(__CHANNEL__)=TIM_CHANNEL_4,则从TIMx捕获/比较寄存器3(TIMx_CCR4)中的CCR3[15:0]读取预装载值

#define _HAL_TIM_ENABLE_OCxPRELOAD(__INSTANCE__, __CHANNEL__)    \
  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__INSTANCE__)->CCMR1 |= TIM_CCMR1_OC1PE) :\
   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__INSTANCE__)->CCMR1 |= TIM_CCMR1_OC2PE) :\
   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__INSTANCE__)->CCMR2 |= TIM_CCMR2_OC3PE) :\
   ((__INSTANCE__)->CCMR2 |= TIM_CCMR2_OC4PE))
//开启TIMx_CCRy寄存器的预装载功能
//若(__CHANNEL__)=TIM_CHANNEL_1,则将"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的OC1PE位置1,开启TIMx_CCR1寄存器的预装载功能
//若(__CHANNEL__)=TIM_CHANNEL_2,则将"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的OC2PE位置1,开启TIMx_CCR2寄存器的预装载功能
//若(__CHANNEL__)=TIM_CHANNEL_3,则将"TIMx捕获/比较模式寄存器2(TIMx_CCMR2)"中的OC3PE位置1,开启TIMx_CCR3寄存器的预装载功能
//若(__CHANNEL__)=TIM_CHANNEL_4,则将"TIMx捕获/比较模式寄存器2(TIMx_CCMR2)"中的OC4PE位置1,开启TIMx_CCR4寄存器的预装载功能

#define _HAL_TIM_DISABLE_OCxPRELOAD(__INSTANCE__, __CHANNEL__)    \
  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__INSTANCE__)->CCMR1 &= ~TIM_CCMR1_OC1PE) :\
   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__INSTANCE__)->CCMR1 &= ~TIM_CCMR1_OC2PE) :\
   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__INSTANCE__)->CCMR2 &= ~TIM_CCMR2_OC3PE) :\
   ((__INSTANCE__)->CCMR2 &= ~TIM_CCMR2_OC4PE))
//禁止TIMx_CCRy寄存器的预装载功能
//若(__CHANNEL__)=TIM_CHANNEL_1,则将"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的OC1PE位置0,禁止TIMx_CCR1寄存器的预装载功能
//若(__CHANNEL__)=TIM_CHANNEL_2,则将"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的OC2PE位置0,禁止TIMx_CCR2寄存器的预装载功能
//若(__CHANNEL__)=TIM_CHANNEL_3,则将"TIMx捕获/比较模式寄存器2(TIMx_CCMR2)"中的OC3PE位置0,禁止TIMx_CCR3寄存器的预装载功能
//若(__CHANNEL__)=TIM_CHANNEL_4,则将"TIMx捕获/比较模式寄存器2(TIMx_CCMR2)"中的OC4PE位置0,禁止TIMx_CCR4寄存器的预装载功能

#define _HAL_TIM_ENABLE_OCxFAST(__INSTANCE__, __CHANNEL__)    \
  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__INSTANCE__)->CCMR1 |= TIM_CCMR1_OC1FE) :\
   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__INSTANCE__)->CCMR1 |= TIM_CCMR1_OC2FE) :\
   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__INSTANCE__)->CCMR2 |= TIM_CCMR2_OC3FE) :\
   ((__INSTANCE__)->CCMR2 |= TIM_CCMR2_OC4FE))
//开启"比较x快速输出"功能,加快CCx输出对触发器x输入事件的响应
//若(__CHANNEL__)=TIM_CHANNEL_1,则将"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的OC1FE位置1,开启"比较1快速输出"功能
//若(__CHANNEL__)=TIM_CHANNEL_2,则将"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的OC2FE位置1,开启"比较2快速输出"功能
//若(__CHANNEL__)=TIM_CHANNEL_3,则将"TIMx捕获/比较模式寄存器2(TIMx_CCMR2)"中的OC3FE位置1,开启"比较3快速输出"功能
//若(__CHANNEL__)=TIM_CHANNEL_4,则将"TIMx捕获/比较模式寄存器2(TIMx_CCMR2)"中的OC4FE位置1,开启"比较4快速输出"功能

#define _HAL_TIM_DISABLE_OCxFAST(__INSTANCE__, __CHANNEL__)    \
  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__INSTANCE__)->CCMR1 &= ~TIM_CCMR1_OC1FE) :\
   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__INSTANCE__)->CCMR1 &= ~TIM_CCMR1_OC2FE) :\
   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__INSTANCE__)->CCMR2 &= ~TIM_CCMR2_OC3FE) :\
   ((__INSTANCE__)->CCMR2 &= ~TIM_CCMR2_OC4FE))
//禁止"比较x快速输出"功能,不用加快CC输出对触发器输入事件的响应
//若(__CHANNEL__)=TIM_CHANNEL_1,则将"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的OC1FE位置0,禁止"比较1快速输出"功能
//若(__CHANNEL__)=TIM_CHANNEL_2,则将"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的OC2FE位置0,禁止"比较2快速输出"功能
//若(__CHANNEL__)=TIM_CHANNEL_3,则将"TIMx捕获/比较模式寄存器2(TIMx_CCMR2)"中的OC3FE位置0,禁止"比较3快速输出"功能
//若(__CHANNEL__)=TIM_CHANNEL_4,则将"TIMx捕获/比较模式寄存器2(TIMx_CCMR2)"中的OC4FE位置0,禁止"比较4快速输出"功能

#define _HAL_TIM_URS_ENABLE(__INSTANCE__)  ((__INSTANCE__)->CR1|= TIM_CR1_URS)
//将"TIMx控制寄存器1(TIM1_CR1)"中的URS位置1
//允许在"计数器溢出/下溢"时,产生一个更新中断或DMA请求;

#define _HAL_TIM_URS_DISABLE(__INSTANCE__)  ((__INSTANCE__)->CR1&=~TIM_CR1_URS)
//将"TIMx控制寄存器1(TIM1_CR1)"中的URS位置0
//允许在"计数器溢出/下溢"时,产生一个更新中断或DMA请求;
//允许在"TIMx_EGR中的UG位置1"时,产生一个更新中断或DMA请求;
//允许在"从模式控制器产生更新"时,产生一个更新中断或DMA请求;



#define _HAL_TIM_SET_ICPRESCALER(__INSTANCE__, __CHANNEL__, __ICPSC__) \
  do{                                                    \
    TIMx_RESET_ICPRESCALERVALUE((__INSTANCE__), (__CHANNEL__));  \
    TIMx_SET_ICPRESCALERVALUE((__INSTANCE__), (__CHANNEL__), (__ICPSC__)); \
  } while(0)
//使用(__ICPSC__)设置通道为(__CHANNEL__)的"输入捕获预分频器"的值
//设置"输入捕获模式,Input Capture mode"
//如果(__CHANNEL__)为TIM_CHANNEL_1,则清除"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的输入/捕获1预分频器C1PSC[1:0]
//如果(__CHANNEL__)为TIM_CHANNEL_2,则清除"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的输入/捕获2预分频器C2PSC[1:0]
//如果(__CHANNEL__)为TIM_CHANNEL_3,则清除"TIMx捕获/比较模式寄存器1(TIMx_CCMR2)"中的输入/捕获3预分频器C3PSC[1:0]
//设置"输入捕获模式,Input Capture mode"
//若(__CHANNEL__)=TIM_CHANNEL_1,则用(__ICPSC__)设置"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的输入/捕获1预分频器C1PSC[1:0]
//若(__CHANNEL__)=TIM_CHANNEL_2,则(__ICPSC__)设置"TIMx捕获/比较模式寄存器1(TIMx_CCMR1)"中的输入/捕获2预分频器C2PSC[1:0]
//若(__CHANNEL__)=TIM_CHANNEL_3,则(__ICPSC__)设置"TIMx捕获/比较模式寄存器2(TIMx_CCMR2)"中的输入/捕获3预分频器C3PSC[1:0]

#define TIMx_RESET_CAPTUREPOLARITY(__INSTANCE__, __CHANNEL__) \
  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__INSTANCE__)->CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP)) :\
   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__INSTANCE__)->CCER &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP)) :\
   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__INSTANCE__)->CCER &= ~(TIM_CCER_CC3P | TIM_CCER_CC3NP)) :\
   ((__INSTANCE__)->CCER &= ~(TIM_CCER_CC4P | TIM_CCER_CC4NP)))
//设置"输入/捕获x的输出极性"
//TIMx捕获/比较使能寄存器(TIMx_CCER)
//当(__CHANNEL__)=TIM_CHANNEL_1,(__POLARITY__)=TIM_CCER_CC1P时,令CC1P=0;CC1P=0表示"输入/捕获1输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_1,(__POLARITY__)=TIM_CCER_CC1NP时,令CC1NP=0;CC1NP=0表示"输入/捕获1互补输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_2,(__POLARITY__)=TIM_CCER_CC2P时,令CC2P=0;CC2P=0表示"输入/捕获2输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_2,(__POLARITY__)=TIM_CCER_CC2NP时,令CC2NP=0;CC2NP=0表示"输入/捕获2互补输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_3,(__POLARITY__)=TIM_CCER_CC3P时,令CC3P=0;CC3P=0表示"输入/捕获3输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_3,(__POLARITY__)=TIM_CCER_CC3NP时,令CC3NP=0;CC3NP=0表示"输入/捕获3互补输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_4,(__POLARITY__)=TIM_CCER_CC4P时,令CC4P=0;CC4P=0表示"输入/捕获4输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_4,(__POLARITY__)=TIM_CCER_CC4NP时,令CC4NP=0;CC4NP=0表示"输入/捕获4互补输出极性"为高电平有效,否则为低电平有效

#define TIMx_SET_CAPTUREPOLARITY(__INSTANCE__, __CHANNEL__, __POLARITY__) \
  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__INSTANCE__)->CCER |= (__POLARITY__)) :\
   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__INSTANCE__)->CCER |= ((__POLARITY__) << 4U)) :\
   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__INSTANCE__)->CCER |= ((__POLARITY__) << 8U)) :\
   ((__INSTANCE__)->CCER |= (((__POLARITY__) << 12U))))
//设置"输入/捕获x的输出极性"
//TIMx捕获/比较使能寄存器(TIMx_CCER)
//当(__CHANNEL__)=TIM_CHANNEL_1,(__POLARITY__)=TIM_CCER_CC1P时,令CC1P=1;CC1P=0表示"输入/捕获1输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_1,(__POLARITY__)=TIM_CCER_CC1NP时,令CC1NP=1;CC1NP=0表示"输入/捕获1互补输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_2,(__POLARITY__)=TIM_CCER_CC2P时,令CC2P=1;CC2P=0表示"输入/捕获2输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_2,(__POLARITY__)=TIM_CCER_CC2NP时,令CC2NP=1;CC2NP=0表示"输入/捕获2互补输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_3,(__POLARITY__)=TIM_CCER_CC3P时,令CC3P=1;CC3P=0表示"输入/捕获3输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_3,(__POLARITY__)=TIM_CCER_CC3NP时,令CC3NP=1;CC3NP=0表示"输入/捕获3互补输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_4,(__POLARITY__)=TIM_CCER_CC4P时,令CC4P=1;CC4P=0表示"输入/捕获4输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_4,(__POLARITY__)=TIM_CCER_CC4NP时,令CC4NP=1;CC4NP=0表示"输入/捕获4互补输出极性"为高电平有效,否则为低电平有效

#define _HAL_TIM_SET_CAPTUREPOLARITY(__INSTANCE__, __CHANNEL__, __POLARITY__)    \
  do{                                                                     \
    TIMx_RESET_CAPTUREPOLARITY((__INSTANCE__), (__CHANNEL__));               \
    TIMx_SET_CAPTUREPOLARITY((__INSTANCE__), (__CHANNEL__), (__POLARITY__)); \
  }while(0)
//设置"输入/捕获x的输出极性"
//TIMx捕获/比较使能寄存器(TIMx_CCER)
//当(__CHANNEL__)=TIM_CHANNEL_1,(__POLARITY__)=TIM_CCER_CC1P时,令CC1P=0;CC1P=0表示"输入/捕获1输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_1,(__POLARITY__)=TIM_CCER_CC1NP时,令CC1NP=0;CC1NP=0表示"输入/捕获1互补输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_2,(__POLARITY__)=TIM_CCER_CC2P时,令CC2P=0;CC2P=0表示"输入/捕获2输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_2,(__POLARITY__)=TIM_CCER_CC2NP时,令CC2NP=0;CC2NP=0表示"输入/捕获2互补输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_3,(__POLARITY__)=TIM_CCER_CC3P时,令CC3P=0;CC3P=0表示"输入/捕获3输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_3,(__POLARITY__)=TIM_CCER_CC3NP时,令CC3NP=0;CC3NP=0表示"输入/捕获3互补输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_4,(__POLARITY__)=TIM_CCER_CC4P时,令CC4P=0;CC4P=0表示"输入/捕获4输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_4,(__POLARITY__)=TIM_CCER_CC4NP时,令CC4NP=0;CC4NP=0表示"输入/捕获4互补输出极性"为高电平有效,否则为低电平有效
//设置"输入/捕获x的输出极性"
//TIMx捕获/比较使能寄存器(TIMx_CCER)
//当(__CHANNEL__)=TIM_CHANNEL_1,(__POLARITY__)=TIM_CCER_CC1P时,令CC1P=1;CC1P=0表示"输入/捕获1输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_1,(__POLARITY__)=TIM_CCER_CC1NP时,令CC1NP=1;CC1NP=0表示"输入/捕获1互补输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_2,(__POLARITY__)=TIM_CCER_CC2P时,令CC2P=1;CC2P=0表示"输入/捕获2输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_2,(__POLARITY__)=TIM_CCER_CC2NP时,令CC2NP=1;CC2NP=0表示"输入/捕获2互补输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_3,(__POLARITY__)=TIM_CCER_CC3P时,令CC3P=1;CC3P=0表示"输入/捕获3输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_3,(__POLARITY__)=TIM_CCER_CC3NP时,令CC3NP=1;CC3NP=0表示"输入/捕获3互补输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_4,(__POLARITY__)=TIM_CCER_CC4P时,令CC4P=1;CC4P=0表示"输入/捕获4输出极性"为高电平有效,否则为低电平有效
//当(__CHANNEL__)=TIM_CHANNEL_4,(__POLARITY__)=TIM_CCER_CC4NP时,令CC4NP=1;CC4NP=0表示"输入/捕获4互补输出极性"为高电平有效,否则为低电平有效	
#endif /* __MyTimer_H */

六、结论

看着很长的代码,很累吧。累就对了,我整理也很累。为了减少TIM使用全局变量,我自己另外添加了类似标准库的用法。

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

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

相关文章

C语言 -- 零基础入门详解

文章目录 引言1. 第一个C语言程序&#xff1a;HelloWorld1.1 编写C语言代码&#xff1a;hello.c1.2 代码分析 2. 数据类型2.1 常量与变量2.1.1 关键字2.1.2 数据类型2.1.3 常量2.1.4 变量2.1.5 使用示例 2.2 整型&#xff1a;int2.2.1 整型变量的定义和输出2.2.2 整型变量的输入…

How to control the model in the webots usingthe ros controller ?

这里写自定义目录标题 how to use controller in Ros to control the model built in the Webots ?section 1: install ubantu 20.04 and webots 2021b ? how to use controller in Ros to control the model built in the Webots ? section 1: install ubantu 20.04 and w…

Ecrett Music:AI音乐创作软件

【产品介绍】 Ecrett Music是一个由人工智能驱动的AI音乐创作软件&#xff0c;可以帮助内容创作者快速、简单、便宜地制作出适合自己的无版权音乐。无论你是做游戏、视频、播客还是其他类型的内容&#xff0c;都可以在Ecrett Music上选择场景、情绪或风格&#xff0c;然后点击一…

算法--冒泡排序

算法步骤 /*** 冒泡排序** version 1.0* date 2023/09/01 15:23:58*/ public class Bubble {/*** 升序冒泡排序** param a 待排序的数组* date 2023/9/1 15:29:10*/public static void sortAes(int[] a) {for (int i a.length - 1; i > 0; i--) {for (int j 0; j < i;…

redis集群hashTag简述

概述 单体redis一般性能可以满足大部分场景的要求了&#xff0c;但是当业务体量起来的时候&#xff0c;就会要求高可用了。 此时一般会将单机redis扩充至集群,一般3主3从 redis集群中master之间各自存储部分数据&#xff0c;master和slave之间数据则是相同的. Redis会把每一…

Cocos独立游戏开发框架(18):配置管理器

引言 本系列是《8年主程手把手打造Cocos独立游戏开发框架》&#xff0c;欢迎大家关注分享收藏订阅。 在游戏开发中&#xff0c;配置是一个重要的角色&#xff0c;他常常由策划去驱动&#xff0c;调整和优化&#xff0c;使得游戏的难度和设定更加符合玩家们的体验&#xff0c;…

如果回到5年前,20几岁的时候,想对过去的自己说点什么

今天跟大家聊一聊,如果回到5年前,10年前,怎么看待当年的自己 与此同时,对于未来3到5年,又有一个什么样的期待,自言自语几句的 对于未来,真的没有办法去预测,尽管如雷军鸡汤里的,永远要相信,美好的事情即将发生,但是不可否认的是,你永远也不知道惊喜和意外哪个先到 但是对于已经…

高级IO-epoll

文章目录 1. I/O多路转接之poll1.1 代码样例1.2 poll优缺点 2. I/O多路转接之epoll2.1 epoll的相关系统调用 3. epoll工作原理3.1 epoll的优点 4. 代码样例4.1 初始化服务器4.2 启动服务器 5. epoll工作方式6. epoll的使用场景 1. I/O多路转接之poll poll函数解决了&#xff0…

delphi 自带的dbgrid表格控件增加下选框

在表格里用combobox很正常 自带的dbgrid加也很方便&#xff0c;环境是xe10 procedure TfrmBaseInfo.LoadDesk; varssql: string;i: Integer;column: TColumn; beginssql : select * from desk_info ;qry_desk.Connection : dmMain.FDConnection1;qry_desk.Close;qry_desk.S…

机器视觉之Basler工业相机使用和配置方法(C++)

basler工业相机做双目视觉用&#xff0c;出现很多问题记录一下&#xff1a; 首先是多看手册&#xff1a;https://zh.docs.baslerweb.com/software 手册内有所有的源码和参考示例&#xff0c;实际上在使用过程中&#xff0c;大部分都是这些源码&#xff0c;具体项目选择对应的…

java实现克里金插值导出geojson矢量数据(kriging)

生成效果 在现代科学研究中&#xff0c;数据的处理和分析是至关重要的一环。然而&#xff0c;我们往往会遇到数据缺失的情况&#xff0c;这时就需要使用插值方法来填补这些缺失值。其中&#xff0c;克里金插值法是一种常用的方法&#xff0c;在很多领域都有广泛的应用。 首先&…

RK3568开发笔记(九):开发板buildroot固件调通RS485口,运行项目中RS485协议调试工具Demo

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/132869448 红胖子网络科技博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬…

【剑指Offer】52.两个链表的第一个公共节点

题目 输入两个链表&#xff0c;找出它们的第一个公共节点。 如下面的两个链表&#xff1a; 在节点 c1 开始相交。 示例 1&#xff1a; 输入&#xff1a;intersectVal 8, listA [4,1,8,4,5], listB [5,0,1,8,4,5], skipA 2, skipB 3 输出&#xff1a;Reference of the n…

【Linux】网络编程套接字(C++)

目录 一、预备知识 【1.1】理解源IP地址和目的IP地址 【1.2】认识端口号 【1.3】理解 "端口号" 和 "进程ID" 【1.4】理解源端口号和目的端口号 【1.5】认识TCP协议 【1.6】认识UDP协议 二、网络字节序 【2.1】socket编程接口 【2.1.1】socket AP…

5款实用的Redis可视化工具

Redis可视化工具是一种用于管理和监视Redis数据库的工具&#xff0c;它提供了一个可视化界面来操作和查看Redis的数据和配置信息&#xff0c; 可以让我们更加直观地管理和操作Redis数据库。下面介绍四款比较不错的Redis可视化工具。 1.Redis可视化工具推荐—RedisInsight Red…

美创科技入选第二届安徽省网络和数据安全应急技术支撑单位

9月11日&#xff0c;2023年安徽省网络安全宣传周活动在阜阳市正式启动。安徽省委常委、宣传部部长陈舜出席并宣布网安周正式启动。阜阳市委书记刘玉杰、省委宣传部副部长、省委网信办主任张杰华出席并致辞。 开幕式上&#xff0c;省委网信办副主任齐海洋发布第二届安徽省网络和…

Template serialization - shared_ptr<class T>

下面包含的所有代码片段都在 boost::serialization 命名空间内定义。 shared_ptr < T > 在 shared_ptr.hpp 中定义。 shared_ptr 的一般类轮廓如下&#xff1a; shared_ptr 包括以下成员&#xff1a; T *px;shared_count pn;&#xff0c;其中包含指向&#xff1a; sp_c…

(二十七)大数据实战——hbase高可用集群安装与部署

前言 本节内容我们主要介绍HBase高可用集群的安装部署。HBase是一个开源的分布式非关系型数据库管理系统&#xff08;NoSQL&#xff09;&#xff0c;它运行在Apache Hadoop之上。它基于Google的Bigtable论文设计&#xff0c;并且具有高扩展性、高可靠性和高性能的特点。HBase通…

Python 04 之变量【列表,元组,集合,字典,字符串】

&#x1f600;前言 在Python编程语言中&#xff0c;我们经常会遇到各种数据类型和相应的操作方法。理解和掌握这些基本构造是进行有效编程的前提。在本文中&#xff0c;我们将介绍两种非常重要的数据结构 - 集合和字典&#xff0c;然后我们将深入探讨字符串及其相关的操作和处理…

父域 Cookie实现sso单点登录

单点登录&#xff08;Single Sign On, SSO&#xff09;是指在同一帐号平台下的多个应用系统中&#xff0c;用户只需登录一次&#xff0c;即可访问所有相互信任的应用系统。Cookie 的作用域由 domain 属性和 path 属性共同决定。在 Tomcat 中&#xff0c;domain 属性默认为当前域…