打印

求助几个m430g2553程序编写问题

[复制链接]
2950|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hitliiu|  楼主 | 2013-7-30 16:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我们最近在做09年电赛的声音导引系统这个题目:小车上面的蜂鸣器发出信号,用三个接收器接收信号,处理后产生规则脉冲,连到单片机的三个端口上分别触发中断,然后通过三个中断的时间差来算出小车的坐标.以上是我们的大体思路.初次用C语言在单片机上编程,而且也是初次接触msp430,查了很多天资料才写出了下面这些代码,但是有几个问题始终是找不到答案,不得已才整段发到这里来希望能有朋友帮忙
1.在使用定时器A时,我可以不打开它的中断,仅使用它的计数功能吗?如果可以,它是不是从打开计数器开始每个机器周期数值加1?这个数值存在哪里,是CCR0吗(我另外开了一个程序发现CCR0的值一直都是0)?
2.我使用了p1.567作为三个中端口,它们作为中端口的时候是不是输入输出口都可以?我在网上看到有的程序是设成输入口可是有的程序是设成输出口.
3.我们算坐标的时候计算过程十分复杂,用到了sin,cos,反三角,目测这样写单片机的负担肯定很大,计算过程不短,可是我们能想到的只能这样算,请问这样算单片机能在1s中算出来吗?有没有什么简化的方**
希望有朋友帮忙解答.
附上程序:
#include<msp430g2253.h>
#include<math.h>
#define PI 3.1415926
unsigned int t1=0;  
unsigned int t2=0;  
unsigned int t3=0;  //定义三个接收器的时刻变量
volatile int i=0;//定义全局变量,用于标记已到达的脉冲信号
//函数声明
void initcount()  //计时初始化
{
     unsigned int iq0;    //延时标志
     BCSCTL1 &= ~XT2OFF;  //打开XT2振荡器
     do
     {
          IFG1 &= ~OFIFG;          //清除振荡器失效标志
          for (iq0=0xFF; iq0>0; iq0--)    //延时,等待XT2起振
          {
          }
     }
     while ((IFG1 & OFIFG)!= 0);      //判断XT2是否起振
      BCSCTL2=SELM_2+SELS;          //选择MCLK、SMCLK为XT2
      TACTL=TASSEL_1+TACLR;          //定时器A,时钟源:ACLK,连续计数模式
        
}

void countbegin(unsigned char doit) //控制计数运行或者停止 doit==0:停止;doit==100:运行;其他:什么都不做
{
     if(doit==0)
     {
          TACTL &= ~MC1;     //关闭计数器
     }
     else if(doit==100)
     {
          TACTL |= MC_2+TACLR;  //打开计数器
     }
     
}
void initport() //端口初始化
{
  //P1DIR=0x00;  //P1.7 1.6 1.5为输入
  P1IE=0xe0; //P1.7 1.6 1.5中断允许
  P1IES=0x00; //上升沿触发
  P1IFG=0; //中断标志清除,对于多源中断必须先清中断标志再打开中断
  _EINT(); //总中断允许
}
void main(void)
{
  double a,b,c,d12,d32,theta,r1;
  WDTCTL = WDTPW + WDTHOLD;
  initcount();
  initport();
  countbegin(100);
  while(1) //等待中断
  {
    if(i==3)
    {
      d12=(t1-t2)/8000000*340;
      d32=(t3-t2)/8000000*340;
      a=d12*d12-1;  
      b=1-d32*d32;
      c=(d32*d32-1)*d12+(1-d12*d12)*d32;
      theta=asin(c/sqrt(a*a+b*b))-atan(a/b);
      r1=(1-d32*d32)/(2*(cos(theta)+d32));
      d32=r1*cos(theta);
      d12=r1*sin(theta);
      //计算坐标.d12--y,d32--x
      t1=0;
      t2=0;
      t3=0;
      i=0;//参数初始化,等待下一次蜂鸣信号
      
            
          // 坐标无线发送
      
    }
  }
}
#pragma vector=PORT1_VECTOR
__interrupt void p1int(void)
{
  if(i==0)
  {
    CCR0=0;
  }
  if((P1IFG&BIT5)==BIT5) //接收器1有信号
  {
    P1IFG&=~BIT5;//清除中断标志
    t1=CCR0;//记录接收器1接收到的时刻
    i++;//计数变量加1
  }
  if((P1IFG&BIT6)==BIT6) //接收器2有信号
  {
    P1IFG&=~BIT6;//清除中断标志
    t2=CCR0;//记录接收器2接收到的时刻
    i++;//计数变量加1
  }
  if((P1IFG&BIT7)==BIT7) //接收器3有信号
  {
    P1IFG&=~BIT7;//清除中断标志
    t3=CCR0;//记录接收器3接收到的时刻
    i++;//计数变量加1
  }
  
   
}

相关帖子

沙发
dirtwillfly| | 2013-7-30 18:57 | 只看该作者
明天给你认真看下吧。今天用的手机上网,回帖不是很方便。

使用特权

评论回复
板凳
hitliiu|  楼主 | 2013-7-30 19:20 | 只看该作者
dirtwillfly 发表于 2013-7-30 18:57
明天给你认真看下吧。今天用的手机上网,回帖不是很方便。

好的,谢谢版主

使用特权

评论回复
地板
1988020566| | 2013-7-30 23:37 | 只看该作者
你可以使用查表的方法的。

使用特权

评论回复
5
1988020566| | 2013-7-30 23:37 | 只看该作者
简化cos sin计算的。

使用特权

评论回复
6
lostelf| | 2013-7-31 11:45 | 只看该作者
这个计算肯定是不行的。查表可行,或者拆分算法。IO开中断是上升沿,应该还要初始化IO口为低电平,输入方式。

使用特权

评论回复
7
波板糖| | 2013-7-31 14:04 | 只看该作者
版主是不是计算sin,cos,atan等三角函数最好是查表方式,我采用反正切,计算显示不完整。单片机52的

使用特权

评论回复
8
仿真人生| | 2013-7-31 15:11 | 只看该作者
关注中。

使用特权

评论回复
9
hitliiu|  楼主 | 2013-7-31 16:31 | 只看该作者
1988020566 发表于 2013-7-30 23:37
简化cos sin计算的。

好主意,我刚才搜了一下,如果是反三角函数有什么好方法吗?我刚才算的时候发现反三角的计算结果是不对的.

使用特权

评论回复
10
hitliiu|  楼主 | 2013-7-31 16:32 | 只看该作者
lostelf 发表于 2013-7-31 11:45
这个计算肯定是不行的。查表可行,或者拆分算法。IO开中断是上升沿,应该还要初始化IO口为低电平,输入方式 ...

就是说PDIR那个寄存器要设成输入方式对吗?

使用特权

评论回复
11
dirtwillfly| | 2013-7-31 22:43 | 只看该作者
sin,cos,atan等三角函数的计算一个是可以采用查表法,另外,如果涉及到浮点数运算,转化为整数的运算速度更快,最后的时候再转化为浮点数

使用特权

评论回复
12
dirtwillfly| | 2013-7-31 23:16 | 只看该作者
关于定时器A,主要有TACTL,TAR,CCTL0,CCR0,CCTL1,CCR1,CCTL2,CCR2,TAIV几个寄存器。其中最主要的是TACTL寄存器,它决定Timer_A的输入时钟信号,Timer_A的工作模式,Timer_A的开启与停止,中断的申请等。 
定时器A大致可分为四个功能模块:计数器、比较/捕获寄存器0、比较/捕获寄存器1、比较/捕获寄存器2.计数器是主体,它是一个开启和关闭的定时器,如果开启它就是一直在循环计数,只会有一个溢出中断,也就是当计数由0xffff到0时会产生一个中断。那怎么实现定时功能呢?这就要靠三个比较/捕获寄存器了以后用CCRx表示。CCR0比较特殊,通过他可以改变计数器的最大计数值,也就是当计数器计数到CCR0的值时自动会将计数器清零。但这需要设置相应的工作模式,模式列表如下: 
0——停止模式,用于定时器的暂停                1——增计数模式,计数器计数到CCR0,再清零计数 
2——连续计数模式,计数器增计数到0xffff,再清零计数  3——增/减计数模式,增计数到CCR0,再减计数到0 
当计数器计数到CCR0时,CCR0单元会产生一个中断。同样当计数器计数到CCR1和CCR2时,两个单元也都会个产生一个中断。这样我们可以通过定时器A得到三个定时时间了。 看程序中的定时器初始化模块。CCTLx是相应比较/捕获寄存器的控制寄存器。它可对比较/捕获寄存器进行设置,在这里只用到比较功能,也就是当计数到CCRx时产生中断,由于CCTLx默认的是比较功能,所以一般也就只用到CCIE这个控制字,就是开启相应比较器的中断。CCRx就是相应比较器的值。

使用特权

评论回复
13
dirtwillfly| | 2013-7-31 23:17 | 只看该作者
这些在datasheet上或有关书籍资料上都有介绍,建议楼主多翻datasheet

使用特权

评论回复
14
dirtwillfly| | 2013-7-31 23:19 | 只看该作者
MSP430的io开启中断功能时,必须要设置为输入状态

使用特权

评论回复
15
1988020566| | 2013-7-31 23:22 | 只看该作者
hitliiu 发表于 2013-7-31 16:31
好主意,我刚才搜了一下,如果是反三角函数有什么好方法吗?我刚才算的时候发现反三角的计算结果是不对的. ...

这还真没有试过的,

使用特权

评论回复
16
hitliiu|  楼主 | 2013-8-1 08:47 | 只看该作者
dirtwillfly 发表于 2013-7-31 23:16
关于定时器A,主要有TACTL,TAR,CCTL0,CCR0,CCTL1,CCR1,CCTL2,CCR2,TAIV几个寄存器。其中最主要的是TACTL寄 ...

这个我在资料上都看到了,照着做不过仿真的时候TAR ,CCR0的值都不改变,后来我直接把launchpad连上烧到里面去仿真就发现TAR的值开始变了,不知道为什么,我觉得应该不是外接晶振或者时钟的问题,因为在simulator模式下我把DCO XT2都试过,SMCLK 和ACLK也都试过,TAR就是不计数,到了FET DEBUGGER模式下TAR就在开了定时器后开始计数了.不过现在问题解决了

使用特权

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

本版积分规则

2

主题

9

帖子

0

粉丝