输入捕获:神舟IV实验

完全照搬正点原子的实验:http://openedv.com/posts/list/11885.htm

我使用的库函数

下面我们介绍输入捕获的配置步骤:

1)开启TIM5时钟,配置PA0为下拉输入。

要使用TIM5,我们必须先开启TIM5的时钟(通过APB1ENR设置)。这里我们还要配置PA0为下拉输入,因为我们要捕获TIM5_CH1上面的高电平脉宽,而TIM5_CH1是连接在PA0上面的。

2)设置TIM5的ARR和PSC

在开启了TIM5的时钟之后,我们要设置ARR和PSC两个寄存器的值来设置输入捕获的自动重装载值和计数频率。

3)设置TIM5的CCMR1

TIM5_CCMR1寄存器控制着输入捕获1和2的模式,包括映射关系,滤波和分频等。这里我们需要设置通道1为输入模式,且IC1映射到TI1(通道1)上面,并且不使用滤波(提高响应速度)器。

4)设置TIM5的CCER,开启输入捕获,并设置为上升沿捕获。

TIM5_CCER寄存器是定时器的开关,并且可以设置输入捕获的边沿。只有TIM5_CCER寄存器使能了输入捕获,我们的外部信号,才能被TIM5捕获到,否则一切白搭。同时要设置好捕获边沿,才能得到正确的结果。

5)设置TIM5的DIER,使能捕获和更新中断,并编写中断服务函数

因为我们要捕获的是高电平信号的脉宽,所以,第一次捕获是上升沿,第二次捕获时下降沿,必须在捕获上升沿之后,设置捕获边沿为下降沿,同时,如果脉宽比较长,那么定时器就会溢出,对溢出必须做处理,否则结果就不准了。这两件事,我们都在中断里面做,所以必须开启捕获中断和更新中断。

设置了中断必须编写中断函数,否则可能导致死机。我们需要在中断函数里面完成数据处理和捕获设置等关键操作,从而实现高电平脉宽统计。

6)设置TIM5的CR1,使能定时器

最后,必须打开定时器的计数器开关,通过设置TIM5_CR1的最低位为1,启动TIM5的计数器,开始输入捕获。

通过以上6步设置,定时器5的通道1就可以开始输入捕获了,同时因为还用到了串口输出结果,所以还需要配置一下串口。

TIM5_Cap_Init
TIM5_IRQHandler

TIM5_IRQHandler是TIM5的中断服务函数,该函数用到了两个全局变量,用于辅助实现高电平捕获。其中TIM5CH1_CAPTURE_STA,是用来记录捕获状态,该变量类似我们在usart.c里面自行定义的USART_RX_STA寄存器。TIM5CH1_CAPTURE_STA各位描述如表15.3.1所示:

TIM5CH1_CAPTURE_STA

bit7

bit6

bit5~0

捕获完成标志

捕获到高电平标志

捕获高电平后定时器溢出的次数

表15.3.1 TIM5CH1_CAPTURE_STA各位描述

       另外一个变量TIM5CH1_CAPTURE_VAL,则用来记录捕获到下降沿的时候,TIM5_CNT的值。

       现在我们来介绍一下,捕获高电平脉宽的思路:首先,设置TIM5_CH1捕获上升沿,这在TIM5_Cap_Init函数执行的时候就设置好了,然后等待上升沿中断到来,当捕获到上升沿中断,此时如果TIM5CH1_CAPTURE_STA的第6位为0,则表示还没有捕获到新的上升沿,就先把

TIM5CH1_CAPTURE_STA、TIM5CH1_CAPTURE_VAL和TIM5->CNT等清零,然后再设置TIM5CH1_CAPTURE_STA的第6位为1,标记捕获到高电平,最后设置为下降沿捕获,等待下降沿到来。如果等待下降沿到来期间,定时器发生了溢出,就在TIM5CH1_CAPTURE_STA里面对溢出次数进行计数,当最大溢出次数来到的时候,就强制标记捕获完成(虽然此时还没有捕获到下降沿)。当下降沿到来的时候,先设置TIM5CH1_CAPTURE_STA的第7位为1,标记成功捕获一次高电平,然后读取此时的定时器值到TIM5CH1_CAPTURE_VAL里面,最后设置为上升沿捕获,回到初始状态。

       这样,我们就完成一次高电平捕获了,只要TIM5CH1_CAPTURE_STA的第7位一直为1,那么就不会进行第二次捕获,我们在main函数处理完捕获数据后,将TIM5CH1_CAPTURE_STA置零,就可以开启第二次捕获

     

       下面看下main函数:

      

main
 1 extern u8  TIM5CH1_CAPTURE_STA;        //输入捕获状态                            
 2 extern u16    TIM5CH1_CAPTURE_VAL;    //输入捕获值
 3 /**
 4   * @brief  Main program.
 5   * @param  None
 6   * @retval None
 7   */
 8 int main(void)
 9 {
10           u32 temp=0; 
11 //省略不少其他硬件配置代码
12          TIM5_Cap_Init(0XFFFF,72-1);    //以1Mhz的频率计数 
13          while(1)
14          {
15             if(TIM5CH1_CAPTURE_STA&0X80)//成功捕获到了一次上升沿
16             {
17                 temp=TIM5CH1_CAPTURE_STA&0X3F;
18                 temp*=65536;//溢出时间总和
19                 temp+=TIM5CH1_CAPTURE_VAL;//得到总的高电平时间
20                 printf("HIGH:%d us\r\n",temp);//打印总的高点平时间
21                 TIM5CH1_CAPTURE_STA=0;//开启下一次捕获
22             }
23 
24 
25          }
26 }

实验OK

 修改一下,在TIM5中断函数中直接输出捕获值,将main函数中代码屏蔽

TIM5_IRQHandler 新
 1 u8  TIM5CH1_CAPTURE_STA=0;    //输入捕获状态                            
 2 u16    TIM5CH1_CAPTURE_VAL;    //输入捕获值
 3 void TIM5_IRQHandler(void)
 4 {   u32 temp=0;
 5      if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获    
 6     {      
 7         if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
 8          
 9         {        
10             if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
11             {
12                 if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
13                 {
14                     TIM5CH1_CAPTURE_STA|=0X80;//标记成功捕获了一次
15                     TIM5CH1_CAPTURE_VAL=0XFFFF;
16 
17                     temp=TIM5CH1_CAPTURE_STA&0X3F;
18                     temp*=65536;//溢出时间总和
19                     temp+=TIM5CH1_CAPTURE_VAL;//得到总的高电平时间
20                     printf("HIGH:%d us\r\n",temp);//打印总的高点平时间
21                     TIM5CH1_CAPTURE_STA=0;//开启下一次捕获
22                 }else TIM5CH1_CAPTURE_STA++;
23             }     
24         }
25     if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
26         {    
27             if(TIM5CH1_CAPTURE_STA&0X40)        //捕获到一个下降沿         
28             {                  
29                 TIM5CH1_CAPTURE_STA|=0X80;        //标记成功捕获到一次上升沿,finish 
30                 TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);
31                    TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
32 
33                 temp=TIM5CH1_CAPTURE_STA&0X3F;
34                 temp*=65536;//溢出时间总和
35                 temp+=TIM5CH1_CAPTURE_VAL;//得到总的高电平时间
36                 printf("HIGH:%d us\r\n",temp);//打印总的高点平时间
37                 TIM5CH1_CAPTURE_STA=0;//开启下一次捕获
38             }else                                  //还未开始,第一次捕获上升沿    ,CNT,VAL开始 count
39             {
40                 TIM5CH1_CAPTURE_STA=0;            //清空
41                 TIM5CH1_CAPTURE_VAL=0;
42                  TIM_SetCounter(TIM5,0);
43                 TIM5CH1_CAPTURE_STA|=0X40;        //标记捕获到了上升沿
44                    TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);        //CC1P=1 设置为下降沿捕获
45             }            
46         }                                                
47      }
48  
49     TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
50 
51 }
原文地址:https://www.cnblogs.com/wwjdwy/p/2964222.html