-1

So Im writing a bitbang SPI sample code for AVR (So I can understand using SPI better and appreciate the SPI hardware), and im a bit confused at some things.

From what I've read on SPI, you shift out the LSB first from master....but im not sure how to do that? I mean essentially I want to pop the LSB off and set the new 8 bit binary value to before but with the LSB popped off

(Im doing this in a loop, taking a unsigned char and then wanting to send out the LSB each loop).

This is what I have so far:

unsigned char transmit_byte(unsigned char data_byte) 
{
    int i;
    char ret_data;

    enable_SPI();       /* Set up correct Data Direction Ports */
    _delay_ms(100);
    ss_low();           /* Set SS Low */
    _delay_ms(100);

    /* SCLK Currently holding low, MOSI is low, SS is low */
    for (i = 0; i <= 7; i++) 
    {
        if (0x80 & SPI_PORT)
        {
            mosi_high();
        }
        else 
        {
            mosi_low();
        }
        /* MOSI Value is latched in */
        _delay_ms(10); // Probably unnecessary

        //something here?
    }
}

Would I just right shift it out?, I will then read the MISO line and check for 1 or 0 and set a new character variable, but that's after each iteration.

fussel
  • 151
  • 1
  • 1
  • 10
msmith1114
  • 2,717
  • 3
  • 33
  • 84
  • Where is your return statement? – Mike Nov 30 '18 at 06:52
  • 3
    Why do you read the port if this is the master code? The master is responsible for generating MOSI and clock both, at the same time - they must be on the same port so you write to them at the same time. Of course depending on clock phase - SPI allows data to be sent later in the phase, and also allows different clock polarity. – Lundin Nov 30 '18 at 10:26
  • Another thing you must realize is that SPI is full duplex. You receive at the same time as you send - it is really just a glorified shift register connected to one rx data register and one tx data register. So if you want to bit bang SPI, you must read MISO shortly (~100ns) after you set MOSI. – Lundin Nov 30 '18 at 10:27
  • `x >>= 1;` is how you "pop the LSB off and set the new 8 bit binary value to before but with the LSB popped off". All the remaining bits get shifted to the right by one spot, and the left-most spot becomes 0. – David Grayson Nov 30 '18 at 19:32
  • First, you have it backwards. SPI is traditionally MSB first, as opposed to an asynchronous UART which is traditionally LSB first. – Chris Stratton Nov 30 '18 at 22:50

1 Answers1

1

there are a number of ways to do this

unsigned char mask;
...
for (mask = 0x01, i = 0; i <= 7; i++, mask<<=1) 
{
   ...
   if(data_out&mask)
   {
       set mosi to 1
   }
   else
   {
       set mosi to 0
   }
}

or

unsigned char data_temp;
...
data_temp = data_out;
for(i = 0; i <= 7 ; i++)
{
   ...
   if(data_temp&1)
   {
      set mosi to 1
   }
   else
   {
      set mosi to 0
   }
}

are the two main styles.

walk the mask through the bits (you can do this in either direction lsb first or msb first), or walk the bits through a mask (works either direction.

You have the masking and shifting figured out for receiving but not sending?

old_timer
  • 69,149
  • 8
  • 89
  • 168