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.

can i use I2C in CC2530 ?

Other Parts Discussed in Thread: CC2533, CC2530, Z-STACK, REMOTI, CC2540, PCA9555, TMP102

Hi TI,

 I am planning to use I2C in CC2530. I understand TI CC2530 dont have the I2c module hardware support.It only support TI CC2533.


So to use I2C in CC2530 ,

GPIO p1.3 and P1.4 pin for I2c master. P1.3 use as a clock (use timer 3 to generate pwm clock for 400khz) and P1.4 for SDA.


Kindly advice .whether i can use the above way to communicate with I2C Slave.if there is anyother way please advice.


Thanks and Regards

Lakshman.

  • Hi Lakshman,

     

    You can implement the communication it the FW level, without using timers.

    Syncronising timer output with data write (read) on P1.4 is a hard work and

    involves constant polling of Timer3 overflow, or interrupt.

    If you need a short access (write/read 10 bytes) to your slave, where this access period

    can be done in a time of ~few dozens of uSeconds you can, and you should, implement

    the I2C inside the code without using timers or interrupts.

  • Hi Igor,

     Thanks for the immediate reply.

    I didnt understand the solution. Can you please throw some light ?

    How can i get the clock for I2C  SCL ???

    I need 400Khz clock whenever i need to send the data . kindly advice.

     

    Thanks and Regards

    Lakshman.

     

     

  • Hi,

     

    Lets say that you toggling P1.3 (which is the SCL) in the following way (transaction of a single byte through I2C):

    P1.3 = HIGH;
    tmpByte = dataFor_I2C_Slave[SomeIndex]; // Just for the example 

    for( int i=0; i<sizeof(byte)-1; i++ ) {
    P1.3 = P1.3 ^ 0x01; // Toggle P1.3 output
    blockingDelay(WRITE_DELAY); // Delay needed for Slave to detect rising/falling of SCL
    p1.4 = !(!(tmpByte & 0x80)); // Set P1.4 with current MSB in tmpByte
    tmpByte <<=  1;
    blockingDelay(CLOCK_DELAY); // Delay needed for generating a ~400KHz SCL
    }

     

    Please note that it is not an accurate example of how to implement the IC2, the important

    thing here is the blockingDelay() function, where in first call for this function used to provide

    a delay for the slave to capture the falling or rising of the SCL. The second call for this function

    intended for delaying the next setting of P1.3 output to create SCL timing of ~400KHz.

    The blockingDelay() can be implemented in the following way:

    void blockingDelay( uint16 delay )
    {
    while( delay ) {
    delay--;
    asm("NOP"); // Here "NOP" is a single system clock instruction (in case
    // of cc2530 1 system clock = ~31.5nSeconds
    }

     

  • Hi Igor,

     Thanks for your reply. I got it. So i simulate 400khz by means of delay.

     

    This is what i need. thank you so much.

     

     

    Thanks and Regards

    Lakshman.

  • Hi,

     

    Just keep in mind that long blocking delays can harm Z-stack normal behavior.

     

  • There are i2c hal drivers (hal_i2c.c, hal_i2c.h) available in RemoTi Stack for cc2530.

    I use them with Z-Stack to read data from different sensors without problems.

  • Hi Felix,

     

    It is a nice thing to know, thank you very much for the information.

  • Hi Felix:

      How could I get the REmoTi Stack for cc2530. I found it on TI's website but it need to request.could you send me one .linux_makefile@qq.com

      thanks and best regards.

    huabai

  • huabai shen said:

    Hi Felix:

      How could I get the REmoTi Stack for cc2530. I found it on TI's website but it need to request.could you send me one .linux_makefile@qq.com

      thanks and best regards.

    huabai

    Hi,

    I attach the original files to this post.

    Felix

    i2c.zip
  • I made modifications to the hal_i2c.c in order to read and write to the TI PCA9555 I2C 16 bit Port expander using theCC2540.

    This allows me to read and write to just about any I2C device.  This is for the CC25xx  that do not have i2c in hardware.

    To read I use this function:

      if ( I2C_ReadMultByte(PCA9555_ADDR_WR, InPort0, data1, 2 )  )
    ...

    To write:

    I2C_WriteMultByte(PCA9555_ADDR_WR, PolInvP0, data1, 2);

    The function I wrote for reading is:

    /*********************************************************************
     * @fn      I2C_ReadMultByte
     * @brief   reads data into a buffer
     * @param   address: linear address on part from which to read
     * @param   reg: internal register address on part read from
     * @param   buffer: target array for read characters
     * @param   len: max number of bytes to read
     * @return  void
     */
    uint8 I2C_ReadMultByte( uint8 address, uint8 reg, uint8 *buffer, uint16 len )
    {
      uint16 i = 0;
      uint8 I2C_ERROR = 0;
      uint8 I2C_SUCCESS = 1;

      if (!len)  {
        return(0);
      }

      /* Send START condition */
      if( hali2cStart())
        return I2C_ERROR;

      /* Set direction of transmission */
      // Reset the address bit0 for write
        address &= OCM_WRITE;

      /* Send Address  and get acknowledgement from slave*/
      if ( !hali2cSendByte(address))
        return I2C_ERROR;

      /* Send internal register to read from to */
      if ( !hali2cSendByte(reg))
        return I2C_ERROR;

      /* Send RESTART condition */
      if( hali2cStart())
        return I2C_ERROR;

      /* Set direction of transmission */
      // Reset the address bit0 for read
        address |= OCM_READ;

      /* Send Address  and get acknowledgement from slave*/
      if ( !hali2cSendByte(address))
        return I2C_ERROR;

      /* Read data into buffer */
      // read bytes of data into buffer
      while ( len )
      {
        // SCL may be high. set SCL low. If SDA goes high when input
        // mode is set the slave won't see a STOP
        hali2cClock(0);
        OCM_DATA_HIGH();

        buffer[i] = hali2cReceiveByte();
        // Acknowledgement if not sending last byte
        if (len > 1)
          hali2cWrite(SMB_ACK); // write leaves SCL high

        // increment buffer register
        i++;
        // Decrement the read bytes counter
        len--;
      }

      // condition SDA one more time...
      hali2cClock(0);
      OCM_DATA_HIGH();
      hali2cWrite(SMB_NAK);

      hali2cStop();
      return I2C_SUCCESS;
    }

    For writing:

    /*********************************************************************
     * @fn      I2C_WriteMultByte
     * @brief   reads data into a buffer
     * @param   address: linear address on part from which to read
     * @param   reg: internal register address on part read from
     * @param   buffer: target array for read characters
     * @param   len: max number of bytes to read
     * @return  void
     */
    uint8 I2C_WriteMultByte( uint8 address, uint8 reg, uint8 *buffer, uint16 len )
    {
      uint16 i = 0;
      uint8 I2C_ERROR = 0;
      uint8 I2C_SUCCESS = 1;

      if (!len)  {
        return(0);
      }

      /* Send START condition */
      if( hali2cStart())
        return I2C_ERROR;

      /* Set direction of transmission */
      // Reset the address bit0 for write
        address &= OCM_WRITE;

      /* Send Address  and get acknowledgement from slave*/
      if ( !hali2cSendByte(address))
        return I2C_ERROR;

      /* Send internal register to read from to */
      if ( !hali2cSendByte(reg))
        return I2C_ERROR;

      /* Write data into register */
      // read bytes of data into buffer
      while ( len )
      {
        // SCL may be high. set SCL low. If SDA goes high when input
        // mode is set the slave won't see a STOP
        hali2cClock(0);
        OCM_DATA_HIGH();

        /* Send Address  and get acknowledgement from slave*/
        if ( !hali2cSendByte(buffer[i]))
          return I2C_ERROR;

        // increment buffer register
        i++;
        // Decrement the read bytes counter
        len--;
      }

      hali2cStop();
      return I2C_SUCCESS;
    }

  • Hi greenja

    Thank you for sharing your code. 

    I am trying to interface a magnetometer to the CC2540 via I2C but I am not able to get the ACK from the magnetometer.

    I am using the hal_i2c.c  from RemoTI and NOPs to generate some delays to get a frequency below 100 kHz from the 32MHz system clock but still not working... =(

    I am able to see in the oscilloscope that the master is sending the slave address correctly and the frequency of the clock is around 10kHz. The problem is that I am never getting the ACK back from the slave.  

    I use the hal_i2c.c implementation with the  HAL_I2C_RETRY_CNT to retry 3 times to send the address . I can see all the retries on the oscilloscope and the sequence is like this:

    slave address - start condition -slave address -start condition -slave address ... 

    Is there any additional delay or clock cycle that has to be added after the slave address is sent to give some time for the ACK?

    Any help would be greatly appreciated!!!

  • Hello Flor,

    What mangnetometer are you using?  I did have some code for the LSM303DL somewhere but I can't remember the specifics on how I got it to work.

    Here are the files that I am currently using to interface the CC2540 to the PCA9555 I/O expander for running a LCD and 7Seg displays. 

    There are slight variations to the Hal_i2c.zip that was originally posted, can't remember exactly what I changed, so I just included the whole file.  I don't think the clock rate section really works.  I think I scoped all the values and there was no change in clock speed.

    4265.Hal_i2c-1.zip

  • Hi greenja,

    Thank you very much!! I will give it a try. The magnetometer I am using is the LSM303DLH.

  • I just llooked over the code. You  obviously have to change the OCM_CLK_PORT, data port and pins to match what you are using.  I think the main problem was with theses three lines:

    #define OCM_ADDRESS  (0x4E)
    #define OCM_READ     (0x01)
    #define OCM_WRITE    (0xFE)
    Your address has to be the write address.  In the case of the LSM303 there are two.
    For the sections I added, you don't have to worry because it doesn't use this, the lines in the hali2cReceive are commented out, so you can read from the compass and the accelerometers.

    hali2cReceive

  • Hello, 

    I know this thread has been dead for a long time now. But I am wondering has anyone tired using the I2C drivers form REMO_TI. That is the new ones, located in the folder "Components\hal\target\CC2530EB_NPI" for the CC2530ZDK 

  • hi,

       I too searched for I2c Code. I have downloaded the same, but I think this has bug(as per my understanding). My comments is below,

    1.  The Function OCM_DATA_HIGH(); is used in hali2cStart, hali2cStop, hali2cReceive, hali2cSendByte, hali2cWrite is conflicting. The actual macro definition of OCM_DATA_HIGH(); in that file is

    #define OCM_DATA_HIGH()\
    { \
      IO_DIR_PORT_PIN(OCM_DATA_PORT, OCM_DATA_PIN, IO_IN); \
    }

    which is to turn data pin in to input pin.

    But, in the function like hali2cStart, hali2cWrite the OCM_DATA_HIGH(); is intend to make the data pin as output port and make it as high, which is conflicting.

    2.  Same for  hali2cClock(), in the function hali2cStart(),  hali2cClock(1) is called in order to make clock pin high. But according to definition of  hali2cClock,

    STATIC void hali2cClock( bool dir )
    {
      if ( dir )
      {
        IO_DIR_PORT_PIN( OCM_CLK_PORT, OCM_CLK_PIN, IO_IN );
        while(!OCM_SCL) /* Wait until clock is high */
            hali2cWait(1);
      }
      else
      {
        IO_DIR_PORT_PIN( OCM_CLK_PORT, OCM_CLK_PIN, IO_OUT );
        OCM_SCL = 0;
      }
      hali2cWait(1);
    }

    it is just turn in to input pin not making pin as high. 

    Can any one correct me if am wrong. 

  • HI Hamza,

    You can refer to I2C wiki..

  • Yikai,

       The link which you have shared is giving "Group not found"

  • Hi Hamza,

    Try again, I revise the link.

  • Thanks Yikai,

           I need one more suggestion from you.

       1. what can I set I2CSPEED.  I am using CC2530 with Zstack 2.5.1a. My I2c Slave sensor operates at 135-165khz clock frequency and 400 kHz i2c interface speed.

    2. And I found same.

    void i2c_start_cond(void) {
      if (started) { // if started, do a restart cond
        // set SDA to 1
        read_SDA();
        I2C_delay();
        while (read_SCL() == 0) {  // Clock stretching
          // You should add timeout to this loop
        }

    set SDA = 1; but read_SDA will set as input and just read the SDA line. Not setting as high(1).

  • Hi Hamza,

    You can control speed by changing hali2cWait().

  • Yikai,

     1. You mean I need to use hali2cwait instead of I2C_delay.

    STATIC __near_func void hali2cWait( uint8 count )
    {
      while ( count-- );
    }

    2. What about my second question.

  • Hi Hamza,

    I mean you can use hali2cWait(2) to replace hali2cWait(1) to slow down the speed for example.

  • Thanks,

      But still I didn't get my answer for 2 question. If I get that answer, then only I can move forward.

  • Hi Hamza,

    For question 2, please refer to the Timing diagram and description in I2C wiki.

  • Hi Yikai,

       I got the timing diagram, I understood that. According to me,

    void i2c_start_cond(void)
     {
      //Set Data as output port
      SDA = 1;
      I2C_delay();
      //Set Clock as output port
      SCL = 0;
      I2C_delay();
      SDA = 0;
     }

    but in the wiki,

    read_SDA(); instead of SDA = 1;

    where read_SDA() //Set SDA as input and return current level of line, 0 or 1.

    My question is why it is setting as input instead of output and where the SDA pin is set?.

    As per I2c Comm, Start sequence is SCL = LOW and SDA is High to LOW.

        

  • I would like get response from you Mr.Yikai.

  • And in function,

    void i2c_write_bit(bool bit) {
      if (bit) {
        read_SDA();
      } else {
        clear_SDA();
      }
      I2C_delay();
      while (read_SCL() == 0) { // Clock stretching
        // You should add timeout to this loop
      }
      // SCL is high, now data is valid
      // If SDA is high, check that nobody else is driving SDA
      if (bit && read_SDA() == 0) {
        arbitration_lost();
      }
      I2C_delay();
      clear_SCL();
    }

    But read_SDA//
    Set SDA as input and return current level of line, 0 or 1.
    Why it is making as input, instead of making output and make SDA high. If yoou clear this, then rest of my things will go smootly. So i request to guide me
     
  • Hi Hazma,

    Data Transfer is initiated with a START bit (S) signaled by SDA being pulled low while SCL stays high.

  • Exactly, that only i am trying to tell, according to me,

    void i2c_start_cond(void)
     {
      //Set Data as output port
      SDA = 1;
      I2C_delay();
      //Set Clock as output port
      SCL = 0;
      I2C_delay();
      SDA = 0;
     }

    but wiki,

    void i2c_start_cond(void) {
      if (started) { // if started, do a restart cond
        // set SDA to 1
        read_SDA();
        I2C_delay();
        while (read_SCL() == 0) {  // Clock stretching
          // You should add timeout to this loop
        }
        // Repeated start setup time, minimum 4.7us
        I2C_delay();
      }
      if (read_SDA() == 0) {
        arbitration_lost();
      }
      // SCL is high, set SDA from 1 to 0.
      clear_SDA();
      I2C_delay();
      clear_SCL();
      started = true;
    }

    Where, it is not making SDA to high, it is making SDA as input.

    read_SDA(void); // Set SDA as input and return current level of line, 0 or 1

    Same in
    void i2c_write_bit(bool bit) {
      if (bit) {
        read_SDA(); // This should be SDA = 1;
      } else {
        clear_SDA();
      }
      I2C_delay();
      while (read_SCL() == 0) { // Clock stretching
        // You should add timeout to this loop
      }
      // SCL is high, now data is valid
      // If SDA is high, check that nobody else is driving SDA
      if (bit && read_SDA() == 0) {
        arbitration_lost();
      }
      I2C_delay();
      clear_SCL();
    }

    But read_SDA//
    Set SDA as input and return current level of line, 0 or 1.
     
  • Hi Felix,

    I am working on a project where I have to use an external temperature sensor to take readings and send the data through the CC2530 chip. I am having trouble finding a what code I need to modify to be able to take readings from an external senor. I found your post today and I was wondering if you have any suggestions on how to implement the i2c hal drivers from the RemoTi? Is it as easy as downloading the driver and using the methods from this driver? Any help or guidance is greatly appreciated. Thank you!!

    Sincerely,

    Ben
  • You should assign your own OCM_CLK_PORT, OCM_CLK_PIN, OCM_DATA_PORT, and OCM_DATA_PIN for SCL and SDA. Then, send I2C commands according to the connected I2C device.
  • Hi YK,

    I have defined these parameters for my setup, but I am struggling to write the 12C commands according to the connected 12C device. I am not sure what methods to use or how to pull the temperature data from the TMP102 sensor. I am sure it is very simple but it has not yet become obvious to me. Thank you for the help!

    Sincerely,

    Ben

  • You are welcome and I think you just need some patience to make it work.
  • Hi YK,

    Do you by any chance have any suggestions about what methods to use and/ or how to pull the temperature data from the TMP102 sensor?

    Sincerely,

    Ben
  • Sorry, I don't have TMP102 to test on this. Try to refer sample code in contiki using TMP102 at contiki.sourceforge.net/.../a01654_source.html.
  • Hi Hamza,

    Regarding your question about the OCM_DATA_HIGH function, the logic seems conflicting, but it does the job actually.

    Once you set the GPIO as an input, the voltage at this input pin should be floating.

    Because there should be an external pull up resister attached to SDA / SCL lines, so the SDA should be pulled high even you set the I/O pin as an input. 

    This code shouldn't cause a problem.

  • Hi Felix,

    I am also using the i2c software provided in the RemoTI kit for cc2530.But I cannot read the value from the sensors.Can you help?

    Thanks

  • When you use I2C driver, do you see signal on SCL pin?
  • Sir,
    I have declared SCl on P0.1 and SDA on P0.0 ,but when I run the prorgram I can see the value on P0.0 is always set to 1.

    Thanks!
  • I suggest you to check SCL pin P0.1 and see if you can see I2C clock with a oscilloscope.
  • 0412.hal_key.c
    /**************************************************************************************************
      Filename:       hal_key.c
      Revised:        $Date: 2010-09-15 19:02:45 -0700 (Wed, 15 Sep 2010) $
      Revision:       $Revision: 23815 $
    
      Description:    This file contains the interface to the HAL KEY Service.
    
    
      Copyright 2006-2010 Texas Instruments Incorporated. All rights reserved.
    
      IMPORTANT: Your use of this Software is limited to those specific rights
      granted under the terms of a software license agreement between the user
      who downloaded the software, his/her employer (which must be your employer)
      and Texas Instruments Incorporated (the "License").  You may not use this
      Software unless you agree to abide by the terms of the License. The License
      limits your use, and you acknowledge, that the Software may not be modified,
      copied or distributed unless embedded on a Texas Instruments microcontroller
      or used solely and exclusively in conjunction with a Texas Instruments radio
      frequency transceiver, which is integrated into your product.  Other than for
      the foregoing purpose, you may not use, reproduce, copy, prepare derivative
      works of, modify, distribute, perform, display or sell this Software and/or
      its documentation for any purpose.
    
      YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
      PROVIDED �AS IS� WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
      INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
      NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
      TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
      NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
      LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
      INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
      OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
      OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
      (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
    
      Should you have any questions regarding your right to use this Software,
      contact Texas Instruments Incorporated at www.TI.com.
    **************************************************************************************************/
    /*********************************************************************
     NOTE: If polling is used, the hal_driver task schedules the KeyRead()
           to occur every 100ms.  This should be long enough to naturally
           debounce the keys.  The KeyRead() function remembers the key
           state of the previous poll and will only return a non-zero
           value if the key state changes.
    
     NOTE: If interrupts are used, the KeyRead() function is scheduled
           25ms after the interrupt occurs by the ISR.  This delay is used
           for key debouncing.  The ISR disables any further Key interrupt
           until KeyRead() is executed.  KeyRead() will re-enable Key
           interrupts after executing.  Unlike polling, when interrupts
           are enabled, the previous key state is not remembered.  This
           means that KeyRead() will return the current state of the keys
           (not a change in state of the keys).
    
     NOTE: If interrupts are used, the KeyRead() fucntion is scheduled by
           the ISR.  Therefore, the joystick movements will only be detected
           during a pushbutton interrupt caused by S1 or the center joystick
           pushbutton.
    
     NOTE: When a switch like S1 is pushed, the S1 signal goes from a normally
           high state to a low state.  This transition is typically clean.  The
           duration of the low state is around 200ms.  When the signal returns
           to the high state, there is a high likelihood of signal bounce, which
           causes a unwanted interrupts.  Normally, we would set the interrupt
           edge to falling edge to generate an interrupt when S1 is pushed, but
           because of the signal bounce, it is better to set the edge to rising
           edge to generate an interrupt when S1 is released.  The debounce logic
           can then filter out the signal bounce.  The result is that we typically
           get only 1 interrupt per button push.  This mechanism is not totally
           foolproof because occasionally, signal bound occurs during the falling
           edge as well.  A similar mechanism is used to handle the joystick
           pushbutton on the DB.  For the EB, we do not have independent control
           of the interrupt edge for the S1 and center joystick pushbutton.  As
           a result, only one or the other pushbuttons work reasonably well with
           interrupts.  The default is the make the S1 switch on the EB work more
           reliably.
    
    *********************************************************************/
    
    /**************************************************************************************************
     *                                            INCLUDES
     **************************************************************************************************/
    #include "hal_mcu.h"
    #include "hal_defs.h"
    #include "hal_types.h"
    #include "hal_board.h"
    #include "hal_drivers.h"
    #include "hal_adc.h"
    #include "hal_key.h"
    #include "osal.h"
    #include "stdio.h"
    #include "oval_acc.h"
    #include "i2csensors.h"
    //#include "i2csensors.h"
    
    //#if (defined HAL_KEY) && (HAL_KEY == TRUE)
    
    /**************************************************************************************************
     *                                              MACROS
     **************************************************************************************************/
    
    /**************************************************************************************************
     *                                            CONSTANTS
     **************************************************************************************************/
    #define HAL_KEY_RISING_EDGE   0
    #define HAL_KEY_FALLING_EDGE  1
    
    #define HAL_KEY_DEBOUNCE_VALUE  25
    
    /* CPU port interrupt */
    #define HAL_KEY_CPU_PORT_0_IF P0IF
    #define HAL_KEY_CPU_PORT_2_IF P2IF
    
    /* SW_6 is at P0.6 */
    #define HAL_KEY_SW_6_PORT   P0
    #define HAL_KEY_SW_6_BIT    BV(0)
    #define HAL_KEY_SW_6_SEL    P2SEL
    #define HAL_KEY_SW_6_DIR    P2DIR
    
    /* edge interrupt */
    #define HAL_KEY_SW_6_EDGEBIT  BV(3)
    #define HAL_KEY_SW_6_EDGE     HAL_KEY_FALLING_EDGE
    
    
    /* SW_6 interrupts */
    #define HAL_KEY_SW_6_IEN      IEN2  /* CPU interrupt mask register */
    #define HAL_KEY_SW_6_IENBIT   BV(1) /* Mask bit for all of Port_0 */
    #define HAL_KEY_SW_6_ICTL     P2IEN /* Port Interrupt Control register */
    #define HAL_KEY_SW_6_ICTLBIT  BV(0) /* P0IEN - P2.0 enable/disable bit */
    #define HAL_KEY_SW_6_PXIFG    P2IFG /* Interrupt flag at source */
    
    
    /* SW_1 interrupts*/
    #define HAL_KEY_SW_1_BIT     BV(3)
    #define HAL_KEY_SW_1_SEL     P2SEL
    #define HAL_KEY_SW_1_DIR     P2DIR
    
    /*Edge interrupt*/
    #define HAL_KEY_SW_1_EDGEBIT  BV(3)
    #define HAL_KEY_SW_1_EDGE     HAL_KEY_FALLING_EDGE
    
    /* SW_1 interrupts */
    #define HAL_KEY_SW_1_IEN      IEN2  /* CPU interrupt mask register */
    #define HAL_KEY_SW_1_IENBIT   BV(1) /* Mask bit for all of Port_0 */
    #define HAL_KEY_SW_1_ICTL     P2IEN /* Port Interrupt Control register */
    #define HAL_KEY_SW_1_ICTLBIT  BV(3) /* P0IEN - P0.1 enable/disable bit */
    #define HAL_KEY_SW_1_PXIFG    P2IFG /* Interrupt flag at source */
    
    /* Joy stick move at P2.0 */
    //#define HAL_KEY_JOY_MOVE_PORT   P2
    //#define HAL_KEY_JOY_MOVE_BIT    BV(0)
    //#define HAL_KEY_JOY_MOVE_SEL    P2SEL
    //#define HAL_KEY_JOY_MOVE_DIR    P2DIR
    
    /* edge interrupt */
    //#define HAL_KEY_JOY_MOVE_EDGEBIT  BV(3)
    //#define HAL_KEY_JOY_MOVE_EDGE     HAL_KEY_FALLING_EDGE
    
    /* Joy move interrupts */
    //#define HAL_KEY_JOY_MOVE_IEN      IEN2  /* CPU interrupt mask register */
    //#define HAL_KEY_JOY_MOVE_IENBIT   BV(1) /* Mask bit for all of Port_2 */
    //#define HAL_KEY_JOY_MOVE_ICTL     P2IEN /* Port Interrupt Control register */
    //#define HAL_KEY_JOY_MOVE_ICTLBIT  BV(0) /* P2IENL - P2.0<->P2.3 enable/disable bit */
    //#define HAL_KEY_JOY_MOVE_PXIFG    P2IFG /* Interrupt flag at source */
    
    #define HAL_KEY_JOY_CHN   HAL_ADC_CHANNEL_6
    
    
    /**************************************************************************************************
     *                                            TYPEDEFS
     **************************************************************************************************/
    
    
    /**************************************************************************************************
     *                                        GLOBAL VARIABLES
     **************************************************************************************************/
    static uint8 halKeySavedKeys;     /* used to store previous key state in polling mode */
    static halKeyCBack_t pHalKeyProcessFunction;
    static uint8 HalKeyConfigured;
    bool Hal_KeyIntEnable;           /* interrupt enable/disable flag */
    
    
    /**************************************************************************************************
     *                                        FUNCTIONS - Local
     **************************************************************************************************/
    void halProcessKeyInterrupt(void);
    uint8 halGetJoyKeyInput(void);
    
    
    
    /**************************************************************************************************
     *                                        FUNCTIONS - API
     **************************************************************************************************/
    
    
    /**************************************************************************************************
     * @fn      HalKeyInit
     *
     * @brief   Initilize Key Service
     *
     * @param   none
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyInit( void )
    {
      /* Initialize previous key to 0 */
      halKeySavedKeys = 0;
    
      P2SEL &= ~(HAL_KEY_SW_6_BIT);    /* Set pin function to GPIO */
      P2DIR &= ~(HAL_KEY_SW_6_BIT);    /* Set pin direction to Input */
      
      /* Initialize callback function */
      pHalKeyProcessFunction  = NULL;
    
      /* Start with key is not configured */
      HalKeyConfigured = FALSE;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyConfig
     *
     * @brief   Configure the Key serivce
     *
     * @param   interruptEnable - TRUE/FALSE, enable/disable interrupt
     *          cback - pointer to the CallBack function
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback)
    {
      /* Enable/Disable Interrupt or */
      Hal_KeyIntEnable = interruptEnable;
      pHalKeyProcessFunction = cback; //register call back function  during configuration of keys.
     
      /* Determine if interrupt is enable or not */
      if (Hal_KeyIntEnable)
      {
        /* Rising/Falling edge configuratinn */
        PICTL &= ~(HAL_KEY_SW_6_EDGEBIT);/* Clear the edge bit */
       
      #if (HAL_KEY_SW_6_EDGE == HAL_KEY_FALLING_EDGE)
         PICTL |= HAL_KEY_SW_6_EDGEBIT ;
      #endif
    
    
        /* Interrupt configuration:
         * - Enable interrupt generation at the port
         * - Enable CPU interrupt
         * - Clear any pending interrupt
         */
        P2IEN |= HAL_KEY_SW_6_ICTLBIT ;
        IEN2  |= HAL_KEY_SW_6_IENBIT ;
        
        P2IFG  = ~BV(0);
    
        if (HalKeyConfigured == TRUE)
        {
           osal_stop_timerEx(Hal_TaskID, HAL_KEY_EVENT);    /* Cancel polling if active */
        }
      }
      else    /* Interrupts NOT enabled */
      {
        P2IEN &= ~(HAL_KEY_SW_6_ICTLBIT);  /* don't generate interrupt */
        IEN2  &= ~(HAL_KEY_SW_6_IENBIT);   /* Clear interrupt enable bit */   
        
            osal_set_event(Hal_TaskID, HAL_KEY_EVENT); 
       
      }
    
      /* Key now is configured */
      HalKeyConfigured = TRUE;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyRead
     *
     * @brief   Read the current value of a key
     *
     * @param   None
     *
     * @return  keys - current keys status
     **************************************************************************************************/
    uint8 HalKeyRead ( void )
    {
      uint8 keys = 0;
    
     if(!HAL_FLOOD_INT()) //if flood interrupt
      {
        keys |= HAL_KEY_SW_6;
      }
      /*if(!(HAL_LUXINT())) //if lux interrupt
      {
        keys |= HAL_KEY_SW_1;
      }
      */
     return keys;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyPoll
     *
     * @brief   Called by hal_driver to poll the keys
     *
     * @param   None
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyPoll (void)
    {
      uint8 keys = 0;
    
      /* If interrupts are not enabled, previous key status and current key status
       * are compared to find out if a key has changed status.
       */
      if (!Hal_KeyIntEnable)
      {
        if (keys == halKeySavedKeys)
        {
          /* Exit - since no keys have changed */
          return;
        }
        /* Store the current keys for comparation next time */
        halKeySavedKeys = keys;
      }
      else
      {
        /* Key interrupt handled here */
      }
    
      if (!HAL_FLOOD_INT())
      {
        keys |= HAL_KEY_SW_6;
      }
     
      /* Invoke Callback if new keys were depressed */
      if (keys && (pHalKeyProcessFunction))
      {
        (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
      }
    }
    
    /**************************************************************************************************
     * @fn      halGetJoyKeyInput
     *
     * @brief   Map the ADC value to its corresponding key.
     *
     * @param   None
     *
     * @return  keys - current joy key status
     **************************************************************************************************/
    uint8 halGetJoyKeyInput(void)
    {
      /* The joystick control is encoded as an analog voltage.
       * Read the JOY_LEVEL analog value and map it to joy movement.
       */
      uint8 adc;
      uint8 ksave0 = 0;
      uint8 ksave1;
    
      /* Keep on reading the ADC until two consecutive key decisions are the same. */
      do
      {
        ksave1 = ksave0;    /* save previouse key reading */
    
        adc = HalAdcRead (HAL_KEY_JOY_CHN, HAL_ADC_RESOLUTION_8);
    
        if ((adc >= 2) && (adc <= 38))
        {
           ksave0 |= HAL_KEY_UP;
        }
        else if ((adc >= 74) && (adc <= 88))
        {
          ksave0 |= HAL_KEY_RIGHT;
        }
        else if ((adc >= 60) && (adc <= 73))
        {
          ksave0 |= HAL_KEY_LEFT;
        }
        else if ((adc >= 39) && (adc <= 59))
        {
          ksave0 |= HAL_KEY_DOWN;
        }
        else if ((adc >= 89) && (adc <= 100))
        {
          ksave0 |= HAL_KEY_CENTER;
        }
      } while (ksave0 != ksave1);
    
      return ksave0;
    }
    
    
    
    
    
    /**************************************************************************************************
     * @fn      halProcessKeyInterrupt
     *
     * @brief   Checks to see if it's a valid key interrupt, saves interrupt driven key states for
     *          processing by HalKeyRead(), and debounces keys by scheduling HalKeyRead() 25ms later.
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    void halProcessKeyInterrupt (void)
    {
      bool valid=FALSE;
    
     if (P2IFG & HAL_KEY_SW_6_BIT)  
      {
         printf("\n\tHola-2\n\t");
         P2IFG = ~(HAL_KEY_SW_6_BIT); 
         valid = TRUE;
      }
    
      if (valid)
      {
        osal_start_timerEx(Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);
      }
      //P2IF=0;
    }
    
    /**************************************************************************************************
     * @fn      HalKeyEnterSleep
     *
     * @brief  - Get called to enter sleep mode
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    void HalKeyEnterSleep ( void )
    {
    }
    
    /**************************************************************************************************
     * @fn      HalKeyExitSleep
     *
     * @brief   - Get called when sleep is over
     *
     * @param
     *
     * @return  - return saved keys
     **************************************************************************************************/
    uint8 HalKeyExitSleep ( void )
    {
      /* Wake up and read keys */
      return ( HalKeyRead () );
    }
    
    /***************************************************************************************************
     *                                    INTERRUPT SERVICE ROUTINE
     ***************************************************************************************************/
    
    /**************************************************************************************************
     * @fn      halKeyPort0Isr
     *
     * @brief   Port0 ISR
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    HAL_ISR_FUNCTION( halKeyPort0Isr, P0INT_VECTOR )
    {
      HAL_ENTER_ISR();
      
    //  if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT)
       {
       // printf("\nMotion Interrupt!\n");
       // halProcessKeyInterrupt();
       }
    
      /*
        Clear the CPU interrupt flag for Port_0
        PxIFG has to be cleared before PxIF
      */
      osal_start_timerEx(Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);
     //  P0IFG = ~(HAL_KEY_SW_6_BIT);
      //HAL_KEY_SW_6_PXIFG = 0;
      HAL_KEY_CPU_PORT_0_IF = 0;
      
      //CLEAR_SLEEP_MODE();
      HAL_EXIT_ISR();
    }
    
    
    /**************************************************************************************************
     * @fn      halKeyPort2Isr
     *
     * @brief   Port2 ISR
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    HAL_ISR_FUNCTION( halKeyPort2Isr, P2INT_VECTOR )
    {
      HAL_ENTER_ISR();
      
      if ((P2IFG & HAL_KEY_SW_6_BIT))//|| (HAL_KEY_SW_1_PXIFG & HAL_KEY_SW_1_BIT))
      {
        printf("\n\tHola-1\t");
        halProcessKeyInterrupt();
      }
      P2IFG = 0;
      P2IF=0;
      CLEAR_SLEEP_MODE();
      HAL_EXIT_ISR();
    }
    
    /*#else
    
    
    void HalKeyInit(void){}
    void HalKeyConfig(bool interruptEnable, halKeyCBack_t cback){}
    uint8 HalKeyRead(void){ return 0;}
    void HalKeyPoll(void){}
    
    #endif *//* HAL_KEY */
    
    
    
    
    
    /**************************************************************************************************
    **************************************************************************************************/
    
    
    
    
    Hello Sir,

    I am using CC2530 Z-stack HA Sample Switch example.I have a key on board on Port 2.0 .When I press the switch ,I get the message on the terminal I/O only for the first time and then program gets stuck somewhere or busy.I am unable to resolve the issue.

  • Please don't do printf in ISR. Try to remove it from your ISR and test again.
  • Sir,

    I have removed the printf from the ISR .I have declared the printf here :

            case KEY_CHANGE:

             printf("\n\tKEY_CHANE event\n\t");

             zclSampleSw_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );

    but now when I run the program I see this on pressing the switch on P2.0

    It doesnt stop ,I hope the problem is clearly stated ?

    Thanks

  • Do you clear interrupt bit in ISR?
  • Yes I did ,I even checked for this Pin if its used somewhere ,but I found none.

    5582.hal_key.c
    /**************************************************************************************************
      Filename:       hal_key.c
      Revised:        $Date: 2010-09-15 19:02:45 -0700 (Wed, 15 Sep 2010) $
      Revision:       $Revision: 23815 $
    
      Description:    This file contains the interface to the HAL KEY Service.
    
    
      Copyright 2006-2010 Texas Instruments Incorporated. All rights reserved.
    
      IMPORTANT: Your use of this Software is limited to those specific rights
      granted under the terms of a software license agreement between the user
      who downloaded the software, his/her employer (which must be your employer)
      and Texas Instruments Incorporated (the "License").  You may not use this
      Software unless you agree to abide by the terms of the License. The License
      limits your use, and you acknowledge, that the Software may not be modified,
      copied or distributed unless embedded on a Texas Instruments microcontroller
      or used solely and exclusively in conjunction with a Texas Instruments radio
      frequency transceiver, which is integrated into your product.  Other than for
      the foregoing purpose, you may not use, reproduce, copy, prepare derivative
      works of, modify, distribute, perform, display or sell this Software and/or
      its documentation for any purpose.
    
      YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
      PROVIDED �AS IS� WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
      INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
      NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
      TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
      NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
      LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
      INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
      OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
      OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
      (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
    
      Should you have any questions regarding your right to use this Software,
      contact Texas Instruments Incorporated at www.TI.com.
    **************************************************************************************************/
    /*********************************************************************
     NOTE: If polling is used, the hal_driver task schedules the KeyRead()
           to occur every 100ms.  This should be long enough to naturally
           debounce the keys.  The KeyRead() function remembers the key
           state of the previous poll and will only return a non-zero
           value if the key state changes.
    
     NOTE: If interrupts are used, the KeyRead() function is scheduled
           25ms after the interrupt occurs by the ISR.  This delay is used
           for key debouncing.  The ISR disables any further Key interrupt
           until KeyRead() is executed.  KeyRead() will re-enable Key
           interrupts after executing.  Unlike polling, when interrupts
           are enabled, the previous key state is not remembered.  This
           means that KeyRead() will return the current state of the keys
           (not a change in state of the keys).
    
     NOTE: If interrupts are used, the KeyRead() fucntion is scheduled by
           the ISR.  Therefore, the joystick movements will only be detected
           during a pushbutton interrupt caused by S1 or the center joystick
           pushbutton.
    
     NOTE: When a switch like S1 is pushed, the S1 signal goes from a normally
           high state to a low state.  This transition is typically clean.  The
           duration of the low state is around 200ms.  When the signal returns
           to the high state, there is a high likelihood of signal bounce, which
           causes a unwanted interrupts.  Normally, we would set the interrupt
           edge to falling edge to generate an interrupt when S1 is pushed, but
           because of the signal bounce, it is better to set the edge to rising
           edge to generate an interrupt when S1 is released.  The debounce logic
           can then filter out the signal bounce.  The result is that we typically
           get only 1 interrupt per button push.  This mechanism is not totally
           foolproof because occasionally, signal bound occurs during the falling
           edge as well.  A similar mechanism is used to handle the joystick
           pushbutton on the DB.  For the EB, we do not have independent control
           of the interrupt edge for the S1 and center joystick pushbutton.  As
           a result, only one or the other pushbuttons work reasonably well with
           interrupts.  The default is the make the S1 switch on the EB work more
           reliably.
    
    *********************************************************************/
    
    /**************************************************************************************************
     *                                            INCLUDES
     **************************************************************************************************/
    #include "hal_mcu.h"
    #include "hal_defs.h"
    #include "hal_types.h"
    #include "hal_board.h"
    #include "hal_drivers.h"
    #include "hal_adc.h"
    #include "hal_key.h"
    #include "osal.h"
    #include "stdio.h"
    #include "oval_acc.h"
    #include "i2csensors.h"
    //#include "i2csensors.h"
    
    //#if (defined HAL_KEY) && (HAL_KEY == TRUE)
    
    /**************************************************************************************************
     *                                              MACROS
     **************************************************************************************************/
    
    /**************************************************************************************************
     *                                            CONSTANTS
     **************************************************************************************************/
    #define HAL_KEY_RISING_EDGE   0
    #define HAL_KEY_FALLING_EDGE  1
    
    #define HAL_KEY_DEBOUNCE_VALUE  25
    
    /* CPU port interrupt */
    //#define HAL_KEY_CPU_PORT_0_IF P0IF
    //#define HAL_KEY_CPU_PORT_2_IF P2IF
    
    /* SW_6 is at P0.6 */
    #define HAL_KEY_SW_6_PORT   P0
    #define HAL_KEY_SW_6_BIT    BV(0)
    #define HAL_KEY_SW_6_SEL    P2SEL
    #define HAL_KEY_SW_6_DIR    P2DIR
    
    /* edge interrupt */
    #define HAL_KEY_SW_6_EDGEBIT  BV(3)
    #define HAL_KEY_SW_6_EDGE     HAL_KEY_FALLING_EDGE
    
    
    /* SW_6 interrupts */
    #define HAL_KEY_SW_6_IEN      IEN2  /* CPU interrupt mask register */
    #define HAL_KEY_SW_6_IENBIT   BV(1) /* Mask bit for all of Port_0 */
    #define HAL_KEY_SW_6_ICTL     P2IEN /* Port Interrupt Control register */
    #define HAL_KEY_SW_6_ICTLBIT  BV(0) /* P0IEN - P2.0 enable/disable bit */
    //#define HAL_KEY_SW_6_PXIFG    P2IFG /* Interrupt flag at source */
    
    
    /* SW_1 interrupts*/
    #define HAL_KEY_SW_1_BIT     BV(3)
    #define HAL_KEY_SW_1_SEL     P2SEL
    #define HAL_KEY_SW_1_DIR     P2DIR
    
    /*Edge interrupt*/
    #define HAL_KEY_SW_1_EDGEBIT  BV(3)
    #define HAL_KEY_SW_1_EDGE     HAL_KEY_FALLING_EDGE
    
    /* SW_1 interrupts */
    #define HAL_KEY_SW_1_IEN      IEN2  /* CPU interrupt mask register */
    #define HAL_KEY_SW_1_IENBIT   BV(1) /* Mask bit for all of Port_0 */
    #define HAL_KEY_SW_1_ICTL     P2IEN /* Port Interrupt Control register */
    #define HAL_KEY_SW_1_ICTLBIT  BV(3) /* P0IEN - P0.1 enable/disable bit */
    #define HAL_KEY_SW_1_PXIFG    P2IFG /* Interrupt flag at source */
    
    /* Joy stick move at P2.0 */
    //#define HAL_KEY_JOY_MOVE_PORT   P2
    //#define HAL_KEY_JOY_MOVE_BIT    BV(0)
    //#define HAL_KEY_JOY_MOVE_SEL    P2SEL
    //#define HAL_KEY_JOY_MOVE_DIR    P2DIR
    
    /* edge interrupt */
    //#define HAL_KEY_JOY_MOVE_EDGEBIT  BV(3)
    //#define HAL_KEY_JOY_MOVE_EDGE     HAL_KEY_FALLING_EDGE
    
    /* Joy move interrupts */
    //#define HAL_KEY_JOY_MOVE_IEN      IEN2  /* CPU interrupt mask register */
    //#define HAL_KEY_JOY_MOVE_IENBIT   BV(1) /* Mask bit for all of Port_2 */
    //#define HAL_KEY_JOY_MOVE_ICTL     P2IEN /* Port Interrupt Control register */
    //#define HAL_KEY_JOY_MOVE_ICTLBIT  BV(0) /* P2IENL - P2.0<->P2.3 enable/disable bit */
    //#define HAL_KEY_JOY_MOVE_PXIFG    P2IFG /* Interrupt flag at source */
    
    #define HAL_KEY_JOY_CHN   HAL_ADC_CHANNEL_6
    
    
    /**************************************************************************************************
     *                                            TYPEDEFS
     **************************************************************************************************/
    
    
    /**************************************************************************************************
     *                                        GLOBAL VARIABLES
     **************************************************************************************************/
    static uint8 halKeySavedKeys;     /* used to store previous key state in polling mode */
    static halKeyCBack_t pHalKeyProcessFunction;
    static uint8 HalKeyConfigured;
    bool Hal_KeyIntEnable;           /* interrupt enable/disable flag */
    
    
    /**************************************************************************************************
     *                                        FUNCTIONS - Local
     **************************************************************************************************/
    void halProcessKeyInterrupt(void);
    uint8 halGetJoyKeyInput(void);
    
    
    
    /**************************************************************************************************
     *                                        FUNCTIONS - API
     **************************************************************************************************/
    
    
    /**************************************************************************************************
     * @fn      HalKeyInit
     *
     * @brief   Initilize Key Service
     *
     * @param   none
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyInit( void )
    {
      /* Initialize previous key to 0 */
      halKeySavedKeys = 0;
    
      P2SEL &= ~(HAL_KEY_SW_6_BIT);    /* Set pin function to GPIO */
      P2DIR &= ~(HAL_KEY_SW_6_BIT);    /* Set pin direction to Input */
      
      /* Initialize callback function */
      pHalKeyProcessFunction  = NULL;
    
      /* Start with key is not configured */
      HalKeyConfigured = FALSE;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyConfig
     *
     * @brief   Configure the Key serivce
     *
     * @param   interruptEnable - TRUE/FALSE, enable/disable interrupt
     *          cback - pointer to the CallBack function
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback)
    {
      /* Enable/Disable Interrupt or */
      Hal_KeyIntEnable = interruptEnable;
      pHalKeyProcessFunction = cback; //register call back function  during configuration of keys.
     
      /* Determine if interrupt is enable or not */
      if (Hal_KeyIntEnable)
      {
        /* Rising/Falling edge configuratinn */
        PICTL &= ~(HAL_KEY_SW_6_EDGEBIT);/* Clear the edge bit */
       
      #if (HAL_KEY_SW_6_EDGE == HAL_KEY_FALLING_EDGE)
         PICTL |= HAL_KEY_SW_6_EDGEBIT ;
      #endif
    
    
        /* Interrupt configuration:
         * - Enable interrupt generation at the port
         * - Enable CPU interrupt
         * - Clear any pending interrupt
         */
        P2IEN |= HAL_KEY_SW_6_ICTLBIT ;
        IEN2  |= HAL_KEY_SW_6_IENBIT ;
       // IEN0 |=BV(7);
        
        P2IFG  = ~BV(0);
    
        if (HalKeyConfigured == TRUE)
        {
           osal_stop_timerEx(Hal_TaskID, HAL_KEY_EVENT);    /* Cancel polling if active */
        }
      }
      else    /* Interrupts NOT enabled */
      {
         P2IEN &= ~(HAL_KEY_SW_6_ICTLBIT);  /* don't generate interrupt */
         IEN2  &= ~(HAL_KEY_SW_6_IENBIT);   /* Clear interrupt enable bit */   
         osal_set_event(Hal_TaskID, HAL_KEY_EVENT); 
       
      }
    
      /* Key now is configured */
      HalKeyConfigured = TRUE;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyRead
     *
     * @brief   Read the current value of a key
     *
     * @param   None
     *
     * @return  keys - current keys status
     **************************************************************************************************/
    uint8 HalKeyRead ( void )
    {
      uint8 keys = 0;
    
     if(!HAL_FLOOD_INT()) //if flood interrupt
      {
        keys |= HAL_KEY_SW_6;
      }
     
     return keys;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyPoll
     *
     * @brief   Called by hal_driver to poll the keys
     *
     * @param   None
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyPoll (void)
    {
      uint8 keys = 0;
    
      /* If interrupts are not enabled, previous key status and current key status
       * are compared to find out if a key has changed status.
       */
      if (!Hal_KeyIntEnable)
      {
        if (keys == halKeySavedKeys)
        {
          /* Exit - since no keys have changed */
          return;
        }
        /* Store the current keys for comparation next time */
        halKeySavedKeys = keys;
      }
      else
      {
        /* Key interrupt handled here */
      }
    
      if (!HAL_FLOOD_INT())
      {
        keys |= HAL_KEY_SW_6;
      }
     
      /* Invoke Callback if new keys were depressed */
      if (keys && (pHalKeyProcessFunction))
      {
        (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
      }
    }
    
    /**************************************************************************************************
     * @fn      halGetJoyKeyInput
     *
     * @brief   Map the ADC value to its corresponding key.
     *
     * @param   None
     *
     * @return  keys - current joy key status
     **************************************************************************************************/
    uint8 halGetJoyKeyInput(void)
    {
      /* The joystick control is encoded as an analog voltage.
       * Read the JOY_LEVEL analog value and map it to joy movement.
       */
      uint8 adc;
      uint8 ksave0 = 0;
      uint8 ksave1;
    
      /* Keep on reading the ADC until two consecutive key decisions are the same. */
      do
      {
        ksave1 = ksave0;    /* save previouse key reading */
    
        adc = HalAdcRead (HAL_KEY_JOY_CHN, HAL_ADC_RESOLUTION_8);
    
        if ((adc >= 2) && (adc <= 38))
        {
           ksave0 |= HAL_KEY_UP;
        }
        else if ((adc >= 74) && (adc <= 88))
        {
          ksave0 |= HAL_KEY_RIGHT;
        }
        else if ((adc >= 60) && (adc <= 73))
        {
          ksave0 |= HAL_KEY_LEFT;
        }
        else if ((adc >= 39) && (adc <= 59))
        {
          ksave0 |= HAL_KEY_DOWN;
        }
        else if ((adc >= 89) && (adc <= 100))
        {
          ksave0 |= HAL_KEY_CENTER;
        }
      } while (ksave0 != ksave1);
    
      return ksave0;
    }
    
    
    
    
    
    /**************************************************************************************************
     * @fn      halProcessKeyInterrupt
     *
     * @brief   Checks to see if it's a valid key interrupt, saves interrupt driven key states for
     *          processing by HalKeyRead(), and debounces keys by scheduling HalKeyRead() 25ms later.
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    void halProcessKeyInterrupt (void)
    {
      bool valid=FALSE;
    
     if (P2IFG & HAL_KEY_SW_6_BIT)  
      {
    
         P2IFG = ~BV(0); 
         valid = TRUE;
      }
      if (valid)
      {
        osal_start_timerEx(Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);
      }
    P2IF=0;
    }
    
    /**************************************************************************************************
     * @fn      HalKeyEnterSleep
     *
     * @brief  - Get called to enter sleep mode
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    void HalKeyEnterSleep ( void )
    {
    }
    
    /**************************************************************************************************
     * @fn      HalKeyExitSleep
     *
     * @brief   - Get called when sleep is over
     *
     * @param
     *
     * @return  - return saved keys
     **************************************************************************************************/
    uint8 HalKeyExitSleep ( void )
    {
      /* Wake up and read keys */
      return ( HalKeyRead () );
    }
    
    /***************************************************************************************************
     *                                    INTERRUPT SERVICE ROUTINE
     ***************************************************************************************************/
    
    /**************************************************************************************************
     * @fn      halKeyPort0Isr
     *
     * @brief   Port0 ISR
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    HAL_ISR_FUNCTION( halKeyPort0Isr, P0INT_VECTOR )
    {
      HAL_ENTER_ISR();
      
    //  if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT)
       {
       // printf("\nMotion Interrupt!\n");
       // halProcessKeyInterrupt();
       }
    
      /*
        Clear the CPU interrupt flag for Port_0
        PxIFG has to be cleared before PxIF
      */
      osal_start_timerEx(Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);
     //  P0IFG = ~(HAL_KEY_SW_6_BIT);
      //HAL_KEY_SW_6_PXIFG = 0;
      P0IF = 0;
      
      //CLEAR_SLEEP_MODE();
      HAL_EXIT_ISR();
    }
    
    
    /**************************************************************************************************
     * @fn      halKeyPort2Isr
     *
     * @brief   Port2 ISR
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    HAL_ISR_FUNCTION( halKeyPort2Isr, P2INT_VECTOR )
    {
      HAL_ENTER_ISR();
      
      if (P2IFG & HAL_KEY_SW_6_BIT)//|| (HAL_KEY_SW_1_PXIFG & HAL_KEY_SW_1_BIT))
      {
        halProcessKeyInterrupt();
      }
      P2IFG = 0;
      P2IF = 0;
      CLEAR_SLEEP_MODE();
      HAL_EXIT_ISR();
    }
    
    /*#else
    
    
    void HalKeyInit(void){}
    void HalKeyConfig(bool interruptEnable, halKeyCBack_t cback){}
    uint8 HalKeyRead(void){ return 0;}
    void HalKeyPoll(void){}
    
    #endif *//* HAL_KEY */
    
    
    
    
    
    /**************************************************************************************************
    **************************************************************************************************/
    
    
    
    

  • Do you use oscilloscope to check if there is noise on P2.0?
  • Hello Sir,

    Is it possible to have multiple HAL_ISR_FUNCTION declaration?

    for e.g it is declared inside the hal_key.c can I also declare it in any other file?

    thanks!

  • No, you cannot do that.
  • Sir,

    I have SCL on P0.1 

               SDA on P0.0

    But on running the program I can see that on SCL pin it is consistently showing 3.1V and on SDA it is 0.I am unable to get the clock work.Can you tell me the ways to troubleshoot it more precisely?

    Thanks