社区导航

 
快捷导航
  • 首页
  • 论坛
  • 查看新帖
  • 最新回复
  • 精华区
  • 社区活动
  • 联系管理员
  • 消灭零回复
  • E金币兑换
搜索
查看: 1415|回复: 13

[求助] 想用430 g2553 TimerA测输入方波的周期,用了下面的代码不成功,请求帮助!

[复制链接]

21

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2015-4-5 18:19:18 | 显示全部楼层 |阅读模式
利用MSP430单片机定时器A和捕获/比较功能模块结合使用,实现脉冲宽度的测量。
    本例程用到了定时器ACCI1A端口(例如MSP430F14XP1.2引脚)作捕获外部输入的脉冲电平跳变,同时结合简单的软件算法就能实现脉冲宽度的测量。在实际应用中可根据例程中的start,end,overflow三个变量来计算脉冲宽度。此功能模块在实际产品应用中体现出有较高的应用价值。
2-例程
#include <msp430x14x.h>
unsigned int start,end;
unsigned char overflow;
void main (void)
{
WDTCTL = WDTPW+WDTHOLD;                   //关闭看门狗定时器
P1DIR = BIT0+BIT4;                        //设置P1.0方向为输出
P1SEL = BIT2;                             //设置P1.2端口为功能模块使用
TACTL = TASSEL0+TACLR+TAIE+MC1;           //定时器A时钟信号选择ACLK,同时设置定时器A计数模式为连续增计模式
CCTL1 = MC0+SCS+CAP+CCIE;                 //输入上升沿捕获,CCI0A为捕获信号源
_EINT();                                  //中断允许
while(1);                                 //LOOP
}
#pragma vector=TIMERA1_VECTOR              //定时器A中断处理
__interrupt void timer_a(void)
{
switch(TAIV)                              //向量查询
{ case 2:                               //捕获中断
       if(CCTL1&CM0)                     //上升沿
        {
           CCTL1=(CCTL1&(~CM0))|CM1;       //更变设置为下降沿触发
           start=TAR;                      //记录初始时间
           overflow=0;                     //溢出计数变量复位
        }
      else if (CCTL1&CM1)                //下降沿
       {  
           CCTL1=(CCTL1&(~CM1))|CM0;       //更变设置为上升沿触发
           end=TAR;                        //start,end,overflow计算脉冲宽度
       }   
      break;
   case 10:                              //定时器溢出中断
      overflow++;
      break;                             //溢出计数加1
   default:break;
}
}
//例程结束

回复

使用道具 举报

21

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2015-4-5 18:23:54 | 显示全部楼层
我之前查到的测周期的思路,P1.0口输入脉搏方波信号,把定时器A设置为上升沿中断,定时器A中计数器设置为连续增计数模式,计数时钟周期为1/32768秒,当输入方波信号上升沿时,定时器捕获中断,计数器的初值a[N-1]被保存并起动计数,当计数器计数到65536溢出时,计数器自动清零重新开始计数,当输入第二个方波信号上升沿时,定时器再次捕获中断,并保存定时器的终值a[n],单片机能记下一个脉搏周期内计数器的初值a[n-1]和终值a[n], 以及计数器溢出次数over—flow。代入下面的公式可算出脉搏的周期
T= [65536 * overflow +(a[n]-a[n-1])]/32768

点评

我觉得说的思路可以得啊。  详情 回复 发表于 2015-4-5 18:34

回复

使用道具 举报

656

TA的帖子

3

TA的资源

版主

Rank: 6Rank: 6

发表于 2015-4-5 18:34:09 | 显示全部楼层
hzlxlzh 发表于 2015-4-5 18:23
我之前查到的测周期的思路,P1.0口输入脉搏方波信号,把定时器A设置为上升沿中断,定时器A中计数器设置为连续增计数模式,计数时钟周期为1/32768秒,当输入方波信号上升沿时,定时器捕获中断,计数器的初值a[N-1]被保存并起动计数,当计数器计数到65536溢出时,计数器自动清零重新开始计数,当输入第二个方波信号上升沿时,定时器再次捕获中断,并保存定时器的终值a[n],单片机能记下一个脉搏周期内计数器的初值a[n-1]和终值a[n], 以及计数器溢出次数over—flow。代入下面的公式可算出脉搏的周期
T= [65536 * overflow +(a[n]-a[n-1])]/32768

我觉得说的思路可以得啊。

点评

这个程序我是能读懂和理解的,但加在我的程序里不成功,心率一直显示535  详情 回复 发表于 2015-4-5 19:26

回复

使用道具 举报

21

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2015-4-5 18:41:57 | 显示全部楼层
nemo1991 发表于 2015-4-5 18:34
我觉得说的思路可以得啊。

那我的思路要改这个例程代码的哪里

点评

你先要学弟的知识: 1.定时其用法。启动、停止如何操作,如何读取数值。 2.想好边沿触发中断函数的处理逻辑,我觉得应该设置为双边沿触发,进入中断读取寄存器,判断电平。 3.g2不是做这个的最佳方案,建议  详情 回复 发表于 2015-4-5 19:04

回复

使用道具 举报

656

TA的帖子

3

TA的资源

版主

Rank: 6Rank: 6

发表于 2015-4-5 19:04:58 | 显示全部楼层
hzlxlzh 发表于 2015-4-5 18:41
那我的思路要改这个例程代码的哪里

你先要学弟的知识:

1.定时其用法。启动、停止如何操作,如何读取数值。

2.想好边沿触发中断函数的处理逻辑,我觉得应该设置为双边沿触发,进入中断读取寄存器,判断电平。

3.g2不是做这个的最佳方案,建议使用带有capture功能的单片机。

回复

使用道具 举报

21

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2015-4-5 19:18:11 | 显示全部楼层
nemo1991 发表于 2015-4-5 19:04
你先要学弟的知识:

1.定时其用法。启动、停止如何操作,如何读取数值。

2.想好边沿触发中断函数的处理逻辑,我觉得应该设置为双边沿触发,进入中断读取寄存器,判断电平。

3.g2不是做这个的最佳方案,建议使用带有capture功能的单片机。

G2的定时器A不带有捕获边沿触发中断的功能吗?但我看过g2553的头文件,里面好像有边沿捕获的定义

回复

使用道具 举报

21

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2015-4-5 19:21:37 | 显示全部楼层
hzlxlzh 发表于 2015-4-5 19:18
G2的定时器A不带有捕获边沿触发中断的功能吗?但我看过g2553的头文件,里面好像有边沿捕获的定义

#define CM_0                (0*0x4000u) /* Capture mode: 0 - disabled */
#define CM_1                (1*0x4000u) /* Capture mode: 1 - pos. edge */
#define CM_2                (2*0x4000u) /* Capture mode: 1 - neg. edge */
#define CM_3                (3*0x4000u) /* Capture mode: 1 - both edges */

回复

使用道具 举报

21

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2015-4-5 19:26:45 | 显示全部楼层
nemo1991 发表于 2015-4-5 18:34
我觉得说的思路可以得啊。

这个程序我是能读懂和理解的,但加在我的程序里不成功,心率一直显示535

回复

使用道具 举报

6082

TA的帖子

4957

TA的资源

至上芯片

Rank: 13Rank: 13Rank: 13Rank: 13

资源大师勋章

发表于 2015-4-6 00:05:18 | 显示全部楼层
你实际模拟仿真测试一下,看看中断响应时的捕获的数据是否正确

点评

TACCTL1 = CAP+CM_1+CCIS_0+SCS+CCIE; // 输入捕捉,上升沿触发(upCM_1,downCM_2,updownCM_3),同步捕捉,CCR0 中断使能 TACTL = TASSEL_2 + MC_2 + TAIE + TACLR; // 选择SMCLK为时钟,连续增  详情 回复 发表于 2015-4-6 05:45

回复

使用道具 举报

21

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2015-4-6 05:45:49 | 显示全部楼层
tiankai001 发表于 2015-4-6 00:05
你实际模拟仿真测试一下,看看中断响应时的捕获的数据是否正确

TACCTL1 = CAP+CM_1+CCIS_0+SCS+CCIE;              // 输入捕捉,上升沿触发(upCM_1,downCM_2,updownCM_3),同步捕捉,CCR0 中断使能
TACTL = TASSEL_2 + MC_2 + TAIE + TACLR;        // 选择SMCLK为时钟,连续增计数模式 ,溢出中断使能
_EINT();                                  //开全局中断
我现在不清楚我这样设置定时器A时,选择SMCLK为时钟,SMCLK的频率是多少,单片机是launchpad g2553

回复

使用道具 举报

21

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2015-4-6 06:30:43 | 显示全部楼层
本帖最后由 hzlxlzh 于 2015-4-7 13:05 编辑

#define uchar            unsigned char
#define uint             unsigned int
uint a[10],n=0,overfloat=0;

int main(void)
{   uint heartrate,i;
   
    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
    P1DIR &=~BIT2;
    P1REN |= BIT2;
    P1SEL |= BIT2;                 //输入捕捉端口(P1.2)
    TACCTL1 = CAP+CM_1+CCIS_0+SCS+CCIE;              // 输入捕捉,上升沿触发(upCM_1,downCM_2,updownCM_3),同步捕捉,CCR0 中断使能
    TACTL = TASSEL_2 + MC_2 + TAIE + TACLR;        // 选择SMCLK为时钟,连续增计数模式 ,溢出中断使能
    _EINT();                                  //开全局中断

    IO_Init();
    LCD_Init();
    uchar LCDBuf1[]={"heart rate:"};
   
    while(1)
      {  
        LCD_Write_Command(0x01);
        if(n>0&&n%2==1)
           heartrate=(2000000*60)/(65535*overfloat+(a[n]-a[n-1]));
              for(i=0;i<80;i++)
               {   
                   LCD_Disp_string(0,0,LCDBuf1);
     LCD_Write_Command(0x80+0x0c);  
                    Disp(heartrate);
                   if(heartrate==0)
   LCD_Disp_string(0,2,message[3]);
            else if(heartrate<=60)
   LCD_Disp_string(0,2,message[0]);
                   else if(heartrate<=120)
   LCD_Disp_string(0,2,message[1]);
                   else
                        LCD_Disp_string(0,2,message[2]);
               }
}
}
#pragma vector=TIMER0_A1_VECTOR  //捕获中断
__interrupt void Timer0_A1(void)
{
  switch(TA0IV)
  {
   case 2:
    {
      if(n%2==0)
        overfloat=0;
      a[n]=TAR;//CCR1
      if(n==9)
        n=0;
      else
        n++;
      break;
    }
   case  4:              break;                          // CCR2 not used
   case 10: overfloat++; break;              // TimerA溢出中断;
  }
}

点评

我也看不出问题出哪了,你调试时,看下那几个量的值是多少,手工一步步算一下  详情 回复 发表于 2015-4-7 16:28

回复

使用道具 举报

21

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2015-4-6 06:42:50 | 显示全部楼层
本帖最后由 hzlxlzh 于 2015-4-7 13:06 编辑

以上是刚刚编好的程序,是用来测心率的,但运行时出了问题,给P1.2输入一个稳定的方波,会测出多个不同的心率值且相差十几到三十几左右,方波频率越大相差越大,比如170次每分钟,会显示一百五十多,一百七十多,二百二十多,不知道为什么,程序哪里出来问题,程序中心率计算使用了之前提到的思路,即输入脉搏方波信号,把定时器A设置为上升沿中断,定时器A中计数器设置为连续增计数模式,计数时钟周期为1/32768秒,当输入方波信号上升沿时,定时器捕获中断,计数器的初值a[N-1]被保存并起动计数,当计数器计数到65536溢出时,计数器自动清零重新开始计数,当输入第二个方波信号上升沿时,定时器再次捕获中断,并保存定时器的终值a[n],单片机能记下一个脉搏周期内计数器的初值a[n-1]和终值a[n], 以及计数器溢出次数over—flow。代入下面的公式可算出脉搏的周期
T= [65536 * overflow +(a[n]-a[n-1])]/32768

回复

使用道具 举报

1975

TA的帖子

0

TA的资源

纯净的硅(高级)

Rank: 6Rank: 6

发表于 2015-4-7 16:28:45 | 显示全部楼层
hzlxlzh 发表于 2015-4-6 06:30
#define uchar            unsigned char
#define uint             unsigned int
uint a[10],n=0,overfloat=0;

int main(void)
{   uint heartrate,i;
   
    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
    P1DIR &=~BIT2;
    P1REN |= BIT2;
    P1SEL |= BIT2;                 //输入捕捉端口(P1.2)
    TACCTL1 = CAP+CM_1+CCIS_0+SCS+CCIE;              // 输入捕捉,上升沿触发(upCM_1,downCM_2,updownCM_3),同步捕捉,CCR0 中断使能
    TACTL = TASSEL_2 + MC_2 + TAIE + TACLR;        // 选择SMCLK为时钟,连续增计数模式 ,溢出中断使能
    _EINT();                                  //开全局中断

    IO_Init();
    LCD_Init();
    uchar LCDBuf1[]={"heart rate:"};
   
    while(1)
      {  
        LCD_Write_Command(0x01);
        if(n>0&&n%2==1)
           heartrate=(2000000*60)/(65535*overfloat+(a[n]-a[n-1]));
              for(i=0;i

我也看不出问题出哪了,你调试时,看下那几个量的值是多少,手工一步步算一下

点评

已经解决,计算心率值时定时器溢出数值一直在增加,所以显示出的心率值也随之一直在跳变  详情 回复 发表于 2015-4-7 20:47

回复

使用道具 举报

21

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2015-4-7 20:47:33 | 显示全部楼层
数码小叶 发表于 2015-4-7 16:28
我也看不出问题出哪了,你调试时,看下那几个量的值是多少,手工一步步算一下

已经解决,计算心率值时定时器溢出数值一直在增加,所以显示出的心率值也随之一直在跳变

回复

使用道具 举报

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

本版积分规则

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

小黑屋|手机版|Archiver|电子工程世界 ( 京ICP证 060456

GMT+8, 2017-9-23 06:30 , Processed in 0.477179 second(s), 26 queries , Redis On.

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