3737|13

19

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

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

利用MSP430单片机定时器A和捕获/比较功能模块结合使用,实现脉冲宽度的测量。
    本例程用到了定时器ACCI1A端口(例如MSP430F14XP1.2引脚)作捕获外部输入的脉冲电平跳变,同时结合简单的软件算法就能实现脉冲宽度的测量。在实际应用中可根据例程中的start,end,overflow三个变量来计算脉冲宽度。此功能模块在实际产品应用中体现出有较高的应用价值。
2-例程
#include
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;
}
}
//例程结束

最新回复

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

回复
举报

19

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
我之前查到的测周期的思路,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
 
 

回复

667

帖子

3

TA的资源

版主

板凳
 
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
 
 
 

回复

19

帖子

0

TA的资源

一粒金砂(中级)

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

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

点评

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

回复

667

帖子

3

TA的资源

版主

5
 
hzlxlzh 发表于 2015-4-5 18:41
那我的思路要改这个例程代码的哪里

你先要学弟的知识:

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

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

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

回复

19

帖子

0

TA的资源

一粒金砂(中级)

6
 
nemo1991 发表于 2015-4-5 19:04
你先要学弟的知识:

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

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

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

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

回复

19

帖子

0

TA的资源

一粒金砂(中级)

7
 
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 */
 
 
 

回复

19

帖子

0

TA的资源

一粒金砂(中级)

8
 
nemo1991 发表于 2015-4-5 18:34
我觉得说的思路可以得啊。

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

回复

6366

帖子

4914

TA的资源

版主

9
 
你实际模拟仿真测试一下,看看中断响应时的捕获的数据是否正确

点评

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
 
 
 

回复

19

帖子

0

TA的资源

一粒金砂(中级)

10
 
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
 
 
 

回复

19

帖子

0

TA的资源

一粒金砂(中级)

11
 
本帖最后由 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
 
 
 

回复

19

帖子

0

TA的资源

一粒金砂(中级)

12
 
本帖最后由 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
 
 
 

回复

2549

帖子

0

TA的资源

五彩晶圆(初级)

13
 
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
 
 
 

回复

19

帖子

0

TA的资源

一粒金砂(中级)

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

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

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表