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.

CC2541 sample code

Other Parts Discussed in Thread: CC2541, CC2530, CC2543, CC2545, CC2544, CC1101, CC2540

Hello,

I was wondering if there is any sample code (like Blink LED sort of code) available for the CC2541? I remember having one for the CC2530 which was very helpful but using the CC2541 seems sort of more complicated. (I am a beginner)

Thanks!

  • Hi Michael! :)

    To make this LED think you have to study the registers:

    PxDIR: make the GPIO pin as output!

    PxOUT: make the GPIO pin output some voltage!

    Where do you have your LED connected? In which pin?

    Come on, it is easy! Check the file hal_led.c :)

    Bye!

  • Hi Michael,

    I guess simplest way would be to use HAL driver API if you are playing with development kit. There are functions like HalLedBlink() which can be used in sample projects to begin with.

    A copy of this document can be found in your PC when you install BLE stack in your computer.

    Regards,
    maharjanbk

  • Hello Michael,

    There will be published some very basic software examples for the CC2541, CC2543, CC2544 and CC2545 very soon.

    These are not related to BLE in any way, but just illustrate same basic usage of the on chip peripherals

    Keep an eye out on the CC2541 product page in the near future.

    BR. Eirik

  • Nice! Some UART processing examples would be nice :-)

  • I hope the same thing will be done for CC1101!

  • Thank You! That would be awesome, for now I will follow kazola and maharjanbk's suggestions, thank you all

  • Hello,

    The first version of the CC2541/43/44/45 Peripherals Software Examples are now available on the product pages.

    BR. Eirik

  • Thank's Eirik, I have a feeling this will be very useful

  • Hello,

    I think it could be very interesting to have an example where we could see Bluetooth Communications.

    Thanks in advance.

  • Juan, 

    The exampled referenced to in this thread will not include BLE/RF. Look at the Bluetooth low energy software stack and tools instead. 

    BR. Eirik

  • Hello Eirik,

    Yes I looked at this link, but I didn't find any code example about Bluetooth.

    Is it necessary to buy the development kit to have code examples of Bluetooth?

    B.R.,

    Juan

  • Hello Juan,

    Download BLE protocol stack and install it. Then you will find sample examples in the installed path. No need to buy DK for sample codes.

    Regards,
    maharjanbk

  • Why do the CC2541_43_44_45_Peripherals_Software_Examples not include the 2540 chip and where can i find similar examples for 2540?

    Thank you

  • Hi Rene,

    CC2540 only supports Bluetooth low energy, not proprietary software solutions.

    Best Regards

  • I was interested in the IO and SPI examples. Certainly you can write a firmware for 2540 that will just blink an LED or read an SPI accelerometer? The software examples for the 2541 that show SPI and IO seem very useful and arguably can be slightly modified to run on a 2540 but i was just wondering why they exclude that chip or why there are no such examples for that chip. Im not talking about RF related examples.

  • Hello,

    I'm NGUYEN Minh Tri, an firmware  engineer from Teleq Company, I used the sample code (I2C) to connect to IDT touchkey via I2C. I wrote a procedure WR(uint16 addr,uint16 data) with addr: address of  register of IDT touchkey, and data: data that I want to sent to IDT touchkey. My problem is if I used the only WR(0x0025,0x3210), it's successful, but if I used two instruction for example WR(0x0025,0x3210) ;WR(0x0025,0x3210); it only one instruction is successful. I'm trying to debug and i found that with the first instruction, the ISR of I2C is ignored and ISR is serviced for the last instruction. I don't know what's happen. Please, help me! Thank

    /***********************************************************************************
    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 0x2C // 7-bit addressing.

    #define READ_FROM_SLAVE 0x01
    #define WRITE_TO_SLAVE 0x00


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

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

    void halMcuWaitUs(uint16 usec)
    {
    usec>>= 1;
    while(usec--)
    {
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    }
    }
    void halMcuWaitMs(uint16 msec)
    {
    while(msec--)
    halMcuWaitUs(1000);
    }

    /***********************************************************************************
    * 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()
    {
    #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)||(len_data==0))
    {
    // 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;
    bufferIndex=0;
    count=count+1;
    //halMcuWaitUs(20);
    }

    // If Slave address or Data byte has been transmitted and acknowledged ...
    else if (I2CSTAT == 0x18 || I2CSTAT == 0x28)
    {
    // Send next I2C byte
    int a=buffer[bufferIndex];
    I2CDATA=buffer[bufferIndex];
    bufferIndex++;

    len_data--;
    }

    // I2CCFG.SI flag must be cleared by software at the end of the ISR.
    I2CCFG &= ~I2CCFG_SI;
    }
    void WR(uint16 addr, uint16 dat)
    {
    CLKCONCMD = (CLKCONCMD & ~(CLKCON_OSC | CLKCON_CLKSPD)) | CLKCON_CLKSPD_32M;
    // Wait until clock source has changed
    while (CLKCONSTA & CLKCON_OSC);
    // Configure I2C for location Alternative 1.
    PERCFG &= ~PERCFG_I2CCFG;

    // Give priority to I2C over Timer 1 for port 0 pins.
    PPRI &= ~PPRI_PRI1P0;

    len_data=4;
    buffer[0]=(addr>>8)&0xFF;
    buffer[1]=addr&0xFF;
    buffer[2]=(dat>>8)&0xFF;
    buffer[3]=dat&0xFF;
    //Start I2C signal
    // Clear I2C CPU interrupt flag.
    I2CIF = 0;

    // Enable interrupt from I2C by setting [IEN2.I2CIE = 1].
    IEN2 |= IEN2_I2CIE;
    I2CCFG = (I2CCFG & ~I2CCFG_CR) | I2CCFG_CR_DIV_960 | I2CCFG_ENS1 | I2CCFG_STA;

    }

    void WRR(uint16 addr, uint16 dat,uint16 addr0,uint16 dat0)
    {
    len_data=8;
    buffer[0]=(addr>>8)&0xFF;
    buffer[1]=addr&0xFF;
    buffer[2]=(dat>>8)&0xFF;
    buffer[3]=dat&0xFF;
    buffer[4]=(addr0>>8)&0xFF;
    buffer[5]=addr0&0xFF;
    buffer[6]=(dat0>>8)&0xFF;
    buffer[7]=dat0&0xFF;
    //Start I2C signal
    // Clear I2C CPU interrupt flag.
    I2CIF = 0;

    // Enable interrupt from I2C by setting [IEN2.I2CIE = 1].
    IEN2 |= IEN2_I2CIE;
    //I2CCFG |= I2CCFG_ENS1 | I2CCFG_STA;

    halMcuWaitUs(200);
    I2CCFG = (I2CCFG & ~I2CCFG_CR) | I2CCFG_CR_DIV_960| I2CCFG_ENS1 | I2CCFG_STA;
    //halMcuWaitUs(2);
    }


    /***********************************************************************************
    * @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;
    //I2CCFG = (I2CCFG & ~I2CCFG_CR) | I2CCFG_CR_DIV_244;

    /***************************************************************************
    * 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;
    //This initial code designed for LDS610A EVK
    //*******************************************
    /////LDS610A EVK-IDT Touch Initial code /////
    //*******************************************
    uint8 tg=0;
    //cold reset
    /*
    WR(0x0000,0x0000);
    halMcuWaitMs(tg);//1

    //touch disable
    WR(0x0040,0x0030);
    halMcuWaitMs(tg);//2

    //DCM config (disable)
    WR(0x000A,0x0000);
    halMcuWaitMs(tg);//3

    //Slider config:5channel
    WR(0x0074,0x801F);
    halMcuWaitMs(tg);//4

    //PSEL
    WR(0x0041,0x03FF);
    halMcuWaitMs(tg);//5
    WR(0x0042,0x0001);
    halMcuWaitMs(tg);//6

    //Interrupt
    WR(0x0043,0x03FF);
    halMcuWaitMs(tg);//7
    WR(0x0044,0x0001);
    halMcuWaitMs(tg);//8

    //Interrupt pin define
    WR(0x0008,0x0002);
    halMcuWaitMs(tg);//9

    //Led PSEL
    WR(0x003F,0x03E0);
    halMcuWaitMs(tg);//10
    WR(0x003E,0x0000);
    halMcuWaitMs(tg);//11

    //Led DWC
    WR(0x002F,0xC005);
    halMcuWaitMs(tg);//12

    //Led100 Dimming
    WR(0x0025,0xF80A);
    halMcuWaitMs(tg);//13
    WR(0x0035,0x0040);
    halMcuWaitMs(tg);//14

    //Led101 Dimming
    WR(0x0026,0xF809);
    halMcuWaitMs(tg);//15
    WR(0x0036,0x0040);
    halMcuWaitMs(tg);//16

    //led 102 Dimming
    WR(0x0027,0xF808);
    halMcuWaitMs(tg);//17
    WR(0x0037,0x0040);
    halMcuWaitMs(tg);//18

    //led 103 Dimming:Blink
    WR(0x0028,0xF807);
    halMcuWaitMs(tg);//19
    WR(0x0038,0x8040);
    halMcuWaitMs(tg);//20

    //led 104 Dimming:Heartbeat
    WR(0x0029,0xF806);
    halMcuWaitMs(tg);//21
    WR(0x0039,0x4040);
    halMcuWaitMs(tg);//22

    //Ambient Caliration
    WR(0x0051,0x0A1F);
    halMcuWaitMs(tg);//23

    //Recalibration configuration
    WR(0x0052,0x07FF);
    halMcuWaitMs(tg);//24

    //Long Touch
    WR(0x0053,0x07FF);
    halMcuWaitMs(tg);//25

    //SELC_Unit configuration
    WR(0x004E,0x5000);
    halMcuWaitMs(tg);//26

    //Noise immunity
    //WR(0x0077,0x8001);
    //halMcuWaitMs(tg);//27

    //C0~C4 threshold:60
    WR(0x005F,0x0001);
    halMcuWaitMs(tg);//28
    WR(0x0060,0x0022);
    halMcuWaitMs(tg);//29
    WR(0x0061,0x002C);
    halMcuWaitMs(tg);//30
    WR(0x0062,0x002C);
    halMcuWaitMs(tg);//31
    WR(0x0063,0x002C);
    halMcuWaitMs(tg);//32
    WR(0x0064,0x002A);
    halMcuWaitMs(tg);//33


    //Button threshold
    WR(0x0066,0x0043);
    halMcuWaitMs(tg);//34
    WR(0x0067,0x0057);
    halMcuWaitMs(tg);//35
    WR(0x0068,0x0054);
    halMcuWaitMs(tg);//36
    WR(0x0069,0x0051);
    halMcuWaitMs(tg);//37
    WR(0x006A,0x003B);
    halMcuWaitMs(tg);//38


    //C7 Ambient Threshold:5
    WR(0x005F,0x0001);
    halMcuWaitMs(tg);//39
    WR(0x0065,0x0090);
    halMcuWaitMs(tg);//40
    WR(0x005F,0x0002);
    halMcuWaitMs(tg);//41
    WR(0x0065,0x0090);
    halMcuWaitMs(tg);//42

    //Debounce & Hysteresis
    WR(0x0057,0x1000);
    halMcuWaitMs(tg);//43
    WR(0x0075,0x0002);
    halMcuWaitMs(tg);//44

    //Guard Channel Enable:C7
    WR(0x007C,0x0000);
    halMcuWaitMs(tg);//45
    WR(0x007D,0x0000);
    halMcuWaitMs(tg);//46

    //Guard Channel Mask
    WR(0x007E,0x0000);
    halMcuWaitMs(tg);//47
    WR(0x007F,0x0000);
    halMcuWaitMs(tg);//48

    //Touch enable
    WR(0x0040,0x8038);
    halMcuWaitMs(tg);//49

    //soft reset
    WR(0x0001,0x0000);
    halMcuWaitMs(tg);//50

    */
    //halMcuWaitMs(200);
    //WR(0x0025,0x3210);
    //halMcuWaitMs(2000);
    //IEN2 &= ~IEN2_I2CIE;
    //WR(0x0026,0x3210);
    //halMcuWaitMs(2000);
    //WR(0x0025,0x3210);
    WR(0x0025,0xF80A);
    //WRR(0x0025,0x3210,0x0026,0x3210);
    //Led100 ON
    //halMcuWaitUs(200);
    WR(0x0026,0xf80a);
    //WR(0x0026,0x3210);
    //IEN2 &= ~IEN2_I2CIE;
    //WR(0x0027,0x3210);
    //halMcuWaitMs(2000);//51
    //Led100 ON
    //WR(0x0026,0x3210);
    //WR(0x0027,0x3210);
    //WR(0x0028,0x3210);
    //WR(0x0029,0x3210);
    //halMcuWaitMs(tg);//52

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


    /***********************************************************************************
    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 “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.
    ***********************************************************************************/

  • I would suspect that you are getting an interrupt while the before the first WR has completed.

  • But I think if the first instruction has not completed, the second instruction can not be called because after instruction I disable Interrupt 

    if ((bufferIndex > BUFFER_SIZE)||(len_data==0))
    {
    // 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;
    bufferIndex=0;

    }

    and enable for new instruction.

    // Clear I2C CPU interrupt flag.
    I2CIF = 0;
    // Enable interrupt from I2C by setting [IEN2.I2CIE = 1].
    IEN2 |= IEN2_I2CIE;

  • At the end of you WR instruction you are enabling the interrupt.  This would overwrite the original data if another call was made immediately.  At least that is how I interpret the code.

    Thanks,

  • But my idea is:

    Assign data to buffer[ ]-> Enable Interrupt -> Send Start signal-> Call interrupt I2C (ISR)-> Send 4  data bytes -> Disable interrupt -> end instruction WR.

     

  • Put a delay between the two calls and see what happens.  Check the interrupt to see if it is being called before the first WR has been completed.

  • I debug step by step and find that after

    I2CCFG = (I2CCFG & ~I2CCFG_CR) | I2CCFG_CR_DIV_960 | I2CCFG_ENS1 | I2CCFG_STA;

    ISR is not enable immediately,  main program serves two instructions

    len_data=4;
    buffer[0]=0x00;

    and after that, ISR enable
    -> this's error

    But how I delay when ISR enable?? 

  • Remove the enabling of the ISR until the program has returned to main, or just before it is to return to main.  As long as it is enable after the last step is completed, then there is no possibility of it interrupting the I2C function.

  • Thank for your advice. I think it's good if I inserted two instructions

    while (I2CIF==0x00); //wait for I2C interrupt enable
    for(int j=0;j<10000;j++);//delay

    after the instruction:

    I2CCFG = (I2CCFG & ~I2CCFG_CR) | I2CCFG_CR_DIV_960 | I2CCFG_ENS1 | I2CCFG_STA;

  • Where can I find the register descriptions of CC2541? The datasheet does not have them!
  • Hello. Please see the chip User's Guide here:

    www.ti.com/.../swru191f.pdf
  • Many thanks Tim!