SPI_Master Help Digi-Pot [Solved w/Example Code]

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

Hello.

Let me start out by saying I've spent a couple days pouring over example code, this forum, tutorials and other helpful tools including Atmel App-notes.

Any help or consideration is much appreciated.

My main problem is I need to transmit four bytes, first two most significant would be 00010001 or 0x11, second two vary from 0 to 255.

What I'm having trouble wrapping my skull around is how to assure the leading 3 zeros are shifted out.

I'm a newb attempting to migrate over from Arduino (que forehead slaps)

/*
 * SPI_Master.c
 *
 * Created: 3/1/2012 9:21:52 AM
 *  Author: dshay
 */ 

#include 
#define DD_MOSI   PINB3
#define DD_SCK    PINB5
#define DDR_SPI   DDRB


void SPI_MasterInit(void)
{
	DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);
	
	SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(0<<CPOL)|(0<<CPHA);
}	

void SPI_MasterTransmit(char cData)
{
	SPDR = cData;
	
	while (!(SPSR &(1<<SPIF)));
}


int main(void)
{
	unsigned int write_pot = B00010001;
	unsigned int val=0;
	
	SPI_MasterInit();
    while(1)
    {
     //This is the part I can't figure out 
	   
    }
}

$ Fixed code tags - JS $

Last Edited: Sat. Mar 3, 2012 - 08:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please use the CODE button when posting code to preserve format.

Quote:
how to assure the leading 3 zeros are shifted out.
What leading 3 zeros? I would have thought you just need to do
SPI_MasterTransmit(0x11);
SPI_MasterTransmit(0x00);
SPI_MasterTransmit(0xFF); (or SPI_MasterTransmit(255);

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Your SPI_init() isn't right, you're not setting up the /CS pin and so it won't work right . RTM about how to deal with it . Also, before you write code for a new peripheral, STUDY how to use it . Look at the sample code in the MCU datasheet and search Atmel's site for app. notes about the subject you're working on .

You should define the spi_tramsmit() like this :

uint8_t SPI_MasterTransmit(char cData)
{
   SPDR = cData;
   
   while (!(SPSR &(1<<SPIF)));

  return  SPDR;
} 

Then when you need a spi_receive(), you can just do :

#define   spi_receive()    SPI_MasterTransmit( 0xFF )

0xFF is a dummy value, it could be any value, since it won't be used by the slave during a master_READ . This way you get TWO functions for the program space of ONE . Example usage :

SPI_MasterTransmit( 0x11 );

some_var = spi_receive( 0xFF );

Just do this, and all other bits will automatically be zero'd by the compiler :

SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

I very much appreciate the input. I have read the datasheet, their app-notes, checked AVR Studio for example code.

I understand the other bits in SPCR would be zero'd by the compiler. It's good practice for a newb like me to write them out as zero'd so I know they're there and what they're for and why.

Thanks again, both of you, this has been of great help.

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

Thank you for your assistance!

Posting in case this can help any other newbs.

This works with a MCP41010 Digital Potentiometer.

/*
 * SPI_Master.c
 *
 * Created: 3/3/2012 
 *  Author: dshay
 */ 


#ifndef F_CPU
#define F_CPU 16000000UL
#endif


#include 
#include 



#define DD_CS     2
#define DD_MOSI   3
#define DD_SCK    5
#define DDR_SPI   DDRB


void SPI_MasterInit(void)
{
	DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_CS);
	
	SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(0<<CPOL)|(0<<CPHA);
}	

uint8_t SPI_MasterTransmit(char cData) 
{ 
   SPDR = cData; 
    
   while (!(SPSR &(1<<SPIF))); 

  return  SPDR; 
}


int main(void)
{
  
  
  
  PORTB |= 1 << DD_CS; 
	
	
SPI_MasterInit();
   
    while(1)
    {
           PORTB &= ~( 1 << DD_CS);
           
           SPI_MasterTransmit(0x11);
           SPI_MasterTransmit(0xFF); 
           
           PORTB |= 1 << DD_CS; 
	   _delay_ms(200);

           PORTB &= ~( 1 << DD_CS);
          
           SPI_MasterTransmit(0x11);
           SPI_MasterTransmit(0x00); 
           
           PORTB |= 1 << DD_CS; 
	   _delay_ms(200);
            
	  

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

You should also make files, like spi.c/spi.h, and put your SPI functions in there for future apps. that need it, then you can add spi_init(), etc. easily to the project .

Also, something to think about doing :

#define   CS_clr    PORTB &= ~( 1 << DD_CS) 
#define   CS_set    PORTB |= 1 << DD_CS

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1