This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

急!!!



程序出问题了,麻烦高手帮忙解决一下!

程序的大体意思是这样的,我定义了一个全局变量USCRX_flag,number1(用于在中断中测试USCRX_flag加了多少次),number2(用于在主函数中测试USCRX_flag减了多少次),在串口中断中一旦接到了一帧以55 开头AA结尾的数据就让该全局变量USCRX_flag++,number1++,然后再main主函数while(1)中有一个while(USCRX_flag){USCRX_flag--;number2++};但是在调试程序中发现一个很严重的问题,如果电脑串口发送速度比较慢时,没问题number1 与(number2+USCRX_flag)是同步相等的(当你再调试中停止时,剩下的USCRX_flag与减少掉的USCRX_flag(number2)应该等于在中断中累计加到的USCRX_flag),但是如果电脑串口发送速度比较快时,就出现了一个现象number1比(number2+USCRX_flag)大。

我写的程序代码,大体如下:(代码不怎么全,我现在主要想知道为什么串口发送速度快了,就会出现number1 与(number2+USCRX_flag)不同步相等的原因,我在想即使是我串口中断程序写错了,或者是我的环形数组  Pre_Rcv_Buf[160满了,覆盖了以前的数据,那就是判断不出一条完整的一帧以55 开头AA结尾的数据,USCRX_flag ,  number1 不加就是了,那也不应该出现  number1 与(number2+USCRX_flag)不同步相等啊?是不是MSP430 单片机内部硬件有问题啊)

volatile unsigned char USCRX_flag=0,Rcv_flag=0;

unsigned char  Pre_Rcv_Buf[160];

unsigned int number1=0;

unsigned int number2=0;

unsigned int number3=0;

#pragma vector=USCIAB0RX_VECTOR __interrupt

void USCI0RX_ISR(void)

 {

    unsigned int number=0

    if((UCA0RXBUF == 0x55)&&(start==0))      //如果是第一次接受到55

  {        

      start=1;                   //已经接受到了一个55

    Pre_Rcv_Buf[ReceNum++]=UCA0RXBUF;   //放入buffer

     return;  

   }   

  if(start==1)                //  如果已经接受到了一个55

 {           

     Pre_Rcv_Buf[ReceNum++]=UCA0RXBUF;     //继续放入到buffer数据

        if(ReceNum>159)      //如果超过了buffer的范围,从头重新存储

          ReceNum=0;        

      testnumber++;           //计数,自55后接受的数据个数,这里不会超过255的,我测试中一帧数据就11个字节

      if(UCA0RXBUF==0xAA)    //如果接受到了一个完整的帧

     {

            start=0;  

        testnumber=0;    

        USCRX_flag++;         // 标志位加1

           number1++;          //该位为测试位,用于测试USCRX_flag 加了几次

    }

  else if((UCA0RXBUF==0x55))   //如果没接收到AA,有接受到了一个55,那就把自上次接受到的55 这组不完整帧的数据删除掉

   {    if((ReceNum-testnumber)>= 0)

       {     ReceNum -= testnumber;     testnumber=0;    }  

     else

   {     ReceNum  =   160-(testnumber-ReceNum);     testnumber=0;    } 

   } 

     }

 }

main()

{

。。。。一段端口初始化程序

while(1)

{

  while(USCRX_flag)  

  {       

        WDTCTL = WDTPW+WDTCNTCL+(WDTCTL&0x00ff);              //清看门狗    

          USCRX_flag--;

           number2++;  

 }

}

}

  • 浏览了下你的代码,有几个问题需要说明一下:

    1. 无论你串口发送的速度再快,也快不过你主函数里两个While语句的嵌套。numb2++的处理速度永远都会大于你number1++的速度,基本上你的USCRX_flag的值就是在0-1之前跳

    2. 如果你要在主函数和中断函数中共享一个全局变量例如本例中的USCRX_flag,并且这个全局变量在主函数和中断函数中都有可能要修改的话,请你在主函数中修改之前关闭中断,修改完成后在打开。(这个和被案问题无关,是编程基础知识)

    3. 一般用指针来实现环形BUFF更简单,中断代码处理接收数据,帧判断放中断外处理.

    4. 芯片硬件没有问题,问题出现在你程序的设计逻辑上。

  •  我开始说过了,如果你停止debug的话,理论上你通过watch1窗口看到的number1应该等于number2和USCRX_flag的和吧,这点应该是没错的吧。

    假设我的程序在中断中有逻辑错误,它就能影响USCRX_flag与number1的值,导致它与实际电脑串口给他的数据不一致,但是他不可能影响到你通过watch1窗口看到的number1应该等于number2和USCRX_flag的和这个理论结果吧。但是我确实是看到了这个现象,他们确实不相等了。真是很令人费解。我开始也怀疑是我程序的问题,所以我就把程序最简化,就剩下串口初始化跟串口数据的一个变量加减的程序,就想你看到的一样,但是还是出现了上述的现象。我开始还以为是我的编译器的问题,但是我用的是debug  ,而不是release版本,所以应该不存在什么编译器优化的问题。我在调试我的大程序时,最后解决这个问题的方法是改变了2个全局变量定义的顺序,让他们定义的顺序颠倒了一下。所以目前到底是我程序逻辑的错误还是硬件的问题,还是我的编译器的问题我现在一头雾水。

    颠倒了2个变量的顺序,无非就是在RAM空间中2个变量的地址空间变了,但是他解决了我上述出现的想象,难道你是说我程序的逻辑问题?  很无解

  • 我今天调试的时候还加了一个

    #define CPU_F     ((double)1000000)

    #define delay_ms(x)                      __delay_cycles((long)(CPU_F*(double)x/1000.0))

    然后再main() 的主while(1){}中添加了一个delay_ms(10);就出现了上述的问题,但是如果添加 delay_ms(1);就出问题了。 很是迷惑。

    main()

    {

    。。。。初始化

    while(1)

    {

        delay_ms(10);   // 添加的延迟函数

        while(USCRX_flag)

        {    

        WDTCTL = WDTPW+WDTCNTCL+(WDTCTL&0x00ff);              //清看门狗       

         USCRX_flag--;   

          number2++;

      }

    }

    }

    居然IAR里自带的一个延迟函数也能导致它出现上述的问题。。。。。。。

  • 给你打个比方,在下面的这段代码中:

        while(USCRX_flag)

        {    

        WDTCTL = WDTPW+WDTCNTCL+(WDTCTL&0x00ff);              //清看门狗       

         USCRX_flag--;        ......................(1)

          number2++;           .......................(2)

      }

    如果程序执行完(1)就进中断了, 正确处理了1帧的数据,USCRX_flag就会被+1,中断返回,number2++,你觉得你的这句话还成立么?

    "number1应该等于number2和USCRX_flag的和"

    所以,你如果要设计一个方案,首先要理顺的就是逻辑关系。

    至于颠倒了2个变量顺序,就变了结果,有可能是你堆栈溢出造成的。那是另一个问题,不能揉在一起来解决。

  • 就按照你的说法,

    中断返回后,nuber2++;

    debug停下来后,

    如果你现在打开watch1窗口的话,你看到的number1 的计数与  number2 +USCRX_flag的数量难道能不相等吗?

    除非只有一种情况,2者之间差1。就是在(1)结束之后我停止了debug.那个时候两者差1,但是我在调试的时候发现的是2者的差 值不定。

    还有就是你说的这个堆栈溢出的问题。我定义的个全部变量,在编译连接的时候IAR 根本也没提示我任何错误,我想不通他是怎么溢出的,我颠倒了2个变量顺序,这2个变量也都是unsigned char 型   ,同一类型的变量啊,我想不可能出现溢出这个问题吧

     

  • 如果只发生一次,Number1 和Number2+uscrx_flag就会相差1,如果发生多次,就相差很多。

     

    如果中断发生在USCRX_flag--这条语句当中,问题会更严重。

    你直接在MAI函数更改全局变量的之前加关闭中断函数指令再测试。为什么要始终纠结在数据是否相等这个问题呢?如果程序有漏洞,即使你现在测试没有问题,以后也是会暴露出来的,因为你没法列举所有的现场环境。我们在找程序问题的时候,首先就是挨着排除程序中的逻辑漏洞。如果有漏洞,你的任何假设都是不成立的,验证也是没有意义的。