定时器 主从模式 大揭秘

STM32的每个定时器都可以由另一个定时器触发启动定时器一般是通过软件设置而启动,STM32的每个定时器也可以通过外部信号触发而启动,还可以通过另外一个定时器的某一个条件被触发而启动.这里所谓某一个条件可以是定时到时、定时器超时、比较成功等许多条件.这种通过一个定时器触发另一个定时器的工作方式称为定时器的同步,发出触发信号的定时器工作于主模式,接受触发信号而启动的定时器工作于从模式。

未完。。。。。

好几个Timer的相互Trigger的功能,而Timer的选择又要对Layout作妥协,代码改来改去的
Timer的Trigger关系也是调来调去的,一怒之下准备牺牲代码可阅读来跟上layout的步伐


STM32 的Timer之间可以用一Timer Internal Trigger联系起
各个Timer之间的联系可以用下表表示

(原文件名:ITR.jpg) 

定时器 主从模式 大揭秘_第1张图片
如果要用TIM4去触发TIM1,需要将TIM1的Internal Triger配置成ITR3
Timer改来改去容易出错,可以写成一张表,用的时候直接读这张表,由于是宏写的,不会影响运行时的效率,如下:
/*---------------------------------------------------------------------------------------------------------------------------------------*/
/* Just make parameter name shorter */
#define     _GetInternalTrigger(S,M) \
  (S == TIM1 ? (M == TIM5 ? TIM_TS_ITR0 : (M == TIM2 ? TIM_TS_ITR1 : (M == TIM3 ? TIM_TS_ITR2 :(M == TIM4 ? TIM_TS_ITR3 : (u16)-1)))): \
  (S == TIM8 ? (M == TIM1 ? TIM_TS_ITR0 : (M == TIM2 ? TIM_TS_ITR1 : (M == TIM4 ? TIM_TS_ITR2 :(M == TIM5 ? TIM_TS_ITR3 : (u16)-1)))): \
  (S == TIM2 ? (M == TIM1 ? TIM_TS_ITR0 : (M == TIM8 ? TIM_TS_ITR1 : (M == TIM3 ? TIM_TS_ITR2 :(M == TIM4 ? TIM_TS_ITR3 : (u16)-1)))): \
  (S == TIM3 ? (M == TIM1 ? TIM_TS_ITR0 : (M == TIM2 ? TIM_TS_ITR1 : (M == TIM5 ? TIM_TS_ITR2 :(M == TIM4 ? TIM_TS_ITR3 : (u16)-1)))): \
  (S == TIM4 ? (M == TIM1 ? TIM_TS_ITR0 : (M == TIM2 ? TIM_TS_ITR1 : (M == TIM3 ? TIM_TS_ITR2 :(M == TIM8 ? TIM_TS_ITR3 : (u16)-1)))): \
  (S == TIM5 ? (M == TIM2 ? TIM_TS_ITR0 : (M == TIM3 ? TIM_TS_ITR1 : (M == TIM4 ? TIM_TS_ITR2 :(M == TIM8 ? TIM_TS_ITR3 : (u16)-1)))): \
  (u16)-1))))))
    #define     GetInternalTrigger(SlaveTimer,MasterTimer)      _GetInternalTrigger(SlaveTimer,MasterTimer)
/*---------------------------------------------------------------------------------------------------------------------------------------*/

这样在要用的时候这样写就行了
/*-----------------------------------------------------------------------------------------------------*/
    TIM_ITRxExternalClockConfig(TIM1,GetInternalTrigger(TIM1,TIM4)); /* 用TIM4去触发TIM1 */
/*-----------------------------------------------------------------------------------------------------*/

不是每一种Timer的组合都会有这样触发方式,如果写错了需要能够报出这个错误
可以用一种叫做Compile Time Assert的方法
比如:
/*-----------------------------------------------------------------------------------------------------*/
    #define compile_assert(exp)   {extern char lxyppc_at_163_dot_com[(exp) ? 1:-1];}
/*-----------------------------------------------------------------------------------------------------*/

这里是利用了数组下标必需大于零作为compile check的条件,也可以写成别的形式

代码可以这样写
/*-----------------------------------------------------------------------------------------------------*/
    compile_assert((u16)GetInternalTrigger(TIM1,TIM4) != (u16)-1);
    TIM_ITRxExternalClockConfig(TIM1,GetInternalTrigger(TIM1,TIM4)); /* 用TIM4去触发TIM1,正确,编译通过 */
    compile_assert((u16)GetInternalTrigger(TIM2,TIM5) != (u16)-1);
    TIM_ITRxExternalClockConfig(TIM1,GetInternalTrigger(TIM2,TIM5)); /* 用TIM5去触发TIM2,错误,编译报错 */
/*-----------------------------------------------------------------------------------------------------*/

以上代码IAR 4.42 (32K限制版测试通过)
/**
   以上写法不一定能被所有编译器支持,本人对此产生的移植性问题不负任何责任
   P.S. 以上针对layout的牢骚纯属杜撰,只是为了引言一下:)
*/


//--------------------------------------------------------------------------------------------------------------------------------------------------------------

STM32 Timer的Gate模式来精确控制脉冲个数 发布时间:2009-12-03 22:04:52
技术类别:ARM  
 

策略:


用到了Timer Master Slave中的Gate模式 
比如TIM1输出PWM, 频率为F 
可以用TIM2通过Gate来控制TIM1的输出 
将TIM2预频设为1/(F*2),则TIM2的Period 就是 脉冲个数*2 - 1 

/*           1     2     3     4     5     6     7     8     9 
             __    __    __    __    __    __    __    __    __            
            |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |             
TIM1:    ___|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |____________________ 
          ->| Period1|<- 
             1) 2) 3) 4) 5) 6) 7) 8) 9) 10)11)12)13)14)15)16)17) 
             __________________________________________________   
            |                                                  |   
TIM2:    ___|                                                  |____________________ 
          ->|  |<--- Pres2 = Period1/2 
            |<------------  Period2 =  N*2-1 = 17 ------------>| 
 */


 


实现代码


软件: 
IAR 4.42限制版 
ST库    2.01 
硬件: 
万利199开发板 STM3210B-LK1 
/*0001*/  /* Includes ------------------------------------------------------------------*/ 
/*0002*/  #include "stm32f10x_lib.h" 
/*0003*/   
/*0004*/  /* Private typedef -----------------------------------------------------------*/ 
/*0005*/  /* Private define ------------------------------------------------------------*/ 
/*0006*/  /* Private macro -------------------------------------------------------------*/ 
/*0007*/  /* Private variables ---------------------------------------------------------*/ 
/*0008*/  ErrorStatus HSEStartUpStatus; 
/*0009*/   
/*0010*/  /* Private function prototypes -----------------------------------------------*/ 
/*0011*/  void  RCC_Configuration(void); 
/*0012*/  void  NVIC_Configuration(void); 
/*0013*/  /* Private functions ---------------------------------------------------------*/ 
/*0014*/   
/*0015*/  #define   PWM_Period      120 
/*0016*/  int main(void
/*0017*/  
/*0018*/    u16       waveNumber = 10
/*0019*/    /* System Clocks Configuration */ 
/*0020*/    RCC_Configuration(); 
/*0021*/   
/*0022*/    /* Enable related peripheral clocks */ 
/*0023*/    RCC_APB2PeriphClockCmd(  RCC_APB2Periph_GPIOA,ENABLE); 
/*0024*/    RCC_APB2PeriphClockCmd(  RCC_APB2Periph_GPIOB,ENABLE); 
/*0025*/    RCC_APB2PeriphClockCmd(  RCC_APB2Periph_TIM1,ENABLE); 
/*0026*/    RCC_APB1PeriphClockCmd(  RCC_APB1Periph_TIM3,ENABLE); 
/*0027*/     
/*0028*/    /* Config IO for related timers */ 
/*0029*/    { 
/*0030*/      GPIO_InitTypeDef GPIO_InitStructure; 
/*0031*/      /* Timer1 Channel 2, PA9 */ 
/*0032*/      GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_9; 
/*0033*/      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
/*0034*/      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
/*0035*/      GPIO_Init(GPIOA, &GPIO_InitStructure); 
/*0036*/      /* Timer3 Channel 4, PB1*/ 
/*0037*/      GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_1; 
/*0038*/      GPIO_Init(GPIOB, &GPIO_InitStructure); 
/*0039*/    } 
/*0040*/    
/* Setup Timer3 channel 4, Timer3 is master timer 
|*0041*|       This timer is used to control the waveform count of timer1 */
 
/*0042*/    { 
/*0043*/      TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; 
/*0044*/      TIM_OCInitTypeDef  TIM_OCInitStructure; 
/*0045*/      TIM_DeInit(TIM3); 
/*0046*/      TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); 
/*0047*/      TIM_OCStructInit(&TIM_OCInitStructure); 
/*0048*/      TIM_TimeBaseStructure.TIM_Prescaler = PWM_Period/2 - 1
/*0049*/      TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
/*0050*/      TIM_TimeBaseStructure.TIM_Period = waveNumber*2
/*0051*/      TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
/*0052*/      TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); 
/*0053*/       
/*0054*/      /* Timer2 Channel 3 Configuration in PWM2 mode, this is used for enable Recive clcok */ 
/*0055*/      TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 
/*0056*/      TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
/*0057*/      TIM_OCInitStructure.TIM_Pulse = waveNumber*2 - 1
/*0058*/      TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 
/*0059*/      TIM_OC4Init(TIM3,&TIM_OCInitStructure); 
/*0060*/      TIM_CtrlPWMOutputs(TIM3, ENABLE); 
/*0061*/      TIM_SelectOnePulseMode(TIM3, TIM_OPMode_Single); 
/*0062*/    } 
/*0063*/    
/* Setup timer1 channel 2, Timer1 is slave timer  
|*0064*|       This timer is used to output waveforms */
 
/*0065*/    { 
/*0066*/      TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; 
/*0067*/      TIM_OCInitTypeDef  TIM_OCInitStructure; 
/*0068*/      TIM_DeInit(TIM1); 
/*0069*/      TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); 
/*0070*/      TIM_OCStructInit(&TIM_OCInitStructure); 
/*0071*/      TIM_TimeBaseStructure.TIM_Prescaler = 0
/*0072*/      TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
/*0073*/      TIM_TimeBaseStructure.TIM_Period = PWM_Period; 
/*0074*/      TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
/*0075*/      TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure); 
/*0076*/       
/*0077*/      /* Timer2 Channel 3 Configuration in PWM2 mode, this is used for enable Recive clcok */ 
/*0078*/      TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 
/*0079*/      TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
/*0080*/      TIM_OCInitStructure.TIM_Pulse = PWM_Period/2
/*0081*/      TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 
/*0082*/      TIM_OC2Init(TIM1,&TIM_OCInitStructure); 
/*0083*/      TIM_CtrlPWMOutputs(TIM1, ENABLE); 
/*0084*/    } 
/*0085*/    
/* Create relationship between timer1 and timer3, timer3 is master, timer1 is slave 
|*0086*|      timer1 is work under gate control mode, and controled by timer3 
|*0087*|      timer3's channel 4 is used as the control signal 
|*0088*|     */
 
/*0089*/      /* Enable timer's master/slave work mode */ 
/*0090*/      TIM_SelectMasterSlaveMode(TIM3,TIM_MasterSlaveMode_Enable); 
/*0091*/      TIM_SelectMasterSlaveMode(TIM1,TIM_MasterSlaveMode_Enable); 
/*0092*/      /* timer3's channel 4 is used as the control signal */ 
/*0093*/      TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_OC4Ref ); 
/*0094*/      /* Check the master/slave is valid or not */ 
/*0095*/      
compile_assert((u16)GetInternalTrigger(TIM1,TIM3) != (u16)-1);  
/*0096*/      /* Config timer1's external clock */ 
/*0097*/      TIM_ITRxExternalClockConfig(TIM1, 
GetInternalTrigger(TIM1,TIM3)); 
/*0098*/      TIM_SelectSlaveMode(TIM1,TIM_SlaveMode_Gated); 
/*0099*/       
/*0100*/    /* Enable the slave tiemr*/ 
/*0101*/    TIM_Cmd(TIM1,ENABLE); 
/*0102*/    //SetupAlltimers(); 
/*0103*/    while(1){ 
/*0104*/      /* Check whether the previous action is done or not */ 
/*0105*/      if(!(TIM3->CR1 & 1)){ 
/*0106*/        TIM1->CNT = 0
/* It would be very perfect if gate mode can  
|*0107*|                          reset the slave timer automatically */
 
/*0108*/        TIM3->ARR = waveNumber*2;  /* Reload wave number*/ 
/*0109*/        TIM3->CCR4 = waveNumber*2 - 1
/*0110*/        TIM3->CR1|=1/* Re-enable the timer */ 
/*0111*/        /* update waveform number */ 
/*0112*/        waveNumber++; 
/*0113*/        if(waveNumber == 13){ 
/*0114*/          waveNumber = 10
/*0115*/        } 
/*0116*/      } 
/*0117*/    } 
/*0118*/  
/*0119*/   
/*0120*/  
/******************************************************************************* 
|*0121*|  * Function Name  : RCC_Configuration 
|*0122*|  * Description    : Configures the different system clocks. 
|*0123*|  * Input          : None 
|*0124*|  * Output         : None 
|*0125*|  * Return         : None 
|*0126*|  *******************************************************************************/
 
/*0127*/  void RCC_Configuration(void
/*0128*/  
/*0129*/    /* RCC system reset(for debug purpose) */ 
/*0130*/    RCC_DeInit(); 
/*0131*/   
/*0132*/    /* Enable HSE */ 
/*0133*/    RCC_HSEConfig(RCC_HSE_ON); 
/*0134*/   
/*0135*/    /* Wait till HSE is ready */ 
/*0136*/    HSEStartUpStatus = RCC_WaitForHSEStartUp(); 
/*0137*/   
/*0138*/    if(HSEStartUpStatus == SUCCESS) 
/*0139*/    { 
/*0140*/      /* Enable Prefetch Buffer */ 
/*0141*/      FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); 
/*0142*/   
/*0143*/      /* Flash 2 wait state */ 
/*0144*/      FLASH_SetLatency(FLASH_Latency_2); 
/*0145*/    
/*0146*/      /* HCLK = SYSCLK */ 
/*0147*/      RCC_HCLKConfig(RCC_SYSCLK_Div1);  
/*0148*/     
/*0149*/      /* PCLK2 = HCLK */ 
/*0150*/      RCC_PCLK2Config(RCC_HCLK_Div1);  
/*0151*/   
/*0152*/      /* PCLK1 = HCLK/2 */ 
/*0153*/      RCC_PCLK1Config(RCC_HCLK_Div2); 
/*0154*/   
/*0155*/      /* PLLCLK = 8MHz * 9 = 72 MHz */ 
/*0156*/      RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); 
/*0157*/   
/*0158*/      /* Enable PLL */  
/*0159*/      RCC_PLLCmd(ENABLE); 
/*0160*/   
/*0161*/      /* Wait till PLL is ready */ 
/*0162*/      while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) 
/*0163*/      { 
/*0164*/      } 
/*0165*/   
/*0166*/      /* Select PLL as system clock source */ 
/*0167*/      RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); 
/*0168*/   
/*0169*/      /* Wait till PLL is used as system clock source */ 
/*0170*/      while(RCC_GetSYSCLKSource() != 0x08
/*0171*/      { 
/*0172*/      } 
/*0173*/    } 
/*0174*/  }

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
PA8-----------------TIM1_CH1 
PA0--------------TIM2_CH1 
上面的是PA8输出,下面的是PA0输出。
完成的功能:PA8和PA0分别输出PWM波,单PA8为低电平的时候PA0才输出PWM波
否则不输出,这个时候PA0可能输出高,也可能输出低,这个暂时不知道怎么解决。。


稍微解释一下代码:
1.TIM1设置为主模式,把PWM的参考电平OC1REF作为TRGO触发输出。
  TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);
  TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_OC1Ref);


2.将TIM2设置为从模式的门控模式,将TIM1的TRG0作为触发输入,控制定时器的开启和关闭。(PS:门控模式:当触发输入(TRGI)为高时,计数器的时钟开启。一旦触发输入变为低,则计数器停止(但不复位)。计数器的启动和停止都是受控的。)
  TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Gated);
  TIM_SelectInputTrigger(TIM2, TIM_TS_ITR0);

定时器 主从模式 大揭秘_第2张图片
参考代码如下:


//定时器主从模式初始化
void TIM_MasterSlaveModeInit(void){
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
         GPIO_InitTypeDef GPIO_InitStructure;

//打开时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 , ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

//配置TIM1定时器周期
  TIM_TimeBaseStructure.TIM_Period = 100;
  TIM_TimeBaseStructure.TIM_Prescaler = 719;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

  //主模式  TIM1_CH1 PWM配置
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 50;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;

  TIM_OC1Init(TIM1, &TIM_OCInitStructure);
//选择主从模式
  TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);

  //主定时器触发输出配置
  TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_OC1Ref); //选择PWM 参考电压OC1REF为触发输出

//配置TIM2定时器周期
  TIM_TimeBaseStructure.TIM_Period = 10;
  TIM_TimeBaseStructure.TIM_Prescaler = 719;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

//从定时器TIM2 PWM输出配置
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 5;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  TIM_OC1Init(TIM2, &TIM_OCInitStructure);

//从模式选择
  TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Gated); //门控模式
  TIM_SelectInputTrigger(TIM2, TIM_TS_ITR0); //定时器1 的Trigger 0做为触发输入

//使能定时器
  TIM_Cmd(TIM2, ENABLE);

  TIM_Cmd(TIM1, ENABLE);
  TIM_CtrlPWMOutputs(TIM1, ENABLE);


}
----------------------------------------------------------------------------------------------------精确个数高速脉冲输出-----------------------------------------
/****************************
**TIM2的通道1使用单脉冲模式
**TIM3使用门控模式用来输出PWM
**
****************************/
//TIM2per:重装值
//Compare1:比较捕获1的预装载值
void Motor_Init(u16 TIM2per, u16 TIM3per, u16 TIM3Compare1)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
  TIM_OCInitTypeDef TIM_OCInitStruct;
  GPIO_InitTypeDef GPIO_InitStruct;
  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能定时器2的时钟
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能定时器3的时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//使能复用IO时钟
  
http://write.blog.csdn.net/postedit  
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_6;//PA0
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA,&GPIO_InitStruct);
  
  //TIM2工作在单脉冲下
  TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//没有时钟分割
  TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式
  TIM_TimeBaseInitStruct.TIM_Prescaler = 7200;//预分频值,每100us计数一次
  TIM_TimeBaseInitStruct.TIM_Period = TIM2per;//重装值
  TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
  
  TIM_SelectOnePulseMode(TIM2,TIM_OPMode_Single);//设置TIM2在单脉冲模式,且是单一的脉冲,在下一个更新事件停止
  TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Enable);//使能定时器2的通道1预装载寄存器
  TIM_SelectOutputTrigger(TIM2,TIM_TRGOSource_OC1Ref);
  
  TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM2;//在向上计数时,一旦TIMx_CNT   TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//OC1输出使能
  TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//有效电平为高
  TIM_OCInitStruct.TIM_Pulse = 1;//比较捕获1的预装载值
  TIM_OC1Init(TIM2,&TIM_OCInitStruct);
  
  TIM_Cmd(TIM2,DISABLE);//先不使能能TIM2
  
  
  //TIM3工作在从模式的门控模式下的PWM输出模式
  TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//没有时钟分割
  TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式
  TIM_TimeBaseInitStruct.TIM_Prescaler = 720;//预分频值,10us计数一次
  TIM_TimeBaseInitStruct.TIM_Period = TIM3per;//重装值
  TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
  
  TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated);//TIM3为门控模式
  TIM_SelectMasterSlaveMode(TIM3,TIM_MasterSlaveMode_Enable);//使能TIM3的主从模式
  TIM_SelectInputTrigger(TIM3,TIM_TS_ITR1);//内部触发,从TIM2触发
  
  TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM2;//在向上计数时,一旦TIMx_CNT   TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//OC1输出使能
  TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//有效电平为高
  TIM_OCInitStruct.TIM_Pulse = TIM3Compare1;//比较捕获1的预装载值
  TIM_OC1Init(TIM3,&TIM_OCInitStruct);
  
  TIM_Cmd(TIM3,ENABLE);//使能TIM3
}


//设置PWM的输出
//Cycle:为周期,单位(us)
//Pulse_Num:为脉冲个数(小于3200)
void TIM2_TIM3_PWM(u16 Cycle, u16 Pulse_Num)
{
  u16 TIM3per = 0;
  u32 Time = 0;
  //改变TIM3的重装值改变脉冲频率这里设置脉冲占空比为50%
  //改变TIM2的预分频器和重装值改变脉冲个数
    
  Time = Cycle * Pulse_Num;
  Time /= 100;              //预分频为7200,100us计数一次
  TIM3per = Cycle/10;       //预分频为720,10us计数一次
  
  TIM_SetAutoreload(TIM2, Time+1);//设置TIM2的重装值
  TIM_SetAutoreload(TIM3, TIM3per-1);//设置TIM3的重装值
  TIM_SetCompare1(TIM3,TIM3per/2);//设置占空比为50%
  TIM_Cmd(TIM2,ENABLE);//使能TIM2
}


你可能感兴趣的:(32,timer)