8051 MCU的定时器基本中断(CC2541)

时间:2013-12-22 20:27:46

标签: c timer interrupt 8051 iar

我正在为CC2541(基于8051的)MCU编写一些代码,这是TI的BTLE SOC,并且在启动基于定时器的中断时遇到问题。我已经成功配置了GPIO中断,甚至可以使用该中断来设置定时器中断标志(然后触发定时器中断)......但我无法让定时器本身在翻转时触发中断。

以下是我正在使用的一些基本代码:

   /**************************************************************************************************
 *                                           Includes
 **************************************************************************************************/
#include <ioCC2541.h>
#include <hal_defs.h>
#include <hal_board_cfg.h>

 unsigned int ISR_Counter = 0;
 uint16 loop_Counter = 0;

void main(void)
{

  HAL_BOARD_INIT();

  P1DIR |= BV(0);
  P0DIR |= BV(4);

  P1_0 = 1;
  P0_4 = 1;


 /*****************************************************************************/
    //Configure sleep timer

   IEN0 &= ~BV(5);  //Disable interrupt

  //Set timer compare value
  ST2 = 0x00;
  ST1 = 0xFF;
  ST0 = 0x00;

  IRCON &= ~0x80;  //Clear flag
  IEN0 |= BV(5);  //Enable interrupt

   EA = 1;   //Enable all interrupts

   while(1){ 

    if (loop_Counter == 0){ P0_4 ^= 1; }
    loop_Counter++;
    }

}
/**************************************************************************************************
                                           CALL-BACKS
**************************************************************************************************/


/*Sleep Timer interrupt */
_PRAGMA(vector=ST_VECTOR)
__interrupt void SLEEP_ISR(void)
{
  P1_0 ^= 1; // P1.0 = toggle
  IRCON &= ~0x80;  //Clear flag
  ISR_Counter++; 
}

HAL_BOARD_INIT函数(和相关的defs)是:

/* Setting Clocks */

// switch to the 16MHz HSOSC and wait until it is stable
#define SET_OSC_TO_HSOSC()                                                     \
{                                                                              \
  CLKCONCMD = (CLKCONCMD & 0x80) | CLKCONCMD_16MHZ;                            \
  while ( (CLKCONSTA & ~0x80) != CLKCONCMD_16MHZ );                            \
}

// switch to the 32MHz XOSC and wait until it is stable
#define SET_OSC_TO_XOSC()                                                      \
{                                                                              \
  CLKCONCMD = (CLKCONCMD & 0x80) | CLKCONCMD_32MHZ;                            \
  while ( (CLKCONSTA & ~0x80) != CLKCONCMD_32MHZ );                            \
}

// set 32kHz OSC and wait until it is stable
#define SET_32KHZ_OSC()                                                        \
{                                                                              \
  CLKCONCMD = (CLKCONCMD & ~0x80) | OSC_32KHZ;                                 \
  while ( (CLKCONSTA & 0x80) != OSC_32KHZ );                                   \
}

#define START_HSOSC_XOSC()                                                     \
{                                                                              \
  SLEEPCMD &= ~OSC_PD;            /* start 16MHz RCOSC & 32MHz XOSC */         \
  while (!(SLEEPSTA & XOSC_STB)); /* wait for stable 32MHz XOSC */             \
}

#define STOP_HSOSC()                                                           \
{                                                                              \
  SLEEPCMD |= OSC_PD;             /* stop 16MHz RCOSC */                       \
}
/* ----------- Board Initialization ---------- */

#define HAL_BOARD_INIT()                                         \
{                                                                \
   /* Set to 16Mhz to set 32kHz OSC, then back to 32MHz */       \
  START_HSOSC_XOSC();                                            \
  SET_OSC_TO_HSOSC();                                            \
  SET_32KHZ_OSC();                                               \
  SET_OSC_TO_XOSC();                                           \
  STOP_HSOSC();                                                  \
                                                                 \
  /* Turn on cache prefetch mode */                              \
  PREFETCH_ENABLE();                                             \
                                                                 \
  /* set direction for GPIO outputs  */                          \
  LED1_DDR |= LED1_BV;                                           \
  LED2_DDR |= LED2_BV;                                           \
  GYRO_VDD_DDR |= GYRO_VDD_BV;                                   \
  DCDC_DDR |= DCDC_BV;     /* Set P0_7 as output */              \
  GYRO_VDD_SBIT = 1;       /* Gyro must be on for I2C to work */ \
  P0DIR |= BV(5);          /* Unused pin as output */            \
  P2DIR |= BV(0);          /* Unused pin as output */            \
  P1DIR |= 0x3C;           /* UART pins as output */             \
  P0INP =  0x4E;           /* Tri-state inputs */                \
}

我已通过调试器运行它,可以看到睡眠定时器寄存器正在改变,因此定时器实际上在运行。就像我说的那样,我也可以通过另一个中断处理程序手动设置中断标志,并且中断会像你期望的那样触发。我也尝试过配置其他定时器,以及UART中断......都具有相同的结果。在这一点上,我不确定这是中断本身的问题还是时钟源配置的问题....无论哪种方式,我都确定这是愚蠢的我做错了。

我应该补充一点,我正在使用TI包含的BTAL堆栈的小部分HAL代码,但我没有使用OSAL的任何部分。事实上,我根本没有使用芯片的BT方面。

3 个答案:

答案 0 :(得分:0)

我仍然没有弄清楚为什么正常的定时器中断不起作用,但我确实设法让睡眠定时器工作(这是我需要将芯片拉出低功耗模式所需的)。

问题是定时器比较事件会抛出一个中断,但不会重置定时器(我假设它会这样)......并且因为它是一个24位定时器,运行频率为32 kHz,所以需要很长时间是时候翻身再次击中旧的设定点。

答案 1 :(得分:0)

问题是您需要读取寄存器,将时间添加到寄存器并写入比较寄存器。计数器无意重置。

答案 2 :(得分:0)

也许睡眠计时器由您导入代码的HAL部分使用。 您可以尝试使用其他定时器之一,而不是BLE堆栈使用的(我认为1,2和4可用)。

当然,您需要修改一组不同的寄存器,用于设置计数器值,以及启用中断。

对于timer1,请参阅T1IET和T1CC0L / H(在ioCC2541.h中定义,以及在CC2541的开发者手册中,ofc)