1

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:

  1. Am I understanding it right?
  2. What this line actually means?
  3. I have removed the semicolon at the end of the line and it compiled OK! Is what I did OK?
  • I prefer to write it like 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. – Gerben Sep 21 '16 at 18:44
  • 1
    It won't compile for me if I omit the last semicolon: “error: expected ‘;’ before ‘}’ token”. – Edgar Bonet Sep 21 '16 at 20:25
  • I tried this one with the curly braces, and it didn't work actually. The one with only semicolon surprisingly work. Which is a new technique for me. I know also you can perform if condition with no curly braces and it would activate only the next line of code. So this while technique with or without curly braces is new to me. So yeah thanks :) – R1S8K Sep 22 '16 at 13:47
  • After some testing with a code with IO pins. I discovered that there is another command which would do the same as while (condition); which is if (condition){ } and if (condition) without curly braces. So the while with the semicolon and the if with the curly braces! OK sounds good to me now :) Thanks all for help. – R1S8K Sep 22 '16 at 15:58
3

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
|improve this answer|||||
  • 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 Sep 22 '16 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 Sep 22 '16 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 Sep 22 '16 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 Sep 22 '16 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 Sep 23 '16 at 7:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.