Sam D21 SPI Interface - Bare Code

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

Hi all!

 

I need to control a Digital Potentiometer MPC41010 through SPI in SAM D21.

My code needs to increase or decrease (0 to 255) through Button 1 and Button 2 of OLED1 Xplained Pro to SPI Potentiometer. 

I did read of Buttons and ok, then my code needs to put in Data register for transmit but no success.

 

Today I read the DS and I am confusing in some things.

 

Anyone has a Bare Code in exemple for SPI interface? Then I can study it based in datasheet. I have no found any example in internet. 

 

Thanks!

Paulo

 

 

Franc

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

ASF provides SPI examples.

 

Also examples of using the OLED1 XPro.

 

Take them as your starting point.

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear awneil, I need it in Bare Code. 

Thanks

Franc

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

Have you used the display on the the OLED1 Xplained Board?

It uses SPI.

What have you tried?

David

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

Bare code here, but note most likely you will want to control the chip select manually (and not using the SERCOM SPI like in the example).  So MSSEN=0 and not setting up pin muxing for that pin (PA18 in the example).

#include "sam.h"

void spiInit(void)
{
    PM->APBCMASK.bit.SERCOM1_ = 1;
    GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_ID_SERCOM1_CORE;
    while(GCLK->STATUS.bit.SYNCBUSY);
    const SERCOM_SPI_CTRLA_Type ctrla = {
      .bit.DORD = 0, // MSB first
      .bit.CPHA = 0, // Mode 0
      .bit.CPOL = 0,
      .bit.FORM = 0, // SPI frame
      .bit.DIPO = 3, // MISO on PAD[3]
      .bit.DOPO = 0, // MOSI on PAD[0], SCK on PAD[1], SS_ on PAD[2]
      .bit.MODE = 3  // Master
    };
    SERCOM1->SPI.CTRLA.reg = ctrla.reg;
    const SERCOM_SPI_CTRLB_Type ctrlb = {
      .bit.RXEN = 1,   // RX enabled
      .bit.MSSEN = 1,  // HW SS
      .bit.CHSIZE = 0 // 8-bit
    };
    SERCOM1->SPI.CTRLB.reg = ctrlb.reg;	

    SERCOM1->SPI.BAUD.reg = 0; // Rate is clock / 2 

    // Mux for SERCOM1 PA16,PA17,PA18,PA19
    const PORT_WRCONFIG_Type wrconfig = {
      .bit.WRPINCFG = 1,
      .bit.WRPMUX = 1,
      .bit.PMUX = MUX_PA16C_SERCOM1_PAD0,
      .bit.PMUXEN = 1,
      .bit.HWSEL = 1,
      .bit.PINMASK = (uint16_t)((PORT_PA16 | PORT_PA17 | PORT_PA18 | PORT_PA19) >> 16)
    };
    PORT->Group[0].WRCONFIG.reg = wrconfig.reg;

    SERCOM1->SPI.CTRLA.bit.ENABLE = 1;
    while(SERCOM1->SPI.SYNCBUSY.bit.ENABLE);
}

uint8_t spiSend(uint8_t data)
{
    while(SERCOM1->SPI.INTFLAG.bit.DRE == 0);
    SERCOM1->SPI.DATA.reg = data;
    while(SERCOM1->SPI.INTFLAG.bit.RXC == 0);
    return SERCOM1->SPI.DATA.reg;
}

int main(void)
{
    SystemInit();
    spiInit();

    volatile uint8_t rData;
    volatile uint8_t sData = 0;
    while (1) {
      rData = spiSend(sData++);
    }
}

/Lars

 

Last Edited: Fri. Oct 28, 2016 - 06:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank so much friends. I will check this bare code. Regards!

Franc

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

eletrocampos wrote:
I need it in Bare Code.

I said take it as your starting point ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks so much for this SPI setup code.  I just tried it and it works perfectly.

 

-troy

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

Hello, thanks Lars for posting the example code. The example code works for me, but when I try to change it to work for SERCOM0 with MOSI on pad0 (PA08), SCLK on pad1 (PA09), CS on pad2 (PA10), and MISO on pad3 (PA11). When I run in debug mode all the code executes and seems to run, but none of the pins are outputting anything which makes me think I am not setting up the pins or pin mux correctly. Below is my code, would greatly appreciate any help.

 

void spiInitSERCOM0(void)
{
	PM->APBCMASK.bit.SERCOM0_ = 1;
	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_ID_SERCOM0_CORE;
	while(GCLK->STATUS.bit.SYNCBUSY);
	const SERCOM_SPI_CTRLA_Type ctrla = {
		.bit.DORD = 0, // MSB first
		.bit.CPHA = 0, // Mode 0
		.bit.CPOL = 0,
		.bit.FORM = 0, // SPI frame
		.bit.DIPO = 3, // MISO on PAD[3]
		.bit.DOPO = 0, // MOSI on PAD[0], SCK on PAD[1], SS_ on PAD[2]
		.bit.MODE = 3  // Master
	};
	SERCOM0->SPI.CTRLA.reg = ctrla.reg;
	const SERCOM_SPI_CTRLB_Type ctrlb = {
		.bit.RXEN = 1,   // RX enabled
		.bit.MSSEN = 1,  // HW SS
		.bit.CHSIZE = 0 // 8-bit
	};
	SERCOM0->SPI.CTRLB.reg = ctrlb.reg;

	SERCOM0->SPI.BAUD.reg = 0; // Rate is clock / 2

	// Mux for SERCOM0 PA08,PA09,PA10,PA11
	const PORT_WRCONFIG_Type wrconfig = {
		.bit.WRPINCFG = 1,
		.bit.WRPMUX = 1,
		.bit.PMUX = MUX_PA08C_SERCOM0_PAD0,
		.bit.PMUXEN = 1,
		.bit.HWSEL = 0,
		.bit.PINMASK = (uint16_t)((PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11) >> 16)
	};
	PORT->Group[0].WRCONFIG.reg = wrconfig.reg;

	SERCOM0->SPI.CTRLA.bit.ENABLE = 1;
	while(SERCOM0->SPI.SYNCBUSY.bit.ENABLE);
}

uint8_t spiSend0(uint8_t data)
{
	while(SERCOM0->SPI.INTFLAG.bit.DRE == 0);
	SERCOM0->SPI.DATA.reg = data;
	while(SERCOM0->SPI.INTFLAG.bit.RXC == 0);
	return SERCOM0->SPI.DATA.reg;
}

int main(void)
{
	SystemInit();
	spiInitSERCOM0();
	delay_init();

	volatile uint8_t rData;
	volatile uint8_t sData = 0;
	while (1) {
		delay_ms(1);
		rData = spiSend0(MAX31856_CONFIG_REG);
		rData |= MAX31856_CONFIG_3WIRE;
		//spiSend1(rData);
	}
}

 

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

You are configuring pins with HWSEL 0 which is correct for the PA08-PA11, but you need to remove the 

>> 16)

for PINMASK, it was needed for PA16-PA19 with HWSEL 1.

/Lars

 

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

That makes sense and it worked. Thank you Lars