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

时间:2021-10-22 21:34:43

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


main.c

[cpp] view plain copy
  1. /********************************************* 
  2.     标题:操作USART的练习 
  3.     软件平台:MDK-ARM Standard Version4.70 
  4.     硬件平台:stm32f4-discovery   
  5.     主频:168M 
  6.     Periph_Driver_version: V1.0.0 
  7.      
  8.     描述:用一个定时器(TIM3),实现四路不同频率、占空比可调的PWM 
  9.           代码参考自STM32F4-Discovery_FW_V1.1.0\Project\Peripheral_Examples\TIM_TimeBase 
  10.  
  11.     author:大舟 
  12.     data:2013-04-13 
  13. **********************************************/  
  14.   
  15. #include "stm32f4_discovery.h"  
  16.   
  17.   
  18.   
  19. TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  
  20. TIM_OCInitTypeDef  TIM_OCInitStructure;  
  21. __IO uint16_t CCR1_Val = 5000;//54618  
  22. __IO uint16_t CCR2_Val = 27309;  
  23. __IO uint16_t CCR3_Val = 13654;  
  24. __IO uint16_t CCR4_Val = 6826;  
  25. uint16_t PrescalerValue = 0;  
  26.   
  27. void TIM_Config(void);  
  28.   
  29.   
  30. int main(void)  
  31. {  
  32.   /*!< At this stage the microcontroller clock setting is already configured,  
  33.        this is done through SystemInit() function which is called from startup 
  34.        file (startup_stm32f4xx.s) before to branch to application main. 
  35.        To reconfigure the default setting of SystemInit() function, refer to 
  36.        system_stm32f4xx.c file 
  37.      */  
  38.   
  39.   /* TIM Configuration */  
  40.   TIM_Config();  
  41.   
  42.   /** ----------------------------------------------------------------------- 
  43.     TIM3 Configuration: Output Compare Timing Mode: 
  44.      
  45.     In this example TIM3 input clock (TIM3CLK) is set to 2 * APB1 clock (PCLK1),  
  46.     since APB1 prescaler is different from 1.    
  47.       TIM3CLK = 2 * PCLK1   
  48.       PCLK1 = HCLK / 4  
  49.       => TIM3CLK = HCLK / 2 = SystemCoreClock /2 
  50.            
  51.     To get TIM3 counter clock at 500 KHz, the prescaler is computed as follows: 
  52.        Prescaler = (TIM3CLK / TIM3 counter clock) - 1 
  53.        Prescaler = ((SystemCoreClock /2) /50 MHz) - 1 
  54.                                                
  55.     CC1 update rate = TIM3 counter clock / CCR1_Val = 9.154 Hz  @note 上面已经将CCR1_Val改为了5000,具体频率,见中断的注释 
  56.     ==> Toggling frequency = 4.57 Hz 
  57.      
  58.     C2 update rate = TIM3 counter clock / CCR2_Val = 18.31 Hz 
  59.     ==> Toggling frequency = 9.15 Hz 
  60.      
  61.     CC3 update rate = TIM3 counter clock / CCR3_Val = 36.62 Hz 
  62.     ==> Toggling frequency = 18.31 Hz 
  63.      
  64.     CC4 update rate = TIM3 counter clock / CCR4_Val = 73.25 Hz 
  65.     ==> Toggling frequency = 36.62 Hz 
  66.  
  67.     Note:  
  68.      SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f4xx.c file. 
  69.      Each time the core clock (HCLK) changes, user had to call SystemCoreClockUpdate() 
  70.      function to update SystemCoreClock variable value. Otherwise, any configuration 
  71.      based on this variable will be incorrect.     
  72.   ----------------------------------------------------------------------- */    
  73.   
  74.   /* Compute the prescaler value */  
  75.   PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 500000) - 1;//=168  
  76.   
  77.   /* Time base configuration */  
  78.   TIM_TimeBaseStructure.TIM_Period = 65535;//65535  
  79.   TIM_TimeBaseStructure.TIM_Prescaler = 0;  
  80.   TIM_TimeBaseStructure.TIM_ClockDivision = 0;  
  81.   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
  82.   
  83.   TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);  
  84.   
  85.   /* Prescaler configuration */  
  86.   TIM_PrescalerConfig(TIM3, PrescalerValue, TIM_PSCReloadMode_Immediate);//对84M进行168分频,即为500KHz  
  87.   
  88.   /* Output Compare Timing Mode configuration: Channel1 */  
  89.   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;  
  90.   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  
  91.   TIM_OCInitStructure.TIM_Pulse = CCR1_Val;  
  92.   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  
  93.   TIM_OC1Init(TIM3, &TIM_OCInitStructure);  
  94.   TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);  
  95.   
  96.   /* Output Compare Timing Mode configuration: Channel2 */  
  97.   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  
  98.   TIM_OCInitStructure.TIM_Pulse = CCR2_Val;  
  99.   TIM_OC2Init(TIM3, &TIM_OCInitStructure);  
  100.   TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable);  
  101.   
  102.   /* Output Compare Timing Mode configuration: Channel3 */  
  103.   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  
  104.   TIM_OCInitStructure.TIM_Pulse = CCR3_Val;  
  105.   TIM_OC3Init(TIM3, &TIM_OCInitStructure);  
  106.   TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Disable);  
  107.   
  108.   /* Output Compare Timing Mode configuration: Channel4 */  
  109.   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  
  110.   TIM_OCInitStructure.TIM_Pulse = CCR4_Val;  
  111.   TIM_OC4Init(TIM3, &TIM_OCInitStructure);  
  112.   TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Disable);  
  113.      
  114.   /* TIM Interrupts enable */    
  115.   TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);  
  116.       
  117.   /* TIM3 enable counter */  
  118.   TIM_Cmd(TIM3, ENABLE);  
  119.   
  120.   while (1);  
  121. }  
  122.   
  123.   
  124.   
  125. /** 
  126.   * @brief  Configure the TIM IRQ Handler. 
  127.   * @param  None 
  128.   * @retval None 
  129.   */  
  130. void TIM_Config(void)  
  131. {  
  132.   NVIC_InitTypeDef NVIC_InitStructure;  
  133.   
  134.   /* TIM3 clock enable */  
  135.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);  
  136.   
  137.   /* Enable the TIM3 gloabal Interrupt */  
  138.   NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  
  139.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
  140.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  
  141.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  142.   NVIC_Init(&NVIC_InitStructure);  
  143.   
  144.   /* Initialize Leds mounted on STM32F4-Discovery board */  
  145.   STM_EVAL_LEDInit(LED4);  
  146.   STM_EVAL_LEDInit(LED3);  
  147.   STM_EVAL_LEDInit(LED5);  
  148.   STM_EVAL_LEDInit(LED6);  
  149.   
  150.   /* Turn on LED4, LED3, LED5 and LED6 */  
  151.   STM_EVAL_LEDOn(LED4);  
  152.   STM_EVAL_LEDOn(LED3);  
  153.   STM_EVAL_LEDOn(LED5);  
  154.   STM_EVAL_LEDOn(LED6);  
  155. }  
  156.   
  157.   
  158.   
  159.   
  160.   
  161.   
  162. #ifdef  USE_FULL_ASSERT  
  163.   
  164. /** 
  165.   * @brief  Reports the name of the source file and the source line number 
  166.   *         where the assert_param error has occurred. 
  167.   * @param  file: pointer to the source file name 
  168.   * @param  line: assert_param error line source number 
  169.   * @retval None 
  170.   */  
  171. void assert_failed(uint8_t* file, uint32_t line)  
  172. {  
  173.   /* User can add his own implementation to report the file name and line number, 
  174.      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */  
  175.   
  176.   while (1)  
  177.   {}  
  178. }  
  179. #endif  
  180.   
  181. /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/  


stm32f4xx_it.c


[cpp] view plain copy
  1. #include "stm32f4xx_it.h"  
  2. #include "stm32f4_discovery.h"  
  3.   
  4. uint16_t capture = 0;  
  5. extern __IO uint16_t CCR1_Val;  
  6. extern __IO uint16_t CCR2_Val;  
  7. extern __IO uint16_t CCR3_Val;  
  8. extern __IO uint16_t CCR4_Val;  
  9.   
  10.   
  11. /** 
  12. 实际上当CCR1_Val每次都变化时,就可以用来改变占空比 
  13. */  
  14. void TIM3_IRQHandler(void)  
  15. {  
  16.     /*7500为一个循环,周期为7500/500000=0.015,频率为66.67Hz*/  
  17.     if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)  
  18.     {  
  19.         TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);  
  20.           
  21.         if(CCR1_Val==5000)  
  22.         {  
  23.             STM_EVAL_LEDOn(LED4);   //PD12=0。ARR增加5000后,到达这条语句。  
  24.             CCR1_Val=2500;          //所以低电平的百分比为5000/7500=2/3。即占空比为1/3  
  25.         }  
  26.         else  
  27.         {  
  28.             STM_EVAL_LEDOff(LED4);  //PD12=1  
  29.             CCR1_Val=5000;  
  30.         }  
  31.         capture = TIM_GetCapture1(TIM3);  
  32.         TIM_SetCompare1(TIM3, capture + CCR1_Val);//在原来的CCR1(即capture)基础上加5000,则再过5000,又会触发中断  
  33.         //另外,有个问题,进入中断时,当ARR计数器快加到65535,而又不足5000时,不是会有数据多余,而产生波形的移动吗?  
  34.         //回答:不用担心。例如进入中断是,ARR=65000,65000+5000=70000>65535,那么高位会舍去,即为70000-65536=4464  
  35.         //等于是来了个循环,两次中断间ARR的增量还是5000。所以为了波形的稳定,初始化时,必须要有TIM_Period = 65535  
  36.     }  
  37.     else if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)  
  38.     {  
  39.         TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);  
  40.   
  41.         /* LED3 toggling with frequency = 9.15 Hz */  
  42.         STM_EVAL_LEDToggle(LED3);//PD13取反  
  43.         capture = TIM_GetCapture2(TIM3);  
  44.         TIM_SetCompare2(TIM3, capture + CCR2_Val);  
  45.     }  
  46.     else if (TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET)  
  47.     {  
  48.         TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);  
  49.   
  50.         /* LED5 toggling with frequency = 18.31 Hz */  
  51.         STM_EVAL_LEDToggle(LED5);//PD14取反  
  52.         capture = TIM_GetCapture3(TIM3);  
  53.         TIM_SetCompare3(TIM3, capture + CCR3_Val);  
  54.     }  
  55.     else  
  56.     {  
  57.         TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);  
  58.   
  59.         /* LED6 toggling with frequency = 36.62 Hz */  
  60.         STM_EVAL_LEDToggle(LED6);//PD15取反  
  61.         capture = TIM_GetCapture4(TIM3);  
  62.         TIM_SetCompare4(TIM3, capture + CCR4_Val);  
  63.     }  
  64. }  
  65.   
  66.   
  67. /******************* (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>
 */