打印
[Kinetis]

kinetis 单路PWM脉宽检测求救

[复制链接]
3228|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
defalut|  楼主 | 2014-6-19 10:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 defalut 于 2014-6-19 10:33 编辑

这段时间在做一个心电采集的功能,现在已经把freescale官方的这个实例移植到我自己的工程了FRDM-KL26Z_SC\FRDM-KL26Z_SC_Rev_1.0\klxx-sc-baremetal\build\iar\LQRUG_tpm_ex1。

我只需要采集单路PWM脉宽,这个实例是互补对称模式的。我屏蔽了一路,发现不能进中断,就4个寄存器。
昨天折腾了一天。


下面是我屏蔽的内容,只留下TPM0的ch1通道(PTC2)发出PWM脉冲,然后用TPM1的CH1通道(PTA13)检测PTC2的脉冲宽度.  PTC2产生PWM是正常的,但是PTA13不产生中断了。



int main (void)
{
  char ch;

  printf("\nRunning the LQRUG_tpm_ex1 project.\n");
  SIM_Init();
  PORT_Init();
  TPM0_Init();
  TPM1_Init();
  
  while(1)
  {
    printf("\nChange PWM duty: 0-9 (0-90%%)\n");
    ch = in_char();
    u16PWMDuty = TPM_MOD_1TO10*(ch - 0x30);
    out_char(ch);
    printf("\nPress any key to detect pulse width");
    ch = in_char();
    printf("\nMeasured Pulse width: %d TPM1 cycles\n\n", i16PulseWidth);
  }
}
/********************************************************************/
/***************************************************************************//*!
* [url=home.php?mod=space&uid=247401]@brief[/url]   SIM module initialization.
******************************************************************************/
void SIM_Init(void)
{
  SIM_SOPT2 |= SIM_SOPT2_TPMSRC(1);
  SIM_SOPT2 &= ~SIM_SOPT2_PLLFLLSEL_MASK;
  SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK| SIM_SCGC5_PORTC_MASK;
  SIM_SCGC6 |= SIM_SCGC6_TPM0_MASK| SIM_SCGC6_TPM1_MASK;
}
/***************************************************************************//*!
* [url=home.php?mod=space&uid=247401]@brief[/url]   PORT module initialization.
******************************************************************************/
void PORT_Init(void)
{
  //PORTA_PCR12 = PORT_PCR_ISF_MASK |PORT_PCR_MUX(0x3);
  PORTA_PCR13 = PORT_PCR_ISF_MASK |PORT_PCR_MUX(0x3);
  PORTC_PCR2 = PORT_PCR_ISF_MASK |PORT_PCR_MUX(0x4)| PORT_PCR_DSE_MASK;
  //PORTC_PCR1 = PORT_PCR_ISF_MASK |PORT_PCR_MUX(0x4)| PORT_PCR_DSE_MASK;         /* TMP0_CH0 located on PTC1 on FRDM KL26Z. TMP0_CH2 not broken out on FRMD KL26Z. */
}
/***************************************************************************//*!
* @brief   TPM0 module initialization.
******************************************************************************/
void TPM0_Init(void)
{
  enable_irq(17); set_irq_priority(17, 3);
  TPM0_CNT = 0;
  TPM0_MOD = 0x12C0;
  TPM0_SC = TPM_SC_TOIE_MASK|TPM_SC_CMOD(1);
  TPM0_C1SC = TPM_CnSC_MSB_MASK| TPM_CnSC_ELSB_MASK;    /* TMP0_CH1 */
  TPM0_C1V = 0x00;
  //TPM0_C0SC = TPM_CnSC_MSB_MASK| TPM_CnSC_ELSA_MASK;    /* TMP0_CH0 */
  //TPM0_C0V = 0x00;
}
/***************************************************************************//*!
* @brief   TPM1 module initialization.
******************************************************************************/
void TPM1_Init(void)
{
  enable_irq(18); set_irq_priority(18, 1);
  TPM1_CONF = TPM_CONF_TRGSEL(8)|TPM_CONF_CSOO_MASK|TPM_CONF_CSOT_MASK;
  TPM1_CNT = 0;
  TPM1_MOD = 0x2BC0;
  TPM1_SC = TPM_SC_TOIE_MASK|TPM_SC_CMOD(1);
  //TPM1_SC |= (1<<5);
  //TPM1_C0SC = TPM_CnSC_ELSA_MASK;
  //TPM1_C0V = 0x00;
  TPM1_C1SC = (TPM_CnSC_ELSB_MASK);
  TPM1_C1V = 0x00;
}
/***************************************************************************//*!
* @brief   TPM0 overflow interrupt service routine.
******************************************************************************/
void tpm0_isr(void)
{
  TPM0_SC |= TPM_SC_TOF_MASK;
  TPM0_C1V = (uint16)u16PWMDuty;        /* TMP0_CH1 */
  //TPM0_C0V = (uint16)u16PWMDuty;        /* TMP0_CH0 */
}

/***************************************************************************//*!
* @brief   TPM1 overflow interrupt service routine.
******************************************************************************/
void tpm1_isr(void)
{
  int16 TPM_c0v = 0, TPM_c1v = 0;
  
  TPM1_SC |= TPM_SC_TOF_MASK;
  TPM_c1v = (int16)TPM1_C1V;
  //TPM_c0v = (int16)TPM1_C0V;
  //i16PulseWidth = TPM_c1v - TPM_c0v;
  i16PulseWidth = TPM_c1v;
  //TPM1_C0SC |= TPM_CnSC_CHF_MASK;
  TPM1_C1SC |= TPM_CnSC_CHF_MASK;
}

相关帖子

沙发
defalut|  楼主 | 2014-6-19 10:31 | 只看该作者
@FSL_TICS_Robin  感谢版主昨天耐心解答,等我把这个产品折腾完了(最后一个心电功能,一个月以内应该能搞定),从头到尾写个调试笔记。

使用特权

评论回复
板凳
FSL_TICS_Robin| | 2014-6-19 10:47 | 只看该作者
这个TPM1产生互补的PWM波形好像不影响你对于其中一路PWM波占空比的测量吧?
你是想用芯片TPM模块产生PWM模拟心电信号吗?

使用特权

评论回复
评论
dong_abc 2014-6-19 10:55 回复TA
需要TPM1的ch0和ch1两个管脚同时工作才能测出占空比。 单路模式只需要一个PIN. 
地板
dong_abc| | 2014-6-19 10:51 | 只看该作者
本帖最后由 dong_abc 于 2014-6-19 10:53 编辑
FSL_TICS_Robin 发表于 2014-6-19 10:47
这个TPM1产生互补的PWM波形好像不影响你对于其中一路PWM波占空比的测量吧?
你是想用芯片TPM模块产生PWM模 ...


不用模拟, 心电模块就是发出一个2K到200KHZ的脉冲,只需要能检测宽度就可以了。
这个实例需要两个引脚才能测量。互补对称模式是ch0 和 ch1同时工作。 我的电路板上只有一个引脚PE21,也可以映射到TPM1的ch1上。

使用特权

评论回复
5
dong_abc| | 2014-6-19 10:57 | 只看该作者
两个马甲搞混了,这个也是我,defalut也是我哈。

使用特权

评论回复
6
FSL_TICS_Robin| | 2014-6-19 10:57 | 只看该作者
就是要用1个TPM的通道测量PWM的占空比(周期、高电平脉宽)是吧?

使用特权

评论回复
7
defalut|  楼主 | 2014-6-19 11:02 | 只看该作者
FSL_TICS_Robin 发表于 2014-6-19 10:57
就是要用1个TPM的通道测量PWM的占空比(周期、高电平脉宽)是吧?

是啊

使用特权

评论回复
8
FSL_TICS_Robin| | 2014-6-19 11:12 | 只看该作者
defalut 发表于 2014-6-19 11:02
是啊

那你要把输入捕捉配置成上下沿都捕捉的那种形式,至于此次捕捉到的Counter值是由上升沿or下降沿导致可以通过读该IO口电平来判断。


使用特权

评论回复
9
FSL_TICS_Robin| | 2014-6-19 11:17 | 只看该作者
FSL_TICS_Robin 发表于 2014-6-19 11:12
那你要把输入捕捉配置成上下沿都捕捉的那种形式,至于此次捕捉到的Counter值是由上升沿or下降沿导致可以 ...

如果即要测周期、又要测占空比的话:
总共要在一个counter MOD值溢出周期内捕捉三次,两次同样边沿捕获的CnV差值作为周期,不同边沿捕获的CnV差值作为脉宽(下降沿CnV 减去 上升沿CnV 就是高电平脉宽)。
先讨论下这种方式是否满足你的需求。

使用特权

评论回复
10
dong_abc| | 2014-6-19 12:05 | 只看该作者
FSL_TICS_Robin 发表于 2014-6-19 11:17
如果即要测周期、又要测占空比的话:
总共要在一个counter MOD值溢出周期内捕捉三次,两次同样边沿捕获的 ...

这样可以,貌视 很麻烦呀。

使用特权

评论回复
11
dong_abc| | 2014-6-19 12:50 | 只看该作者
下午有客户来了,明天再折腾了。

使用特权

评论回复
12
FSL_TICS_Robin| | 2014-6-19 12:51 | 只看该作者
dong_abc 发表于 2014-6-19 12:05
这样可以,貌视 很麻烦呀。

我对心电信号不了解,如果你只要测周期(不测占空比)就不麻烦啦:捕捉两次相同边沿的CnV做差就可得出周期了。

使用特权

评论回复
13
FSL_TICS_Robin| | 2014-6-19 12:51 | 只看该作者
dong_abc 发表于 2014-6-19 12:50
下午有客户来了,明天再折腾了。

明天我不在呢
FSL_TICS_Jeremy他明天在,可以问一下他

使用特权

评论回复
14
dong_abc| | 2014-6-19 13:11 | 只看该作者
本帖最后由 dong_abc 于 2014-6-19 13:14 编辑
FSL_TICS_Robin 发表于 2014-6-19 12:51
明天我不在呢
FSL_TICS_Jeremy他明天在,可以问一下他

能把两路互补对称改成单路模式,就差不多了。
随便周期 或者占空比 。之后的我应该能搞定。


  
版主改改那个例子,看能实现不,那4个寄存器我配置了一天,都没弄好。

使用特权

评论回复
15
FSL_TICS_Robin| | 2014-6-19 15:20 | 只看该作者
dong_abc 发表于 2014-6-19 13:11
能把两路互补对称改成单路模式,就差不多了。
随便周期 或者占空比 。之后的我应该能搞定。

最好将你提到的心率信号描述更清楚一点,因为这会影响到程序处理。
感觉你是只测心跳频率(来一次心跳,输出一个高电平窄脉冲),如果是这样的话只需配置上升沿捕捉,两次捕捉到CnV差值就可计算出周期。

如果你要测不定频PWM波的周期、占空比,那程序要复杂的多。


使用特权

评论回复
16
dong_abc| | 2014-6-19 15:59 | 只看该作者
FSL_TICS_Robin 发表于 2014-6-19 15:20
最好将你提到的心率信号描述更清楚一点,因为这会影响到程序处理。
感觉你是只测心跳频率(来一次心跳, ...

心率有个算法,什么信号我也不清楚,我只是给别人实现这个底层的功能。
不用那么复杂, 版主帮我配置个 能检测脉宽的就行(频率就是固定的),其他的都好办,我现在主要是不能将那个互补对称模式改成单路模式。

使用特权

评论回复
17
FSL_TICS_Robin| | 2014-6-19 16:34 | 只看该作者
dong_abc 发表于 2014-6-19 15:59
心率有个算法,什么信号我也不清楚,我只是给别人实现这个底层的功能。
不用那么复杂, 版主帮我配置个  ...

程序现在捕捉3次,为了得出高电平脉宽故在TPM1中断函数里判断最后次捕捉口电平状态,以确定哪两次相减才是高电平CnV差。
如果3次捕捉跨了MOD溢出,就清除这3次值不做计算。

试一下吧
不过实际使用时要注意:
capture的TPM模块MOD溢出周期放大些,建议在信号周期的2、3倍以上。
TPM1那捕捉也没必要通过TPM0的溢出去触发。

FRDM-KL26Z_SC_CaptureHighPulse.zip (551.51 KB)


使用特权

评论回复
18
dong_abc| | 2014-6-19 19:59 | 只看该作者
本帖最后由 dong_abc 于 2014-6-19 20:02 编辑
FSL_TICS_Robin 发表于 2014-6-19 16:34
程序现在捕捉3次,为了得出高电平脉宽故在TPM1中断函数里判断最后次捕捉口电平状态,以确定哪两次相减才 ...


好的,谢谢了,下午跟客户联调去了。 我调试看看。

使用特权

评论回复
19
defalut|  楼主 | 2014-6-23 11:20 | 只看该作者
本帖最后由 defalut 于 2014-6-23 11:26 编辑
FSL_TICS_Robin 发表于 2014-6-19 16:34
程序现在捕捉3次,为了得出高电平脉宽故在TPM1中断函数里判断最后次捕捉口电平状态,以确定哪两次相减才 ...


谢谢版主的耐心解答,这个问题是楼主在犯晕。楼主把TPM1的ch1线拔掉了,发现脉宽没有变成0,就以为TPM1失效了。实际是TPM1的ch1检测不到中断,数据就一直保持了。
1楼其实是正确的,版主的demo更好。
这段时间被逼的太紧,再加上对FREESCALE,PE,IAR之类的不太熟悉,脑袋短路了。

再次谢谢版主,我这个项目跟芯片相关的部分算是整完了。

使用特权

评论回复
20
FSL_TICS_Robin| | 2014-6-23 13:08 | 只看该作者
defalut 发表于 2014-6-23 11:20
谢谢版主的耐心解答,这个问题是楼主在犯晕。楼主把TPM1的ch1线拔掉了,发现脉宽没有变成0,就以为TPM1失 ...

不用客气
以后开发过程中遇到什么问题,欢迎来飞思卡尔MCU论坛发帖与大家一起讨论。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

48

帖子

0

粉丝