注册 登录
查看: 2790|回复: 36

K60输入捕捉问题,麻烦山外大哥看一下,谢谢!

[复制链接]
发表于 2014-11-30 16:23:58 | 显示全部楼层 |阅读模式
本帖最后由 快乐的味道92 于 2014-12-1 12:52 编辑

现在有四路周期性的信号(波形如下),需要知道高电平持续时间或者计数器在高电平时间内的累加值或减少值。关于输入捕捉的思路,有没有更好的。我打算使用触发中断后,用lmptr进行计时。

  1. //      模块通道    端口          可选范围              建议
  2. #define FTM1_CH0    PTA12       //PTA8、PTA12、PTB0
  3. #define FTM1_CH1    PTA13       //PTA9、PTA13、PTB1

如果用用FTM1模块作为输入捕捉,获取四路周期信号的高电平数据,可以吗?FTM1模块的通道只有两个,但管脚有很多,FTM1同一个通道的不同管脚可以作为输入捕捉的引脚吗(4输入信号,对应四个引脚。必然有不同引脚占用同一模块的同一个通道)?


如果FTM0 FTM1模块配置为产生PWM,那可以同时配置FTM0 FTM1的其他引脚为输入捕捉引脚吗?以上两种情况会不会冲突?



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

 楼主| 发表于 2014-12-1 22:35:09 | 显示全部楼层
山外メ雲ジ 发表于 2014-12-1 22:12
一来清中断之后,就可以马上清计数器值,不然会增大误差。

另外,不是写好了获取计数值的函数吗?干嘛还 ...

我把修改过的程序附上去,有空你看下吧,谢谢。测得高脉冲宽度的数据,先后几次变大再变小,再变大。应该是这句的问题,FTM0的计数周期有错误。
  1. RC_CH[0] = bus_clk_khz*1000/(1<<FTM_PS_2) - CH1_CAPTURE_UPVAL + CH1_CAPTURE_DOWNVAL;// bus_clk_khz*1000/(1<<FTM_PS_2)为FTM计数周期,待修改

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2014-12-1 20:59:26 | 显示全部楼层
山外メ雲ジ 发表于 2014-12-1 20:53
当然可以在中断里修改触发方式。

你参考一下底层,添加一个函数来修改触发方式,写一个接口函数就好。 ...
  1. void config_pin_mode(FTMn_e ftmn, FTM_CHn_e ch, FTM_Input_cfg cfg)
  2. {
  3.     switch(cfg)
  4.     {
  5.         //输入捕捉模式下:DECAPEN = 0 , DECAPEN = 0 ,CPWMS = 0, MSnB:MSnA = 0

  6.         // ELSnB:ELSnA         1          10          11
  7.         // 配置             上升沿      下降沿      跳变沿

  8.     case FTM_Rising:    //上升沿触发
  9.         FTM_CnSC_REG(FTMN[ftmn], ch) |=  ( FTM_CnSC_ELSA_MASK  | FTM_CnSC_CHIE_MASK );                   //置1
  10.         FTM_CnSC_REG(FTMN[ftmn], ch) &= ~( FTM_CnSC_ELSB_MASK  | FTM_CnSC_MSB_MASK | FTM_CnSC_MSA_MASK); //清0
  11.         break;

  12.     case FTM_Falling:   //下降沿触发
  13.         FTM_CnSC_REG(FTMN[ftmn], ch) |= (FTM_CnSC_ELSB_MASK  | FTM_CnSC_CHIE_MASK );                    //置1
  14.         FTM_CnSC_REG(FTMN[ftmn], ch) &= ~( FTM_CnSC_ELSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_MSA_MASK); //清0
  15.         break;

  16.     case FTM_Rising_or_Falling: //上升沿、下降沿都触发
  17.         FTM_CnSC_REG(FTMN[ftmn], ch) |=  ( FTM_CnSC_ELSB_MASK | FTM_CnSC_ELSA_MASK  | FTM_CnSC_CHIE_MASK ); //置1
  18.         FTM_CnSC_REG(FTMN[ftmn], ch) &= ~( FTM_CnSC_MSB_MASK  | FTM_CnSC_MSA_MASK); //清0
  19.         break;
  20.     }
  21. }
添加了下面的函数

回复 支持 1 反对 0

使用道具 举报

发表于 2014-11-30 16:37:36 | 显示全部楼层
不用lptmr,直接一个输入捕捉就好。
来自安卓客户端来自安卓客户端
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-1 12:54:19 | 显示全部楼层
微粒子 发表于 2014-11-30 16:37
不用lptmr,直接一个输入捕捉就好。

输入捕捉后,我的知道高电平持续的时间,仅仅一个输入捕捉不够吧
回复 支持 反对

使用道具 举报

发表于 2014-12-1 13:13:52 | 显示全部楼层
快乐的味道92 发表于 2014-12-1 12:54
输入捕捉后,我的知道高电平持续的时间,仅仅一个输入捕捉不够吧

是一个输入捕捉就好。ftm本身就是计时器,论坛有例程的,我回去给你找找。
来自安卓客户端来自安卓客户端
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-1 14:04:30 | 显示全部楼层
本帖最后由 快乐的味道92 于 2014-12-1 14:06 编辑
微粒子 发表于 2014-12-1 13:13
是一个输入捕捉就好。ftm本身就是计时器,论坛有例程的,我回去给你找找。


K60的FTM1模块的CH0、CH1有好些引脚都是(如图)。用FTM1模块作为输入捕捉,下面这个程序是历程里面的:

  1. /*!
  2. *     COPYRIGHT NOTICE
  3. *     Copyright (c) 2013,野火科技
  4. *     All rights reserved.
  5. *     技术讨论:野火初学论坛 http://www.chuxue123.com
  6. *
  7. *     除注明出处外,以下所有内容版权均属野火科技所有,未经允许,不得用于商业用途,
  8. *     修改内容时必须保留野火科技的版权声明。
  9. *
  10. * @file       main.c
  11. * @brief      野火K60 平台主程序
  12. * @author     野火科技
  13. * @version    v5.0
  14. * @date       2013-08-28
  15. */

  16. #include "common.h"
  17. #include "include.h"

  18. //全局变量定义
  19. volatile uint32 irqflag = 0;                //标志位定义,非0 表示进入中断

  20. //函数声明
  21. void FTM0_INPUT_IRQHandler(void);        //FTM0中断服务函数


  22. /*!
  23. *  @brief      main函数
  24. *  @since      v5.0
  25. *  @note       FTM 输入捕捉 测试
  26. */

  27. void main()
  28. {
  29.     FTM_Input_init(FTM0, FTM_CH7, FTM_Falling);     //初始化FTM输入捕捉模式,下降沿捕捉(FTM0_CH7 为 PTD7)
  30.     port_init_NoALT(FTM0_CH7 ,PULLUP);              //配置端口为上拉(保留原先的复用配置)

  31.     set_vector_handler(FTM0_VECTORn ,FTM0_INPUT_IRQHandler);    //设置FTM0的中断服务函数为 FTM0_INPUT_IRQHandler
  32.     enable_irq (FTM0_IRQn);                                     //使能FTM0中断

  33.     led_init(LED0);                 //初始化LED端口

  34.     while(1)
  35.     {
  36.         if(irqflag != 0)
  37.         {
  38.             led_turn(LED0);         //通过 LED 看效果
  39.             DELAY_MS(200);          //由于是通过按键按下,查看LED状态,因此需要按键延时消抖
  40.             irqflag = 0;
  41.         }
  42.     }
  43. }


  44. void FTM0_INPUT_IRQHandler(void)
  45. {
  46.     uint8 s = FTM0_STATUS;          //读取捕捉和比较状态  All CHnF bits can be checked using only one read of STATUS.
  47.     uint8 CHn;

  48.     FTM0_STATUS = 0x00;             //清中断标志位

  49.     CHn = 7;
  50.     if( s & (1 << CHn) )
  51.     {
  52.         /*     用户任务       */
  53.         irqflag++;

  54.         /*********************/
  55.     }

  56. }

上面的程序在初始化FTM模块时,只设置了FTM模块号和通道号,而没有设置是那个管脚,那对FTM1模块来说,设置输入捕捉后,配置的是哪个管脚具有输入捕捉的功能(FTM1的一个通道对应多个引脚)。另外当配置FTM模块为输入PWM,那么还能在配置这个模块的某个通道为输入捕捉模式吗?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-1 14:08:14 | 显示全部楼层
微粒子 发表于 2014-12-1 13:13
是一个输入捕捉就好。ftm本身就是计时器,论坛有例程的,我回去给你找找。

找到后告诉我一下,谢谢你哈
回复 支持 反对

使用道具 举报

发表于 2014-12-1 14:37:03 | 显示全部楼层
快乐的味道92 发表于 2014-12-1 14:08
找到后告诉我一下,谢谢你哈

又发现一个测脉冲方法(输入捕捉测脉冲周期) - 水漫之城 - 山外论坛 http://vcan123.com/forum.php?mod ... amp;extra=#pid48583
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-1 20:43:20 | 显示全部楼层
山外メ雲ジ 发表于 2014-12-1 14:37
又发现一个测脉冲方法(输入捕捉测脉冲周期) - 水漫之城 - 山外论坛 http://vcan123.com/forum.php?mod= ...

在输入捕捉模式下,能否在中断里修改引脚的触发方式?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-1 20:45:29 | 显示全部楼层
山外メ雲ジ 发表于 2014-12-1 14:37
又发现一个测脉冲方法(输入捕捉测脉冲周期) - 水漫之城 - 山外论坛 http://vcan123.com/forum.php?mod= ...

对FTM1模块来说,设置输入捕捉后,配置的是哪个管脚具有输入捕捉的功能(FTM1的一个通道对应多个引脚)?
回复 支持 反对

使用道具 举报

发表于 2014-12-1 20:53:27 | 显示全部楼层
快乐的味道92 发表于 2014-12-1 20:43
在输入捕捉模式下,能否在中断里修改引脚的触发方式?

当然可以在中断里修改触发方式。

你参考一下底层,添加一个函数来修改触发方式,写一个接口函数就好。

任何一个FTM通道都可以的。
回复 支持 反对

使用道具 举报

发表于 2014-12-1 21:08:32 | 显示全部楼层

测试成功没?讲解一下经验吧
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-1 21:13:44 | 显示全部楼层
仰逸致 发表于 2014-12-1 21:08
测试成功没?讲解一下经验吧

还没呢?正在测试
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-1 21:14:52 | 显示全部楼层
山外メ雲ジ 发表于 2014-12-1 20:53
当然可以在中断里修改触发方式。

你参考一下底层,添加一个函数来修改触发方式,写一个接口函数就好。 ...

调用ftm_input_get(FTM0,(FTM_CHn_e)CHn)这个函数,FTM定时器的周期是多少怎样查看?
回复 支持 反对

使用道具 举报

发表于 2014-12-1 21:18:11 | 显示全部楼层
快乐的味道92 发表于 1417439692
调用ftm_input_get(FTM0,(FTM_CHn_e)CHn)这个函数,FTM定时器的周期是多少怎样查看?
时钟源是bus频率,还要看传递进去的分频系数是多少。
来自PC客户端 来自PC客户端
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-1 21:24:11 | 显示全部楼层
山外メ雲ジ 发表于 2014-12-1 21:18
时钟源是bus频率,还要看传递进去的分频系数是多少。

程序里的初始化


  1. void sysinit (void)
  2. {
  3.     core_clk_mhz = pll_init(CORE_CLK);     //设置系统时钟

  4.     core_clk_khz = core_clk_mhz * 1000;     //把配置好的时钟都保存在全局变量里,以便后续使用
  5.     bus_clk_khz = core_clk_khz / (((SIM_CLKDIV1 & SIM_CLKDIV1_OUTDIV2_MASK) >> 24) + 1);

  6.     uart_init (VCAN_PORT, VCAN_BAUD);   //初始化printf用到的管脚
  7. }


  1. #if defined(MK60DZ10)                        //以下为 MK60DZ10 的超频配置
  2. /*
  3. * 定义 PLL 超频 频率
  4. */
  5. #define CORE_CLK                PLL96       // 从 PLL_e 里选择 已提供的 配置方案
  6.                                             // bus 、 flex bus 、 flash 频率 都是 core 整数倍分频而来
  7. #define MAX_BUS_CLK             48          // bus      (bus        >= core/16  )
  8. #define MAX_FLEXBUS_CLK         25          // flex bus (flex bus   >= core/16  )
  9. #define MAX_FLASH_CLK           25          // flash    (flash      >= core/16  )


上面都是默认的初始化。

怎样计算FTM计数周期?有公式吧,我对着不太了解?
回复 支持 反对

使用道具 举报

发表于 2014-12-1 21:26:57 | 显示全部楼层

用 bus_clk_khz 和 分频系数,就知道 FTM 的一个计数值代表的时钟周期
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-1 21:34:19 | 显示全部楼层
仰逸致 发表于 2014-12-1 21:26
用 bus_clk_khz 和 分频系数,就知道 FTM 的一个计数值代表的时钟周期

我把程序附上去,帮我看下,哪里出问题了?没有捕捉到数据

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-1 21:41:39 | 显示全部楼层
仰逸致 发表于 2014-12-1 21:26
用 bus_clk_khz 和 分频系数,就知道 FTM 的一个计数值代表的时钟周期

刚才上面程序里有低级逻辑错误,不好意思
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-1 21:46:57 | 显示全部楼层
山外メ雲ジ 发表于 2014-12-1 21:18
时钟源是bus频率,还要看传递进去的分频系数是多少。

bus_clk_khz*1000/(1<<FTM_PS_2)为FTM计数周期????
回复 支持 反对

使用道具 举报

发表于 2014-12-1 21:49:45 | 显示全部楼层
快乐的味道92 发表于 1417440859
我把程序附上去,帮我看下,哪里出问题了?没有捕捉到数据
要上升沿触发,清计数值,改成下降沿触发,
然后下降沿触发获取计数值,从而算得脉冲宽度。
来自PC客户端 来自PC客户端
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-1 21:56:51 | 显示全部楼层
山外メ雲ジ 发表于 2014-12-1 21:49
要上升沿触发,清计数值,改成下降沿触发,
然后下降沿触发获取计数值,从而算得脉冲宽度。

我把中断服务函数写成这个样子,不知道逻辑思路是否正确?
  1. void FTM0_INPUT_IRQHandler(void)
  2. {
  3.     uint8 s = FTM0_STATUS;          //读取捕捉和比较状态  All CHnF bits can be checked using only one read of STATUS.
  4.     uint8 CHn;
  5.     FTM0_STATUS = 0x00;             //清中断标志位    All CHnF bits can be cleared by reading STATUS followed by writing 0x00 to STATUS.
  6.     CHn = 6;
  7.     if( s & (1 << CHn) )
  8.     {
  9.       if(CH1_CAPTURE_STA == 0)//捕获上升沿
  10.       {
  11.         CH1_CAPTURE_UPVAL = ftm_input_get(FTM0,(FTM_CHn_e)CHn);//获取上升沿数据
  12.         CH1_CAPTURE_STA = 1;//标记捕获到了上升沿
  13.         config_pin_mode(FTM0, FTM_CH6, FTM_Falling);//改变下降沿触发
  14.       }
  15.       else
  16.       {
  17.         CH1_CAPTURE_DOWNVAL = ftm_input_get(FTM0,(FTM_CHn_e)CHn);//获取下降沿数据
  18.         
  19.         //判断是否溢出,计算高电平脉冲期间FTM累加值
  20.         if(CH1_CAPTURE_DOWNVAL < CH1_CAPTURE_UPVAL)
  21.         {
  22.           RC_CH[0] = bus_clk_khz*1000/(1<<FTM_PS_2) - CH1_CAPTURE_UPVAL + CH1_CAPTURE_DOWNVAL;// bus_clk_khz*1000/(1<<FTM_PS_2)为FTM计数周期,待修改
  23.         }
  24.         else
  25.         {
  26.           RC_CH[0] = CH1_CAPTURE_DOWNVAL- CH1_CAPTURE_UPVAL;
  27.         }
  28.         
  29.         CH1_CAPTURE_STA = 0;
  30.         config_pin_mode(FTM0, FTM_CH6, FTM_Rising); //设置上升沿捕捉
  31.       }
  32.       ftm_input_clean(FTM0);  //清计数器计数值
  33.     }
  34. }

回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-1 22:00:03 | 显示全部楼层
山外メ雲ジ 发表于 2014-12-1 21:49
要上升沿触发,清计数值,改成下降沿触发,
然后下降沿触发获取计数值,从而算得脉冲宽度。

只测高电平宽度
回复 支持 反对

使用道具 举报

发表于 2014-12-1 22:12:38 | 显示全部楼层
快乐的味道92 发表于 1417442211
我把中断服务函数写成这个样子,不知道逻辑思路是否正确?
一来清中断之后,就可以马上清计数器值,不然会增大误差。

另外,不是写好了获取计数值的函数吗?干嘛还要调用寄存器?
来自PC客户端 来自PC客户端
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-1 22:23:50 | 显示全部楼层
山外メ雲ジ 发表于 2014-12-1 22:12
一来清中断之后,就可以马上清计数器值,不然会增大误差。

另外,不是写好了获取计数值的函数吗?干嘛还 ...

不是写好了获取计数值的函数吗?干嘛还要调用寄存器?你是指哪句程序?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-1 22:30:12 | 显示全部楼层
山外メ雲ジ 发表于 2014-12-1 22:12
一来清中断之后,就可以马上清计数器值,不然会增大误差。

另外,不是写好了获取计数值的函数吗?干嘛还 ...

清不清零应该没关系吧,程序是根据前后计数器的差值得到脉冲宽度的
回复 支持 反对

使用道具 举报

发表于 2015-1-21 17:51:10 | 显示全部楼层
请问,如果FTM1 CH0 CH1,FTM2 CH0 CH1,四个通道同时测高电平时间,知道怎样搞?
回复 支持 反对

使用道具 举报

发表于 2015-1-21 21:49:51 | 显示全部楼层
逝去的星光 发表于 2015-1-21 17:51
请问,如果FTM1 CH0 CH1,FTM2 CH0 CH1,四个通道同时测高电平时间,知道怎样搞?

分时复用咯~
来自安卓客户端来自安卓客户端
回复 支持 反对

使用道具 举报

发表于 2015-1-22 09:46:40 | 显示全部楼层

分时复用就是,我使用ch0的时候就要ch1关了,使用ch1的时候就要吧ch0关了吧,我试过还是会经常跳变,下面是我想的办法,不知道为什么测一个固定的脉冲很准,但一个总在变化的脉冲就不准了,

  1. void FTM1_IRQHandler()
  2. {
  3.     u8 s = FTM1_STATUS;             //读取捕捉和比较状态  All CHnF bits can be checked using only one read of STATUS.
  4.     u8 CHn;
  5.     FTM1_STATUS = 0x00;             //清中断标志位

  6.     CHn = 0;
  7.     if( s & (1 << CHn) )
  8.     {

  9.         if(GPIO_Get(PORTB, 0)==1)
  10.          {
  11.            Rise[0]=PIT_CVAL_REG(PIT_BASE_PTR,PIT0);      //说明发生上升沿中断,记录此时的时刻 Rise[0]
  12.          
  13.          }
  14.           else
  15.           {
  16.         
  17.           Drop[0]=PIT_CVAL_REG(PIT_BASE_PTR,PIT0);     //说明发生下升沿中断,记录此时的时刻  Drop[0]
  18.    
  19.          if(Rise[0]>Drop[0])
  20.            Rc_Data.YAW =(Rise[0]  -  Drop[0])/50 ;     //  |Rise[0]  -  Drop[0]|差值的绝对值等于高电平的时间
  21.           else   
  22.           Rc_Data.YAW = (125000- Drop[0]+ Rise[0])/50; // 计时器从125000开始递减计数,共2.5ms ,捕捉的通道频率为400HZ
  23.       
  24.         }

  25.     }

  26.    CHn = 1;
  27.    if( s & (1 << CHn) )
  28.     {

  29.         if(GPIO_Get(PORTB, 1)==1)
  30.          {
  31.         
  32.            Rise[1]=PIT_CVAL_REG(PIT_BASE_PTR,PIT0);         //说明发生上升沿中断,记录此时的时刻 Rise[1]

  33.          }
  34.           else
  35.           {
  36.             
  37.             Drop[1]=PIT_CVAL_REG(PIT_BASE_PTR,PIT0);         //说明发生上升沿中断,记录此时的时刻 Rise[1]
  38.    
  39.            if(Rise[1]>Drop[1])
  40.            Rc_Data.THROTTLE =(Rise[1]  -  Drop[1])/50 ;     //  |Rise[1]  -  Drop[1]|差值的绝对值等于高电平的时间
  41.              else   
  42.             Rc_Data.THROTTLE= (125000- Drop[1]+ Rise[1])/50;   // 计时器从125000开始递减计数,共2.5ms ,捕捉的通道频率为400HZ
  43.          

  44.           }
  45.     }

  46. }


回复 支持 反对

使用道具 举报

发表于 2015-1-22 13:44:02 | 显示全部楼层
逝去的星光 发表于 2015-1-22 09:46
分时复用就是,我使用ch0的时候就要ch1关了,使用ch1的时候就要吧ch0关了吧,我试过还是会经常跳变,下面 ...

经常跳变?


总是变化的脉冲,你怎么确定不准?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-1-22 19:23:54 | 显示全部楼层
逝去的星光 发表于 2015-1-21 17:51
请问,如果FTM1 CH0 CH1,FTM2 CH0 CH1,四个通道同时测高电平时间,知道怎样搞?

不能同时测,肯定有先后顺序。
来自安卓客户端来自安卓客户端
回复 支持 反对

使用道具 举报

发表于 2015-1-22 19:42:25 | 显示全部楼层
快乐的味道92 发表于 2015-1-22 19:23
不能同时测,肯定有先后顺序。

我先后测也会有问题,比如使用ch0,就关闭ch1.不知多路测量这个问题你解决没有,能否借鉴?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-1-23 16:23:26 | 显示全部楼层
逝去的星光 发表于 2015-1-22 19:42
我先后测也会有问题,比如使用ch0,就关闭ch1.不知多路测量这个问题你解决没有,能否借鉴?

多路测量我没弄过,只做过单路测量,STM32可以同时测多路
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-2-1 09:14:03 | 显示全部楼层
逝去的星光 发表于 2015-1-22 19:42
我先后测也会有问题,比如使用ch0,就关闭ch1.不知多路测量这个问题你解决没有,能否借鉴?

你的问题解决没?
来自安卓客户端来自安卓客户端
回复 支持 反对

使用道具 举报

发表于 2015-5-22 17:37:23 | 显示全部楼层
快乐的味道92 发表于 2014-12-1 14:08
找到后告诉我一下,谢谢你哈

同求啊,,求助攻
回复 支持 反对

使用道具 举报

发表于 2016-1-26 13:24:30 | 显示全部楼层
问题解决了吗?同问啊
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回列表 返回顶部