本帖最后由 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;
}
}
|