Search code examples
cmicrocontrollerspiatmega

Why is not my SPI communication working? (Atmega644)


I'm building a drum machine, and I have stored a sample header file with a kick sound which takes values between 0 and 170. I want to send it over SPI to a 10-bit MCP4811 DAC which then outputs it to a 3.5mm audio jack.

I have my MISO,MOSI,SCK and RESET pins connected to my USB programmer as well as the DAC.

Here is a snippet of the audio file stored in "samples.h"

unsigned const char sample_1[2221] PROGMEM = {0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, ...}
unsigned int sample_len[1] = {2221}

So it is a sample of 2221 bits. This I want to send to the DAC using SPI with freq = 22 kHz.

I'm using a 16 MHz Crystal, so I set the fuses accordingly to use it.

I am using a Timer which overflows 22 kHz.

volatile unsigned int sample_count[1] = {0};
volatile unsigned int audio_out = 0;
volatile unsigned char spi_junk;

int main (void)
sei();
DDRB = 0b10110000; //Set MOSI, SCK and SS as output.
PORTB = (1 << PINB4) //active low on SS.

TIMSK1 = (1<<OCIE1A); //Enable interrupt
TCCR1B = (1<<WGM12) | (1<<CS11); // set CTC mode and divide clk by 8 
OCR1A = 91; //16 MHz/(8*91) ~ 22068 Hz

//SPI Init
SPCR = (1<<SPE) | (1<<MSTR);  //master, 8 MHz
SPSR = (1<<SPI2X);

ISR (TIMER1_COMPA_vect) {
    audio_out = 0;

//If play_track == 1, then the sound should be played back.
if (play_track && sample_count[0] < sample_len[0]){
   audio_out += (pgm_read_byte(&(sample_1[sample_count[0]++)));

// send audio_out to 10-bit DAC on SPI
PORTB &= ~(1<<PINB4); // B.4 (DAC /CS)
SPDR = (char) ((audio_out >> 6) & 0x000f); //byte 1 0 0 0 0 b9 b8 b7 b6
while (!(SPSR & (1<<SPIF)));
spi_junk = SPDR;

SPDR = (char) ((audio_out & 0x003f) << 2); //byte 2 b5 b4 b3 b2 b1 b0 0 0
while (!(SPSR & (1<<SPIF)));
spi_junk = SPDR;
PORTB |= (1<<PINB4);
}

My PIN set up is.

Atmega644 -> DAC

MOSI -> SDI

SCK -> SCK

SS -> /CS

On MCP4811

Vdd -> 5V

Vss -> GND

V_out -> Audio jack.

The rest of the pins on the MCP4811 are not connected to anything.

I have seen that the audio_out is working as expected, by displaying the audio_out value on a LCD screen. But nothing is being output to the DAC. Anyone see what could be wrong?

EDIT: Added the SPI init which I had missed to add.


Solution

  • Your line here

    SPDR = (char) ((audio_out >> 6) & 0x000f); //byte 1 0 0 0 0 b9 b8 b7 b6

    Will set ¬SHDN to 0 which will shutdown the DAC

    0 = Shutdown the device. Analog output is not available. VOUT pin is connected to 500 kohm typical)

    Set bit 12 to 1 instead

    SPDR = (char) ((audio_out >> 6) & 0x0f)|0x10; //byte 1 0 0 0 1 b9 b8 b7 b6

    from datasheet

    1 = Active mode operation. VOUT is available.