打印
[STM32F1]

求助下:TIM3 DMA 捕获 + 溢出计数

[复制链接]
1387|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 kent8013 于 2015-7-19 15:31 编辑

用TIM3 捕获来测量一个 ,频率变化的方波信号,定时器分频=0; 把捕获值用DMA存入数组; 用溢出中断方式,累加溢出计数值; DAM 传输3个值到数组,由于定时器只做短时间捕获,捕获完成后,然后关闭溢出中断,捕获前在开启,DMA由于是单次模式,捕获完成后,也会自动停止,下次捕获前在启用,但是定时器不关闭;
现在出现一个问题,溢出中断计数不对;

1);上升沿捕获,方波信号周期=9.44mS;一个周期计数=9.44*1000/(1/72)=684057,
2): 溢出次数=684057/0XFFFF=10.437;  连续捕获三个值,溢出计数应该=30;
3):由于中断的开启,在方波信号的位置无法确定,那么溢出计数至少大于20;
4): 由于捕获到的第一个溢出计数可能不准,所以要抛弃第一值;开启触发中断,TIM3->DIER |=BIT6;,用该中断来抛弃第一个捕获值的溢出计数;
5):encoder.tim3_irqh_count++; 用来统计进中断的次数;从仿真的计数结果上看,溢出计数值不对,
6)   :encoder.tim3_overflow_count++; 是实际两个周期的累加计数;
7)从仿真上看:encoder.tim3_irqh_count=17; encoder.tim3_overflow_count=11; 这与计算也差太多了吧


这个问题,搞了一个多星期了,也没有解决,还请个位路过的指点下



void TIM3_configure(void) //定时器基本配置
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);        
   TIM_DeInit(TIM3);
   TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

   TIM_TimeBaseStructure.TIM_Prescaler = 0;  // 分频系数
   TIM_TimeBaseStructure.TIM_Period = 0xffff;  //计数值
   TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;// 计数模式
   TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;                   //通道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 = 0x0;       //滤波器0x0~0xF
TIM_ICInit(TIM3,&TIM_ICInitStructure);  //捕获模式初始化
                        
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);  //IC1为触发源
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); //TIM从模式         
TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable); //主从模式选择

}
//=========================================================
void DAM_TIM3_capture(void) //---DMA1---TIM3-----------
{

    DMA_InitTypeDef DMA_InitStructure;  

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  //启动DMA时钟  
    DMA_DeInit(DMA1_Channel6);  //DMA1通道6配置  
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&TIM3->CCR1);  //外设地址
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)encoder_count;  //内存地址  
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //dma传输方向单向  
    DMA_InitStructure.DMA_BufferSize = 3;  //设置DMA在传输时缓冲区的长度
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //设置DMA的外设递增模式,一个外设
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //设置DMA的内存递增模式  
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  //外设数据字长
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;  //内存数据字长
                                
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  //设置DMA的传输模式:单次
    //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;   //设置DMA的传输模式:循环

    DMA_InitStructure.DMA_Priority = DMA_Priority_High; //设置DMA的优先级别         
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  
    DMA_Init(DMA1_Channel6,&DMA_InitStructure);               

        
    TIM_DMAConfig(TIM3,TIM_DMABase_CCR1,TIM_DMABurstLength_2Bytes);//配置定时器的DMA   
    DMA_ITConfig(DMA1_Channel6,DMA_IT_TC, ENABLE);
               
    TIM_DMACmd(TIM3, TIM_DMA_CC1, ENABLE);   //产生DMA请求信号
                                
    DMA_Cmd(DMA1_Channel6, ENABLE);                                

   TIM_Cmd(TIM3, ENABLE);  //打开定时器  

}//=================================================
void DMA1_Channel6_IRQHandler (void)//编码器捕获计数
{

        TIM3->DIER &=(~0x40);
        TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE); //溢出中断
       
        DMA_ClearFlag(DMA1_FLAG_TC6);   //请中断标志
        encoder.dma_finish_flag=0;       
}


//==================================================
void TIM3_IRQHandler(void)  
{
        encoder.tim3_irqh_count++;
        if((TIM3->SR&0x0040)==0x0040 &&encoder.tim3_irqh_flag==0)//丢弃第一个捕获值,通过TIF位检测边沿
        {
                TIM3->SR &=(~0x40);
                encoder.tim3_irqh_flag=1; //中断进入标志
                encoder.tim3_overflow_count=0;//清除溢出标志
        }
       
        else if((TIM3->SR&0x0040)==0x0040)
        {
                TIM3->SR &=(~0x40);
        }
       
        else
        {
         TIM_ClearITPendingBit(TIM3,TIM_FLAG_Update);
       
         encoder.tim3_overflow_count++;
       
        }
}


//=======================================================



int main(void)
{
   switch(encoder.dma_finish_flag)
{
                 //---启动DMA 捕获---
case 0:        TIM3->SR=0;

                  DMA_Cmd(DMA1_Channel6, DISABLE);
                   DMA_ClearFlag(DMA1_FLAG_TC6);   //请中断标志
                 DMA1_Channel6->CNDTR=3;       
                 TIM3->DIER |=BIT6;
                                                 
                TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); //溢出中断
                DMA_Cmd(DMA1_Channel6, ENABLE);
                encoder.tim3_irqh_count=0;
                 encoder.tim3_overflow_count=0;//溢出计数清零
                encoder.tim3_irqh_flag=0;// 第一次触发中断标志                                                  
                 encoder.dma_finish_flag=1;//DMA 处理标志
                break;
case 1: break;
}

}


沙发
mmuuss586| | 2015-7-19 15:54 | 只看该作者

这个不知道什么问题;
你的程序已经比较简化了;

使用特权

评论回复
板凳
kent8013|  楼主 | 2015-7-19 15:57 | 只看该作者
用触发中断,TIF 位抛弃第一个捕获值,不知道有没有问题?
弄的我自己都怀疑,但是又找不到原因

使用特权

评论回复
地板
kent8013|  楼主 | 2015-7-20 15:48 | 只看该作者
没人帮忙看看吗--------------------------

使用特权

评论回复
5
amanda_s| | 2015-7-20 16:55 | 只看该作者
在计数的中断里面,加个IO口翻转的测试。
拿示波器同时看你要测的波形和这个IO口的翻转情况,看看和程序是否一样。
根据结果再往后找原因。

使用特权

评论回复
6
kent8013|  楼主 | 2015-7-22 08:20 | 只看该作者
中断里面已经加了一个,进入中断次数的变量encoder.tim3_irqh_count++; 从这个变量的值上看,进入中断的次数,明显不对

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

12

帖子

0

粉丝