A3BU SPI Issue

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi!

 

I'm trying to establish a connection between a Raspberry Pi 2 and an A3BU Xplained Board via SPI. SPI-master is Raspberry, slave is A3BU. I use wiringPi for the Raspberry.

This is the Code I'm currently running at my A3BU:

int main(void)
{
    board_init();
    //sysclk_init();	// if I uncomment this, SPI is not working at all !! do I need this function ?!

    // SPI -> initialization
    PORTC.DIR = 0x40;          // MISO output; MOSI, SCK, SS inputs
    SPIC.CTRL = 0x40;
    // SPI -> received Byte
    uint8_t rx_byte;
    // SPI -> transceived byte
    uint8_t tx_byte;

    /* Flush slave receive buffer */
    while(SPIC.STATUS & 0x80)
    {
        rx_byte = SPIC.DATA;   // flush spi receive buffer
    }

    while(1)
    {
        // SPI -> wait till data arrived
        while((SPIC.STATUS & 0x80) == 0);
        // SPI -> read byte
        rx_byte = SPIC.DATA;

        // read Data from ADC
        // ...
        // Code
        // ...

        // SPI -> set transceive-byte (for debugging)
        tx_byte = rx_byte;

        // SPI -> send Byte
        SPIC.DATA = tx_byte;
        // wait, till transfer is done
        while(SPIC.STATUS & SPI_IF_bm);
        // SPI -> reset status
        SPIC.STATUS = 0x00;
    }
}

 

I'm able to send and receive data but I'm observing the following:

After starting the A3BU and starting a new "SPI-talk", every time the first received Byte is 0x00.

After that every Byte is shifted by 4 bit.

Update: After that every Byte is "delayed" by one byte (till next transmission).

 

Remark:

The Code which is excluded at the moment, reads data from the ADC and returns a 2 Byte-value, which is splitted up for transmission into two single bytes.

For example the Raspberry sends 0x00 and 0x00 and after that 0x01 and 0x01, which is at the A3BU interpreted as "read ADC-0-value" (+ second byte for transceived value) and "read ADC-1-value" (+ second byte for transceived value).

Currently I've connected 5 different sensors at the ADC and trying to read them one by one, repeated as long as I need the values.

 

 

So If I send the bytes 0x01, 0x02 and 0x03 to the A3BU I receive 0x00, 0x10, 0x20.

If I then for example send the bytes 0x05, 0x06 and 0x07 I receive 0x30, 0x50 and 0x60 so as you can see the last byte seems to remain in the A3BU buffer...

Update:

  So if I send the bytes 0x01, 0x02 and 0x03 to the A3BU I receive 0x00, 0x01, 0x02.

  If I then for example send the bytes 0x05, 0x06 and 0x07 I receive 0x03, 0x05, 0x06 so as you can see the last byte seems to remain in the A3BU buffer...

If I would restart my A3BU then, the first byte would be 0x00 again.

 

At the moment I'm "cleaning" the data via my Raspberry-Application as I switch both bytes. Actually this is incorrect, as one of the half-bytes belongs to a different byte which was read by a different ADC-source...

 

Is there any error in my code or did I forget some initialization?

Does anybody know a solution for my problem? I'm grateful for any help!

 

Best regards,

Limnfo

Last Edited: Fri. Sep 29, 2017 - 02:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
    board_init();
    //sysclk_init();	// if I uncomment this, SPI is not working at all !! do I need this function ?!

You need to decide whether or not you are going to use ASF.  board_init() and sysclk_init() are ASF calls.  The reason the SPI fails to work at all after calling sysclk_init() is because it turns off the peripheral clock to all peripherals.  ASF calls to enable the various peripherals turn the clock on for that peripheral.

SPIC.STATUS = 0x00;

This is not how you clear flags in the status register.  Writing a 1 to a particular flag clears that bit.

 

Greg Muth

Portland, OR, US

Xplained Boards mostly

Atmel Studio 7.0 on Windows 10

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh, thanks for the comment!

 

So... Is it right that every predefined function belongs to ASF? Do I need any ASF-calls at all, if not I can remove board_init(), right?

 

For clearing the status register, would then

SPIC.STATUS = 1;

be correct?

 

But besides this, do you know why I'm observing this strange error? For me - as an inexperienced person - it looks like that the A3BU is too slow at the beginning of the SPI connection because it sends 0x00 every first time... Or maybe I've missed some flags which I have to set for a successful SPI-connection...?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is it right that every predefined function belongs to ASF? Do I need any ASF-calls at all, if not I can remove board_init(), right?

No. No, Yes.

 

For clearing the status register, would then

SPIC.STATUS = 1;

be correct?

No.

SPIC.STATUS = SPI_IF_bm;        // clear IF
SPIC.STATUS = SPI_WRCOL_bm;     // clear WRCOL

 

 Is the ADC result left or right justified?  

Greg Muth

Portland, OR, US

Xplained Boards mostly

Atmel Studio 7.0 on Windows 10

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greg_Muth wrote:

Is it right that every predefined function belongs to ASF? Do I need any ASF-calls at all, if not I can remove board_init(), right?

No. No, Yes.

 

Perfect, thank you! Do I have to set the value of any register manually now?

 

Greg_Muth wrote:

For clearing the status register, would then

SPIC.STATUS = 1;

be correct?

No.

SPIC.STATUS = SPI_IF_bm;        // clear IF
SPIC.STATUS = SPI_WRCOL_bm;     // clear WRCOL

 

Thank you very much! I didn't find this in my manuals. I just found that the flag has to be cleared...

 

Greg_Muth wrote:

 Is the ADC result left or right justified?

 

The result is right adjusted.

This is the code how I initialize my ADC

void ADCinit (void)
{
	ADCA.CTRLA	= ADC_FLUSH_bm;		        // Flush pipeline

	// So I guess this belongs to ASF and I don't really need this?
	ADCA.CAL	= adc_get_calibration_data(ADC_CAL_ADCA); // get calibration data

	// Ref 1V
	ADCA.REFCTRL	= ADC_REFSEL_INT1V_gc | ADC_BANDGAP_bm;

	ADCA.EVCTRL	= ADC_EVACT_NONE_gc;		// No event-action
	ADCA.CTRLB	= ADC_RESOLUTION_12BIT_gc;	// Set resolution for 12bit, right adjusted (high impendance, no curr.limit, unsigned mode, no free running mode)
	ADCA.CTRLA	= ADC_ENABLE_bm;		// Enable the ADC
}

And this is my code to read data from the ADC

// in endless loop
// ...
if(rx_byte == 0x00)
{
	value = readValue(&(ADCA.CH0), rx_byte);
}
else if(rx_byte == 0x01)
{
        value = readValue(&(ADCA.CH1), rx_byte);
}
// etc...

// function outside of main()
uint16_t readValue(ADC_CH_t* channel, char pin)
{
	// set channel-mode
	channel->CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;
	// set pin
	channel->MUXCTRL= (pin << 3);
	// start conversion
	channel->CTRL |= ADC_CH_START_bm;
	// wait, till conversion is done
	while(!channel->INTFLAGS);
	// clear interrupt flags
	channel->INTFLAGS = ADC_CH0IF_bp;
	// return result
	return channel->RES;
}

 

UPDATE:

I'm sorry, I made a mistake in my first post:

The returned SPI-values are not shifted by a half byte, they are "delayed" by one byte.

So with my above code, if I send 0x01, 0x01, 0x02, 0x02, 0x03, 0x03,

I receive 0x00, 0x01, 0x01, 0x02, 0x02, 0x03.

At the next transmission of the above bytes I receive

0x03, 0x01, 0x01, 0x02, 0x02, 0x03.

I also updated this in my question.

 

 

Does anybody know the reason for this strange behaviour of my A3BU?

Last Edited: Mon. Oct 2, 2017 - 04:56 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can anybody give me a hint if this is either normal when using SPI or if there is an error in my code?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can anybody give me a hint if this is either normal when using SPI or if there is an error in my code?

    This is not a normal; definitely an error on your side. Check clock polarity and phase. It looks that the slave does not fully receives the previous byte. Being still in the shift register it gets received when the next byte starts to clock again. A logic analyzer should tell you this. If you have a spare pin, toggle the pin on your receive interrupt and you should see when this happen: at the beginning of receiving a byte or at the end.