简体   繁体   English

atmega328上的SPI无法正常工作

[英]SPI on atmega328 not working

We're trying to use SPI to communicate with another IC using an atmel atmega328 MCU. 我们正在尝试使用SPI与使用Atmel atmega328 MCU的另一IC进行通信。 The target IC takes a command (the header in the code) and then feeds us back the information stored in the requested register (or writes to it if the command is a write). 目标IC接收命令(代码中的标头),然后将存储在请求的寄存器中的信息反馈给我们(如果命令是写操作,则将其写入)。 However, we're having two problems here: 但是,我们这里有两个问题:

  1. Nothing comes out of the SPI, the only change is on the CS line (which we control). SPI没有任何变化,唯一的变化是在CS线上(由我们控制)。 No SPI clock, no data on the data lines. 没有SPI时钟,数据线上没有数据。

  2. The first iteration of the for loop when writing the header the program does not enter the while loop (The LED on port 6 won't turn on). 编写标题时,for循环的第一次迭代不会使程序进入while循环(端口6上的LED不会点亮)。

Any help with this would be much appreciated, code provided down below. 对此的任何帮助将不胜感激,下面提供了代码。

#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;
}

Edit: Added the defines for the initialization 编辑:添加了初始化的定义

Your code seems to be correct, but due to you're not using the SPI Interrupt handler, you need to clear the SPIF bit in the SPSR before you are sending data via SPDR. 您的代码似乎是正确的,但是由于您没有使用SPI中断处理程序,因此在通过SPDR发送数据之前,需要清除SPSR中的SPIF位。 The SPDR doesn't accept any data with a SPIF flag set. SPDR不接受设置了SPIF标志的任何数据。

According to the manual 19.5.2 根据手册19.5.2

Alternatively, the SPIF bit is cleared by first reading the SPI Status Register with SPIF set, then accessing the SPI Data Register (SPDR). 或者,通过首先读取设置了SPIF的SPI状态寄存器,然后访问SPI数据寄存器(SPDR),来清除SPIF位。

Your code does not do this so maybe there's a flag set which never gets cleared. 您的代码不会执行此操作,因此可能存在一个永远不会清除的标志集。 Try to change the code to: 尝试将代码更改为:

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
}

We solved it, the problem was that the default SS on port B2 need to be defined as an output in the initialization stage, otherwise the MCU can change to Slave operation mode if the pin is left floating. 我们解决了这个问题,问题是在初始化阶段需要将端口B2上的默认SS定义为输出,否则,如果该引脚悬空,则MCU可以更改为从设备操作模式。 This sets the SPIF-flag to 1 every time it happens, which messed with our checks. 每次将SPIF标志设置为1,这与我们的检查混乱了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM