ATMEGA8A + SPI 内存异常行为

Posted

技术标签:

【中文标题】ATMEGA8A + SPI 内存异常行为【英文标题】:ATMEGA8A + SPI memory strange behavior 【发布时间】:2017-08-26 10:31:34 【问题描述】:

我已经购买了 SPI 内存MX25L8006EPI,现在我尝试将它连接到 ATMEGA8A 进行测试。原理图非常简单,与互联网上的其他人没有什么不同:

ATMEGA8A 工作在 8Mz 内部振荡器,3.3V。保险丝为 HIGH:0xD1,LOW:0xE4。

我使用 Atmel Studio 7 进行编码,使用 AVRISP mkII 对 uC 进行编程。 由于 EEPROM 需要 3.3V,我使用 LM317 连接了 5V 700mA 电源模块,如您在方案中看到的那样。我认为这并不重要,但无论如何......

代码也很简单,我从网上的某个页面复制了一部分:

#define SLAVESELECT (PORTB &= ~(1<<PORTB2))
#define SLAVEDESELECT (PORTB |= (1<<PORTB2))

#define WREN  6
#define WRDI  4
#define RDSR  5
#define WRSR  1
#define READ  3
#define WRITE 2
#define RDID 0x9F

#define byte unsigned char

void SPI_Init()

    DDRB = (1<<PORTB2)|(1<<PORTB3)|(1<<PORTB5);
    SLAVEDESELECT;
    //SPSR |= (1<<SPI2X);
    SPCR |= (1<<SPE)|(1<<MSTR)|(1 << SPR1);
    _delay_ms(10);


byte SPI_Transfer(volatile byte data)

    SPDR = data;
    while (!(SPSR & (1<<SPIF)));
    return SPDR;


void Get_Identification(byte data[3])

    SLAVESELECT;
    SPI_Transfer(RDID);
    data[0] = SPI_Transfer(0xFF);
    data[1] = SPI_Transfer(0xFF);
    data[2] = SPI_Transfer(0xFF);
    SLAVEDESELECT;


byte GetStatus()

    byte status;
    SLAVESELECT;
    SPI_Transfer(RDSR);
    status = SPI_Transfer(0xFF);
    SLAVEDESELECT;
    return status;


void SetWriteEnable(short ebable)

    SLAVESELECT;
    SPI_Transfer((ebable != 0) ? WREN : WRDI);
    SLAVEDESELECT;


void SetStatus(byte status)

    SetWriteEnable(1);
    SLAVESELECT;
    SPI_Transfer(WRSR);
    SPI_Transfer(status);
    SLAVEDESELECT;
    _delay_ms(100);


int main(void)

    SPI_Init();
    byte status = 0x1C;
    DEBUG_PRINT("\r\nSet status:%d\r\n",status);
    SetStatus(status);
    status = GetStatus();
    DEBUG_PRINT("\r\nGet status:%d\r\n",status);
    byte buffer[3];
    Get_Identification(buffer);
    DEBUG_PRINT("Byte0:%x\r\n", buffer[0]);
    DEBUG_PRINT("Byte1:%x\r\n", buffer[1]);
    DEBUG_PRINT("Byte2:%x\r\n", buffer[2]);

    while (1) 
           
    

DEBUG_PRINT 是我通过 USART 发送格式化字符串的函数。我用它来打印调试信息。

一切看起来都很好,但是当我运行时,我得到了一些奇怪的行为。输出是:

Set status:28
Get status:24
Byte0:80
Byte1:0
Byte2:10

首先我使用WRSR 操作码设置状态寄存器。它应该将其设置为 00011100,但是当我使用 RDSR 操作码读取状态时,我得到 00011000。

好的,状态寄存器可能有问题。然后我尝试使用RDID 操作码读取 ID 寄存器。它应该返回 3 个字节 - 0xC2 0x20 0x14。但是我得到了 0x80 0x0 0x10。

如果我没有得到任何答案或全是 0x00 或 0xFF,这将是可以理解的。但是在这里我读到了一些答案,这个问题是完全错误的。更有趣的是,如果我使用至少相同的代码将 EEPROM 连接到 Arduino,它可以正常工作。

我觉得问题很小。看起来可能是某些数据顺序错误或传输速度或类似问题,但我无法正常工作。

【问题讨论】:

SPI 时钟相位和极性设置是否符合 EEPROM 的要求? 是的,芯片工作在 SPI 模式 0 和 3。目前 CPOL=0,CPHA=0 所以它在模式 0 但我也尝试过模式 3 - 结果相同。 【参考方案1】:

根据datasheet,当 BP2:0 设置为 5、6 或 7 时,所有块都受到保护。也许当您将其设置为 7 时,内存仅将其设置为 6,因为它没有有所作为。

【讨论】:

感谢@UncleO 的回复!你是对的。可以通过将 BP 设置为 5、6 或 7 来保护内存。但是 BP2 是可写的,应该设置。另外,如果我发送11111111 然后读取状态它返回相同的错误结果(00011000)。至少应该设置SRWD。如果我将芯片连接到Arduino,所有状态寄存器的位都设置没有问题

以上是关于ATMEGA8A + SPI 内存异常行为的主要内容,如果未能解决你的问题,请参考以下文章

STM32 F4xx Fault 异常错误定位指南

Redis异常记录

SystemParametersInfoForDPI破坏了内存

Java内存溢出异常(上)

OutOfMemoryError/OOM/内存溢出异常实例分析--堆内存异常

第二章:本机直接内存异常