stm32f10 TIM复位模式+DMA+中断

2019-03-23 19:04发布

最近在做曼切斯特的解码,用TIM2-ch2复位模式+输入捕获模式 来捕捉每2个上升沿间的计数值,并用DMA传输到指定数组(编码率1.5M,必须用DMA)。另外,由于一帧数据内的上升沿个数不定,需要检测一帧数据是否结束。我这么考虑的:一帧结束时,TIM2在接收下一帧的上升沿前,计数器肯定溢出,在溢出中断里修改标志位即可;而在接收数据时,TIM2被上升沿复位,不会有溢出。
    但是,程序跑下来发现,使能了TIM2的DMA请求后,TIM2的溢出中断标志位一直为1,清零语句无效。然后,我改用了TIM5-ch2(和TIM2-ch2共用PA1引脚)来做帧结束的检测,仍旧遇到TIM5中断溢出标志一直为1的问题,初始化完成后就直接进入TIM5中断,并且不能清楚中断标志位。用TIM5ch2的代码如下,希望懂的帮忙解答下~
 int main(void)
{
  RCC_Configuration();            
  GPIO_Configuration();
  NVIC_Configuration();   
   DMA_Configuration();
   TIM2_init(); //TIM2 捕捉曼切斯特码2个上升沿间时间,用于解码
   Tim5_init();   //用于超时检测,从触发器复位模式,会被上升沿不断复位 ,直到数据接收完毕,没有上升沿了
    while(1){
  while(decTag){} //decTag 一帧数据结束的标志位,在TIM5的中断函数里设置
   }
}
void RCC_Configuration(void){
  SystemInit();
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA  , ENABLE);
}
void GPIO_Configuration(void)
{
   GPIO_InitTypeDef GPIO_InitStructure;
   
  /* TIM3 channel 2 pin (PA.07) configuration */
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;    //PA1对应TIM2-CH2和 TIM5-ch2
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
   GPIO_Init(GPIOA, &GPIO_InitStructure);              
}
void NVIC_Configuration(void)
{
   NVIC_InitTypeDef NVIC_InitStructure;
   /* Enable the TIM3 global Interrupt */
   NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
/* */  
   NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);   
}
void DMA_Configuration(void)
{
   
  TIM_ICInitTypeDef  TIM_ICInitStructure;
  DMA_InitTypeDef  DMA_InitStructure;
     
   TIM_ClearFlag(TIM2, TIM_FLAG_Update);
   TIM_ClearFlag(TIM2, TIM_FLAG_CC2);
   TIM_ClearFlag(TIM2, TIM_FLAG_CC1OF);  
   TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;   //tim2-ch2 上升沿触发
   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 = 0x0;         
   
    DMA_DeInit(DMA1_Channel7);                     
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)0x40000038; // ((u32)TIM2->CCR2);   
    DMA_InitStructure.DMA_MemoryBaseAddr =(u32)data;           
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;           
    DMA_InitStructure.DMA_BufferSize = 100;   //137  270               数据个数
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;         
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word ; //一字节数据
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;  
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// DMA_Mode_Circular;           
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                          
   
   TIM_ICInit(TIM2, &TIM_ICInitStructure);   
   TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2 );   
   TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset); //  TIM2使用了从触发器,复位模式
   TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable); //启动定时器的被动触发
   TIM_SetCompare2(TIM2, 0); //设置捕获计数器初值

    TIM_DMACmd(TIM2,TIM_DMA_CC2,ENABLE);
    DMA_Init(DMA1_Channel7, &DMA_InitStructure);  
//  DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);  
//  DMA_ClearITPendingBit(DMA1_IT_TC7|DMA1_IT_HT7|DMA1_IT_TE7);
     DMA_Cmd(DMA1_Channel7, ENABLE);     
}
void TIM2_init()
{
          //TIM2的设置代码 有部分移到DMA_init()了
  TIM_TimeBaseInitTypeDef  TIM2_TimeBaseStructure;  
  TIM2_TimeBaseStructure.TIM_Prescaler =0;
  TIM2_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //计数器向上计数模式
  TIM2_TimeBaseStructure.TIM_Period =0xFFFF;     
  TIM2_TimeBaseStructure.TIM_ClockDivision = 0x0;     
   
  TIM_TimeBaseInit(TIM2,&TIM2_TimeBaseStructure);
   TIM_ClearFlag(TIM2, TIM_IT_CC2);
    TIM_ARRPreloadConfig(TIM2, DISABLE);
// TIM_ITConfig(TIM2,TIM_IT_CC2,ENABLE);    //TIM2ch2不开中断使能
     TIM_Cmd(TIM2, ENABLE);   
} 

void Tim5_init()
{  
   TIM_ICInitTypeDef  TIM_ICInitStructure;
   TIM_TimeBaseInitTypeDef  TIM5_TimeBaseStructure;
   TIM5_TimeBaseStructure.TIM_Prescaler =0;   
   TIM5_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //计数器向上计数模式
   TIM5_TimeBaseStructure.TIM_Period =2000;//一帧数据结束时的超时
   TIM5_TimeBaseStructure.TIM_ClockDivision = 0x0;   
   TIM_TimeBaseInit(TIM5,&TIM5_TimeBaseStructure);
  
   TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;      
   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 = 0x0;      
   TIM_ICInit(TIM5, &TIM_ICInitStructure);
   TIM_SelectInputTrigger(TIM5, TIM_TS_TI2FP2 );   
   TIM_SelectSlaveMode(TIM5, TIM_SlaveMode_Reset); //复位模式,被上升沿复位
   TIM_SelectMasterSlaveMode(TIM5, TIM_MasterSlaveMode_Enable);
   TIM_SetCompare1(TIM5, 0); //设置捕获计数器初值
      
   TIM_ClearFlag(TIM5, TIM_IT_CC2);
   TIM_ARRPreloadConfig(TIM5, DISABLE);
   TIM_ITConfig(TIM5,TIM_IT_CC2,ENABLE);   //使能 TIM5_ch2的通道2中断
   TIM_Cmd(TIM5, ENABLE);
}
void TIM5_IRQHandler(void)
{  
 if (TIM_GetITStatus(TIM5, TIM_IT_CC2) != RESET){
       DMA1_Channel7->CCR &= (uint16_t)(~DMA_CCR7_EN); // 关DMA
   TIM5->SR = (uint16_t)~TIM_IT_CC2;  //清中断标志
     decTag=1; // 一帧数据接收完,设置标志位
   
      }
}

[ 本帖最后由 Inownl 于 2013-12-5 15:20 编辑 ] 此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
9条回答
Li_Lei
1楼-- · 2019-03-24 16:33
把范围缩小一点,
你这样,先不管帧结束,先取上升沿扑获和dma这块儿行了没有?
信号给进去先看看dma有数据没有?
Inownl
2楼-- · 2019-03-24 17:30
 精彩回答 2  元偷偷看……
Inownl
3楼-- · 2019-03-24 19:42
中断进不去的原因找到了,开发板的例程里的中断函数名和startup里定义的不一样,晕....

一周热门 更多>