为什么我的SPI通信无法正常工作? (Atmega644)

时间:2019-04-24 17:06:25

标签: c microcontroller spi atmega

我正在构建鼓机,并且存储了一个带有踢声音的样本头文件,该文件的值介于0到170之间。我想通过SPI将其发送到10位MCP4811 DAC,然后将其输出到一个3.5毫米音频插孔。

我的MISO,MOSI,SCK和RESET引脚连接到USB编程器以及DAC。

以下是存储在“ 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}

因此它是2221位的样本。我想使用频率为22 kHz的SPI发送到DAC。

我使用的是16 MHz晶振,所以我相应地设置了保险丝以使用它。

我正在使用一个溢出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);
}

我的PIN设置为。

Atmega644-> DAC

MOSI -> SDI

SCK -> SCK

SS -> /CS

在MCP4811上

Vdd -> 5V

Vss -> GND

V_out -> Audio jack.

MCP4811上的其余引脚均未连接任何东西。

我已经看到,通过在LCD屏幕上显示audio_out值,audio_out可以正常工作。但是没有任何输出到DAC。有人看到有什么问题吗?

编辑:添加了我想添加的SPI初始化。

2 个答案:

答案 0 :(得分:0)

您的代码中没有SPI初始化。

添加到main()

SPSR = (1 << SPI2X);  // double speed (to get maximum of 8MHz output)
SPCR = (1 << SPE)  | (1 << MSTR); // 1:1 prescaler, master mode, SPI mode 0, SPI enable

对您的代码也有几点说明:

仅在所有初始化完成后才使用sei(),以避免在未初始化的外围设备上发生中断。

最好先将PB4设置为高电平,然后将其设置为输出,以避免在两个命令之间将PB4设置为低电平:

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

答案 1 :(得分:0)

您的行在这里

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

将¬SHDN设置为0将关闭DAC

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

将位12改为1

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

从数据表

1 = Active mode operation. VOUT is available.