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.
Hello TI community! I am working on a project that requires SPI communication with several modules, after my initial code broke I split it up and am now working on one section at a time. I'm trying to talk with a module from Adafruit (the CAP1188) which is a capacitive multi-touch sensor. When I try to send a byte, I get stuck in an infinite loop after writing to the buffer. My spi_xfer() function looks like this:
char spi_xfer(char data){
UCB0TXBUF = data;
while(!(IFG2 & UCB0TXIFG)){}
return UCB0RXBUF;
}
I'm getting stuck in that while loop. My SPI initialization looks like this:
void initializeSPI(){
P1SEL |= BIT5 + BIT6 + BIT7;
P1SEL2 |= BIT5 + BIT6 + BIT7;
UCB0CTL1 = UCSWRST;
UCB0CLT0 |= + UCSMB + UCMST + UCMODE_2 + UCSYNC;
UCB0CTL1 |= UCSSEL_2;
UCB0BR0 |= 0x02;
UCB0BR1 &= 0x00;
UCB0CTL1 &= ~(UCSWRST);
}
The Adafruit module latches on the rising edge and has and idle high clock and data line.
Previously, I had not set the UCCPKL bit, and was able to transmit data but I got garbage back on the MISO line. That is when I went back and looked at the CAP1188 data sheet and saw that I had set the SPI polarity wrong. But now I can't get it to send either. I'm hoping someone on here might be able to point me in the right direction. Thanks in advance!
Hi David!
This one here does not work:
while( !(IFG2 & UCB0TXIFG) ){} return UCB0RXBUF;
The reason is the following: The TXIFG is not set when the byte is completely transmitted out of the TX buffer - it is set when the byte was moved from the TX buffer to the transmit shift register and the buffer is empty again to fetch the next byte. But in the background, the other byte is currently transmitted bit by bit. That means, returning the RX buffer after the TX IFG is set does not work because since the byte is not transmitted completely yet, you also do not have received a complete byte. You will have to wait for the transmission to be finished.
To do so, you can a) check the RX IFG
IFG2 &= ~UCB0RXIFG; // Clear a pending flag UCB0TXBUF = data; // Copy your byte while( !(IFG2 & UCB0RXIFG) ){} // Wait for the receive interrupt flag return UCB0RXBUF; // Return the received data
or you can b) check the BUSY bit of the USCI module
UCB0TXBUF = data; // Copy your byte while( UCB0STAT & UCBUSY ){} // Wait for completion return UCB0RXBUF; // Return the received data
Doesn't the compiler complain about the following line?
UCB0CLT0 |= + UCSMB + UCMST + UCMODE_2 + UCSYNC;
Or is it just a residue from your tests with the clock phase/polarity? Are you using the 4-wire SPI to control the slave? You can also use UCMODE_0 for 3-wire SPI and use one of the microcontroller's output pins to control the slave. I alsways prefer this method.
Those two lines work...
UCB0BR0 |= 0x02; UCB0BR1 &= 0x00;
..but you better set their values using "=" because when BR0 would have anything set already, you would not get your expected 2 as divider. You would simply add this bit to the existing ones. So better use
UCB0BR0 = 2; UCB0BR1 = 0;
Dennis
Dennis, thanks for the quick response! I'll answer your questions in order.
1. I did not know that about the TXIFG, I assumed it set whenever the byte had been sent. I tied changing to both the UCBUSY wait loop and using the UCB0TXIFG in combination with UCB0RXIFG wait loops. The problem I encountered was first that the UCBUSY bit never set, which tells me that it was never actively transmitting what I had just sent it. And the second time the UCB0RXIFG bit never sent, which also tells me the device never sent anything. (edit) My first thought was that the adafruit module might not be powered. But from what I understand about SPI, the master doesn't care if nothing is listening, it will still send the data into the nothingness. So it should still send the data.
2. Yes, the compiler did complain, that was just me forgetting to remove the '+' as well as the variable.
3. I am wary of 3-wire because I am completely new to SPI and just started getting a grasp of 4-wire. Unless there is a major performance advantage, I would prefer to stay with what I am familiar with.
4. I went ahead and changed this per your suggestion for good measure.
David Sargent said:But from what I understand about SPI, the master doesn't care if nothing is listening, it will still send the data into the nothingness.
Exactly! There is no ACK as a response from the slave like you would get with I²C. And this is the same for receiving anything - the master clocks out 8 bits of data, regardless if it is 0x00, 0x01, 0xFF or whatever. At the same time it receives 8 bits of data and the master does not know if there is a slave connected. There will always be received data, but if no slave is connected (or does not drive the data line), the received data can be anything. 8 times 0, or 8 times 1 or anything in between if the line is floating. And in between does not mean 0.5 it is a wild mixture of 0s and 1s, of course.
**Attention** This is a public forum