TIM2CH1_CAPTURE_STA的通俗理解,分享下我的理解

2019-07-20 22:43发布

以下是输入捕获实验的理解


//定时器5中断服务程序  
void TIM2_IRQHandler(void)

/*第一个if很关键,最后看第三步:   
 捕获完成后 请问TIM2CH1_CAPTURE_STA第七位状态几何?我们的目的是什么?
 获取高电平时间后是不是要显示,显示后还需不需要再次捕获呢?
 捕获后 TIM2CH1_CAPTURE_STA为1,无法进行下列if判断,无法进入中断判断,
 故TIM2CH1_CAPTURE_STA=0需要清零,main函数有所体现。

 会有人问 if((TIM2CH1_CAPTURE_STA&0X80)==0)可不可以不要,我认为可以。
 原因每次捕获都是从上升沿开始再捕获下降沿,可以下降沿读取捕获值
 主函数中if(TIM2CH1_CAPTURE_STA&0X80)改为TIM2CH1_CAPTURE_STA&0x40即可
*/
  if((TIM2CH1_CAPTURE_STA&0X80)==0) //还未成功捕获
{  
/* 再看 第二步

从下面看:读取溢出标号,在捕获上升沿后,没来得及捕获下降沿时发生溢出。说明什么?
溢出必发生在高电平 IM2CH1_CAPTURE_STA&0X40表示已经捕获到高电平(上升沿阶段)。
来一次溢出,则(TIM2CH1_CAPTURE_STA&0X3F)++,表示溢出次数。
溢出超出了,怎么办?
TIM_APR 16位预装载值,即CNT>65536-1时溢出。 
0X3F个65536共4128768单位,约4128768/72=58ms 即最大值。 程序是不是就完了了?

没有,若超过最大值,不作处理则形成bug 。
(TIM2CH1_CAPTURE_STA&0X3F)++等于0x40 ,溢出数等于清0,结果有出现没发生溢出情况下的脉宽值TIM2CH1_CAPTURE_VAL
 所以必须做处理,可以做强制结束该次捕获,设为测量范围的最大值,超过就不准了,一杆秤最大只能称多重的一样,超过范围则无法使用。
 TIM2CH1_CAPTURE_VAL=0XFFFF;


*/

if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
 
{    
if(TIM2CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
{
if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
{
TIM2CH1_CAPTURE_STA|=0X80;//标记成功捕获了一次
TIM2CH1_CAPTURE_VAL=0XFFFF;
}else TIM2CH1_CAPTURE_STA++;
}  
}

/* 先看 第一步

从下面看:TIM2CH1_CAPTURE_STA=0 默认为0,TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; 
发生第一次捕获肯定是上升沿无疑,
进入中断程序 判断if(TIM2CH1_CAPTURE_STA&0X40) 第6位必为0,
也就是说第6位为0表示捕获上升沿,为了方便计数高电平,由高电平开始计数,即清零工作。
为了下次进中断程序 TIM2CH1_CAPTURE_STA第6位还为0,难道还捕获上升沿吗?
故TIM2CH1_CAPTURE_STA|=0X40,也就是说第6位为1表示准备捕获下升沿,标号没有
实际作用,接着用TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling)来体现第6位表示实际作用功能(0:上。1:下)。
至此,一次高电平完成,TIM2CH1_CAPTURE_STA|=0X80用第7位表示,完成的作用意义就是读取捕获值(高电平) 存放TIM2CH1_CAPTURE_VAL。
也就是说第7位的作用是读捕获值(0:不读。1:读)。
最后用TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising)来进入第2或第3等多次捕获跳转。

注意:这里用到了TIM2CH1_CAPTURE_STA第7位表示,读取捕获值 存放TIM2CH1_CAPTURE_VAL。这里的捕获没考虑溢出的情况
*/
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
{
if(TIM2CH1_CAPTURE_STA&0X40) //捕获到一个下降沿
{  
TIM2CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次上升沿
TIM2CH1_CAPTURE_VAL=TIM_GetCapture1(TIM2);
  TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
}else   //还未开始,第一次捕获上升沿
{
TIM2CH1_CAPTURE_STA=0; //清空
TIM2CH1_CAPTURE_VAL=0;
TIM_SetCounter(TIM2,0);
TIM2CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿
  TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获
}    
}           
  }
 
    TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
18条回答
流芷静兰
1楼-- · 2019-07-22 16:44
楼主大赞~~
威点子极客制作
2楼-- · 2019-07-22 20:44
以下是个人对此段代码的理解:
unsigned char   TIM4CH1_CAPTURE_STA=0;        //输入捕获状态                                                   
unsigned int          TIM4CH1_CAPTURE_VAL;          //输入捕获值
/*
注: TIM4CH1_CAPTURE_STA 为自定义的一个寄存器,用以表示定时器4的通道1的‘输入捕获’状态位
其中
7位表示:‘边沿触发’后半段标识,捕获到了则为1,无则为0
6位表示:‘边沿触发’前半段标识,捕获到了有则为1,无则为0
5-0表示:定时器溢出的总次数,为对付长脉冲而生
*/
       
/*
1、第一段if用来处理因为‘更新’而触发的定时器中断溢出,第二段if用来处理‘输入捕获’而触发的中断
2、从未检测过信号时,中断中应该不做实际工作。做实际工作时,一定先触发‘输入捕获’
3、应加入锁定功能,防止要采集的‘脉冲时间’被后续脉冲信号刷掉
*/


void TIM4_IRQHandler(void) //定时器4用作输入捕获‘一个脉冲信号’时间的中断函数(默认‘边沿触发’前半段为‘下降沿’)
{

        if((TIM4CH1_CAPTURE_STA&0X80)==0)//从未测量过一次脉冲信号的长度时,才进行if内的操作,测过一次的不可再测。此if语句的作用是锁定
        {          
               
                if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET)//发生捕获事件,接下来需要判断是‘边沿触发’前半段还是后半段
                        {       
                                if((TIM4CH1_CAPTURE_STA&0X40) == 0)                //‘前半段’为零,说明这是首次捕获                                          
                                {                 
                                        TIM4CH1_CAPTURE_STA = 0;                        //初始化标识位,开始计时工作 m_m
                                        TIM4CH1_CAPTURE_VAL = 0;      //将自定义的计数器清零
                                        TIM_SetCounter(TIM4,0);       //将TIM4的计数器清零,使TIM4计数寄存器的数值与自定义的‘TIM4CH1_CAPTURE_VAL’相等
                                        TIM4CH1_CAPTURE_STA |= 0X40;        //将‘边沿触发’前半段标识为‘1’
                                        TIM_OC1PolarityConfig(TIM4,TIM_ICPolarity_Rising);                //因为本次试验采用的是端口上拉‘按键检测’,所以‘边沿触发’前半段为‘下降沿’,后半段自然是‘上升沿’,所以此处要对TIM4的通道1进行一次边沿的极性转换
                                       
                    }else                          //如果已经捕获过了‘边沿触发’前半段,则这次捕获的肯定是‘边沿触发’后半段
                                {
                                       
                                        TIM4CH1_CAPTURE_STA |= 0X80;                //标记成功捕获‘边沿触发’后半段,至此,完成一次脉冲时间的测量
                                        TIM4CH1_CAPTURE_VAL = TIM_GetCapture1(TIM4); //获得脉冲时间
                                        TIM_OC1PolarityConfig(TIM4,TIM_ICPolarity_Rising); // 切换会默认极性
                                }                    
                        }       
                       
                if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) //时间到了,本次循环没有检测到‘边沿触发’,定时器溢出
                 
                {            
                        if(TIM4CH1_CAPTURE_STA&0X40)//已经捕获到‘边沿触发’前半段才进行‘定时器溢出计数器’自加操作
                        {
                                if((TIM4CH1_CAPTURE_STA&0X3F) == 0X3F)//脉冲信号太长,TIM4CH1_CAPTURE_STA中的‘5-0’位表示的‘定时器溢出计数器’也装不下时,应强制结束此次测量,保持最大时间
                                {
                                        TIM4CH1_CAPTURE_STA |= 0X80;//强制标记捕获‘边沿触发’后半段,完成一次脉冲时间的测量
                                        TIM4CH1_CAPTURE_VAL= 0XFFFF;//将自定义的计数器强制设为最大
                                }else TIM4CH1_CAPTURE_STA++;
                        }         
                }                       
        }

    TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位       
}


最后向代码作者致敬

invisible
3楼-- · 2019-07-22 20:51
chenshoubao 发表于 2015-4-23 02:21
回复【3楼】正点原子:
---------------------------------
我有个不理解的地方,定义的TIM2CH1_CAPTURE_STA ...

你好 这个问题您现在懂了吗? 我也是对这个有疑问
dotalky
4楼-- · 2019-07-22 23:05
 精彩回答 2  元偷偷看……
xcf0038
5楼-- · 2019-07-23 03:42
楼主或者哪位大佬,解答一下怎么捕获低电平
清酒醉逍遥
6楼-- · 2019-07-23 09:00
xcf0038 发表于 2019-4-18 09:17
楼主或者哪位大佬,解答一下怎么捕获低电平

你解决了吗

一周热门 更多>