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.

cc1101 register read/write help needed tm4c123gh6pm

Other Parts Discussed in Thread: CC1101, EK-TM4C123GXL, TM4C123GH6PM

Hello E2E Community,

I am trying to read/write to the registers of the CC1101 radio. I have a EK-tm4c123gxl hooked up to a chinese cc1101 from aliexpress. I am able to issue strobe commands. When I issue SRX and SNOP the cc1101 returns 0x1f(RX state according to the chip status byte in the datasheet). Because of this i am assuming my device is working and i can correctly send strobe commands.

However, when I try to read/write any register or burst read any status register the return value always reads 0x0 or 0xF.

I have tried dummy value's(0x65), 0x0, SNOP in the write following the address write. I have searched online for similar problems. I have read "SPI Access DesignNote DN503 about CC11xx/CC25XX". At this moment I am out of idea's. Any help is appreciated.

I posted the output on pastebin: http://pastebin.com/yXucz0uj

My SSI0 init function:

void
initSSI0()
{
	SysCtlPeripheralPowerOn(SYSCTL_PERIPH_SSI0);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // cc1101 GDO0-GDO2
    GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7); // GDO0 GDO2
	SSIDisable(SSI0_BASE);
	SSIClockSourceSet(SSI0_BASE, SSI_CLOCK_SYSTEM); // SSI_CLOCK_PIOSC
	GPIOPinConfigure(GPIO_PA2_SSI0CLK);
	GPIOPinConfigure(GPIO_PA3_SSI0FSS);//	GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);
	GPIOPinConfigure(GPIO_PA4_SSI0RX);
	GPIOPinConfigure(GPIO_PA5_SSI0TX);
	SSIConfigSetExpClk(SSI0_BASE,SysCtlClockGet(),SSI_FRF_MOTO_MODE_0,SSI_MODE_MASTER,32000,8); //1000000
	GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);
	SSIEnable(SSI0_BASE);
}

My main function:

int
main(void)
{
	initSystem();
	initGPIO();
	initUSART();
	initSSI0();

    IntMasterEnable();

    UARTprintf("\r\x1B[2JLog Output: \r\n");// carriage return(\r), Clear entire screen (\x1B[2J), put hex char esc (\x1B) escape code clear screen ([2J)

	reset();
	UARTprintf("SRX, 4x snop\r\n");
	readReg(CC1101_SRX);
	readReg(CC1101_SNOP);
	readReg(CC1101_SNOP);
	readReg(CC1101_SNOP);
	readReg(CC1101_SNOP);
	UARTprintf("4x snop\r\n");

    uint8_t i;
	UARTprintf("burst read all status regs\r\n");
    for(i = 0;i <= 14; ++i){
    	burst(0x30|i);
    }

	UARTprintf("write conf regs\r\n");
    for(i = 0; i <= 23; ++i){
    	writeReg(address[i],settings[i]);
    }

	UARTprintf("read all conf regs\r\n"); //0x00-0x2e
	for(i = 0; i <= CC1101_CONF; ++i){
		readReg(address[i]);
	}

	readReg(CC1101_SNOP);
	readReg(CC1101_SNOP);
	readReg(CC1101_SNOP);
	readReg(CC1101_SNOP);

//	UARTprintf("read to all strobes\r\n");
//	for(i = 0; i <= 0x0E; ++i){
//		readReg(0x30|i);
//	}

	while(1)
    {
    }
}

My single byte read function:

void
readReg(uint8_t raddr)
{
    uint8_t header_read = (CC1101_READ | raddr);    //Set up header for reading

    //Pull the CSn low
    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0x00);

    //Wait until the MISO pin goes low
    while (GPIOPinRead(GPIO_PORTA_BASE, GPIO_PIN_4));

    //When not busy, write header for reading data from MISO Pin
    UARTprintf("write address for readback: 0x%x\r\n",header_read);
    while(SSIBusy(SSI0_BASE)){}                             //Wait for SSI to not be busy
    SSIDataPut(SSI0_BASE, header_read);            //write header for reading data
    SSIDataGet(SSI0_BASE, &dummy);					//read status byte
    UARTprintf("Status 0x%x ", dummy & 0x00FF);

    //Wait until the MISO pin goes low
    while (GPIOPinRead(GPIO_PORTA_BASE, GPIO_PIN_4));

    //When not busy, read data from MISO pin
    while(SSIBusy(SSI0_BASE)){}                             //wait for SSI to be ready
    SSIDataPut(SSI0_BASE, 0);                          //Write dummy value
    SSIDataGet(SSI0_BASE, &dummy);					//read dummy value
    UARTprintf(" \t\treadback value 0x%x\r\n", dummy & 0x00FF);

    //Pull CSN high
    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0x1);
}

My single byte write function:

void 
writeReg(unsigned char addr,unsigned char value){
    uint8_t header_adr = (CC1101_WRITE | addr);    //Set up header for writing
    //Pull the CSn low
    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0x00);

    //Wait until the MISO pin goes low
    while (GPIOPinRead(GPIO_PORTA_BASE, GPIO_PIN_4));
    //When not busy, write header for writing data
    UARTprintf("write addr: 0x%x, header: 0x%x\r\n",addr,header_adr);
    while(SSIBusy(SSI0_BASE)){}                             //Wait for SSI to not be busy
    SSIDataPut(SSI0_BASE, header_adr);            //write header for reading data
    SSIDataGet(SSI0_BASE, &dummy);					//read dummy value
    UARTprintf("readback status 0x%x\r\n", dummy & 0x00FF);

    //Wait until the MISO pin goes low
    while (GPIOPinRead(GPIO_PORTA_BASE, GPIO_PIN_4));

    //When not busy, write value
    UARTprintf("write val: 0x%x\r\n",value);
	while(SSIBusy(SSI0_BASE)){}                             //Wait for SSI to not be busy
	SSIDataPut(SSI0_BASE, value);            //write header for reading data
	SSIDataGet(SSI0_BASE, &dummy);					//read dummy value
    UARTprintf("readback 2nd status 0x%x\r\n", dummy & 0x00FF);

    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0x01);

}

My burst read function:

void
burst(uint8_t raddr) //burst reads for status registers
{
    uint8_t header_burst = (CC1101_BURST| raddr);    //Set up header for reading

    //Pull the CSn low
    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0x00);

    //Wait until the MISO pin goes low
    while (GPIOPinRead(GPIO_PORTA_BASE, GPIO_PIN_4));

    //When not busy, write header for reading data from MISO Pin
    UARTprintf("write burstaddr: 0x%x\r\n",header_burst);
    while(SSIBusy(SSI0_BASE)){}                             //Wait for SSI to not be busy
    SSIDataPut(SSI0_BASE, header_burst);            //write header for reading data
    SSIDataGet(SSI0_BASE, &dummy);					//read dummy value
    UARTprintf("readback status 0x%x", dummy & 0x00FF);

    //When not busy, read data from MISO pin
    while(SSIBusy(SSI0_BASE)){}                             //wait for SSI to be ready
    SSIDataPut(SSI0_BASE, 0);                          //Write dummy value
    SSIDataGet(SSI0_BASE, &dummy);					//read dummy value
    UARTprintf(" readback 2nd status 0x%x\r\n", dummy & 0x00FF);

    //Pull CSN high
    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0x1);
}

My reset function:

void reset(void){
//Old
//	  Pull the CSn low
//    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0x01);
//    SysCtlDelay(SysCtlClockGet()*5 / (1000000)); //5us
//    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0x00);
//    SysCtlDelay(SysCtlClockGet()*10 / (1000000)); //10us
//    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0x01);
//    SysCtlDelay(SysCtlClockGet()*41 / (1000000)); //41us
//
//    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0x00);
//    //Wait until the MISO pin goes low
//    while (GPIOPinRead(GPIO_PORTA_BASE, GPIO_PIN_4));
//    //When not busy, read data from MISO pin
//    while(SSIBusy(SSI0_BASE)){}                             //wait for SSI to be ready
//    SSIDataPut(SSI0_BASE, CC1101_SRES);                          //Write dummy value
//    SSIDataGet(SSI0_BASE, &dummy);					//read dummy value
//    UARTprintf("reset readback status 0x%x\r\n", dummy & 0x00FF);
//
//    GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0x00);

	GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_2,0x1); //SCLK 1
	GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_5,0x0);//MOSI 0

	GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0x00);//CSn 0
	SysCtlDelay(SysCtlClockGet()*5 / (1000000)); //5us
	GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0x01);//CSn 1
	SysCtlDelay(SysCtlClockGet()*41 / (1000000)); //41us
	GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0x00);//CSn 0

	//Wait until the MISO pin goes low
	while (GPIOPinRead(GPIO_PORTA_BASE, GPIO_PIN_4)){}
	SSIDataPut(SSI0_BASE, CC1101_SRES); //SRES strobe

	//Wait until the MISO pin goes low
	while (GPIOPinRead(GPIO_PORTA_BASE, GPIO_PIN_4)){}
	UARTprintf("reset done\r\n");
	GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0x01);//CSn 1
}
  • Hello Frank

    Moving it to the CC1101 forum.
  • frank schrijver,

    Do you have an O-scope or a digital logic analyzer? We need to confirm that your SPI format is correct as per the CC1101 datasheet.

    Common errors are:

    • SPI speed too high (8MHz max)
    • Data on the wrong edge of the CLK signal
    • Timing is too aggressive ( when using fast ARM processors you can overrun the CC1101)

    My debug steps are typically.

    • First try to write the registers and see if you get a status byte back, it seems you have done this.
    • Then try to write to all registers and then read them back and compare. This needs to work before we can continue.
    • Then write to TX FIFO, and confirm that bytes arrive in FIFO by checking the FIFO status byte.
    • Then execute STX stobe and confirm using the MARCSTATE that the transceiver goes back to IDLE after the packet has been sent and that there is not error (like FIFO underflow, etc, etc)
    • Then I recommend making sure that the packet is being sent on the right frequency by using a spectrum analyzer.

    Regards,
    /TA

  • Thank you for your response,

    Yes the status byte that gets returned is correct as far as I know.
    I am using "Driverlib/ssi.h" for interfacing with SPI.
    Unfortunately I don't have a Oscilloscope or a digital logic analyzer.
    In the function call SSIConfigSetExpClk I set the bitrate to 32000, but I read that 1mhz is what the cc1101 is capable of. This is what you meant with "SPI speed too high", right?
    I am not handling the clock generation or the actual transmission through SSI/SPI, I left that up to Driverlib.
    Do you know of a way I could change rising/falling edge trigger for the data transmission?
    I am using a TM4C123GH6PM at 80MHz should I add some delay between the first and second transmission, and how long do you recommend the delay should last?

    Regards,

    Frank.
  • Hello all,

    I was reading about different ways of interfacing ssi with the cc1101 on the e2e forum when I came across this page.

    https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/217117

    "DeKay" mentions in the 6th post:

    "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."

    Increasing the datawidth in SSIConfigSetExpClk and adjusting the headers solved all my problems, I am now able to read and write.

    Thanks everyone, Especially "DeKay"

  • What are you doing when sending strobe commands that are only 8 bits wide?
  • i send the strobe and a SNOP strobe
  • OK. Just be aware if you are sending strobe commands that are not executed immediately but first when CSn is pulled high again, for example SPWD. It might be that in this case you need to send the SNOP first and then SPWD.

    Siri