I was looking into ATmega32u4
datasheet to configure the SPI
, and there is initialization snippet for data transmission.
void SPI_MasterTransmit(char cData)
{
/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)));
}
What I didn't quite get is the last line of the snippet with the while condition to check the state of the SPIF
bit in SPSR
register.
What I think I understand that it means, if SPIF
bit with the a conditional value of 1 which would be in the ALU for comparing it with the actual bit state in SPSR
. If this is true with & bitwise operator which would be true if the actual bit in the SPSR
is set with the given value (1 << SPIF
).
My questions:
- Am I understanding it right?
- What this line actually means?
- I have removed the semicolon at the end of the line and it compiled OK! Is what I did OK?
1 Answer 1
SPI transmitt is started by writing one Byte into SPDR
. And this code won't return from SPI_MasterTransmit
function before it's complete. Transmitt completition is anounced by setting SPIF by hardware (and if SPI interrupt and global interrupts are enabled, it'll run also ISR and clear that flag).
If you write into SPDR
before transmission is completed you'll corrupt current "transaction", so you have to wait until it's complete before another write.
Bitwise & is used for bit masking. Bits in the result are set if bits at corresponding positions in arguments are both set:
0b00110011
&
0b00100001
==
0b00100001
So if bit at position SPIF is not set, it will loop again and when it's set, it exits the loop, as there is inverted logic.
( SPSR & (1<<SPIF)) !(SPRS &(1<<SPIF))
0b0xxxxxxx & 0b10000000 == 0b00000000 => !0b00000000 == true
0b1xxxxxxx & 0b10000000 == 0b10000000 => !0b10000000 == false
-
OK First, the SPIF would be set always whether SPIE is enabled or not. So, in this piece of code the while condition is at the end of the transmit function, would the while condition work the same whether the SPIE is set or not? If this it would work the same because it's connected with a bit mask of SPIF and SPSR. If the SPIE is enabled then the interrupt request would take another action other than while condition.R1S8K– R1S8K2016年09月22日 13:41:37 +00:00Commented Sep 22, 2016 at 13:41
-
@PerchEagle Well, if SPIE and global interrupts are enabled, it might result into infinite loop or not executing ISR. Depends how ISRs are done in hardware when you clear that flag before entering ISR (few clock cycles). So if you have interrupt driven transmission, you can write it into the buffer and ISR will send it..KIIV– KIIV2016年09月22日 13:54:24 +00:00Commented Sep 22, 2016 at 13:54
-
OK, so if I want an interrupt then I have to remove the while line of code and apply another code with enabling SPIE and ISR handling. Correct? So the technique here it that they don't require an interrupt for SPI TX completion so they only doing it by checking SPIF with requirement for ISR.R1S8K– R1S8K2016年09月22日 15:54:30 +00:00Commented Sep 22, 2016 at 15:54
-
If you want interrupt driven SPI, you'll need buffer, buffer size, ISR handler that will send next character from buffer and decrements size and maybe CS pin number to release it at the transaction end. The first character must be sent in transfer request (which adds rest of the data into buffer and sets correct size)KIIV– KIIV2016年09月22日 16:02:15 +00:00Commented Sep 22, 2016 at 16:02
-
OK I'm doing testing with IO pins all configured as outputs with one pull-up pin and drive the other two to high with testing different while & if code configurations: So, 1. while (condition); code >> drive o/p pins from low to high 2. while (condition){code} >> do the opposite drive them from high to low 3. if (condition) {code} >> drive high to low 4. if (!(condition)){code} >> drive low to high >>>> so the only two which works as I want are while (condition); code & if(!(condition)){code}, but I don't understand how they work?!R1S8K– R1S8K2016年09月23日 07:03:59 +00:00Commented Sep 23, 2016 at 7:03
while(!(SPSR & (1<<SPIF))){};
(with curly braces). In essence it just wait till the SPIF bit in the SPSR register is set. Removing the semicolon probably only worked because it was the last line of the function.