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.

Interfacing LM4F232 with CC1101

Other Parts Discussed in Thread: CC1101, SIMPLICITI, EK-EVALBOT, CC1121

Hi

I am trying to interface CC1101 RF chip with LM4F232 controllers. I am using SSI 0 SPI channel of LM4F232 to configure RF chip.

 Pin connection of CC1101_DK_Em433 (eval board) to

         SCLK -> SSIOCLK

         S1->SSIOTX

         S0-> SIORX

         CSN1->SSI0FSS

         Configured SPI channel to communicate at 10khz.

 My queries are

1) Which SPI format should I use to communicate with CC1101.

         SSI_FRF_MOTO_MODE_0

         SSI_FRF_MOTO_MODE_1

         SSI_FRF_MOTO_MODE_2

        SSI_FRF_MOTO_MODE_3

        SSI_FRF_TI        

        SSI_FRF_NMW       

2) When I try to write and read back CC1101 registers I always get back 0x0F (on any register read). Can you please look in to my code and help me to find out missing steps

void InitializeRfSpiChannel(void)
{
   UINT32 dummy;

   // The SSI0 peripheral must be enabled for use.
   MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
   MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

   //Give some delay to allow the peripheral to start up
   MAP_SysCtlDelay(2);

   // Configure the pin muxing for SSI0 functions on port A2, A3, A4, and A5.
   // This step is not necessary if your part does not support pin muxing.
   // TODO: change this to select the port/pin you are using.
   MAP_GPIOPinConfigure(GPIO_PA2_SSI0CLK);
   MAP_GPIOPinConfigure(GPIO_PA3_SSI0FSS);
   MAP_GPIOPinConfigure(GPIO_PA4_SSI0RX);
   MAP_GPIOPinConfigure(GPIO_PA5_SSI0TX);

   //Give some delay to allow the peripheral to start up
   MAP_SysCtlDelay(2);
   //
   // Configure the GPIO settings for the SSI pins.
   MAP_GPIOPinTypeSSI(GPIO_PORTA_BASE,
                      GPIO_PIN_2 | GPIO_PIN_3 |
                      GPIO_PIN_4 | GPIO_PIN_5);

   //set clock source
   MAP_SSIClockSourceSet(SSI0_BASE, SSI_CLOCK_SYSTEM);


   MAP_SSIConfigSetExpClk(SSI0_BASE, SystemClockFreq, SSI_FRF_MOTO_MODE_0,
                          SSI_MODE_MASTER, 10000, 8);

   //disable SPI interrupts we are not going to use interrupts
   MAP_SSIIntDisable(SSI0_BASE, SSI_TXFF | SSI_RXFF | SSI_RXOR | SSI_RXTO);

   //disable DMA
   MAP_SSIDMADisable(SSI0_BASE, SSI_DMA_RX | SSI_DMA_TX);

   // Enable the SSI0 module.
   SSIEnable(SSI0_BASE);

   while(SSIDataGetNonBlocking(SSI0_BASE, &dummy))
   {
   }
}

void WriteDataToRfSpiChannel(UINT8 address, UINT8 data)
{
   UINT32 tempData;

   // write address
   MAP_SSIDataPut(SSI0_BASE, (UINT32)((UINT32)address & (UINT32)0x000000FF));

   // Wait until SSI0 is done transferring all the data in the transmit FIFO.
   while(MAP_SSIBusy(SSI0_BASE))
   {
   }

   // read to clear
   MAP_SSIDataGet(SSI0_BASE, &tempData);

   // write data
   MAP_SSIDataPut(SSI0_BASE, (UINT32)((UINT32)data & (UINT32)0x000000FF));

   // Wait until SSI0 is done transferring all the data in the transmit FIFO.
   while(MAP_SSIBusy(SSI0_BASE))
   {
   }

   // read to clear
   MAP_SSIDataGet(SSI0_BASE, &tempData);

}

UINT8 ReadDataFromRfSpiChannel(UINT8 address)
{
   UINT32 tempData;

   address = (address & 0x3F)|0x80;

   // write address
   MAP_SSIDataPut(SSI0_BASE, (UINT32)((UINT32)address & (UINT32)0x000000FF));

   // Wait until SSI0 is done transferring all the data in the transmit FIFO.
   while(MAP_SSIBusy(SSI0_BASE))
   {
   }

   // read to clear
   MAP_SSIDataGet(SSI0_BASE, &tempData);

   // write dummy char char to get data from slave
   MAP_SSIDataPut(SSI0_BASE, (UINT32)((UINT32)0x00000000 & (UINT32)0x000000FF));

   // Wait until SSI0 is done transferring all the data in the transmit FIFO.
   while(MAP_SSIBusy(SSI0_BASE))
   {
   }

   // now read actual data from received from  slave
   MAP_SSIDataGet(SSI0_BASE, &tempData);


   return (tempData & 0x000000FF);
}

 

 

  • Hi,

    The CC1101 is supported in StellarisWare with a BSP (board support package) and example applications for the SimpliciTI stack on the EK-EVALBOT board.  Even if you do not plan to use the SimpliciTI stack, the BSP source code will be a useful reference.

    Search for the file mrfi_board_defs.h in the full StellarisWare tree.  You'll find macros that configure the various GPIO signals to the CC1101 and the SSI peripheral configuration.  There are also macros for writing and reading from the CC1101.

    For example here's the configuration call for the SSI/SPI module:

    MAP_SSIConfigSetExpClk(SSI1_BASE, MAP_SysCtlClockGet(),  SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, SPI_RATE, 8); 

    You appear to be using FSS as a SSI-controlled framing signal.  Since the driver controls the chip select as GPIO, my suggestion is that you change that part of your code using the SimpliciTI BSP macros as a reference.

  • Hi Thanks for your quick response.

    After modifying read and write functions a bit and directly grounding chip select pin of CC1101, I am able to read and write CC1101 registers. However I am yet to try connecting back FSS signal as chip select pin.

     

    In our target board we are using FSS signal as chip select pin. SSI0FSS single is driven by SSI module on read and write operation, Is there any way, we can forcefully set/toggle state of SSI0FSS pin and continue using SSI0 module as SPI master? (on LM4F232 micro)

  • Dhanyakumar H C said:
    Is there any way, we can forcefully set/toggle state of SSI0FSS pin and continue using SSI0 module as SPI master?

    Yes.  Just configure the SSI0FSS pin to it's GPIO output function. 

    I'm a bit surprised that reads and writes are successful with the chip select tied low, but am pleased to hear that it's working.

  • Hi, I'm working on interfacing between an LM4F120H5QR and the CC1121 and am having significant difficulties trying to even get a clock signal. I'm guessing I'm configuring things wrong, but I haven't been able to find any good examples on how to do it right. Are there any? If there are no examples could you show me a sample SPI config using SSI1 (an alternate function for those particular pins) on the ARM? Thanks a bunch.

  • I just got this working today on a CC1101 sitting on a RF1100SE breakout board connected to Stellaris LM4F120 Launchpad.  The trick is to use 16 bit reads and writes.  This gives you 16 clock pulses and the CS line held low for the appropriate time.  The SPI comms are full duplex, so your command should be shifted left 8 bits and the data received should have the highest 8 bits masked off.

    I had some code in here to talk to a BMP085 that I yanked out.  Hopefully I didn't pull too much out.  But this code will tell you all you need to know.  Like I said, I just got this working and so it is super hacky right now, being able to only ask for the chip version and getting the right value back.

    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_ssi.h"
    #include "inc/hw_ints.h"
    #include "driverlib/i2c.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/gpio.h"
    #include "driverlib/systick.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/ssi.h"
    #include "utils/ustdlib.h"
    #include "utils/uartstdio.h"
    void main(void)
    {
        unsigned long ulDataTx;
        unsigned long ulDataRx;
        //
        // Enable lazy stacking for interrupt handlers.  This allows floating-point
        // instructions to be used within interrupt handlers, but at the expense of
        // extra stack usage.
        //
        ROM_FPULazyStackingEnable();
        ROM_SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
        ROM_IntMasterEnable();
        //
        // Initialize the UART.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
        ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
        ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        UARTStdioInit(0);
        //
        // Now set up the SPI port to talk to the CC1101
        //
       SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
       SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
       GPIOPinConfigure(GPIO_PA2_SSI0CLK);
       GPIOPinConfigure(GPIO_PA3_SSI0FSS);
       GPIOPinConfigure(GPIO_PA4_SSI0RX);
       GPIOPinConfigure(GPIO_PA5_SSI0TX);
       GPIOPinTypeSSI(GPIO_PORTA_BASE,GPIO_PIN_5|GPIO_PIN_4|GPIO_PIN_3|GPIO_PIN_2);
       //
       // Radio SPI Specs
       // Max SPI Clock : 10 MHz
       // Data Order : MSB transmitted first
       // Clock Polarity: low when idle
       // Clock Phase : sample on leading edge
       //
       //
       // We read and write 8 bits to the CC1101 but we need the Stellaris to drive the clock.  SSI_FRF_MOTO_MODE_0
       // is full duplex, so we play a trick and say we are using 16 bits.  When we do a write, all 16 bits are written.
       // When we do a read, we take the command byte and shift left 8 bits, writing 0's as the last eight bits.
       // Since this mode is full duplex, we'll get 16 bits back but mask off the top 8, leaving only the read data we are
       // interested in.
       SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 16);
       SSIEnable(SSI0_BASE);
        //
        // Read any residual data from the SSI port.  This makes sure the receive
        // FIFOs are empty, so we don't read any unwanted junk.  This is done here
        // because the SPI SSI mode is full-duplex, which allows you to send and
        // receive at the same time.  The SSIDataGetNonBlocking function returns
        // "true" when data was returned, and "false" when no data was returned.
        // The "non-blocking" function checks if there is any data in the receive
        // FIFO and does not "hang" if there isn't.
        //
        while(SSIDataGetNonBlocking(SSI0_BASE, &ulDataRx))
        {
        }
        //
        // Initialize the data to send.
        // Ask for the CC1101 version number: register 0x31 OR'ed with 0xc0 (status register)
        // and shifted left 8 bits.
        ulDataTx = 0xf100;
        while(1)
        {
    //
    // Send the data using the "blocking" put function.  This function
    // will wait until there is room in the send FIFO before returning.
    // This allows you to assure that all the data you send makes it into
    // the send FIFO.
    //
    SSIDataPut(SSI0_BASE, ulDataTx);
    UARTprintf("Sent: %x\n", ulDataTx);
    //
    // Wait until SSI0 is done transferring all the data in the transmit FIFO.
    //
    while(SSIBusy(SSI0_BASE))
    {
    }
    //
    // Receive the data using the "blocking" Get function. This function
    // will wait until there is data in the receive FIFO before returning.
    //
    SSIDataGet(SSI0_BASE, &ulDataRx);
    //
    // Since we are using 8-bit data, mask off the MSB that was read full
    // duplex while we were sending our command byte.
    // 
    ulDataRx &= 0x00FF;
    //
    // Display the data that SSI0 received.
    // The datasheet says this value should be 4.
    //
    UARTprintf("Received: %x\n", ulDataRx);
        }
    }