微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > TI蓝牙设计交流 > 关于keyfob添加I2C

关于keyfob添加I2C

时间:10-02 整理:3721RD 点击:

我现在想在keyfob的例程上添加一个传感器,原本是没有I2C的功能的,然后我就把他的I2C.C跟I2C.H加进去,然后就出现了RAM超出这个问题,是不是我哪里设置不对?

hongliang,

你看一下编译出来的.map 文件,看看每个模块占用的ram 有多大,特别是你加进去的i2c 模块。

如果太大,试着削减一下其他模块的代码。

你可以参考sensortag的源码,sensortag 的6个传感器都是用硬件iic进行通讯的,程序很稳,你可以直接将其中的iiC部分一直到keyfob里边

/***********************************************************************************
  Filename:     i2c_master_send.c

  Description:  This example uses a master to send data to a slave using I2C.

  Comments:     To execute this example, use the IAR project i2c_slave_receive
                as the slave. The slave's code must be executed before executing
                the master's code, since the slave is clocked by the Master. The
                bytes sent are simply numbers 0x00 upto BUFFER_SIZE. When bytes
                up to BUFFER_SIZE are sent, the example will end and LED1 will
                be set on the SmartRF05EB.

  Note:         On the SmartRF05EB, P0_6 and P0_7 from CC2543EM is shared by the
                EM_JOY_LEVEL and EM_LCD_CS signals. These have to be disconnected
                by removing jumpers 7-8 and 3-4 on P10 I/O Connector. Thus the I2C
                and SRF05EB LCD can't be used simultaneously.

                The I2C pins also have external pullups on the EM, at the as
                required by the I2C standard.

***********************************************************************************/

/***********************************************************************************
* INCLUDES
*/

#include <hal_types.h>
// Include Name definitions of individual bits and bit-fields in the CC254x device registers.
#include <ioCC254x_bitdef.h>
// Include device specific file
#if (chip==2541)
#include "ioCC2541.h"
#elif (chip==2543)
#include "ioCC2543.h"
#elif (chip==2545)
#include "ioCC2545.h"
#else
#error "Chip not supported!"
#endif


/***********************************************************************************
* CONSTANTS
*/

// Define size of buffer and number of bytes to send.
#define BUFFER_SIZE 0xFF
#define SLAVE_ADDRESS 0x53    // 7-bit addressing.

#define READ_FROM_SLAVE 0x01
#define WRITE_TO_SLAVE 0x00


/***********************************************************************************
* LOCAL VARIABLES
*/

// Masters's transmit buffer
static uint8 buffer[BUFFER_SIZE];
static uint16 bufferIndex = 0;


/***********************************************************************************
* LOCAL FUNCTIONS
*/

/***********************************************************************************
* @fn          I2C_ISR
*
* @brief       Function which sends the next I2C data byte.
*
* @param       none
*
* @return      0
*/
#pragma vector = I2C_VECTOR
__interrupt void I2C_ISR(void)
{
#if(chip==2541)
    // Clear I2C CPU interrupt flag.
    P2IF = 0;
#elif(chip==2543 || chip==2545)
    // Clear I2C CPU interrupt flag.
    I2CIF = 0;
#endif
 
    // If a Start or Restart condition has been transmitted ...
    if (I2CSTAT == 0x08 || I2CSTAT == 0x10)
    {
        // Send Slave address and R/W access.
        I2CDATA = (SLAVE_ADDRESS << 1) | WRITE_TO_SLAVE;

        // End Start condition.
        I2CCFG &= ~I2CCFG_STA;
    }

    // If finished transmitting ...
    if (bufferIndex > BUFFER_SIZE)
    {
        // Generate Stop condition.
        I2CCFG |= I2CCFG_STO;
     
#if(chip==2541)
    // Disable interrupt from I2C by setting [IEN2.I2CIE = 0].
    IEN2 &= ~IEN2_P2IE;
#elif(chip==2543 || chip==2545)
    // Disable interrupt from I2C by setting [IEN2.I2CIE = 0].
    IEN2 &= ~IEN2_I2CIE;
#endif
   
    // Set SRF05EB LED1.
    P1_0 = 1;  
  }

    // If Slave address or Data byte has been transmitted and acknowledged ...
    else if (I2CSTAT == 0x18 || I2CSTAT == 0x28)
    {
        // Send next I2C byte
        I2CDATA = buffer[bufferIndex++];
    }
  
    // I2CCFG.SI flag must be cleared by software at the end of the ISR.
    I2CCFG &= ~I2CCFG_SI;
}


/***********************************************************************************
* @fn          main
*
* @brief       Send data to a single slave using I2C in Master mode
*
* @param       void
*
* @return      0
*/
int main(void)
{
    /****************************************************************************
    * Clock setup
    * See basic software example "clk_xosc_cc254x"
    */
 
    // Set system clock source to HS XOSC, with no pre-scaling.
    CLKCONCMD = (CLKCONCMD & ~(CLKCON_OSC | CLKCON_CLKSPD)) | CLKCON_CLKSPD_32M;
    // Wait until clock source has changed
    while (CLKCONSTA & CLKCON_OSC);
 
    // Note the 32 kHz RCOSC starts calibrating, if not disabled.

#if (chip==2543)
    /***************************************************************************
    * Setup I/O ports
    *
    * Port and pins used by I2C, at the alternative 1 location:
    * I2C SCL:   P0_6    (Debug Connector P18_5)
    * I2C SDA:   P0_7    (Debug Connector P18_3)
    */

    // Configure I2C for location Alternative 1.
    PERCFG &= ~PERCFG_I2CCFG;
 
    // Give priority to I2C over Timer 1 for port 0 pins.
    PPRI &= ~PPRI_PRI1P0;

    // Set P0_6 and P0_7 as peripheral I/O.
    P0SEL |= BIT7 | BIT6;
 
#elif(chip==2545)
    /***************************************************************************
    * Setup I/O ports
    *
    * Port and pins used by I2C, at the alternative 2 location:
    * I2C SCL:   P2_5    (Debug Connector P18_5)
    * I2C SDA:   P2_6    (Debug Connector P18_3)
    */

    // Configure I2C for location Alternative 2.
    PERCFG |= PERCFG_I2CCFG;
  
    // Give priority to I2C over USART0, then Timer3.
    PPRI = (PPRI & ~PPRI_PRI1P1) | PPRI_PRI1P1_I2C;

    // Set P2_5 and P2_6 as peripheral I/O.
    P2SEL |= BIT6 | BIT5;
 
#elif(chip==2541)
    /***************************************************************************
    * Setup I/O ports
    *
    * CC2541 has dedicated I2C ports
    * I2C SCL:   Pin 2   (Debug Connector P18_5)
    * I2C SDA:   Pin 3   (Debug Connector P18_3)
    */
 
    // Enable I2C on CC2541.
    I2CWC &= ~0x80;
#endif
 
    // Configure P1_0 as GPIO output for LED1
    P1SEL &= BIT0;      // GPIO
    P1DIR |= BIT0;      // Output
    P1_0 = 0;           // LED1 off


  /***************************************************************************
  * Setup interrupt
  */

#if(chip==2541)
    // Clear I2C (P2) CPU interrupt flag.
    P2IF = 0;

    // Enable interrupt from I2C by setting [IEN2.P2IE = 1].
    IEN2 |= IEN2_P2IE;
#else
    // Clear I2C CPU interrupt flag.
    I2CIF = 0;

    // Enable interrupt from I2C by setting [IEN2.I2CIE = 1].
    IEN2 |= IEN2_I2CIE;
#endif
 
    // Enable global interrupts.
    EA = 1;
 
 
    /***************************************************************************
    * Configure I2C
    */

    // Fill the buffer with values 0x00++.
    uint8 value = 0x00;
    uint8 i;
    for (i = 0; i < BUFFER_SIZE; i++)
    {
        buffer[i] = value++;
    }

    // Enable the I2C module with 33 kHz clock rate.
    // The STArt bit signals a master.
    I2CCFG = (I2CCFG & ~I2CCFG_CR) | I2CCFG_CR_div_960 | I2CCFG_ENS1 | I2CCFG_STA;

    /* Main Loop, the transfers are interrupt handled. */
    while(1);
}

/**************************************************************************************************
  Filename:       hal_i2c.c
  Revised:        $Date: 2012-09-21 06:30:38 -0700 (Fri, 21 Sep 2012) $
  Revision:       $Revision: 31581 $

  Description:    This module defines the HAL I2C API for the CC2541ST. It
                  implements the I2C master.


  Copyright 2012 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 揂S 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.
**************************************************************************************************/

/* ------------------------------------------------------------------------------------------------
 *                                          Includes
 * ------------------------------------------------------------------------------------------------
 */
#include "hal_assert.h"
#include "hal_board_cfg.h"
#include "hal_i2c.h"

/* ------------------------------------------------------------------------------------------------
 *                                          Constants
 * ------------------------------------------------------------------------------------------------
 */
#define I2C_ENS1            BV(6)
#define I2C_STA             BV(5)
#define I2C_STO             BV(4)
#define I2C_SI              BV(3)
#define I2C_AA              BV(2)
#define I2C_MST_RD_BIT      BV(0)  // Master RD/WRn bit to be OR'ed with Slave address.

#define I2C_CLOCK_MASK      0x83

#define I2C_PXIFG           P2IFG
#define I2C_IF              P2IF
#define I2C_IE              BV(1)

/* ------------------------------------------------------------------------------------------------
 *                                           Typedefs
 * ------------------------------------------------------------------------------------------------
 */

typedef enum
{
  // HAL_I2C_MASTER mode statuses.
  mstStarted   = 0x08,
  mstRepStart  = 0x10,
  mstAddrAckW  = 0x18,
  mstAddrNackW = 0x20,
  mstDataAckW  = 0x28,
  mstDataNackW = 0x30,
  mstLostArb   = 0x38,
  mstAddrAckR  = 0x40,
  mstAddrNackR = 0x48,
  mstDataAckR  = 0x50,
  mstDataNackR = 0x58,
} i2cStatus_t;

/* ------------------------------------------------------------------------------------------------
 *                                           Macros
 * ------------------------------------------------------------------------------------------------
 */

#define I2C_WRAPPER_DISABLE() st( I2CWC    =     0x00;              )
#define I2C_CLOCK_RATE(x)     st( I2CCFG  &=    ~I2C_CLOCK_MASK;    \
                                  I2CCFG  |=     x;                 )
#define I2C_SET_NACK()        st( I2CCFG &= ~I2C_AA; )
#define I2C_SET_ACK()         st( I2CCFG |=  I2C_AA; )

// Enable I2C bus
#define I2C_ENABLE()          st( I2CCFG |= (I2C_ENS1); )
#define I2C_DISABLE()         st( I2CCFG &= ~(I2C_ENS1); )

// Must clear SI before setting STA and then STA must be manually cleared.
#define I2C_STRT() st (             \
  I2CCFG &= ~I2C_SI;                \
  I2CCFG |= I2C_STA;                \
  while ((I2CCFG & I2C_SI) == 0);   \
  I2CCFG &= ~I2C_STA; \
)

// Must set STO before clearing SI.
#define I2C_STOP() st (             \
  I2CCFG |= I2C_STO;                \
  I2CCFG &= ~I2C_SI;                \
  while ((I2CCFG & I2C_STO) != 0);  \
)

// Stop clock-stretching and then read when it arrives.
#define I2C_READ(_X_) st (          \
  I2CCFG &= ~I2C_SI;                \
  while ((I2CCFG & I2C_SI) == 0);   \
  (_X_) = I2CDATA;                  \
)

// First write new data and then stop clock-stretching.
#define I2C_WRITE(_X_) st (         \
  I2CDATA = (_X_);                  \
  I2CCFG &= ~I2C_SI;                \
  while ((I2CCFG & I2C_SI) == 0);   \
)


/* ------------------------------------------------------------------------------------------------
 *                                       Local Variables
 * ------------------------------------------------------------------------------------------------
 */
static uint8 i2cAddr;  // Target Slave address pre-shifted up by one leaving RD/WRn LSB as zero.

/**************************************************************************************************
 * @fn          i2cMstStrt
 *
 * @brief       Attempt to send an I2C bus START and Slave Address as an I2C bus Master.
 *
 * input parameters
 *
 * @param       RD_WRn - The LSB of the Slave Address as Read/~Write.
 *
 * @return      The I2C status of the START request or of the Slave Address Ack.
 */
static uint8 i2cMstStrt(uint8 RD_WRn)
{
  I2C_STRT();

  if (I2CSTAT == mstStarted) /* A start condition has been transmitted */
  {
    I2C_WRITE(i2cAddr | RD_WRn);
  }

  return I2CSTAT;
}

/**************************************************************************************************
 * @fn          HalI2CInit
 *
 * @brief       Initialize the I2C bus as a Master.
 *
 * input parameters
 *
 * @param       address - I2C slave address.
 * @param       clockRate - I2C clock rate.
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 */
void HalI2CInit(uint8 address, i2cClock_t clockRate)
{
  i2cAddr = address << 1;

  I2C_WRAPPER_DISABLE();
  I2CADDR = 0; // no multi master support at this time
  I2C_CLOCK_RATE(clockRate);
  I2C_ENABLE();
}

/**************************************************************************************************
 * @fn          HalI2CRead
 *
 * @brief       Read from the I2C bus as a Master.
 *
 * input parameters
 *
 * @param       len - Number of bytes to read.
 * @param       pBuf - Pointer to the data buffer to put read bytes.
 *
 * output parameters
 *
 * None.
 *
 * @return      The number of bytes successfully read.
 */
uint8 HalI2CRead(uint8 len, uint8 *pBuf)
{
  uint8 cnt = 0;

  if (i2cMstStrt(I2C_MST_RD_BIT) != mstAddrAckR)
  {
    len = 0;
  }

  // All bytes are ACK'd except for the last one which is NACK'd. If only
  // 1 byte is being read, a single NACK will be sent. Thus, we only want
  // to enable ACK if more than 1 byte is going to be read.
  if (len > 1)
  {
    I2C_SET_ACK();
  }

  while (len > 0)
  {
    // slave devices require NACK to be sent after reading last byte
    if (len == 1)
    {
      I2C_SET_NACK();
    }

    // read a byte from the I2C interface
    I2C_READ(*pBuf++);
    cnt++;
    len--;

    if (I2CSTAT != mstDataAckR)
    {
      if (I2CSTAT != mstDataNackR)
      {
        // something went wrong, so don't count last byte
        cnt--;
      }
      break;
    }
  }
  I2C_STOP();

  return cnt;
}

/**************************************************************************************************
 * @fn          HalI2CWrite
 *
 * @brief       Write to the I2C bus as a Master.
 *
 * input parameters
 *
 * @param       len - Number of bytes to write.
 * @param       pBuf - Pointer to the data buffer to write.
 *
 * output parameters
 *
 * None.
 *
 * @return      The number of bytes successfully written.
 */
uint8 HalI2CWrite(uint8 len, uint8 *pBuf)
{
  if (i2cMstStrt(0) != mstAddrAckW)
  {
    len = 0;
  }

  for (uint8 cnt = 0; cnt < len; cnt++)
  {
    I2C_WRITE(*pBuf++);

    if (I2CSTAT != mstDataAckW)
    {
      if (I2CSTAT == mstDataNackW)
      {
        len = cnt + 1;
      }
      else
      {
        len = cnt;
      }
      break;
    }
  }

  I2C_STOP();

  return len;
}

/**************************************************************************************************
 * @fn          HalI2CDisable
 *
 * @brief       Places the I2C bus in inactive mode
 *
 * input parameters
 *
 * None.
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 */
void HalI2CDisable(void)
{
  I2C_DISABLE();
}

/*********************************************************************
*********************************************************************/

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top