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.

lm4f120xl - SPI problem

I have a problem with my LM4F120XL. I need to connect it with IMU sensor LSM9DS0 via SPI. 

 I think that problem is with Chip Select. 

Only several first reads are correct. Then I get 255. Quantity of correct reads depends of clock or bitRate (it varies from ~3 to 8) :

SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet() , SSI_FRF_MOTO_MODE_1, SSI_MODE_MASTER, 1000000, 8); ).

I have checked all SSI_FRF_MOTO_MODES - problem still exists.

I think the problem is with Chip Select lines


GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 0x00); //select device
When I am not toggling CS pin, but instead set it low permanently in initialization, I've got correct reads.


Thanks for help in advance!


void SPIInit() {
	SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
	                   SYSCTL_XTAL_8MHZ);
	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);

	SSIClockSourceSet(SSI0_BASE, SSI_CLOCK_SYSTEM);
	SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet()/1 , SSI_FRF_MOTO_MODE_1,
	SSI_MODE_MASTER, 1000000, 8);

	//cs pins
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
	GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_6 | GPIO_PIN_3);
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6 | GPIO_PIN_3, 0xFF);

	SSIEnable(SSI0_BASE);
	
       //get rid of old data in fifo
	unsigned long junk;
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 0x00);	//select device
	do {
		SSIDataPut(SSI0_BASE, 143);
	}
	while(SSIDataGetNonBlocking(SSI0_BASE, &junk));
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 0xff);	//deselect device
}

int SPI_x() {

	SysCtlDelay(1000);    
	unsigned long who_am_i_value;
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 0x00);    //start comunication
	SSIDataPut(SSI0_BASE, 143);
	SSIDataGet(SSI0_BASE, &who_am_i_value);
	SysCtlDelay(10000);    
	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 0xff);    //staph comunication
	return who_am_i_value;
}
  • Not to be rude but the Stellaris forum is in here:
    e2e.ti.com/.../stellaris_arm

    You are in the Tiva forum.

    Anyway, you have it now the CS connected to PD6. You did try to connect it to PA3 prior to using the GPIO method?

    Do you have a scope to monitor the signals?
  • Hello Bartosz,

    I think the issue is in the code here. To get rid of the data the whole code needs to be replaced from

    //get rid of old data in fifo
    unsigned long junk;
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 0x00); //select device
    do {
    SSIDataPut(SSI0_BASE, 143);
    }
    while(SSIDataGetNonBlocking(SSI0_BASE, &junk));
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 0xff); //deselect device

    to

    while(SSIDataGetNonBlocking(SSI0_BASE, &junk));

    The reason is because any old data needs to be flushed before any new data is to be read out. By doing the CS stuff, you are making the slave respond to the data.

    Regards
    Amit
  • Thanks for reply.

    I have connected CS to A3 pin, but problem had still existed.

    Currently I do not have any scope, but I am going to buy Logic Analyzer .


    I have have changed code as Amit suggested.
    My problem has changed. Now I am receaving value, that I send as an address. As example: I send address 143, and I receive 143 value.
    I tried doing "dummy send" ( according to LSM9DS0 datasheet [page 35], during SPI read, MOSI line isn't empty).
    SSIDataPut(SSI0_BASE, 143);
    SSIDataPut(SSI0_BASE, 142);
    SSIDataGet(SSI0_BASE, &who_am_i_value);

    Then I get
    143
    142
    143
    142, etc.

    What could be an issue?

    PS.
    My bad about wrong forum ;)
    If you dont mind, I will not change it. As far as I know Stellaris and Tiva are very similar for Cortex M4f.

  • Hello Bartosz,

    When working with Legacy mode one important thing is that for every SSIDataPut a SSIDataGet is required. The last code post does not show that. Perhaps having the corrected code for review shall be more helpful before the LA comes.

    Regards
    Amit
  • Ok, I have finally solve this.

    This was a hardware problem. I powered LM4F120XL and LSM9DS0  from independent power sources (both 3.3V). Howewer I did not connect their grounds together. And that was causing all these problems. 

    After connecting their grounds together everything works great.

    Also, in software, I have to do double put (and double get like Amit suggested).

    My code:

    void SPIInit() {
    	SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
    	                   SYSCTL_XTAL_8MHZ);
    	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);
    
    	SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet() , SSI_FRF_MOTO_MODE_3,
    	SSI_MODE_MASTER, 100000, 8);
    
    	//cs pin
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    	GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_6);
    	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6 , 0xFF);
    
    	SSIEnable(SSI0_BASE);
    
    	unsigned long junk;
    	while(SSIDataGetNonBlocking(SSI0_BASE, &junk));
    
    
    }
    
    int SPI_x() {
    
    	SysCtlDelay(1000);    
    	unsigned long who_am_i_value = 187;
    	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 0x00);    //start comunication
    	SysCtlDelay(10000);  
    	SSIDataPut(SSI0_BASE, 143);
    	SSIDataPut(SSI0_BASE, 143);                           //DOUBLE PUT
    	SSIDataGet(SSI0_BASE, &who_am_i_value);   //DOUBLE GET
    	SSIDataGet(SSI0_BASE, &who_am_i_value);
    	SysCtlDelay(10000);  
    	GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 0xff);    //stop comunication
    	return who_am_i_value;
    }

    Thanks for all help!