单片机中断程序中修改的变量在退出中断是又被改回去了该怎么办?

koko   2008-1-22 21:19 楼主
我在单片机的串口发送的中断程序中设置了一个计数器,使其能发送同样的数据n次后发送下一个数据n次,但是运行后发现串口每个数据只发送了3、4次就换下一个数据了,我猜想是因为变量n的初始值在进入中断的时候被压入堆栈,所以每次退出是都又把原始值又弹回去了,所以每次都只在初始值附近徘徊,这是我的猜想,不知道对不对,盼望各位给我解答一下,最好能说一下怎么修改,谢谢了。

回复评论 (4)

把你的程序发上来看下,这么说没有办法的。有可能是在中断外,修改了数据
点赞  2008-1-23 11:17
设置成静态变量。
点赞  2008-1-24 15:38
哦,我想错了,看来不是那个问题,把代码发出来,这段程序是个测试程序,主要功能是把UART_Buffer中的11个数依次发送出来,每个数发送很多遍,每两个不同的数用很多个“11”隔开(这是我自定义的空闲字符),读过程序大家可以看出,我用一个int count和一个 unsigned char count1来延时,而且每个字符我发送的时间等于64000*8次count++的时间,关键是我把count++写在了中断程序中,那么应该是每个字符的发送时间等于64000*8次中断的时间,也就是每个字符我发送了64000*8次,但实际上在相同的时间里,相同的波特率下,在接收端只接收了大约600个字符,请问这是怎么回事,难道要中断很多次才能把一个数据发送出去?

  1. #include                  // SFR declarations
  2. #include

  3. //-----------------------------------------------------------------------------
  4. // Global CONSTANTS
  5. //-----------------------------------------------------------------------------

  6. #define SYSTEMCLOCK      24500000           // SYSCLK frequency in Hz
  7. #define BAUDRATE             2400           // Baud rate of UART in bps


  8. //-----------------------------------------------------------------------------
  9. // Function PROTOTYPES
  10. //-----------------------------------------------------------------------------

  11. void SYSCLK_Init (void);
  12. void UART0_Init (void);
  13. void PORT_Init (void);
  14. void Timer2_Init (int);

  15. //-----------------------------------------------------------------------------
  16. // Global Variables
  17. //-----------------------------------------------------------------------------

  18. #define UART_BUFFERSIZE 11
  19. unsigned char UART_Buffer[UART_BUFFERSIZE]=
  20.                         {0,1,2,3,4,5,6,7,9,10,12};
  21. //unsigned char UART_Buffer_Size = 0;
  22. //unsigned char UART_Input_First = 0;
  23. //unsigned char UART_Output_First = 0;
  24. unsigned char TX_Ready =1;//发送准备好
  25. static char Byte;
  26. unsigned char index=0,count1=0;
  27. unsigned int count=0;

  28. //-----------------------------------------------------------------------------
  29. // MAIN Routine
  30. //-----------------------------------------------------------------------------

  31. void main (void)
  32. {
  33.    PCA0MD &= ~0x40;                    // WDTE = 0 (clear watchdog timer
  34.                                        // enable)
  35.    Byte=UART_Buffer[0];
  36.    PORT_Init();                        // Initialize Port I/O
  37.    SYSCLK_Init ();                     // Initialize Oscillator
  38.    UART0_Init();                                                //初始化UART0串口

  39.   // RI0 = 0;//禁止接收数据,只发送

  40.    EA = 1;//开启中断 EA:IE.7 open all interrupts,descide by their marks

  41.   

  42.    while(1)
  43.    {
  44.                    if(TX_Ready==1)
  45.                 {
  46.                         TX_Ready=0;
  47.                         if(count==64000)
  48.                         {       
  49.                                 count1++;
  50.                                 if(count1==8)
  51.                                 {
  52.                                         Byte = 11;//发送空闲字符
  53.                                 }
  54.                                 if(count1==16)
  55.                                 {
  56.                                         index++;
  57.                                         index%=11;
  58.                                         Byte = UART_Buffer[index];
  59.                                         count1=0;
  60.                                 }
  61.                                 count=0;
  62.                         }
  63.                     TI0 = 1;
  64.                 }
  65.    }
  66. }

  67. //-----------------------------------------------------------------------------
  68. // Initialization Subroutines
  69. //-----------------------------------------------------------------------------

  70. //-----------------------------------------------------------------------------
  71. // PORT_Init
  72. //-----------------------------------------------------------------------------
  73. //
  74. // Return Value : None
  75. // Parameters   : None
  76. //
  77. // Configure the Crossbar and GPIO ports.
  78. //
  79. // P0.4   digital   push-pull    UART TX
  80. // P0.5   digital   open-drain   UART RX
  81. //
  82. //-----------------------------------------------------------------------------
  83. void PORT_Init (void)
  84. {//P0MDOUT:P0口输出方式寄存器
  85.    P0MDOUT |= 0x10;     // Enable UTX as push-pull outputP0.4为推挽式
  86.    XBR0    = 0x01;      //Enable UART on P0.4(TX) and P0.5(RX)TX,RX连到P0.4,P0.5
  87.    XBR1    = 0x40;      // Enable crossbar and weak pull-ups交叉开关使能
  88. }

  89. //-----------------------------------------------------------------------------
  90. // SYSCLK_Init
  91. //-----------------------------------------------------------------------------
  92. //
  93. // Return Value : None
  94. // Parameters   : None
  95. //
  96. // This routine initializes the system clock to use the internal oscillator
  97. // at its maximum frequency.
  98. // Also enables the Missing Clock Detector.
  99. //-----------------------------------------------------------------------------

  100. void SYSCLK_Init (void)
  101. {
  102.    OSCICN |= 0x03;                     // Configure internal oscillator for
  103.                                        // its maximum frequency
  104.    RSTSRC  = 0x04;                     // Enable missing clock detector
  105. }

  106. //-----------------------------------------------------------------------------
  107. // UART0_Init
  108. //-----------------------------------------------------------------------------
  109. //
  110. // Return Value : None
  111. // Parameters   : None
  112. //
  113. // Configure the UART0 using Timer1, for and 8-N-1.
  114. // UART0的波特率由定时器1工作在8位自动重装方式产生,溢出信号经过2分频后产生波特
  115. // 率。UART的波特率=[定时器1的时钟频率/(256-T1H)]/2,
  116. //-----------------------------------------------------------------------------
  117. void UART0_Init (void)
  118. {
  119.    SCON0 = 0x00;                       // SCON0: 8-bit variable bit rate
  120.                                        //        level of STOP bit is ignored
  121.                                        //        RX enabled
  122.                                        //        ninth bits are zeros
  123.                                        //        clear RI0 and TI0 bits
  124.                                                                            //receive is forbidden.
  125.    if (SYSTEMCLOCK/BAUDRATE/2/256 < 1) {
  126.       TH1 = -(SYSTEMCLOCK/BAUDRATE/2);
  127.       CKCON &= ~0x0B;// 定时器0使用系统时钟
  128.       CKCON |=  0x08;// 定时器1使用系统时钟
  129.    } else if (SYSTEMCLOCK/BAUDRATE/2/256 < 4) {
  130.       TH1 = -(SYSTEMCLOCK/BAUDRATE/2/4);
  131.       CKCON &= ~0x0B;   // 定时器0使用系统时钟
  132.       CKCON |=  0x01;        //系统时钟4分频 因为此时位3为0,所以定时器1使用4分频
  133.    } else if (SYSTEMCLOCK/BAUDRATE/2/256 < 12) {
  134.       TH1 = -(SYSTEMCLOCK/BAUDRATE/2/12);
  135.       CKCON &= ~0x0B;                  // 定时器1使用系统时钟12分频
  136.    } else {
  137.       TH1 = -(SYSTEMCLOCK/BAUDRATE/2/48);
  138.       CKCON &= ~0x0B;                  // 定时器1使用系统时钟48分频
  139.       CKCON |=  0x02;
  140.    }

  141.    TL1 = TH1;                          // init Timer1
  142.    TMOD &= ~0xf0; // 定时器1在TR1=1时工作,使用T1M定义的时钟,即上面的结果
  143.    TMOD |=  0x20; //工作在方式2,自动重装
  144.    TR1 = 1;                            // START Timer1
  145.    TX_Ready = 1;                       // Flag showing that UART can transmit
  146.    IP |= 0x10;                         // Make UART high priority
  147.    ES0 = 1;                            // Enable UART0 interrupts

  148. }

  149. //-----------------------------------------------------------------------------
  150. // Interrupt Service Routines
  151. //-----------------------------------------------------------------------------

  152. //-----------------------------------------------------------------------------
  153. // UART0_Interrupt
  154. //-----------------------------------------------------------------------------
  155. //
  156. // This routine is invoked whenever a character is entered or displayed on the
  157. // Hyperterminal.
  158. //
  159. //-----------------------------------------------------------------------------

  160. void UART0_Interrupt (void) interrupt 4
  161. {


  162.    if (TI0 == 1&&TX_Ready==0)                   // Check if transmit flag is set
  163.    {
  164.             count++;
  165.         SBUF0 = Byte;
  166.                 TI0 = 0;                           // Clear interrupt flag
  167.                 TX_Ready=1;
  168.    }
  169. }

  170. //-----------------------------------------------------------------------------
  171. // End Of File
  172. //---------------------------------------------------------------
点赞  2008-1-24 21:31
这样用的变量

用volatile声明一下

另让系统优化了,不然怎么死都不知道

还有就是,在读写的时候,要注意控制访问

不然,如果不知道谁动了这个变量的话,那也会死得很惨
呵呵

LZ可以找相关的内容:临界变量
点赞  2008-1-25 09:08
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复