atmega328上的SPI无法正常工作

时间:2017-04-04 07:41:38

标签: c embedded microcontroller spi atmel

我们正在尝试使用atmel atmega328 MCU与另一个IC通信。目标IC接受一个命令(代码中的标题),然后将存储在请求寄存器中的信息反馈给我们(如果命令是写,则写入它)。但是,我们在这里遇到两个问题:

  1. SPI没有任何结果,唯一的变化是CS线(我们控制)。没有SPI时钟,数据线上没有数据。

  2. 写入标题时for循环的第一次迭代程序没有进入while循环(端口6上的LED将不会打开)。

  3. 非常感谢任何帮助,下面提供的代码。

    #define DDR_SPI DDRB
    #define DD_MISO DDB4
    #define DD_MOSI DDB3
    #define DD_SCK DDB5
    #define DD_SS DDB6
    
    void SPI_MasterInit(void)
    {
        /* Set MOSI, SCK and CS output, all others input */
        DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);
        /* Enable SPI, Master, set clock rate = System clock / 16 */
        SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
    }
    
    int readfromspilow(uint16 headerLength, const uint8 *headerBuffer, uint32 readLength, uint8 *readBuffer)
    {
    
    
        PORTB &= ~(1 << PORTB6);                // Set CS low
    
        for(int i=0; i<headerLength; i++)
        {
            SPDR = headerBuffer[i];             //Send entry i of the header to the spi register
            sleep_us(5);                        // Give the flag time to reset, might be unnecessary
            PORTD |= (1 << PORTD5);             //LED for diagnostics
            while(!(SPSR & (1<<SPIF))){         //Wait for SPIFinished flag
                PORTD |= (1 << PORTD6);         //LED for diagnostics
            }
    
            PORTD &= ~(1 << PORTD3);            //LED for diagnostics
    
    
    
            //readBuffer[0] = SPDR; // Dummy read as we write the header
        }
    
        for(int i=0; i<readLength; i++)
        {
            SPDR = 0xFF;                        // Dummy write as we read the message body
            sleep_us(5);                        // Give the flag time to reset, might be unnecessary
            while(!(SPSR & (1<<SPIF)));         //Wait for SPIFinished flag
            readBuffer[i] = SPDR ;              //Store the value in the buffer
        }
    
        PORTB |= (1 << PORTB6);                 // Set CS high
    
    
        return;
    }
    

    编辑:添加了初始化的定义

3 个答案:

答案 0 :(得分:1)

您的代码似乎是正确的,但由于您没有使用SPI中断处理程序,因此在通过SPDR发送数据之前,需要清除SPSR中的SPIF位。 SPDR不接受任何设置了SPIF标志的数据。

答案 1 :(得分:1)

根据手册19.5.2

  

或者,首先读取SPI状态,清除SPIF位   注册SPIF集,然后访问SPI数据寄存器(SPDR)。

你的代码没有这样做,所以也许有一个永远不会被清除的标志。尝试将代码更改为:

volatile uint8_t spsr = SPSR;       //Dummy-read the flag register to clear flags
SPDR = headerBuffer[i];             //Send entry i of the header to the spi register
PORTD |= (1 << PORTD5);             //LED for diagnostics
while(!(SPSR & (1<<SPIF))){         //Wait for SPIFinished flag
  PORTD |= (1 << PORTD6);           //LED for diagnostics
}

答案 2 :(得分:0)

我们解决了它,问题是端口B2上的默认SS需要在初始化阶段定义为输出,否则如果引脚悬空,MCU可以切换到从操作模式。这会在每次发生时将SPIF标志设置为1,这与我们的检查相混淆。