最近在做曼切斯特的解码,用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 编辑 ]
此帖出自
小平头技术问答
你这样,先不管帧结束,先取上升沿扑获和dma这块儿行了没有?
信号给进去先看看dma有数据没有?
一周热门 更多>