MSP430在运行过程中会出现复位

2019-07-23 15:50发布

本帖最后由 mouxiang 于 2014-12-10 11:06 编辑

想请教大家一个问题。

使用了MSP430的两个串口,UART0和UART1。上位机通过UART0与MSP430通信,根据其发送过来的指令,MSP430会启动UART1发送相应的指令去查询一个485设备,然后将查询到的值通过UART0回送给上位机。UART0和UART1的波特率都设定为115200,这样一个通信周期为7.5~8ms。

使用了定时器A,其中,A0的周期为2ms,A1的周期为100us。在A0中我打开了总中断,这样A1的中断能够打断A0的中断,从而使得100us定时器能够准确定时。在A0的中断服务程序中,我放了一些判断代码和IO操作的代码,例如获取光电管状态的代码,但是不多。现在的问题是,MSP430运行一段时间后会发生复位。如果我将获取光电管状态的代码放在main中执行,就不会复位了。

我比较迷惑的是,造成复位的原因是定时器呢还是UART通信?或者是两者共同造成的?因为我放在定时器中断服务中的代码的执行时间应该是很短的,不会超过1ms,照理说那段代码放在定时器里和放在main中是没什么区别的。

各位朋友如果有这方面的经验,还请指点一下,十分感谢!

整个代码比较复杂,各种命名的含义也不太好解释,我贴出来大家也不一定看得明白。所以我后面会陆续将一些函数做一些简化修改会贴出来。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
16条回答
mouxiang
1楼-- · 2019-07-23 21:21
本帖最后由 mouxiang 于 2014-12-10 11:05 编辑
  1. void TIMERA_init(void)
  2. {
  3.   CCTL0 = CCIE;                     // 开启比较器0中断
  4.   CCR0 = 2000;                    // 2ms
  5.   CCTL1 = CCIE;                     // 开启比较器1中断
  6.   CCR1 = 100;                      //
  7.   TACTL = TASSEL_2 + ID_3 + MC_1;           // SMCLK, 8分频为1Mhz, Up to CCR0
  8. }

  9. #pragma vector=TIMERA0_VECTOR
  10. __interrupt void Timer_A (void)
  11. {
  12.   _EINT();//开总中断,以便100us定时器能够正常进行

  13.   if(System_Time_Interval(Timer_2ms_Count, System_Timer) >= 20)//时间间隔20*100us=2ms
  14.   {
  15.     Get_System_Time_Current_Count(Old_Timer_2ms_Count, Timer_2ms_Count);
  16.     Get_System_Time_Current_Count(Timer_2ms_Count, System_Timer);
  17.       
  18.     Timer_A1_count++;
  19.     Flag_Timer_A1_Updated = 1;
  20.    
  21.     //下面这段被注释掉的代码,此时放在main中运行,MSP430不会出现复位;若放在此处运行,则MSP430运行一段时间后就会出现复位
  22. //    if(Phototube_Info_is_Needed)
  23. //    {
  24. //      Get_Phototube_Info_In_TimerA();
  25. //    }      
  26.   }

  27.   /***************************/
  28.   //这里是一些输出口开关操作
  29.   /***************************/
  30. }

  31. #pragma vector=TIMERA1_VECTOR
  32. __interrupt void Timer_A1 (void)
  33. {
  34.   if( TAIV != 0x02)//比较器1中断
  35.     return;
  36.   
  37.   CCR1 += 100;
  38.   if(CCR1 >= 2000)
  39.     CCR1 -= 2000;
  40.   
  41.   System_Time_Increase(System_Timer);
  42. }
复制代码以上是定时器的初始化和中断服务程序。

mouxiang
2楼-- · 2019-07-23 23:18
UART0和UART1只会触发接收中断,其发送是在main中进行的,这里我贴出其初始化代码和发送代码。
  1. //初始化串口通信UART0, UART0为控制板与PC机的通信
  2. void InitUART0(void)
  3. {
  4.   P3SEL |= 0x30;                            // P3.4,5 = USART0 TXD/RXD
  5.   
  6.   ME1 |= UTXE0 + URXE0;                     // Enable USART0 TXD/RXD
  7.   
  8.   UCTL0 |= CHAR;                            // 8-bit character, USART0

  9.   UTCTL0 |= SSEL1;                          // UCLK = SMCLK, USART0

  10.   if( ((P4IN&0x04)>>2) == 1){//根据工作模式确定波特率,如果MODE_INPUT0为0,即P4.2为1,则采用57600波特率
  11.   UBR00 = 0x8A;//0x45;                             // USART0,波特率:57600
  12.   UBR10 = 0x00;//0x00;                             //
  13.   UMCTL0 = 0xDE;//0xAA;                            // Modulation
  14.   }
  15.   else{//否则采用115200波特率
  16.   UBR00 = 0x45;//0x45;                             // USART0,波特率:115200
  17.   UBR10 = 0x00;//0x00;                             //
  18.   UMCTL0 = 0x4A;//0xAA;                            // Modulation
  19.   }

  20.   UCTL0 &= ~SWRST;                          // USART0,SWRST复位

  21.   IE1 |= URXIE0;                            // USART0,接收中断允许
  22. }

  23. //初始化串口通信UART1
  24. void InitUART1(void)
  25. {
  26.   P3SEL |= 0xC0;                            // P3.6,7 = USART1 TXD/RXD
  27.   
  28.   ME2 |= UTXE1 + URXE1;                     // Enable USART1 TXD/RXD
  29.   
  30.   UCTL1 |= CHAR;                            // 8-bit character, USART1
  31.   
  32.   UTCTL1 |= SSEL1;                          // UCLK = SMCLK, USART0

  33.   if( ((P4IN&0x04)>>2) == 1){//根据工作模式确定波特率,如果MODE_INPUT0为0,即P4.2为1,则采用57600波特率
  34.   UBR01 = 0x8A;//0x45;                             // USART0,波特率:57600
  35.   UBR11 = 0x00;//0x00;                             //
  36.   UMCTL1 = 0xDE;//0xAA;                            // Modulation
  37.   }
  38.   else{//否则采用115200波特率
  39.   UBR01 = 0x45;//0x45;                             // USART0,波特率:115200
  40.   UBR11 = 0x00;//0x00;                             //
  41.   UMCTL1 = 0x4A;//0xAA;                            // Modulation
  42.   }
  43.   
  44.   UCTL1 &= ~SWRST;                          // USART1,SWRST复位
  45.   
  46.   IE2 |= URXIE1;                            // USART1,接收中断允许
  47. }

  48. void UART0_LONG_CMD_Send(void)//附加协议长指令发送函数,一条指令24个字节
  49. {
  50.   unsigned i;
  51.   COM2_DE_HIGH();//P4.0输出高电平,使能COM2的MAX485的DI口用于输出数据
  52.   for(i=0; i<MAX_BYTES_LONG_CMD; i++)
  53.   {
  54.     TXBUF0=UART0_Long_CMD_buffer[i];
  55.     while((UTCTL0&0x01)==0);   
  56.     if(UART0_Long_CMD_buffer[i]==CMDEND_EXTRA)
  57.     {
  58.       COM2_DE_LOW();//P4.0输出低电平,禁止COM2的MAX485的DI口,等待数据传入
  59.       return;
  60.     }
  61.   }
  62. }

  63. void UART1_Send(unsigned * UARTRX_buf)
  64. {
  65.   unsigned i;
  66.   COM1_DE_HIGH();//P4.1输出高电平,使能COM1的MAX485的DI口用于输出数据
  67.   for(i=0; i<Max_bytes_UART1; i++)
  68.   {
  69.     TXBUF1=UARTRX_buf[i];
  70.     while((UTCTL1&0x01)==0);   
  71.   }
  72.   COM1_DE_LOW();//P4.1输出低电平,禁止COM1的MAX485的DI口,等待数据传入
  73. }
复制代码
dirtwillfly
3楼-- · 2019-07-24 03:06
 精彩回答 2  元偷偷看……
mouxiang
4楼-- · 2019-07-24 07:28
Get_Phototube_Info_In_TimerA()定义如下:
  1. void Get_Phototube_Info_In_TimerA(void)//精简的函数,仅用于在定时器中断中获取光电管状态变化的时刻
  2. {  
  3.   if(!Flag_for_Non_Trigger)
  4.   {
  5.     Phototube_1_State = Obtain_Phototube_State_1();//获取光电管1状态,这是一个读取IO口状态的操作
  6.   }
  7.   else
  8.   {
  9.     Phototube_1_State = 7;//处于不触发时间内,光电管状态设定为一直遮挡
  10.     if(Count_for_Non_Trigger >= Effective_Irregular_Object_Not_Trigger_Time*5)//不触发时间到
  11.     {
  12.       Flag_for_Non_Trigger = 0;
  13.       Count_for_Non_Trigger = 0;
  14.     }
  15.   }
  16.   
  17.   if(Phototube_1_State == 1 || Phototube_1_State == 5)         //这表明光电管开始被遮挡
  18.   {
  19.     Rejection_Admin[Rejection_Num].Rise_Time = Timer_A1_count;//存储光电管上升沿时刻
  20.   }  
  21. }
复制代码一般情况下,如果光电管不被遮挡,则Flag_for_Non_Trigger=0,Phototube_1_State=0,也就是说Get_Phototube_Info_In_TimerA()这个函数中仅仅只是获取光电管状态。
mouxiang
5楼-- · 2019-07-24 10:28
我要将光电管状态的代码放在定时器里的原因是,我需要精确获取光电管被遮挡的上升沿时刻,从而确定传送带上的物体位置。由于传送带速度较高,如果我获取光电上升沿时刻有误差,则物体位置就可能会有1cm以上的偏差。将获取光电管状态的代码放在main中的话,由于UART通信的执行时间能够达到8ms左右,那么这个上升沿时刻的误差肯定会比较大。
as564335sa
6楼-- · 2019-07-24 16:01
查查数组越界堆栈溢出之类的,函数里不要开大数组

一周热门 更多>