STM32一个Timer输出4路不同频率、可调占空比的PWM

时间:2022-06-20 21:02:20

源码下载地址:http://download.csdn.net/detail/dazhou158/5253187


main.c

/*********************************************
标题:操作USART的练习
软件平台:MDK-ARM Standard Version4.70
硬件平台:stm32f4-discovery
主频:168M
Periph_Driver_version: V1.0.0

描述:用一个定时器(TIM3),实现四路不同频率、占空比可调的PWM
代码参考自STM32F4-Discovery_FW_V1.1.0\Project\Peripheral_Examples\TIM_TimeBase

author:大舟
data:2013-04-13
**********************************************/

#include "stm32f4_discovery.h"



TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
__IO uint16_t CCR1_Val = 5000;//54618
__IO uint16_t CCR2_Val = 27309;
__IO uint16_t CCR3_Val = 13654;
__IO uint16_t CCR4_Val = 6826;
uint16_t PrescalerValue = 0;

void TIM_Config(void);


int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f4xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f4xx.c file
*/

/* TIM Configuration */
TIM_Config();

/** -----------------------------------------------------------------------
TIM3 Configuration: Output Compare Timing Mode:

In this example TIM3 input clock (TIM3CLK) is set to 2 * APB1 clock (PCLK1),
since APB1 prescaler is different from 1.
TIM3CLK = 2 * PCLK1
PCLK1 = HCLK / 4
=> TIM3CLK = HCLK / 2 = SystemCoreClock /2

To get TIM3 counter clock at 500 KHz, the prescaler is computed as follows:
Prescaler = (TIM3CLK / TIM3 counter clock) - 1
Prescaler = ((SystemCoreClock /2) /50 MHz) - 1

CC1 update rate = TIM3 counter clock / CCR1_Val = 9.154 Hz @note 上面已经将CCR1_Val改为了5000,具体频率,见中断的注释
==> Toggling frequency = 4.57 Hz

C2 update rate = TIM3 counter clock / CCR2_Val = 18.31 Hz
==> Toggling frequency = 9.15 Hz

CC3 update rate = TIM3 counter clock / CCR3_Val = 36.62 Hz
==> Toggling frequency = 18.31 Hz

CC4 update rate = TIM3 counter clock / CCR4_Val = 73.25 Hz
==> Toggling frequency = 36.62 Hz

Note:
SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f4xx.c file.
Each time the core clock (HCLK) changes, user had to call SystemCoreClockUpdate()
function to update SystemCoreClock variable value. Otherwise, any configuration
based on this variable will be incorrect.
----------------------------------------------------------------------- */

/* Compute the prescaler value */
PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 500000) - 1;//=168

/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 65535;//65535
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

/* Prescaler configuration */
TIM_PrescalerConfig(TIM3, PrescalerValue, TIM_PSCReloadMode_Immediate);//对84M进行168分频,即为500KHz

/* Output Compare Timing Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);

/* Output Compare Timing Mode configuration: Channel2 */
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable);

/* Output Compare Timing Mode configuration: Channel3 */
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
TIM_OC3Init(TIM3, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Disable);

/* Output Compare Timing Mode configuration: Channel4 */
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
TIM_OC4Init(TIM3, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Disable);

/* TIM Interrupts enable */
TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);

/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);

while (1);
}



/**
* @brief Configure the TIM IRQ Handler.
* @param None
* @retval None
*/
void TIM_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

/* TIM3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

/* Enable the TIM3 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

/* Initialize Leds mounted on STM32F4-Discovery board */
STM_EVAL_LEDInit(LED4);
STM_EVAL_LEDInit(LED3);
STM_EVAL_LEDInit(LED5);
STM_EVAL_LEDInit(LED6);

/* Turn on LED4, LED3, LED5 and LED6 */
STM_EVAL_LEDOn(LED4);
STM_EVAL_LEDOn(LED3);
STM_EVAL_LEDOn(LED5);
STM_EVAL_LEDOn(LED6);
}






#ifdef USE_FULL_ASSERT

/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

while (1)
{}
}
#endif

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/


stm32f4xx_it.c


#include "stm32f4xx_it.h"
#include "stm32f4_discovery.h"

uint16_t capture = 0;
extern __IO uint16_t CCR1_Val;
extern __IO uint16_t CCR2_Val;
extern __IO uint16_t CCR3_Val;
extern __IO uint16_t CCR4_Val;


/**
实际上当CCR1_Val每次都变化时,就可以用来改变占空比
*/
void TIM3_IRQHandler(void)
{
/*7500为一个循环,周期为7500/500000=0.015,频率为66.67Hz*/
if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);

if(CCR1_Val==5000)
{
STM_EVAL_LEDOn(LED4); //PD12=0。ARR增加5000后,到达这条语句。
CCR1_Val=2500; //所以低电平的百分比为5000/7500=2/3。即占空比为1/3
}
else
{
STM_EVAL_LEDOff(LED4); //PD12=1
CCR1_Val=5000;
}
capture = TIM_GetCapture1(TIM3);
TIM_SetCompare1(TIM3, capture + CCR1_Val);//在原来的CCR1(即capture)基础上加5000,则再过5000,又会触发中断
//另外,有个问题,进入中断时,当ARR计数器快加到65535,而又不足5000时,不是会有数据多余,而产生波形的移动吗?
//回答:不用担心。例如进入中断是,ARR=65000,65000+5000=70000>65535,那么高位会舍去,即为70000-65536=4464
//等于是来了个循环,两次中断间ARR的增量还是5000。所以为了波形的稳定,初始化时,必须要有TIM_Period = 65535
}
else if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);

/* LED3 toggling with frequency = 9.15 Hz */
STM_EVAL_LEDToggle(LED3);//PD13取反
capture = TIM_GetCapture2(TIM3);
TIM_SetCompare2(TIM3, capture + CCR2_Val);
}
else if (TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);

/* LED5 toggling with frequency = 18.31 Hz */
STM_EVAL_LEDToggle(LED5);//PD14取反
capture = TIM_GetCapture3(TIM3);
TIM_SetCompare3(TIM3, capture + CCR3_Val);
}
else
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);

/* LED6 toggling with frequency = 36.62 Hz */
STM_EVAL_LEDToggle(LED6);//PD15取反
capture = TIM_GetCapture4(TIM3);
TIM_SetCompare4(TIM3, capture + CCR4_Val);
}
}


/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/



ReadMe.txt


/**
  @page TIM_TimeBase TIM_TimeBase
  
  @verbatim
  ******************************************************************************
  * @file    TIM_TimeBase/readme.txt
  * @author  MCD Application Team
  * @version V1.0.0
  * @date    19-September-2011
  * @brief   Description of the TIM Time Base example.
  ******************************************************************************
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  ******************************************************************************
   @endverbatim


@par Example Description 


This example shows how to configure the TIM peripheral in Output Compare Timing 
mode with the corresponding Interrupt requests for each channel in order to generate
4 different time bases.


The TIM3CLK frequency is set to SystemCoreClock / 2 (Hz), to get TIM3 counter 
clock at 500 KHz so the Prescaler is computed as following:
   - Prescaler = (TIM3CLK / TIM3 counter clock) - 1


SystemCoreClock is set to 168 MHz for STM32F4xx Devices Revision A.


The TIM3 CC1 register value is equal to 54618, 
CC1 update rate = TIM3 counter clock / CCR1_Val = 9.154 Hz,
so the TIM3 Channel 1 generates an interrupt each 109.2ms


The TIM3 CC2 register is equal to 27309, 
CC2 update rate = TIM3 counter clock / CCR2_Val = 18.31 Hz
so the TIM3 Channel 2 generates an interrupt each 54.6ms


The TIM3 CC3 register is equal to 13654, 
CC3 update rate = TIM3 counter clock / CCR3_Val = 36.62 Hz
so the TIM3 Channel 3 generates an interrupt each 27.3ms


The TIM3 CC4 register is equal to 6826, 
CC4 update rate = TIM3 counter clock / CCR4_Val =  73.25 Hz
so the TIM3 Channel 4 generates an interrupt each 13.65ms.


When the counter value reaches the Output compare registers values, the Output 
Compare interrupts are generated and, in the handler routine, 4 pins(PD.12, PD.13,
PD.14 and PD.15) are toggled with the following frequencies: 


//引脚输出的频率
- PD.12:  4.57 Hz (CC1)
- PD.13:  9.15 Hz (CC2)
- PD.14: 18.31 Hz (CC3) 
- PD.15: 36.62 Hz (CC4)


@par Directory contents 


  - TIM_TimeBase/stm32f4xx_conf.h     Library Configuration file
  - TIM_TimeBase/stm32f4xx_it.c       Interrupt handlers
  - TIM_TimeBase/stm32f4xx_it.h       Interrupt handlers header file
  - TIM_TimeBase/main.c               Main program 
  - TIM_TimeBase/system_stm32f4xx.c   STM32F4xx system clock configuration file
  
 


@par Hardware and Software environment 


  - This example runs on STM32F4xx Devices Revision A.
  
  - This example has been tested with STM32F4-Discovery (MB997) RevA and can be
    easily tailored to any other development board.
    


  - STM32F4-Discovery  
    - Use LED4, LED3, LED5 and LED6 connected respectively to PD.12, PD.13,D.14 
    and PD.15 pins and connect them on an oscilloscope to show the different 
    Time Base signals.  


@par How to use it ? 


In order to make the program work, you must do the following :


 + EWARM
    - Open the TIM_TimeBase.eww workspace 
    - Rebuild all files: Project->Rebuild all
    - Load project image: Project->Debug
    - Run program: Debug->Go(F5)


 + MDK-ARM
    - Open the TIM_TimeBase.uvproj project
    - Rebuild all files: Project->Rebuild all target files
    - Load project image: Debug->Start/Stop Debug Session
    - Run program: Debug->Run (F5)    


 + TASKING
    - Open TASKING toolchain.
    - Click on File->Import, select General->'Existing Projects into Workspace' 
      and then click "Next". 
    - Browse to  TASKING workspace directory and select the project "TIM_TimeBase"   
    - Rebuild all project files: Select the project in the "Project explorer" 
      window then click on Project->build project menu.
    - Run program: Select the project in the "Project explorer" window then click 
      Run->Debug (F11)


 + TrueSTUDIO
    - Open the TrueSTUDIO toolchain.
    - Click on File->Switch Workspace->Other and browse to TrueSTUDIO workspace 
      directory.
    - Click on File->Import, select General->'Existing Projects into Workspace' 
      and then click "Next". 
    - Browse to the TrueSTUDIO workspace directory and select the project "TIM_TimeBase" 
    - Rebuild all project files: Select the project in the "Project explorer" 
      window then click on Project->build project menu.
    - Run program: Select the project in the "Project explorer" window then click 
      Run->Debug (F11)
   
 * <h3><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h3>
 */