欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 幼教 > STM32:TIM中断配置应用(1)呼吸灯:库函数讲解笔记+代码讲解笔记

STM32:TIM中断配置应用(1)呼吸灯:库函数讲解笔记+代码讲解笔记

2025/2/23 14:50:15 来源:https://blog.csdn.net/bc202205/article/details/141785839  浏览:    关键词:STM32:TIM中断配置应用(1)呼吸灯:库函数讲解笔记+代码讲解笔记

        声明:本博客为哔哩哔哩up主@江协科技 “STM32入门教程”的听课笔记,仅供学习、参考使用,不得用作其他用途,违者必究。如有版权问题,请联系作者修改。

目录

一、综述

二、TIM库(有关输出比较的函数)

2.1、TIM_OCxInit 输出比较模块配置*

2.2、TIM_CtrlPWMOutputs 高级定时器使能主输出

2.3、TIM_OCStructInit 输出比较结构体赋默认值

2.4、TIM_ForcedOCxConfig 配置强制输出模式

2.5、TIM_OCxPreloadConfig 配置CCR寄存器预装功能

2.6、TIM_OCxFastConfig 配置快速使能

2.7、TIM_ClearOCxRef 外部事件时清除REF信号

2.8、TIM_OCxPolarityConfig && 

        TIM_OCxNPolarityConfig 设置输出比较的极性

2.9、TIM_CCxCmd && TIM_CCxNCmd 单独修改输出使能参数的

2.10、TIM_SelectOCxM 选择输出比较模式

2.11、TIM_SetComparex 更改CCR寄存器的值的函数

2.12TIM结构体讲解

2.12.1、TIM_OCMode 输出比较模式

2.12.2、TIM_OCPolarity 输出比较极性

2.12.3、TIM_OutputState 输出比较状态

2.12.4、TIM_Pulse 设置CCR寄存器的值

2.12.5、一个问题

三、呼吸灯完整代码

3.1、PWM.h

3.2、PWM.c

3.2.1、具体步骤

3.2.2、完整代码

3.3、main.c

四、引脚重映射到PA15端口

4.1、映射讲解

4.2、完整代码

4.2.1、PWM.h

4.2.2、PWM.c

4.2.3、main.c


一、综述

        具体步骤:

        第一步:RCC开启时钟,将我们要用的TIM外设和GPIO外设的时钟打开;

        第二步:配置时基单元,包括前面的时钟源选择和这里的时基单元 都配置好;

        第三步:配置输出比较单元,包括CCR的值、输出比较模式、极性选择、输出使能等参数;

        第四步:配置GPIO,把PWM对应的GPIO抠,初始化为复用推挽输出的配置;

        第五步:运行控制,启动计数器,这样就能输出PWM了。

二、TIM库(有关输出比较的函数)

2.1、TIM_OCxInit 输出比较模块配置*

        函数原型:

void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

        函数讲解:这四个函数是用来配置输出比较模块的。OC即OutputCompare。第一个参数:选择定时器;第二个参数:结构体,配置输出比较的参数。

        函数定义

/*** @brief  Initializes the TIMx Channel1 according to the specified*         parameters in the TIM_OCInitStruct.* @param  TIMx: where x can be  1 to 17 except 6 and 7 to select the TIM peripheral.* @param  TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure*         that contains the configuration information for the specified TIM peripheral.* @retval None*/
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
{uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;/* Check the parameters */assert_param(IS_TIM_LIST8_PERIPH(TIMx));assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode));assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState));assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity));   /* Disable the Channel 1: Reset the CC1E Bit */TIMx->CCER &= (uint16_t)(~(uint16_t)TIM_CCER_CC1E);/* Get the TIMx CCER register value */tmpccer = TIMx->CCER;/* Get the TIMx CR2 register value */tmpcr2 =  TIMx->CR2;/* Get the TIMx CCMR1 register value */tmpccmrx = TIMx->CCMR1;/* Reset the Output Compare Mode Bits */tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_OC1M));tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_CC1S));/* Select the Output Compare Mode */tmpccmrx |= TIM_OCInitStruct->TIM_OCMode;/* Reset the Output Polarity level */tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC1P));/* Set the Output Compare Polarity */tmpccer |= TIM_OCInitStruct->TIM_OCPolarity;/* Set the Output State */tmpccer |= TIM_OCInitStruct->TIM_OutputState;if((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM15)||(TIMx == TIM16)|| (TIMx == TIM17)){assert_param(IS_TIM_OUTPUTN_STATE(TIM_OCInitStruct->TIM_OutputNState));assert_param(IS_TIM_OCN_POLARITY(TIM_OCInitStruct->TIM_OCNPolarity));assert_param(IS_TIM_OCNIDLE_STATE(TIM_OCInitStruct->TIM_OCNIdleState));assert_param(IS_TIM_OCIDLE_STATE(TIM_OCInitStruct->TIM_OCIdleState));/* Reset the Output N Polarity level */tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC1NP));/* Set the Output N Polarity */tmpccer |= TIM_OCInitStruct->TIM_OCNPolarity;/* Reset the Output N State */tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC1NE));    /* Set the Output N State */tmpccer |= TIM_OCInitStruct->TIM_OutputNState;/* Reset the Output Compare and Output Compare N IDLE State */tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS1));tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS1N));/* Set the Output Idle state */tmpcr2 |= TIM_OCInitStruct->TIM_OCIdleState;/* Set the Output N Idle state */tmpcr2 |= TIM_OCInitStruct->TIM_OCNIdleState;}/* Write to TIMx CR2 */TIMx->CR2 = tmpcr2;/* Write to TIMx CCMR1 */TIMx->CCMR1 = tmpccmrx;/* Set the Capture Compare Register value */TIMx->CCR1 = TIM_OCInitStruct->TIM_Pulse; /* Write to TIMx CCER */TIMx->CCER = tmpccer;
}/*** @brief  Initializes the TIMx Channel2 according to the specified*         parameters in the TIM_OCInitStruct.* @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15 to select *         the TIM peripheral.* @param  TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure*         that contains the configuration information for the specified TIM peripheral.* @retval None*/
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
{uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;/* Check the parameters */assert_param(IS_TIM_LIST6_PERIPH(TIMx)); assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode));assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState));assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity));   /* Disable the Channel 2: Reset the CC2E Bit */TIMx->CCER &= (uint16_t)(~((uint16_t)TIM_CCER_CC2E));/* Get the TIMx CCER register value */  tmpccer = TIMx->CCER;/* Get the TIMx CR2 register value */tmpcr2 =  TIMx->CR2;/* Get the TIMx CCMR1 register value */tmpccmrx = TIMx->CCMR1;/* Reset the Output Compare mode and Capture/Compare selection Bits */tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_OC2M));tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_CC2S));/* Select the Output Compare Mode */tmpccmrx |= (uint16_t)(TIM_OCInitStruct->TIM_OCMode << 8);/* Reset the Output Polarity level */tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC2P));/* Set the Output Compare Polarity */tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCPolarity << 4);/* Set the Output State */tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputState << 4);if((TIMx == TIM1) || (TIMx == TIM8)){assert_param(IS_TIM_OUTPUTN_STATE(TIM_OCInitStruct->TIM_OutputNState));assert_param(IS_TIM_OCN_POLARITY(TIM_OCInitStruct->TIM_OCNPolarity));assert_param(IS_TIM_OCNIDLE_STATE(TIM_OCInitStruct->TIM_OCNIdleState));assert_param(IS_TIM_OCIDLE_STATE(TIM_OCInitStruct->TIM_OCIdleState));/* Reset the Output N Polarity level */tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC2NP));/* Set the Output N Polarity */tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCNPolarity << 4);/* Reset the Output N State */tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC2NE));    /* Set the Output N State */tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputNState << 4);/* Reset the Output Compare and Output Compare N IDLE State */tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS2));tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS2N));/* Set the Output Idle state */tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCIdleState << 2);/* Set the Output N Idle state */tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCNIdleState << 2);}/* Write to TIMx CR2 */TIMx->CR2 = tmpcr2;/* Write to TIMx CCMR1 */TIMx->CCMR1 = tmpccmrx;/* Set the Capture Compare Register value */TIMx->CCR2 = TIM_OCInitStruct->TIM_Pulse;/* Write to TIMx CCER */TIMx->CCER = tmpccer;
}/*** @brief  Initializes the TIMx Channel3 according to the specified*         parameters in the TIM_OCInitStruct.* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure*         that contains the configuration information for the specified TIM peripheral.* @retval None*/
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
{uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx)); assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode));assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState));assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity));   /* Disable the Channel 2: Reset the CC2E Bit */TIMx->CCER &= (uint16_t)(~((uint16_t)TIM_CCER_CC3E));/* Get the TIMx CCER register value */tmpccer = TIMx->CCER;/* Get the TIMx CR2 register value */tmpcr2 =  TIMx->CR2;/* Get the TIMx CCMR2 register value */tmpccmrx = TIMx->CCMR2;/* Reset the Output Compare mode and Capture/Compare selection Bits */tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_OC3M));tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_CC3S));  /* Select the Output Compare Mode */tmpccmrx |= TIM_OCInitStruct->TIM_OCMode;/* Reset the Output Polarity level */tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC3P));/* Set the Output Compare Polarity */tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCPolarity << 8);/* Set the Output State */tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputState << 8);if((TIMx == TIM1) || (TIMx == TIM8)){assert_param(IS_TIM_OUTPUTN_STATE(TIM_OCInitStruct->TIM_OutputNState));assert_param(IS_TIM_OCN_POLARITY(TIM_OCInitStruct->TIM_OCNPolarity));assert_param(IS_TIM_OCNIDLE_STATE(TIM_OCInitStruct->TIM_OCNIdleState));assert_param(IS_TIM_OCIDLE_STATE(TIM_OCInitStruct->TIM_OCIdleState));/* Reset the Output N Polarity level */tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC3NP));/* Set the Output N Polarity */tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCNPolarity << 8);/* Reset the Output N State */tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC3NE));/* Set the Output N State */tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputNState << 8);/* Reset the Output Compare and Output Compare N IDLE State */tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS3));tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS3N));/* Set the Output Idle state */tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCIdleState << 4);/* Set the Output N Idle state */tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCNIdleState << 4);}/* Write to TIMx CR2 */TIMx->CR2 = tmpcr2;/* Write to TIMx CCMR2 */TIMx->CCMR2 = tmpccmrx;/* Set the Capture Compare Register value */TIMx->CCR3 = TIM_OCInitStruct->TIM_Pulse;/* Write to TIMx CCER */TIMx->CCER = tmpccer;
}/*** @brief  Initializes the TIMx Channel4 according to the specified*         parameters in the TIM_OCInitStruct.* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure*         that contains the configuration information for the specified TIM peripheral.* @retval None*/
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
{uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx)); assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode));assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState));assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity));   /* Disable the Channel 2: Reset the CC4E Bit */TIMx->CCER &= (uint16_t)(~((uint16_t)TIM_CCER_CC4E));/* Get the TIMx CCER register value */tmpccer = TIMx->CCER;/* Get the TIMx CR2 register value */tmpcr2 =  TIMx->CR2;/* Get the TIMx CCMR2 register value */tmpccmrx = TIMx->CCMR2;/* Reset the Output Compare mode and Capture/Compare selection Bits */tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_OC4M));tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_CC4S));/* Select the Output Compare Mode */tmpccmrx |= (uint16_t)(TIM_OCInitStruct->TIM_OCMode << 8);/* Reset the Output Polarity level */tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC4P));/* Set the Output Compare Polarity */tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCPolarity << 12);/* Set the Output State */tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputState << 12);if((TIMx == TIM1) || (TIMx == TIM8)){assert_param(IS_TIM_OCIDLE_STATE(TIM_OCInitStruct->TIM_OCIdleState));/* Reset the Output Compare IDLE State */tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS4));/* Set the Output Idle state */tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCIdleState << 6);}/* Write to TIMx CR2 */TIMx->CR2 = tmpcr2;/* Write to TIMx CCMR2 */  TIMx->CCMR2 = tmpccmrx;/* Set the Capture Compare Register value */TIMx->CCR4 = TIM_OCInitStruct->TIM_Pulse;/* Write to TIMx CCER */TIMx->CCER = tmpccer;
}

2.2、TIM_CtrlPWMOutputs 高级定时器使能主输出

        函数原型:void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);

        函数讲解使能高级定时器的PWM波形输出的函数。仅高级定时器使用,在使用高级定时器输出PWM时需要调用这个函数,使能主输出,否则PWM将不能正常输出。

        函数定义

/*** @brief  Enables or disables the TIM peripheral Main Outputs.* @param  TIMx: where x can be 1, 8, 15, 16 or 17 to select the TIMx peripheral.* @param  NewState: new state of the TIM peripheral Main Outputs.*   This parameter can be: ENABLE or DISABLE.* @retval None*/
void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState)
{/* Check the parameters */assert_param(IS_TIM_LIST2_PERIPH(TIMx));assert_param(IS_FUNCTIONAL_STATE(NewState));if (NewState != DISABLE){/* Enable the TIM Main Output */TIMx->BDTR |= TIM_BDTR_MOE;}else{/* Disable the TIM Main Output */TIMx->BDTR &= (uint16_t)(~((uint16_t)TIM_BDTR_MOE));}  
}

2.3、TIM_OCStructInit 输出比较结构体赋默认值

        函数原型:void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);

        函数讲解:这个函数是用来给输出比较结构体赋默认值的。

        函数定义

/*** @brief  Fills each TIM_OCInitStruct member with its default value.* @param  TIM_OCInitStruct : pointer to a TIM_OCInitTypeDef structure which will*         be initialized.* @retval None*/
void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct)
{/* Set the default configuration */TIM_OCInitStruct->TIM_OCMode = TIM_OCMode_Timing;TIM_OCInitStruct->TIM_OutputState = TIM_OutputState_Disable;TIM_OCInitStruct->TIM_OutputNState = TIM_OutputNState_Disable;TIM_OCInitStruct->TIM_Pulse = 0x0000;TIM_OCInitStruct->TIM_OCPolarity = TIM_OCPolarity_High;TIM_OCInitStruct->TIM_OCNPolarity = TIM_OCPolarity_High;TIM_OCInitStruct->TIM_OCIdleState = TIM_OCIdleState_Reset;TIM_OCInitStruct->TIM_OCNIdleState = TIM_OCNIdleState_Reset;
}

2.4、TIM_ForcedOCxConfig 配置强制输出模式

        函数原型

void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

        函数讲解:这四个函数是用来配置强制输出模式的。如果你在运行中想要暂停输出波形并强制输出高电平或低电平,可以使用这个函数。

        但是这四个函数用得不多,因为强制输出高电平和设置占空比100%是一样的,强制输出低电平和设置占空比0%是一样的。

        函数定义

/*** @brief  Forces the TIMx output 1 waveform to active or inactive level.* @param  TIMx: where x can be  1 to 17 except 6 and 7 to select the TIM peripheral.* @param  TIM_ForcedAction: specifies the forced Action to be set to the output waveform.*   This parameter can be one of the following values:*     @arg TIM_ForcedAction_Active: Force active level on OC1REF*     @arg TIM_ForcedAction_InActive: Force inactive level on OC1REF.* @retval None*/
void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction)
{uint16_t tmpccmr1 = 0;/* Check the parameters */assert_param(IS_TIM_LIST8_PERIPH(TIMx));assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction));tmpccmr1 = TIMx->CCMR1;/* Reset the OC1M Bits */tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1M);/* Configure The Forced output Mode */tmpccmr1 |= TIM_ForcedAction;/* Write to TIMx CCMR1 register */TIMx->CCMR1 = tmpccmr1;
}/*** @brief  Forces the TIMx output 2 waveform to active or inactive level.* @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.* @param  TIM_ForcedAction: specifies the forced Action to be set to the output waveform.*   This parameter can be one of the following values:*     @arg TIM_ForcedAction_Active: Force active level on OC2REF*     @arg TIM_ForcedAction_InActive: Force inactive level on OC2REF.* @retval None*/
void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction)
{uint16_t tmpccmr1 = 0;/* Check the parameters */assert_param(IS_TIM_LIST6_PERIPH(TIMx));assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction));tmpccmr1 = TIMx->CCMR1;/* Reset the OC2M Bits */tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2M);/* Configure The Forced output Mode */tmpccmr1 |= (uint16_t)(TIM_ForcedAction << 8);/* Write to TIMx CCMR1 register */TIMx->CCMR1 = tmpccmr1;
}/*** @brief  Forces the TIMx output 3 waveform to active or inactive level.* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_ForcedAction: specifies the forced Action to be set to the output waveform.*   This parameter can be one of the following values:*     @arg TIM_ForcedAction_Active: Force active level on OC3REF*     @arg TIM_ForcedAction_InActive: Force inactive level on OC3REF.* @retval None*/
void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction)
{uint16_t tmpccmr2 = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction));tmpccmr2 = TIMx->CCMR2;/* Reset the OC1M Bits */tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3M);/* Configure The Forced output Mode */tmpccmr2 |= TIM_ForcedAction;/* Write to TIMx CCMR2 register */TIMx->CCMR2 = tmpccmr2;
}/*** @brief  Forces the TIMx output 4 waveform to active or inactive level.* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_ForcedAction: specifies the forced Action to be set to the output waveform.*   This parameter can be one of the following values:*     @arg TIM_ForcedAction_Active: Force active level on OC4REF*     @arg TIM_ForcedAction_InActive: Force inactive level on OC4REF.* @retval None*/
void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction)
{uint16_t tmpccmr2 = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction));tmpccmr2 = TIMx->CCMR2;/* Reset the OC2M Bits */tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4M);/* Configure The Forced output Mode */tmpccmr2 |= (uint16_t)(TIM_ForcedAction << 8);/* Write to TIMx CCMR2 register */TIMx->CCMR2 = tmpccmr2;
}

2.5、TIM_OCxPreloadConfig 配置CCR寄存器预装功能

        函数原型

void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

        函数讲解:这四个函数是用来配置CCR寄存器的预装功能的。预装功能就是影子寄存器,即写入的值不会立即生效,而是在更新时间才会生效,这样可以避免一些小问题。

        函数定义

/*** @brief  Enables or disables the TIMx peripheral Preload register on CCR1.* @param  TIMx: where x can be  1 to 17 except 6 and 7 to select the TIM peripheral.* @param  TIM_OCPreload: new state of the TIMx peripheral Preload register*   This parameter can be one of the following values:*     @arg TIM_OCPreload_Enable*     @arg TIM_OCPreload_Disable* @retval None*/
void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload)
{uint16_t tmpccmr1 = 0;/* Check the parameters */assert_param(IS_TIM_LIST8_PERIPH(TIMx));assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload));tmpccmr1 = TIMx->CCMR1;/* Reset the OC1PE Bit */tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1PE);/* Enable or Disable the Output Compare Preload feature */tmpccmr1 |= TIM_OCPreload;/* Write to TIMx CCMR1 register */TIMx->CCMR1 = tmpccmr1;
}/*** @brief  Enables or disables the TIMx peripheral Preload register on CCR2.* @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15 to select *         the TIM peripheral.* @param  TIM_OCPreload: new state of the TIMx peripheral Preload register*   This parameter can be one of the following values:*     @arg TIM_OCPreload_Enable*     @arg TIM_OCPreload_Disable* @retval None*/
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload)
{uint16_t tmpccmr1 = 0;/* Check the parameters */assert_param(IS_TIM_LIST6_PERIPH(TIMx));assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload));tmpccmr1 = TIMx->CCMR1;/* Reset the OC2PE Bit */tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2PE);/* Enable or Disable the Output Compare Preload feature */tmpccmr1 |= (uint16_t)(TIM_OCPreload << 8);/* Write to TIMx CCMR1 register */TIMx->CCMR1 = tmpccmr1;
}/*** @brief  Enables or disables the TIMx peripheral Preload register on CCR3.* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_OCPreload: new state of the TIMx peripheral Preload register*   This parameter can be one of the following values:*     @arg TIM_OCPreload_Enable*     @arg TIM_OCPreload_Disable* @retval None*/
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload)
{uint16_t tmpccmr2 = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload));tmpccmr2 = TIMx->CCMR2;/* Reset the OC3PE Bit */tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3PE);/* Enable or Disable the Output Compare Preload feature */tmpccmr2 |= TIM_OCPreload;/* Write to TIMx CCMR2 register */TIMx->CCMR2 = tmpccmr2;
}/*** @brief  Enables or disables the TIMx peripheral Preload register on CCR4.* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_OCPreload: new state of the TIMx peripheral Preload register*   This parameter can be one of the following values:*     @arg TIM_OCPreload_Enable*     @arg TIM_OCPreload_Disable* @retval None*/
void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload)
{uint16_t tmpccmr2 = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload));tmpccmr2 = TIMx->CCMR2;/* Reset the OC4PE Bit */tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4PE);/* Enable or Disable the Output Compare Preload feature */tmpccmr2 |= (uint16_t)(TIM_OCPreload << 8);/* Write to TIMx CCMR2 register */TIMx->CCMR2 = tmpccmr2;
}

2.6、TIM_OCxFastConfig 配置快速使能

        函数原型

void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

        函数讲解:这四个函数是用来配置快速使能的。

        函数定义

/*** @brief  Configures the TIMx Output Compare 1 Fast feature.* @param  TIMx: where x can be  1 to 17 except 6 and 7 to select the TIM peripheral.* @param  TIM_OCFast: new state of the Output Compare Fast Enable Bit.*   This parameter can be one of the following values:*     @arg TIM_OCFast_Enable: TIM output compare fast enable*     @arg TIM_OCFast_Disable: TIM output compare fast disable* @retval None*/
void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast)
{uint16_t tmpccmr1 = 0;/* Check the parameters */assert_param(IS_TIM_LIST8_PERIPH(TIMx));assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast));/* Get the TIMx CCMR1 register value */tmpccmr1 = TIMx->CCMR1;/* Reset the OC1FE Bit */tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1FE);/* Enable or Disable the Output Compare Fast Bit */tmpccmr1 |= TIM_OCFast;/* Write to TIMx CCMR1 */TIMx->CCMR1 = tmpccmr1;
}/*** @brief  Configures the TIMx Output Compare 2 Fast feature.* @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15 to select *         the TIM peripheral.* @param  TIM_OCFast: new state of the Output Compare Fast Enable Bit.*   This parameter can be one of the following values:*     @arg TIM_OCFast_Enable: TIM output compare fast enable*     @arg TIM_OCFast_Disable: TIM output compare fast disable* @retval None*/
void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast)
{uint16_t tmpccmr1 = 0;/* Check the parameters */assert_param(IS_TIM_LIST6_PERIPH(TIMx));assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast));/* Get the TIMx CCMR1 register value */tmpccmr1 = TIMx->CCMR1;/* Reset the OC2FE Bit */tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2FE);/* Enable or Disable the Output Compare Fast Bit */tmpccmr1 |= (uint16_t)(TIM_OCFast << 8);/* Write to TIMx CCMR1 */TIMx->CCMR1 = tmpccmr1;
}/*** @brief  Configures the TIMx Output Compare 3 Fast feature.* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_OCFast: new state of the Output Compare Fast Enable Bit.*   This parameter can be one of the following values:*     @arg TIM_OCFast_Enable: TIM output compare fast enable*     @arg TIM_OCFast_Disable: TIM output compare fast disable* @retval None*/
void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast)
{uint16_t tmpccmr2 = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast));/* Get the TIMx CCMR2 register value */tmpccmr2 = TIMx->CCMR2;/* Reset the OC3FE Bit */tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3FE);/* Enable or Disable the Output Compare Fast Bit */tmpccmr2 |= TIM_OCFast;/* Write to TIMx CCMR2 */TIMx->CCMR2 = tmpccmr2;
}/*** @brief  Configures the TIMx Output Compare 4 Fast feature.* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_OCFast: new state of the Output Compare Fast Enable Bit.*   This parameter can be one of the following values:*     @arg TIM_OCFast_Enable: TIM output compare fast enable*     @arg TIM_OCFast_Disable: TIM output compare fast disable* @retval None*/
void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast)
{uint16_t tmpccmr2 = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast));/* Get the TIMx CCMR2 register value */tmpccmr2 = TIMx->CCMR2;/* Reset the OC4FE Bit */tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4FE);/* Enable or Disable the Output Compare Fast Bit */tmpccmr2 |= (uint16_t)(TIM_OCFast << 8);/* Write to TIMx CCMR2 */TIMx->CCMR2 = tmpccmr2;
}

2.7、TIM_ClearOCxRef 外部事件时清除REF信号

        函数原型

void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);

        函数讲解:这四个函数用于外部事件时清除REF信号

        函数定义

/*** @brief  Clears or safeguards the OCREF1 signal on an external event* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_OCClear: new state of the Output Compare Clear Enable Bit.*   This parameter can be one of the following values:*     @arg TIM_OCClear_Enable: TIM Output clear enable*     @arg TIM_OCClear_Disable: TIM Output clear disable* @retval None*/
void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear)
{uint16_t tmpccmr1 = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear));tmpccmr1 = TIMx->CCMR1;/* Reset the OC1CE Bit */tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1CE);/* Enable or Disable the Output Compare Clear Bit */tmpccmr1 |= TIM_OCClear;/* Write to TIMx CCMR1 register */TIMx->CCMR1 = tmpccmr1;
}/*** @brief  Clears or safeguards the OCREF2 signal on an external event* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_OCClear: new state of the Output Compare Clear Enable Bit.*   This parameter can be one of the following values:*     @arg TIM_OCClear_Enable: TIM Output clear enable*     @arg TIM_OCClear_Disable: TIM Output clear disable* @retval None*/
void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear)
{uint16_t tmpccmr1 = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear));tmpccmr1 = TIMx->CCMR1;/* Reset the OC2CE Bit */tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2CE);/* Enable or Disable the Output Compare Clear Bit */tmpccmr1 |= (uint16_t)(TIM_OCClear << 8);/* Write to TIMx CCMR1 register */TIMx->CCMR1 = tmpccmr1;
}/*** @brief  Clears or safeguards the OCREF3 signal on an external event* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_OCClear: new state of the Output Compare Clear Enable Bit.*   This parameter can be one of the following values:*     @arg TIM_OCClear_Enable: TIM Output clear enable*     @arg TIM_OCClear_Disable: TIM Output clear disable* @retval None*/
void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear)
{uint16_t tmpccmr2 = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear));tmpccmr2 = TIMx->CCMR2;/* Reset the OC3CE Bit */tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3CE);/* Enable or Disable the Output Compare Clear Bit */tmpccmr2 |= TIM_OCClear;/* Write to TIMx CCMR2 register */TIMx->CCMR2 = tmpccmr2;
}/*** @brief  Clears or safeguards the OCREF4 signal on an external event* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_OCClear: new state of the Output Compare Clear Enable Bit.*   This parameter can be one of the following values:*     @arg TIM_OCClear_Enable: TIM Output clear enable*     @arg TIM_OCClear_Disable: TIM Output clear disable* @retval None*/
void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear)
{uint16_t tmpccmr2 = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear));tmpccmr2 = TIMx->CCMR2;/* Reset the OC4CE Bit */tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4CE);/* Enable or Disable the Output Compare Clear Bit */tmpccmr2 |= (uint16_t)(TIM_OCClear << 8);/* Write to TIMx CCMR2 register */TIMx->CCMR2 = tmpccmr2;
}

2.8、TIM_OCxPolarityConfig && 

        TIM_OCxNPolarityConfig 设置输出比较的极性

        函数原型

void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

        函数讲解:这七个函数是用来设置输出比较的极性的,其中TIM_OCxPolarityConfig 和 TIM_OCxNPolarityConfig 互为互补通道,OC4没有互补通道

        此处设置极性和结构体初始化时设置极性的作用是一样的,只不过是用结构体时,是一起初始化的,在这里是一个单独的函数进行修改的。

        一般来说,结构体里的参数,都会有一个单独的函数可以进行更改。这里的函数就是用来单独更改输出极性的。

        函数定义

/*** @brief  Configures the TIMx channel 1 polarity.* @param  TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.* @param  TIM_OCPolarity: specifies the OC1 Polarity*   This parameter can be one of the following values:*     @arg TIM_OCPolarity_High: Output Compare active high*     @arg TIM_OCPolarity_Low: Output Compare active low* @retval None*/
void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)
{uint16_t tmpccer = 0;/* Check the parameters */assert_param(IS_TIM_LIST8_PERIPH(TIMx));assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity));tmpccer = TIMx->CCER;/* Set or Reset the CC1P Bit */tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC1P);tmpccer |= TIM_OCPolarity;/* Write to TIMx CCER register */TIMx->CCER = tmpccer;
}/*** @brief  Configures the TIMx Channel 1N polarity.* @param  TIMx: where x can be 1, 8, 15, 16 or 17 to select the TIM peripheral.* @param  TIM_OCNPolarity: specifies the OC1N Polarity*   This parameter can be one of the following values:*     @arg TIM_OCNPolarity_High: Output Compare active high*     @arg TIM_OCNPolarity_Low: Output Compare active low* @retval None*/
void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity)
{uint16_t tmpccer = 0;/* Check the parameters */assert_param(IS_TIM_LIST2_PERIPH(TIMx));assert_param(IS_TIM_OCN_POLARITY(TIM_OCNPolarity));tmpccer = TIMx->CCER;/* Set or Reset the CC1NP Bit */tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC1NP);tmpccer |= TIM_OCNPolarity;/* Write to TIMx CCER register */TIMx->CCER = tmpccer;
}/*** @brief  Configures the TIMx channel 2 polarity.* @param  TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.* @param  TIM_OCPolarity: specifies the OC2 Polarity*   This parameter can be one of the following values:*     @arg TIM_OCPolarity_High: Output Compare active high*     @arg TIM_OCPolarity_Low: Output Compare active low* @retval None*/
void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)
{uint16_t tmpccer = 0;/* Check the parameters */assert_param(IS_TIM_LIST6_PERIPH(TIMx));assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity));tmpccer = TIMx->CCER;/* Set or Reset the CC2P Bit */tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC2P);tmpccer |= (uint16_t)(TIM_OCPolarity << 4);/* Write to TIMx CCER register */TIMx->CCER = tmpccer;
}/*** @brief  Configures the TIMx Channel 2N polarity.* @param  TIMx: where x can be 1 or 8 to select the TIM peripheral.* @param  TIM_OCNPolarity: specifies the OC2N Polarity*   This parameter can be one of the following values:*     @arg TIM_OCNPolarity_High: Output Compare active high*     @arg TIM_OCNPolarity_Low: Output Compare active low* @retval None*/
void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity)
{uint16_t tmpccer = 0;/* Check the parameters */assert_param(IS_TIM_LIST1_PERIPH(TIMx));assert_param(IS_TIM_OCN_POLARITY(TIM_OCNPolarity));tmpccer = TIMx->CCER;/* Set or Reset the CC2NP Bit */tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC2NP);tmpccer |= (uint16_t)(TIM_OCNPolarity << 4);/* Write to TIMx CCER register */TIMx->CCER = tmpccer;
}/*** @brief  Configures the TIMx channel 3 polarity.* @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_OCPolarity: specifies the OC3 Polarity*   This parameter can be one of the following values:*     @arg TIM_OCPolarity_High: Output Compare active high*     @arg TIM_OCPolarity_Low: Output Compare active low* @retval None*/
void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)
{uint16_t tmpccer = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity));tmpccer = TIMx->CCER;/* Set or Reset the CC3P Bit */tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC3P);tmpccer |= (uint16_t)(TIM_OCPolarity << 8);/* Write to TIMx CCER register */TIMx->CCER = tmpccer;
}/*** @brief  Configures the TIMx Channel 3N polarity.* @param  TIMx: where x can be 1 or 8 to select the TIM peripheral.* @param  TIM_OCNPolarity: specifies the OC3N Polarity*   This parameter can be one of the following values:*     @arg TIM_OCNPolarity_High: Output Compare active high*     @arg TIM_OCNPolarity_Low: Output Compare active low* @retval None*/
void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity)
{uint16_t tmpccer = 0;/* Check the parameters */assert_param(IS_TIM_LIST1_PERIPH(TIMx));assert_param(IS_TIM_OCN_POLARITY(TIM_OCNPolarity));tmpccer = TIMx->CCER;/* Set or Reset the CC3NP Bit */tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC3NP);tmpccer |= (uint16_t)(TIM_OCNPolarity << 8);/* Write to TIMx CCER register */TIMx->CCER = tmpccer;
}/*** @brief  Configures the TIMx channel 4 polarity.* @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_OCPolarity: specifies the OC4 Polarity*   This parameter can be one of the following values:*     @arg TIM_OCPolarity_High: Output Compare active high*     @arg TIM_OCPolarity_Low: Output Compare active low* @retval None*/
void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)
{uint16_t tmpccer = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity));tmpccer = TIMx->CCER;/* Set or Reset the CC4P Bit */tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC4P);tmpccer |= (uint16_t)(TIM_OCPolarity << 12);/* Write to TIMx CCER register */TIMx->CCER = tmpccer;
}

2.9、TIM_CCxCmd && TIM_CCxNCmd 单独修改输出使能参数的

        函数原型

void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);
void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);

        函数讲解:这两个函数是用来单独修改输出使能参数的。

        函数定义

/*** @brief  Enables or disables the TIM Capture Compare Channel x.* @param  TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.* @param  TIM_Channel: specifies the TIM Channel*   This parameter can be one of the following values:*     @arg TIM_Channel_1: TIM Channel 1*     @arg TIM_Channel_2: TIM Channel 2*     @arg TIM_Channel_3: TIM Channel 3*     @arg TIM_Channel_4: TIM Channel 4* @param  TIM_CCx: specifies the TIM Channel CCxE bit new state.*   This parameter can be: TIM_CCx_Enable or TIM_CCx_Disable. * @retval None*/
void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx)
{uint16_t tmp = 0;/* Check the parameters */assert_param(IS_TIM_LIST8_PERIPH(TIMx));assert_param(IS_TIM_CHANNEL(TIM_Channel));assert_param(IS_TIM_CCX(TIM_CCx));tmp = CCER_CCE_Set << TIM_Channel;/* Reset the CCxE Bit */TIMx->CCER &= (uint16_t)~ tmp;/* Set or reset the CCxE Bit */ TIMx->CCER |=  (uint16_t)(TIM_CCx << TIM_Channel);
}/*** @brief  Enables or disables the TIM Capture Compare Channel xN.* @param  TIMx: where x can be 1, 8, 15, 16 or 17 to select the TIM peripheral.* @param  TIM_Channel: specifies the TIM Channel*   This parameter can be one of the following values:*     @arg TIM_Channel_1: TIM Channel 1*     @arg TIM_Channel_2: TIM Channel 2*     @arg TIM_Channel_3: TIM Channel 3* @param  TIM_CCxN: specifies the TIM Channel CCxNE bit new state.*   This parameter can be: TIM_CCxN_Enable or TIM_CCxN_Disable. * @retval None*/
void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN)
{uint16_t tmp = 0;/* Check the parameters */assert_param(IS_TIM_LIST2_PERIPH(TIMx));assert_param(IS_TIM_COMPLEMENTARY_CHANNEL(TIM_Channel));assert_param(IS_TIM_CCXN(TIM_CCxN));tmp = CCER_CCNE_Set << TIM_Channel;/* Reset the CCxNE Bit */TIMx->CCER &= (uint16_t) ~tmp;/* Set or reset the CCxNE Bit */ TIMx->CCER |=  (uint16_t)(TIM_CCxN << TIM_Channel);
}

2.10、TIM_SelectOCxM 选择输出比较模式

        函数原型

        void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel,

                uint16_t TIM_OCMode);

        函数讲解:这个函数是用来选择输出比较模式的。

        函数定义

/*** @brief  Selects the TIM Output Compare Mode.* @note   This function disables the selected channel before changing the Output*         Compare Mode.*         User has to enable this channel using TIM_CCxCmd and TIM_CCxNCmd functions.* @param  TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.* @param  TIM_Channel: specifies the TIM Channel*   This parameter can be one of the following values:*     @arg TIM_Channel_1: TIM Channel 1*     @arg TIM_Channel_2: TIM Channel 2*     @arg TIM_Channel_3: TIM Channel 3*     @arg TIM_Channel_4: TIM Channel 4* @param  TIM_OCMode: specifies the TIM Output Compare Mode.*   This parameter can be one of the following values:*     @arg TIM_OCMode_Timing*     @arg TIM_OCMode_Active*     @arg TIM_OCMode_Toggle*     @arg TIM_OCMode_PWM1*     @arg TIM_OCMode_PWM2*     @arg TIM_ForcedAction_Active*     @arg TIM_ForcedAction_InActive* @retval None*/
void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode)
{uint32_t tmp = 0;uint16_t tmp1 = 0;/* Check the parameters */assert_param(IS_TIM_LIST8_PERIPH(TIMx));assert_param(IS_TIM_CHANNEL(TIM_Channel));assert_param(IS_TIM_OCM(TIM_OCMode));tmp = (uint32_t) TIMx;tmp += CCMR_Offset;tmp1 = CCER_CCE_Set << (uint16_t)TIM_Channel;/* Disable the Channel: Reset the CCxE Bit */TIMx->CCER &= (uint16_t) ~tmp1;if((TIM_Channel == TIM_Channel_1) ||(TIM_Channel == TIM_Channel_3)){tmp += (TIM_Channel>>1);/* Reset the OCxM bits in the CCMRx register */*(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_CCMR1_OC1M);/* Configure the OCxM bits in the CCMRx register */*(__IO uint32_t *) tmp |= TIM_OCMode;}else{tmp += (uint16_t)(TIM_Channel - (uint16_t)4)>> (uint16_t)1;/* Reset the OCxM bits in the CCMRx register */*(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_CCMR1_OC2M);/* Configure the OCxM bits in the CCMRx register */*(__IO uint32_t *) tmp |= (uint16_t)(TIM_OCMode << 8);}
}

2.11、TIM_SetComparex 更改CCR寄存器的值的函数

        函数原型

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);

        函数讲解:这四个函数是用来单独更改CCR寄存器的值的函数。这四个函数比较重要,我们在运行时更改占空比,就要用到这四个函数。

        函数定义

/*** @brief  Sets the TIMx Capture Compare1 Register value* @param  TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.* @param  Compare1: specifies the Capture Compare1 register new value.* @retval None*/
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1)
{/* Check the parameters */assert_param(IS_TIM_LIST8_PERIPH(TIMx));/* Set the Capture Compare1 Register value */TIMx->CCR1 = Compare1;
}/*** @brief  Sets the TIMx Capture Compare2 Register value* @param  TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.* @param  Compare2: specifies the Capture Compare2 register new value.* @retval None*/
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2)
{/* Check the parameters */assert_param(IS_TIM_LIST6_PERIPH(TIMx));/* Set the Capture Compare2 Register value */TIMx->CCR2 = Compare2;
}/*** @brief  Sets the TIMx Capture Compare3 Register value* @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  Compare3: specifies the Capture Compare3 register new value.* @retval None*/
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3)
{/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));/* Set the Capture Compare3 Register value */TIMx->CCR3 = Compare3;
}/*** @brief  Sets the TIMx Capture Compare4 Register value* @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  Compare4: specifies the Capture Compare4 register new value.* @retval None*/
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4)
{/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));/* Set the Capture Compare4 Register value */TIMx->CCR4 = Compare4;
}

2.12TIM结构体讲解

/** * @brief  TIM Output Compare Init structure definition  */typedef struct
{uint16_t TIM_OCMode;        /*!< Specifies the TIM mode.This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */uint16_t TIM_OutputState;   /*!< Specifies the TIM Output Compare state.This parameter can be a value of @ref TIM_Output_Compare_state */uint16_t TIM_OutputNState;  /*!< Specifies the TIM complementary Output Compare state.This parameter can be a value of @ref TIM_Output_Compare_N_state@note This parameter is valid only for TIM1 and TIM8. */uint16_t TIM_Pulse;         /*!< Specifies the pulse value to be loaded into the Capture Compare Register. This parameter can be a number between 0x0000 and 0xFFFF */uint16_t TIM_OCPolarity;    /*!< Specifies the output polarity.This parameter can be a value of @ref TIM_Output_Compare_Polarity */uint16_t TIM_OCNPolarity;   /*!< Specifies the complementary output polarity.This parameter can be a value of @ref TIM_Output_Compare_N_Polarity@note This parameter is valid only for TIM1 and TIM8. */uint16_t TIM_OCIdleState;   /*!< Specifies the TIM Output Compare pin state during Idle state.This parameter can be a value of @ref TIM_Output_Compare_Idle_State@note This parameter is valid only for TIM1 and TIM8. */uint16_t TIM_OCNIdleState;  /*!< Specifies the TIM Output Compare pin state during Idle state.This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State@note This parameter is valid only for TIM1 and TIM8. */
} TIM_OCInitTypeDef;

2.12.1、TIM_OCMode 输出比较模式

        这个参数可以是TIM_Output_Compare_and_PWM_modes中的一个值。

        TIM_Output_Compare_and_PWM_modes:

/** @defgroup TIM_Output_Compare_and_PWM_modes * @{*/#define TIM_OCMode_Timing                  ((uint16_t)0x0000)
#define TIM_OCMode_Active                  ((uint16_t)0x0010)
#define TIM_OCMode_Inactive                ((uint16_t)0x0020)
#define TIM_OCMode_Toggle                  ((uint16_t)0x0030)
#define TIM_OCMode_PWM1                    ((uint16_t)0x0060)
#define TIM_OCMode_PWM2                    ((uint16_t)0x0070)
#define IS_TIM_OC_MODE(MODE) (((MODE) == TIM_OCMode_Timing) || \((MODE) == TIM_OCMode_Active) || \((MODE) == TIM_OCMode_Inactive) || \((MODE) == TIM_OCMode_Toggle)|| \((MODE) == TIM_OCMode_PWM1) || \((MODE) == TIM_OCMode_PWM2))
#define IS_TIM_OCM(MODE) (((MODE) == TIM_OCMode_Timing) || \((MODE) == TIM_OCMode_Active) || \((MODE) == TIM_OCMode_Inactive) || \((MODE) == TIM_OCMode_Toggle)|| \((MODE) == TIM_OCMode_PWM1) || \((MODE) == TIM_OCMode_PWM2) ||	\((MODE) == TIM_ForcedAction_Active) || \((MODE) == TIM_ForcedAction_InActive))

        TIM_OCMode_Timing 冻结模式;

        TIM_OCMode_Active 相等时置有效电平;

        TIM_OCMode_Inactive 相等时置无效电平;

        TIM_OCMode_Toggle 相等时电平翻转;

        TIM_OCMode_PWM1 PWM模式1;

        TIM_OCMode_PWM2 PWM模式2;

        TIM_ForcedAction_Active 强制有效电平输出;

        TIM_ForcedAction_InActive 强制无效电平输出。

2.12.2、TIM_OCPolarity 输出比较极性

        它可以是TIM_Output_Compare_Polarity中的一个值。

/** @defgroup TIM_Output_Compare_Polarity * @{*/#define TIM_OCPolarity_High                ((uint16_t)0x0000)
#define TIM_OCPolarity_Low                 ((uint16_t)0x0002)
#define IS_TIM_OC_POLARITY(POLARITY) (((POLARITY) == TIM_OCPolarity_High) || \((POLARITY) == TIM_OCPolarity_Low))

        TIM_OCPolarity_High 高极性,即极性不翻转,REF波形直接输出;或者说是有效电平是高电平,REF有效时,输出高电平。

        TIM_OCPolarity_Low 低极性,就是REF电平取反,或者说有效电平为低电平。

2.12.3、TIM_OutputState 输出比较状态

        这个值可以是TIM_Output_Compare_state中的一个值。

/** @defgroup TIM_Output_Compare_state * @{*/#define TIM_OutputState_Disable            ((uint16_t)0x0000)
#define TIM_OutputState_Enable             ((uint16_t)0x0001)
#define IS_TIM_OUTPUT_STATE(STATE) (((STATE) == TIM_OutputState_Disable) || \((STATE) == TIM_OutputState_Enable))

        TIM_OutputState_Disable 输出比较失能;

        TIM_OutputState_Enable输出比较使能。

2.12.4、TIM_Pulse 设置CCR寄存器的值

        注释:注释写的是指定Pulse的值,会被加载到Capture Compare Register。这就是CCR捕获比较寄存器。这个参数可以是0到FFFF之间的一个值,也就是16位的范围。

         PWM的频率==计数器的更新频率。

        如果现在要产生一个频率为1kHz、占空比为50%、分辨率为1%的PWM波形,则带入公式就是:

        72MHz/(PSC+1)/(ARR+1)=1000,CCR/(ARR+1)=0.5,1/(ARR+1)=0.01。

        计算可得:ARR = 100 - 1;CCR = 50;PSC = 720 - 1;

        则赋值:

/*配置时基单元中的部分代码*/
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSC/*配置输出比较单元中的部分代码*/
TIM_OCInitStructure.TIM_Pulse = 50;/*用来设置CCR的*/		//RCC

2.12.5、一个问题

            一个问题:出现的结构体并没有给所有成员赋值,对于结构体变量来说,它是一个局部变量,如果不给他的成员赋初始值,他成员的值就是不确定的,这可能会导致一些问题。
        比如你想把高级定时器当做普通定时器输出PWM时,就需要把OC_Init中的TIM2改成TIM1。这样,这个结构体原本用不到的成员现在就都需要用了。但是有关高级定时器的结构体中的一些成员并没有给赋初值,就会导致高级定时器输出PWM时出现一些奇怪的问题。
        让高级定时器输出4路PWM,如果把初始化函数放在程序的第一行,就没有问题;如果初始化函数之前出现了其他的代码,则4路PWM就会有三路不能输出。
        所以就需要用到TIM_OCStructInit函数了,这个函数就是给结构体赋初始值的。

	/*第三步:配置输出比较单元*/TIM_OCInitTypeDef TIM_OCInitStructure;/*需要TIM_OCStructInit的原因见模块下面。*//*如果不想把所有的结构体成员赋值,就可以先用TIM_OCStructInit赋一个初始值,再更改想要修改的值就可以了*/TIM_OCStructInit(&TIM_OCInitStructure);//TIM_OCInitStructure.TIM_OCIdleState = ;/*高级定时器*/TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;/*设置输出比较的模式*///TIM_OCInitStructure.TIM_OCNIdleState = ;//TIM_OCInitStructure.TIM_OCNPolarity = ;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;/*设置输出比较的极性*///TIM_OCInitStructure.TIM_OutputNState = ;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;/*设置输出使能*///TIM_OCInitStructure.TIM_Pulse = 50;/*用来设置CCR的*/		//RCCTIM_OC1Init(TIM2,&TIM_OCInitStructure);/*一个问题:出现的结构体并没有给所有成员赋值,对于结构体变量来说,它是一个局部变量,如果不给他的成员赋初始值,他成员的值就是不确定的,这可能会导致一些问题。*//*比如你想把高级定时器当做普通定时器输出PWM时,就需要吧ocinit中的TIM2改成TIM1。这样,这个觉构体原本用不到的成员现在就都需要用了。但是有关高级定时器的结构体中的一些成员并没有给赋初值,就会导致高级定时器输出PWM时出现一些奇怪的问题。*//*让高级定时器输出4路PWM,如果把初始化函数放在程序的第一行,就没有问题;如果初始化函数之前出现了其他的代码,则4路PWM就会有三路不能输出。*//*所以就需要用到TIM_OCStructInit函数了,这个函数就是给结构体赋初始值的。*/

三、呼吸灯完整代码

3.1、PWM.h

#ifndef _PWM_H
#define _PWM_Hvoid pwm_init(void);
void pwm_setcompare1(uint16_t compare);#endif

3.2、PWM.c

3.2.1、具体步骤

具体步骤:

        第一步:RCC开启时钟,将我们要用的TIM外设和GPIO外设的时钟打开;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

        第二步:配置时基单元,包括前面的时钟源选择和这里的时基单元 都配置好;

	/*第二步:配置时基单元*/TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARRTIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);TIM_ClearFlag(TIM2,TIM_FLAG_Update);TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);

        第三步:配置输出比较单元,包括CCR的值、输出比较模式、极性选择、输出使能等参数;

	/*第三步:配置输出比较单元*/TIM_OCInitTypeDef TIM_OCInitStructure;/*需要TIM_OCStructInit的原因见模块下面。*//*如果不想把所有的结构体成员赋值,就可以先用TIM_OCStructInit赋一个初始值,再更改想要修改的值就可以了*/TIM_OCStructInit(&TIM_OCInitStructure);//TIM_OCInitStructure.TIM_OCIdleState = ;/*高级定时器*/TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;/*设置输出比较的模式*///TIM_OCInitStructure.TIM_OCNIdleState = ;//TIM_OCInitStructure.TIM_OCNPolarity = ;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;/*设置输出比较的极性*///TIM_OCInitStructure.TIM_OutputNState = ;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;/*设置输出使能*///TIM_OCInitStructure.TIM_Pulse = 50;/*用来设置CCR的*/		//RCCTIM_OC1Init(TIM2,&TIM_OCInitStructure);

        第四步:配置GPIO,把PWM对应的GPIO抠,初始化为复用推挽输出的配置;

	/*第四步:配置GPIO*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;/*选择为复用推挽输出*//*对于普通的推挽输出,引脚的控制权是来自于输出数据寄存器的,如果想要定时器来控制引脚,就需要使用复用开漏推挽输出模式。在这里,输出数据寄存器将会被断开,输出控制权将转移给片上外设,00:21:00*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);

        第五步:运行控制,启动计数器,这样就能输出PWM了。

TIM_Cmd(TIM2,ENABLE);

3.2.2、完整代码

#include "stm32f10x.h"                  // Device headervoid pwm_init(void)
{/*第一步:RCC开启时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);/*第二步:配置时基单元*/TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARRTIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);TIM_ClearFlag(TIM2,TIM_FLAG_Update);TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);/*第三步:配置输出比较单元*/TIM_OCInitTypeDef TIM_OCInitStructure;/*需要TIM_OCStructInit的原因见模块下面。*//*如果不想把所有的结构体成员赋值,就可以先用TIM_OCStructInit赋一个初始值,再更改想要修改的值就可以了*/TIM_OCStructInit(&TIM_OCInitStructure);//TIM_OCInitStructure.TIM_OCIdleState = ;/*高级定时器*/TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;/*设置输出比较的模式*///TIM_OCInitStructure.TIM_OCNIdleState = ;//TIM_OCInitStructure.TIM_OCNPolarity = ;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;/*设置输出比较的极性*///TIM_OCInitStructure.TIM_OutputNState = ;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;/*设置输出使能*///TIM_OCInitStructure.TIM_Pulse = 50;/*用来设置CCR的*/		//RCCTIM_OC1Init(TIM2,&TIM_OCInitStructure);/*一个问题:出现的结构体并没有给所有成员赋值,对于结构体变量来说,它是一个局部变量,如果不给他的成员赋初始值,他成员的值就是不确定的,这可能会导致一些问题。*//*比如你想把高级定时器当做普通定时器输出PWM时,就需要吧ocinit中的TIM2改成TIM1。这样,这个觉构体原本用不到的成员现在就都需要用了。但是有关高级定时器的结构体中的一些成员并没有给赋初值,就会导致高级定时器输出PWM时出现一些奇怪的问题。*//*让高级定时器输出4路PWM,如果把初始化函数放在程序的第一行,就没有问题;如果初始化函数之前出现了其他的代码,则4路PWM就会有三路不能输出。*//*所以就需要用到TIM_OCStructInit函数了,这个函数就是给结构体赋初始值的。*//*第四步:配置GPIO*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;/*选择为复用推挽输出*//*对于普通的推挽输出,引脚的控制权是来自于输出数据寄存器的,如果想要定时器来控制引脚,就需要使用复用开漏推挽输出模式。在这里,输出数据寄存器将会被断开,输出控制权将转移给片上外设,00:21:00*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);TIM_Cmd(TIM2,ENABLE);
}/*修改CCR的值*/
void pwm_setcompare1(uint16_t compare)
{TIM_SetCompare1(TIM2,compare);
}

3.3、main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"uint8_t i;
int main(void)
{OLED_Init();pwm_init();while (1){/*逐渐变亮*/for(i = 0; i <= 100; i++){pwm_setcompare1(i);Delay_ms(10);}/*逐渐变暗*/for(i = 0; i <= 100; i++){pwm_setcompare1(100 - i);Delay_ms(10);}	}
}

四、引脚重映射到PA15端口

4.1、映射讲解

        从引脚定义表中可以看到, TIM2的CH1可以从PA0挪到PA15引脚上。这步的操作需要用到AFIO了。

        具体步骤:

        第一步:开启AFIO的时钟。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

        第二步:引脚重映射设置。

        在stm32f10x_gpio.h中,获取函数GPIO_PinRemapConfig。

        引脚重映射函数的定义和声明:

/*** @brief  Changes the mapping of the specified pin.* @param  GPIO_Remap: selects the pin to remap.*   This parameter can be one of the following values:*     @arg GPIO_Remap_SPI1             : SPI1 Alternate Function mapping*     @arg GPIO_Remap_I2C1             : I2C1 Alternate Function mapping*     @arg GPIO_Remap_USART1           : USART1 Alternate Function mapping*     @arg GPIO_Remap_USART2           : USART2 Alternate Function mapping*     @arg GPIO_PartialRemap_USART3    : USART3 Partial Alternate Function mapping*     @arg GPIO_FullRemap_USART3       : USART3 Full Alternate Function mapping*     @arg GPIO_PartialRemap_TIM1      : TIM1 Partial Alternate Function mapping*     @arg GPIO_FullRemap_TIM1         : TIM1 Full Alternate Function mapping*     @arg GPIO_PartialRemap1_TIM2     : TIM2 Partial1 Alternate Function mapping*     @arg GPIO_PartialRemap2_TIM2     : TIM2 Partial2 Alternate Function mapping*     @arg GPIO_FullRemap_TIM2         : TIM2 Full Alternate Function mapping*     @arg GPIO_PartialRemap_TIM3      : TIM3 Partial Alternate Function mapping*     @arg GPIO_FullRemap_TIM3         : TIM3 Full Alternate Function mapping*     @arg GPIO_Remap_TIM4             : TIM4 Alternate Function mapping*     @arg GPIO_Remap1_CAN1            : CAN1 Alternate Function mapping*     @arg GPIO_Remap2_CAN1            : CAN1 Alternate Function mapping*     @arg GPIO_Remap_PD01             : PD01 Alternate Function mapping*     @arg GPIO_Remap_TIM5CH4_LSI      : LSI connected to TIM5 Channel4 input capture for calibration*     @arg GPIO_Remap_ADC1_ETRGINJ     : ADC1 External Trigger Injected Conversion remapping*     @arg GPIO_Remap_ADC1_ETRGREG     : ADC1 External Trigger Regular Conversion remapping*     @arg GPIO_Remap_ADC2_ETRGINJ     : ADC2 External Trigger Injected Conversion remapping*     @arg GPIO_Remap_ADC2_ETRGREG     : ADC2 External Trigger Regular Conversion remapping*     @arg GPIO_Remap_ETH              : Ethernet remapping (only for Connectivity line devices)*     @arg GPIO_Remap_CAN2             : CAN2 remapping (only for Connectivity line devices)*     @arg GPIO_Remap_SWJ_NoJTRST      : Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST*     @arg GPIO_Remap_SWJ_JTAGDisable  : JTAG-DP Disabled and SW-DP Enabled*     @arg GPIO_Remap_SWJ_Disable      : Full SWJ Disabled (JTAG-DP + SW-DP)*     @arg GPIO_Remap_SPI3             : SPI3/I2S3 Alternate Function mapping (only for Connectivity line devices)*                                        When the SPI3/I2S3 is remapped using this function, the SWJ is configured*                                        to Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST.   *     @arg GPIO_Remap_TIM2ITR1_PTP_SOF : Ethernet PTP output or USB OTG SOF (Start of Frame) connected*                                        to TIM2 Internal Trigger 1 for calibration (only for Connectivity line devices)*                                        If the GPIO_Remap_TIM2ITR1_PTP_SOF is enabled the TIM2 ITR1 is connected to *                                        Ethernet PTP output. When Reset TIM2 ITR1 is connected to USB OTG SOF output.    *     @arg GPIO_Remap_PTP_PPS          : Ethernet MAC PPS_PTS output on PB05 (only for Connectivity line devices)*     @arg GPIO_Remap_TIM15            : TIM15 Alternate Function mapping (only for Value line devices)*     @arg GPIO_Remap_TIM16            : TIM16 Alternate Function mapping (only for Value line devices)*     @arg GPIO_Remap_TIM17            : TIM17 Alternate Function mapping (only for Value line devices)*     @arg GPIO_Remap_CEC              : CEC Alternate Function mapping (only for Value line devices)*     @arg GPIO_Remap_TIM1_DMA         : TIM1 DMA requests mapping (only for Value line devices)*     @arg GPIO_Remap_TIM9             : TIM9 Alternate Function mapping (only for XL-density devices)*     @arg GPIO_Remap_TIM10            : TIM10 Alternate Function mapping (only for XL-density devices)*     @arg GPIO_Remap_TIM11            : TIM11 Alternate Function mapping (only for XL-density devices)*     @arg GPIO_Remap_TIM13            : TIM13 Alternate Function mapping (only for High density Value line and XL-density devices)*     @arg GPIO_Remap_TIM14            : TIM14 Alternate Function mapping (only for High density Value line and XL-density devices)*     @arg GPIO_Remap_FSMC_NADV        : FSMC_NADV Alternate Function mapping (only for High density Value line and XL-density devices)*     @arg GPIO_Remap_TIM67_DAC_DMA    : TIM6/TIM7 and DAC DMA requests remapping (only for High density Value line devices)*     @arg GPIO_Remap_TIM12            : TIM12 Alternate Function mapping (only for High density Value line devices)*     @arg GPIO_Remap_MISC             : Miscellaneous Remap (DMA2 Channel5 Position and DAC Trigger remapping, *                                        only for High density Value line devices)     * @param  NewState: new state of the port pin remapping.*   This parameter can be: ENABLE or DISABLE.* @retval None*/
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState)
{uint32_t tmp = 0x00, tmp1 = 0x00, tmpreg = 0x00, tmpmask = 0x00;/* Check the parameters */assert_param(IS_GPIO_REMAP(GPIO_Remap));assert_param(IS_FUNCTIONAL_STATE(NewState));  if((GPIO_Remap & 0x80000000) == 0x80000000){tmpreg = AFIO->MAPR2;}else{tmpreg = AFIO->MAPR;}tmpmask = (GPIO_Remap & DBGAFR_POSITION_MASK) >> 0x10;tmp = GPIO_Remap & LSB_MASK;if ((GPIO_Remap & (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) == (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)){tmpreg &= DBGAFR_SWJCFG_MASK;AFIO->MAPR &= DBGAFR_SWJCFG_MASK;}else if ((GPIO_Remap & DBGAFR_NUMBITS_MASK) == DBGAFR_NUMBITS_MASK){tmp1 = ((uint32_t)0x03) << tmpmask;tmpreg &= ~tmp1;tmpreg |= ~DBGAFR_SWJCFG_MASK;}else{tmpreg &= ~(tmp << ((GPIO_Remap >> 0x15)*0x10));tmpreg |= ~DBGAFR_SWJCFG_MASK;}if (NewState != DISABLE){tmpreg |= (tmp << ((GPIO_Remap >> 0x15)*0x10));}if((GPIO_Remap & 0x80000000) == 0x80000000){AFIO->MAPR2 = tmpreg;}else{AFIO->MAPR = tmpreg;}  
}

         第一个参数选项非常多。里面都是重映射的方式。在手册中可以找到每个凡是对应的重映射关系。

        据表,如果想将PA0改为PA15,就可以选择“部分重映射方式1”或者“完全重映射”。

        从引脚重映射代码注释中查询,发现TIM2有部分重映射1、部分重映射2和完全重映射,分别为:

        GPIO_PartialRemap1_TIM2、GPIO_PartialRemap2_TIM2、GPIO_FullRemap_TIM2。

        故在PWM.c文件中,添加一行代码用于引脚重映射:

GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);

        这样就能把PA0换到PA15了。 

        但是PA15上电后默认复用为了调试端口JTDI(对照引脚定义表),所以如果想让它作为普通的GPIO或者复用定时器的通道,还需要先关闭调试端口的复用

        关闭方式:依旧使用GPIO_PinRemapConfig函数。

        从引脚重映射函数代码的注释中查询,发现这里有三个参数用来解除调试端口的复用的,分别是:

        GPIO_Remap_SWJ_NoJTRST:SWJ是SWD和JTAG两种调试方式,NoJTRST即解除JTRST引脚的复用。在引脚定义表第40行可以看到,如果使用这个参数,那么NJTRST(PB4)就变味正常的GPIO口了,其他的四个端口仍然是调试端口,不能当做GPIO来使用。

        GPIO_Remap_SWJ_JTAGDisable:解除JTAG调试端口的复用。在引脚定义中就是PA15、PB3、PB4三个端口变为GPIO,上面的PA13和PA14仍为SWD的调试端口。

        GPIO_Remap_SWJ_Disable:解除SWD和JTAG的调试端口全部解除。在引脚定义中,就是PA13、PA14、PA15、PB3、PB4这5个引脚全部变成普通的GPIO,没有调试功能了。

        所以以上参数千万不能随便调用,一旦调用这个参数且下载程序之后,调试端口就都没有了,这之后再使用STLINK就下载不进去程序了。这时就只能使用串口下载,下载一个新的、没有解除调试端口的程序,这样才能把调试端口弄回来

        在这里,如果我们需要使用PA15、PB3、PB4这三个引脚,那么通常就只需要解除JTAG的复用,保留SWD的复用。

        所以函数的第一个参数可以选择GPIO_Remap_SWJ_JTAGDisable。

GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);

        这样就可以正常使用PA15这个引脚了。 

        总结

        如果想让PA15、PB3、PB4这三个引脚当做GPIO来使用的话:先打开AFIO时钟,再用AFIO将JTAG复用解除掉;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);

        如果想重映射定时器或者其他外设的复用引脚:先打开AFIO时钟,再用AFO重映射外设复用的引脚。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);

        打开AFIO时钟-》重映射引脚-》解除调试端口。 

4.2、完整代码

4.2.1、PWM.h

#ifndef _PWM_H
#define _PWM_Hvoid pwm_init(void);
void pwm_setcompare1(uint16_t compare);#endif

4.2.2、PWM.c

#include "stm32f10x.h"                  // Device headervoid pwm_init(void)
{/*第一步:RCC开启时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);/*第二步:配置时基单元*/TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARRTIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);TIM_ClearFlag(TIM2,TIM_FLAG_Update);TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);/*第三步:配置输出比较单元*/TIM_OCInitTypeDef TIM_OCInitStructure;/*需要TIM_OCStructInit的原因见模块下面。*//*如果不想把所有的结构体成员赋值,就可以先用TIM_OCStructInit赋一个初始值,再更改想要修改的值就可以了*/TIM_OCStructInit(&TIM_OCInitStructure);//TIM_OCInitStructure.TIM_OCIdleState = ;/*高级定时器*/TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;/*设置输出比较的模式*///TIM_OCInitStructure.TIM_OCNIdleState = ;//TIM_OCInitStructure.TIM_OCNPolarity = ;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;/*设置输出比较的极性*///TIM_OCInitStructure.TIM_OutputNState = ;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;/*设置输出使能*///TIM_OCInitStructure.TIM_Pulse = 50;/*用来设置CCR的*/		//RCCTIM_OC1Init(TIM2,&TIM_OCInitStructure);/*第四步:配置GPIO*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;/*选择为复用推挽输出*//*对于普通的推挽输出,引脚的控制权是来自于输出数据寄存器的,如果想要定时器来控制引脚,就需要使用复用开漏推挽输出模式。在这里,输出数据寄存器将会被断开,输出控制权将转移给片上外设,00:21:00*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);TIM_Cmd(TIM2,ENABLE);
}/*修改CCR的值*/
void pwm_setcompare1(uint16_t compare)
{TIM_SetCompare1(TIM2,compare);
}

4.2.3、main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"uint8_t i;
int main(void)
{OLED_Init();pwm_init();while (1){/*逐渐变亮*/for(i = 0; i <= 100; i++){pwm_setcompare1(i);Delay_ms(10);}/*逐渐变暗*/for(i = 0; i <= 100; i++){pwm_setcompare1(100 - i);Delay_ms(10);}	}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词