1323|0

3836

帖子

19

TA的资源

纯净的硅(中级)

楼主
 

MSP430 多路捕获问题… [复制链接]

本帖最后由 fish001 于 2017-4-26 19:56 编辑

编了一个MSP430f169 捕获8路PWM波信号的程序。分别用定时器B的所有捕获比较寄存器以及定时器A的一个捕获比较寄存器进行捕获。结果只有TBCCR0和TBCCR1捕获的两路信号是对的,其他几路都不对。实在找不出哪出问题了,各位前辈帮我看一下。下面是代码。

主函数代码:
C/C++ code


/*********************************************************
程序功能:分别检测加速度计模块从P4.0到P4.6端口输入的PWM波
          信号的T1和T2(T1为高电平脉宽,T2为周期),并将数
          据通过串口发送到PC(理想PWM波周期1600us情况下)
-----------------------------------------------------------
通信格式:N.8.1, 9600
-----------------------------------------------------------
**********************************************************/
#include
#include "UART0_Func.c"
#include "function.c"
//#define M1 16
//unsigned int cap1=0,cap2=0,N1=0,N2=0;
unsigned int cap[8]={0,0,0,0,0,0,0,0};//存放捕获是6路信号各自的上升沿时计数器的数值
unsigned int n[8]={0,0,0,0,0,0,0,0};//存放计数溢出的次数
long widthT01[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT02[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//存放每路信号的高点平宽度和周期信息
long widthT03[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT04[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT11[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT12[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT13[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT14[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT21[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT22[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT23[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT24[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT31[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT32[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT33[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long widthT34[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//char m=0,n=0,a=0,b=0;
char m[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//用于记录每路数据已经采集了的个数,每路信号采集M1个数,
long XT1[4]={0,0,0,0};//存放8路信号取平均后的值。
long XT2[4]={0,0,0,0};
long YT1[4]={0,0,0,0};
long YT2[4]={0,0,0,0};
unsigned char data_T[34];//存放将要发送的数据


void main( void )
{
  char k1;
   // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;//关闭看门狗
//-------开晶振XT2---------

   BCSCTL1&=~XT2OFF;                //打开XT2振荡器
   do
   {
   IFG1 &= ~OFIFG;                     // 清除振荡器失效标志
   for (int i=256;i>0;i--);                     // 延时,等待XT2起振
   }
  while ((IFG1 & OFIFG) != 0);            // 判断XT2是否起振 */
   IFG1&=~OFIFG;

  BCSCTL2=SELM1+SELS+DIVS0+DIVS1;//SMCLK=XT2,8分频
  P4SEL|=BIT0+BIT1+BIT2+BIT3+BIT4+BIT5+BIT6;////P4.0和P4.1作为捕获模块功能输入端输入方波
  //TBCCTL0=0;//捕获源为P4.0,即CCI0A(也是CCI0B)
  P1DIR = BIT0+BIT4;   //设置P1.0方向为输出
  P1SEL = BIT2;  //设置P1.2端口为功能模块使用
  TACTL = TACLR+TASSEL_2+TAIE+MC1;
  //==定时器A时钟信号选择SMCLK,8分频,同时设置定时器A计数模式为连续增计模式==
  TACCTL1|=CM_1+SCS+CAP+CCIE; //MC0
     //输入上升沿捕获,CCI0A为捕获信号源
  TBCCTL0|=CM_1+SCS+CAP+CCIE;//上升沿捕获,同步捕获,工作在捕获模式+中断允许
  TBCCTL1|=CM_1+SCS+CAP+CCIE;//上升沿捕获,同步捕获,工作在捕获模式+中断允许
  TBCCTL2|=CM_1+SCS+CAP+CCIE;//上升沿捕获,同步捕获,工作在捕获模式+中断允许
  TBCCTL3|=CM_1+SCS+CAP+CCIE;//上升沿捕获,同步捕获,工作在捕获模式+中断允许
  TBCCTL4|=CM_1+SCS+CAP+CCIE;//上升沿捕获,同步捕获,工作在捕获模式+中断允许
  TBCCTL5|=CM_1+SCS+CAP+CCIE;//上升沿捕获,同步捕获,工作在捕获模式+中断允许
  TBCCTL6|=CM_1+SCS+CAP+CCIE;//上升沿捕获,同步捕获,工作在捕获模式+中断允许
  TBCTL|=TBSSEL_2+MC_2+TBIE;//选择SMCLK+连续计数模式
   //+终端允许
  InitUART();//初始化UART端口
  _EINT();//中断允许

  while(1)
  {
    for(k1=0;k1     {
      XT1[0]+=widthT01[k1];
      XT2[0]+=widthT02[k1];
      YT1[0]+=widthT03[k1];
      YT2[0]+=widthT04[k1];
      XT1[1]+=widthT11[k1];
      XT2[1]+=widthT12[k1];
      YT1[1]+=widthT13[k1];
      YT2[1]+=widthT14[k1];
      XT1[2]+=widthT21[k1];
      XT2[2]+=widthT22[k1];
      YT1[2]+=widthT23[k1];
      YT2[2]+=widthT24[k1];
      XT1[3]+=widthT31[k1];
      XT2[3]+=widthT32[k1];
      YT1[3]+=widthT33[k1];
      YT2[3]+=widthT34[k1];
    }
    XT1[0]>>= 4;
    XT2[0]>>= 4;
    YT1[0]>>= 4;
    YT2[0]>>= 4;
    XT1[1]>>= 4;
    XT2[1]>>= 4;
    YT1[1]>>= 4;
    YT2[1]>>= 4;
    XT1[2]>>= 4;
    XT2[2]>>= 4;
    YT1[2]>>= 4;
    YT2[2]>>= 4;
    XT1[3]>>= 4;
    XT2[3]>>= 4;
    YT1[3]>>= 4;
    YT2[3]>>= 4;//求和取平均
    if(n[0]==0)
    {
      Hex2Dec(0,XT1,XT2,YT1,YT2,data_T);//将第一对信号放入data_T数组准备发送
      Hex2Dec(1,XT1,XT2,YT1,YT2,data_T);//第二对信号
      Hex2Dec(2,XT1,XT2,YT1,YT2,data_T);//第三对信号
      Hex2Dec(3,XT1,XT2,YT1,YT2,data_T);//第四对信号
      //数据转为char型进行传输
      //数据每路PWM波周期为1600us,每路信号用4bit就可把数据表示完整
      //T1用data_T的前2位,T2用后2位,低位在前
      //前4位存X轴数据,后4位存Y轴数据
      PutString(data_T);
    }
  }

// return 0;
}

//全局变量可以通过中断服务程序改,只要函数中没有相同的局部变量就行
#pragma vector=TIMERB0_VECTOR
__interrupt void TimerB0(void)//定时器TB的CCR0的中断,用于检测脉冲上升与下降
{
   Capture_B(0,m,cap,n,widthT01,widthT02);
}

//Timer_B7 Interrupt Vector(TBIV) handler
#pragma vector=TIMERB1_VECTOR
__interrupt void Timer_B(void)//定时器TB的CCR1的中断,
{
   //TBCCTL0&=~BIT0;
   switch(TBIV)
  {
    case 2:
       Capture_B(1,m,cap,n,widthT03,widthT04);
       break;/**/
    case 4:
       Capture_B(2,m,cap,n,widthT11,widthT12);
       break;/**/
    case 6:
       Capture_B(3,m,cap,n,widthT13,widthT14);
       break;/**/
    case 8:
       Capture_B(4,m,cap,n,widthT21,widthT22);
       break;/**/
    case 10:
       Capture_B(5,m,cap,n,widthT23,widthT24);
       break;/**/
    case 12:
       Capture_B(6,m,cap,n,widthT31,widthT32);
       break;/**/
    case 14:n[0]++,n[1]++,n[2]++,n[3]++,n[4]++,n[5]++,n[6]++;break;//溢出
  }
}
#pragma vector=TIMERA1_VECTOR  //定时器A中断处理
__interrupt void timer_a(void)
{
switch(TAIV)   //向量查询
  { case 2:             //捕获中断
       Capture_A(1,m,cap,n,widthT33,widthT34);
       break;
    case 10:      //定时器溢出中断
       n[7]++; break;      //溢出计数加1
    default:break;
  }
}


串口通讯-UART0_Func.c文件代码:
C/C++ code

#include
typedef unsigned char uchar;
/*******************************************
函数名称:InitUART
功    能:初始化UART端口
参    数:无
返回值  :无
********************************************/
void InitUART(void)
{
    P3SEL |= 0x30;                            // P3.4,5 = USART0 TXD/RXD
    ME1 |= URXE0 + UTXE0;                             // Enable USART0 T/RXD
    UCTL0 |= CHAR;                            // 8-bit character
    UTCTL0 |= SSEL0;                          // UCLK = ACLK
    UBR00 = 0x03;                             // 32k/9600 - 3.41
    UBR10 = 0x00;                             //
    UMCTL0 = 0x6B;                            // Modulation
    UCTL0 &= ~SWRST;                          // Initialize USART state machine
}
/*******************************************
函数名称:Send1Char
功    能:向PC机发送一个字符
参    数:sendchar--要发送的字符
返回值  :无
********************************************/
void Send1Char(uchar sendchar)
{
      while (!(IFG1 & UTXIFG0));    //等待发送寄存器为空         
      TXBUF0 = sendchar;

}
/*******************************************
函数名称:PutSting
功    能:向PC机发送字符串,无换行
参    数:ptr--指向发送字符串的指针
返回值  :无
********************************************/
void PutString(uchar *ptr)
{
  int i;
  for(i=0;i<34;i++)
  {
   Send1Char(ptr);                     // 发送数据
  }
}
/********************************************
函数名称:Hex2Dec
功    能:将long型数据变换成char型的形式
参    数:Hex_Val--long型数据  
          ptr--指向存放转换结果的指针
返回值  :无
********************************************/
void Hex2Dec(unsigned char channel,long *XT1,long *XT2,long *YT1,long *YT2,uchar *ptr)
{
  int i;//数组ptr有34bit,2bit标注位,32bit数据位。
  unsigned char num=channel*8;//channel取0到3.
  ptr[0]=ptr[1]=0xFF;//作为标志位//,XT1,XT2,YT1,YT2,data_T
  for(i=0;i<2;i++)//存放占空比信号,此时低位在前
  {
    ptr[i+num+2]=XT1[channel]%256;//存放X轴高电平宽度
    ptr[i+num+4]=XT2[channel]%256;//存放X轴周期
    ptr[i+num+6]=YT1[channel]%256;//存放Y轴高电平宽度
    ptr[i+num+8]=YT2[channel]%256;//存放Y轴周期
    XT1[channel]>>= 8;
    XT2[channel]>>= 8;
    YT1[channel]>>= 8;
    YT2[channel]>>= 8;
  }
}


功能函数-function.c文件代码:
C/C++ code
?
#include
//typedef unsigned char uchar;
#define M1 16

void Capture_B(unsigned short channel,char *m,unsigned int *cap,unsigned int *n,long *widthT1,long *widthT2)
{
  volatile unsigned short *tbcctlx,*tbccrx;//设置指向相应寄存器的指针
  unsigned char num=channel*2;//channel取0到6.
  tbcctlx=&TBCCTL0+channel;//0x0182u为TBCCTL0地址,相邻两个控制寄存器地址相差2.确定相应通道。
  tbccrx=&TBCCR0+channel;//0x0192u为地址。当channel==0,指向TBCCR0。
  //当channel==1,指向TBCCR1.以此类推。
  if(*tbcctlx&CM1)//捕获到下降沿
  {
    widthT1[m[num]++]=65536*n[channel]+*tbccrx-cap[channel];//记录下结束时间,保存高电平宽度
    //N1=0;
    //cap1=TBCCR0;//添加这段的话,T2将保存低电平的宽度
    *tbcctlx=CM_1+SCS+CAP+CCIE;//+TBCLR;
    //改为上升沿捕获,CM0置1,CM1置0
    if(m[num]==M1) m[channel]=0;
  }
  else if(*tbcctlx&CM0)//捕获到上升沿
  {
    widthT2[m[num+1]++]=65536*n[channel]+*tbccrx-cap[channel];//记录下结束时间,保存周期宽度
    n[channel]=0;
    cap[channel]=*tbccrx;//始终保存上升沿时的数值
    *tbcctlx=CM_2+SCS+CAP+CCIE;//+TBCLR;
    //改为下降沿捕获,CM0置0,CM1置1
    if(m[num+1]==M1) m[num+1]=0;
  }
}

void Capture_A(unsigned short channel,char *m,unsigned int *cap,unsigned int *n,long *widthT1,long *widthT2)
{
  volatile unsigned short *tacctlx,*taccrx;//设置指向相应寄存器的指针
// unsigned char num=channel*2;//channel取0到6.
  tacctlx=&TACCTL0+channel;//0x0162u相邻两个控制寄存器地址相差2.确定相应通道。
  taccrx=&TACCR0+channel;//0x0172u当channel==0,指向TACCR0。
  //当channel==1,指向TACCR1.以此类推。
  if(*tacctlx&CM1)//捕获到下降沿
  {
    widthT1[m[7]++]=65536*n[7]+*taccrx-cap[7];//记录下结束时间,保存高电平宽度
    //N1=0;
    //cap1=TBCCR0;//添加这段的话,T2将保存低电平的宽度
    *tacctlx=CM_1+SCS+CAP+CCIE;//+TBCLR;
    //改为上升沿捕获,CM0置1,CM1置0
    if(m[14]==M1) m[14]=0;
  }
  else if(*tacctlx&CM0)//捕获到上升沿
  {
    widthT2[m[15]++]=65536*n[7]+*taccrx-cap[7];//记录下结束时间,保存周期宽度
    n[7]=0;
    cap[7]=*taccrx;//始终保存上升沿时的数值
    *tacctlx=CM_2+SCS+CAP+CCIE;//+TBCLR;
    //改为下降沿捕获,CM0置0,CM1置1
    if(m[15]==M1) m[15]=0;
  }
}

 
点赞 关注

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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

 
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
快速回复 返回顶部 返回列表