STM32定时器和外部触发同步的应用

一、定时器和外部触发的同步

TIMx定时器能够在多种模式下和一个外部的触发同步:复位模式、门控模式和触发模式。

  • 从模式:复位模式

复位模式时序图如下所示:

配置通道1以检测TI1的上升沿,配置定时器为复位模式,计数器为向上计数模式,选择T1位输入源。每一个计数器时钟周期计数器寄存器自增。当TI1产生一个上升沿时,计数器寄存器清0重新开始计数。

  • 从模式:门控模式

门控模式时序图如下所示:

配置通道1以检测TI1的低电平,配置定时器为门控模式,计数器为向上计数模式,选择T1为输入源。每一个计数器时钟周期计数器寄存器自增。只要TI1为低,计数器开始依据内部时钟计数,在TI1为高电平时停止计数。

  • 从模式:触发模式

配置通道2检测TI2的上升沿。配置定时器为触发模式,选择TI2为输入源。当TI2出现一个上升沿时,计数器开始在内部时钟的驱动下计数。

二、利用复位模式串口接收不定长数据

利用复位模式串口接收不定长数据的思路为:将定时器通道引脚与串口RX引脚硬件上连接,串口接收使用DMA方式,定时器在串口未收到数据时不工作,当串口收到数据时,配置定时器,关闭串口中断,当串口上还有数据未接收完成时,计数器不断清0重新开始计数,一旦串口无接收数据时,计数器不再复位,知道产生计数器中断,然后将收到的数据读出。

  • 串口配置:

这里都是些常规配置。

/***************************************************************************
 * @fn          Usart1_Configuration
 *     
 * @brief       
 *     
 * @data        
 *     
 * @param       BaudRate - 
 *              NewState - ENABLE/DISABLE
 *              
 * @return      void
 ***************************************************************************
 */ 
void Usart1_Configuration(uint32_t BaudRate,uint16_t parity, uint16_t wordlength, uint16_t stopbits,FunctionalState NewState)
{
  USART_InitTypeDef USART_InitStructure;        
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* config USART1 clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);
  
  /* USART1 GPIO config */
  /* Configure USART1 Tx (PA.9) as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);    

  /* Configure USART1 Rx (PA.10) as input floating */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  USART_DeInit(USART1);
	
  
  USART_InitStructure.USART_BaudRate            = BaudRate ;         //
  USART_InitStructure.USART_WordLength          = wordlength;  //
  USART_InitStructure.USART_StopBits            = stopbits;   //´
  USART_InitStructure.USART_Parity              = parity ;   //
  USART_InitStructure.USART_HardwareFlowControl =        USART_HardwareFlowControl_None;//Ó²¼þÁ÷ʧÄÜ
  USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx; //
  USART_Init(USART1, &USART_InitStructure);               //´
  USART_ITConfig(USART1,USART_IT_RXNE,NewState);              //

  __nop(); __nop();
  USART_Cmd(USART1, NewState);                          //
}



/***************************************************************************
 * @fn          USART1_NVIC_Configuration
 *     
 * @brief       ÅäÖô®¿Ú1Öжϡ£
 *              USART1ÖжÏ×éΪµÚ3×飬ÇÀÕ¼ÓÅÏȼ¶1£¬ÏìÓ¦ÓÅÏȼ¶0
 *
 * @data        2015Äê08ÔÂ05ÈÕ
 *     
 * @param       NewState - ENABLE/DISABLE
 *     
 * @return      void
 ***************************************************************************
 */
void USART1_NVIC_Configuration(FunctionalState NewState)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  NVIC_SetVectorTable (NVIC_VectTab_FLASH, NVIC_VECTTAB_FLASH_OFFSET);  
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;  
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = NewState;
  NVIC_Init(&NVIC_InitStructure);
	
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;  
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;  
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  NVIC_Init(&NVIC_InitStructure); 
	
}
/***************************************************************************
 * @fn          Usart1_DMA_Configuration
 *     
 * @brief       ÅäÖÃUSART1µÄDMA½ÓÊպͷ¢ËÍ,USART2->TXʹÓÃDMA1_Channel6,
 *              USART2->RXʹÓÃDMA1_Channel7¡£
 *     
 * @data        2015Äê08ÔÂ05ÈÕ
 *     
 * @param       void
 *     
 * @return      void
 ***************************************************************************
 */ 

void Usart1_DMA_Configuration(void)
{
  DMA_InitTypeDef DMA_InitStructure;
  /* DMA clock enable */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//DMA1
  
  /* DMA1 Channel5 (triggered by USART1 Rx event) Config */
  DMA_DeInit(DMA1_Channel5);  
  DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40013804;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)usart1_recv_data.RecvData;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = USART1_DMA_BUFFER_SIZE;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel5, &DMA_InitStructure);
  //DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);
  //DMA_ITConfig(DMA1_Channel6, DMA_IT_TE, ENABLE);
  
  /* Enable USART1 DMA RX request */
  USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
  DMA_Cmd(DMA1_Channel5, ENABLE);  
}
  • 定时器配置:

定时器配置比较重要,我这里设置了输出比较,并且开了CC2中断,当计数器寄存器的值达到输出比较寄存器的值时会产生中断。然后选择TI2为输入源,且为复位模式,当TI2有信号时则计数器清零,这样不会产生CC1比较中断。

/***************************************************************************
 * @fn          TIM4_Configuration
 *     
 * @brief       TIM4ÅäÖÃ,ʹÓø´Î»Ä£Ê½¡£TIM4µÄ²¶»ñ/±È½ÏÊäÈë2ºÍ´®¿Ú2µÄRXÔÚÓ²¼þ
 *              ÉÏÏàÁ¬, ´®¿ÚÓÐÊý¾Ýʱ£¬TIM4Ò»Ö±¸´Î»£¬Ò»µ©´®¿ÚûÓÐÊý¾Ý£¬ÔòTIM4
 *              ²»ÔÙ¸´Î»¡£TIM4³¬Ê±ºó£¬»á²úÉúÒ»¸ö³¬Ê±Öжϡ£
 *     
 * @data        2015Äê08ÔÂ05ÈÕ
 *     
 * @param       void
 *     
 * @return      void
 ***************************************************************************
 */ 
void TIM4_Configuration(uint32_t bandrate)
{
  
	uint16_t tim_pluse = bandrate == 2400?  80: 40;//2400²¨ÌØÂÊʱ ¼ÆÊý80¸öÖÜÆÚ ÆäÓà40¸öÖÜÆÚ	
	
  /* TIM4 configuration -------------------------------------*/ 
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_OCInitTypeDef  TIM_OCInitStructure;
  TIM_ICInitTypeDef  TIM_ICInitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;   
      /* Enable TIM4 clock */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4 , ENABLE);
  TIM_DeInit(TIM4);
  TIM_TimeBaseStructure.TIM_Period = 65535;                           //65535
  TIM_TimeBaseStructure.TIM_Prescaler = (7200 - 1);                   //3600
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
  TIM_ARRPreloadConfig(TIM4, DISABLE);  
  
  /* Output Compare  Mode configuration: Channel1 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;
  TIM_OCInitStructure.TIM_Pulse = tim_pluse;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  TIM_OC2Init(TIM4, &TIM_OCInitStructure);
  
   /* TIM4 Channel 1 Input Capture Configuration */
//  TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
//  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
//  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
//  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
//  TIM_ICInitStructure.TIM_ICFilter = 0;
//  TIM_ICInit(TIM4, &TIM_ICInitStructure);

  /* TIM4 Input trigger configuration: External Trigger connected to TI2 */
  TIM_SelectInputTrigger(TIM4, TIM_TS_TI2FP2);
  
  /* TIM4 configuration in slave reset mode  where the timer counter is 
     re-initialied in response to rising edges on an input capture (TI2) */
  TIM_SelectSlaveMode(TIM4,  TIM_SlaveMode_Reset);
  /* TIM4 IT CC1 enable */
  TIM_ITConfig(TIM4, TIM_IT_CC2, ENABLE);
	
	NVIC_SetVectorTable (NVIC_VectTab_FLASH, NVIC_VECTTAB_FLASH_OFFSET);
  NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);  
  TIM_Cmd(TIM4, ENABLE);  
  
}  
  • 串口中断:
/***************************************************************************
 * @fn          USAR1_IRQHandler
 *     
 * @brief       ½ÓÊÕµ½Ò»¸öByteµÄÊý¾Ýºó£¬²úÉú´®¿ÚÖжϡ£¹Ø±Õ´®¿ÚÖжϣ¬Ê¹Äܶ¨Ê±Æ÷.
 *     
 * @data        2015Äê08ÔÂ05ÈÕ
 *     
 * @param       
 *     
 * @return      
 ***************************************************************************
 */ 
void USART1_IRQHandler() 
{
  RS485_recving = 1;
	
  globalFlag.uart1_dma_flag = 1;
  uint32_t rs485_bandrate = 0;	
	
  USART1_NVIC_Configuration(DISABLE); 
	
  change_to_rate(rs485_para.band_rate, &rs485_bandrate);	
  TIM4_Configuration(rs485_bandrate);
}
  • 定时器中断:

定时器中断产生后将DMA缓冲区数据提取出来。

/***************************************************************************
 * @fn          TIM4_IRQHandler
 *     
 * @brief       TIM4³¬Ê±ÖжÏ
 *     
 * @data        2015Äê08ÔÂ05ÈÕ
 *     
 * @param       void
 *     
 * @return      void
 ***************************************************************************
 */ 
void TIM4_IRQHandler(void)
{
  TIM_Cmd(TIM4, DISABLE); 
  TIM_ClearFlag(TIM4, TIM_IT_CC2);  
  TIM_SetCounter(TIM4,0);
  
  NVIC_ClearPendingFlag(USART1_IRQn);
  USART1_NVIC_Configuration(ENABLE);
	
  Iterates_usart1_buffer();
	
}

猜你喜欢

转载自blog.csdn.net/qq_15391889/article/details/84997620