2017-04-11 476 views
2

我试图用STM32F469I-DISCO驱动EEPROM Chip 25LC256,但无法实现它。 我试图用HAL API基础创建自己的函数,但显然有些问题:我不知道是否因为无法读取而在芯片上写入数据。让我再解释一下。STM32F4:通过SPI管理EEPROM 25LC256

所以我的芯片是一个DIP 25LC256(DS是以上是你的愿望)。 EEPROM的PIN保持和WP连接到VCC(3.3V)。 PIN CS连接到PH6(板载ARD_D10)并由软件管理。 PIN SI和PIN SO分别通过右侧复用功能(GPIO_AF5_SPI2)连接到PB15(ARD_D11)和PB14(ARD_D12)。 PIN SCK也连接到PD3(ADR_D13)。

这是我的SPI配置代码:

EEPROM_StatusTypeDef ConfigurationSPI2(SPI_HandleTypeDef *spi2Handle){ 

    __HAL_RCC_GPIOB_CLK_ENABLE(); 
    __HAL_RCC_GPIOD_CLK_ENABLE(); 
    __HAL_RCC_GPIOH_CLK_ENABLE(); 

    GPIO_InitTypeDef gpioInit; 

    //// SCK [PD3] 
    gpioInit.Pin = GPIO_PIN_3; 
    gpioInit.Mode = GPIO_MODE_AF_PP; 
    gpioInit.Pull = GPIO_PULLDOWN; 
    gpioInit.Speed = GPIO_SPEED_FREQ_HIGH; 
    gpioInit.Alternate = GPIO_AF5_SPI2; 

    HAL_GPIO_Init(GPIOD, &gpioInit); 

    //// MOSI [PB15] 
    gpioInit.Pin = GPIO_PIN_15; 
    gpioInit.Pull = GPIO_PULLUP; 
    HAL_GPIO_Init(GPIOB, &gpioInit); 

    //// MISO [PB14] 
    gpioInit.Pin = GPIO_PIN_14; 
    gpioInit.Pull = GPIO_NOPULL; 
    HAL_GPIO_Init(GPIOB, &gpioInit); 

    //// CS [PH6] 
    gpioInit.Pin = GPIO_PIN_6; 
    gpioInit.Mode = GPIO_MODE_OUTPUT_PP; 
    gpioInit.Speed = GPIO_SPEED_FREQ_HIGH; 
    HAL_GPIO_Init(GPIOH, &gpioInit); 
    HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6, GPIO_PIN_SET); 

    //// SPI2 

    __HAL_RCC_SPI2_CLK_ENABLE(); 

    spi2Handle->Instance = SPI2; 

    spi2Handle->Init.Mode =    SPI_MODE_MASTER; 
    spi2Handle->Init.Direction =   SPI_DIRECTION_2LINES; 
    spi2Handle->Init.DataSize =   SPI_DATASIZE_8BIT; 
    spi2Handle->Init.CLKPolarity =  SPI_POLARITY_LOW; 
    spi2Handle->Init.CLKPhase =   SPI_PHASE_1EDGE; 
    spi2Handle->Init.NSS =    SPI_NSS_SOFT; 
    spi2Handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; 
    spi2Handle->Init.FirstBit =   SPI_FIRSTBIT_MSB; 
    spi2Handle->Init.TIMode =    SPI_TIMODE_DISABLE; 
    spi2Handle->Init.CRCCalculation =  SPI_CRCCALCULATION_DISABLE ; 
    spi2Handle->Init.CRCPolynomial =  7; 

    if(HAL_SPI_Init(spi2Handle) != HAL_OK){ 
     return EEPROM_ERROR; 
    } 

    return EEPROM_OK; 
} 

和两个函数分别(和theorically)允许写入和读取到的芯片:

写功能:

EEPROM_StatusTypeDef WriteEEPROM(SPI_HandleTypeDef *spi2Handle, uint8_t *txBuffer, uint16_t size, uint16_t addr){ 

    uint8_t addrLow = addr & 0xFF; 
    uint8_t addrHigh = (addr >> 8); 

    uint8_t wrenInstruction = WREN_EEPROM; // Value : 0x06 

    uint8_t buffer[32] = {WRITE_EEPROM, addrHigh, addrLow}; //Value : 0x02 

    for(uint i = 0 ; i < size ; i++){ 
     buffer[3+i] = txBuffer[i]; 
    } 

    HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6, RESET); 
    if(HAL_SPI_Transmit(spi2Handle, &wrenInstruction, 1, TIMEOUT_EEPROM) != HAL_OK){ 
     return EEPROM_ERROR;; 
    } 
    HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6, SET); 

    HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6, RESET); 
    if(HAL_SPI_Transmit(spi2Handle, buffer, (size + 3), TIMEOUT_EEPROM) != HAL_OK){ 
     return EEPROM_ERROR; 
    } 
    HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6, SET); 

    return EEPROM_OK; 
} 

阅读功能:

EEPROM_StatusTypeDef ReadEEPROM(SPI_HandleTypeDef *spi2Handle, uint8_t *rxBuffer, uint16_t size, uint16_t addr){ 

    uint8_t addrLow = addr & 0xFF; 
    uint8_t addrHigh = (addr >> 8); 
    uint8_t txBuffer[3] = {READ_EEPROM, addrHigh, addrLow}; 

    HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6, RESET); 

    HAL_SPI_Transmit(spi2Handle, txBuffer, 3, TIMEOUT_EEPROM); 

    HAL_SPI_Receive(spi2Handle, rxBuffer, size, TIMEOUT_EEPROM);  

    HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6, SET); 

    return EEPROM_OK; 
} 

我知道我的功能不是很“漂亮”,但这是第一次尝试。在我的主,我在写到芯片中的数据“0×05”,在0×01 ADRESS首先试图再读取该数据传回:

uint8_t bufferEEPROM[1] = {5}; 
uint8_t bufferEEPROM2[1] = {1}; 

WriteEEPROM(&spi2Handle, bufferEEPROM, 1, 0x01); 
ReadEEPROM(&spi2Handle, bufferEEPROM2, 1, 0x01); 

我有一台示波器等等,因为它没有工作(与STM Studio的监控)我想象的CLK和SI引脚,则CLK和SO引脚(只能看到两个频道在同一时间):

Monitoring of CLK (Yellow) and SI (Blue)

Monitoring of CLK (Yellow) and SO (Blue)

正如你所看到的,与显示CLK的第一张图片(黄色)和SI(或MOSI)蓝色,我有预期的所有数据:WRITE ENABLE指令然后WRITE指令。继地址,然后数据

之后,读取功能开始。首先是READ指令和ADDRESS我想获取数据。最后8位应该是存储在地址中的数据(在这种情况下为0x01)。 SI PIN发生了什么,但我想这是因为HAL_SPI_Receive()函数实际上调用HAL_SPI_TransmitReceive()与我的数组bufferEEPROM2作为参数(这就是为什么我们可以选择0b00000001)。所以这是因为我的SPI配置参数(全双工)。

无论如何,理论上我应该在SO PIN上看到0b00000101,但正如您在第二张照片中所看到的......没有任何东西。

我试图改变gpioInit.Pull SOUP上PULLUP和PULLDOWN,但没有任何改变。 NOPULL是因为这是我尝试过的最后一件事。

事情是我不知道从哪里开始。我的传输似乎工作(但它实际上?)。我的初始化有什么问题吗?我的主要问题将是:为什么我没有收到我的EEPROM中的任何数据?

非常感谢!

回答

2

写入操作需要一些时间才能完成(您的数据表在第4页上说5 ms),在此期间除读取状态以外不能进行任何操作。尝试使用RDSR (0x05)操作码轮询状态寄存器,以确定它何时准备就绪(位0)。您也可以在发行WREN前后检查状态(位1),看它是否成功。

0

所以这个问题现在已经解决了。以下是改进:

实际上有两个问题。第一个,当然最重要的是,如berendi所述,一个时间问题。在我的WRITE功能中,我没有让EEPROM完成写周期(数据表上的5 ms)。添加以下代码行以我所有写函数结束:

HAL_Delay(10); //10 ms wait for the EEPROM to complete the write cycle 

延迟值可以是少,我认为如果时间preicous(theorically为5ms)。虽然我没有在10毫秒以下进行测试。另一件事。随着示波器我也看到,我的芯片选择曾经去在我的最后时钟边缘的中间。我不能说这是否也意味着某些问题,因为这是我首先通过在HAl_Delay(10)之前添加代码行解决的问题。我所有的SPI传输功能,现在完成这样:

while(HAL_GPIO_ReadPin(CLK_PORT, CLK_PIN) == GPIO_PIN_SET){ 
} 
HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_SET); 
HAL_Delay(10); 

这样,我有合适的模式,我可以在EEPROM中的写入和读回我写的。

注意:最后一件事让我对事件的误解更加深入:由于我的写入功能不起作用,我专注于状态寄存器写入和读取功能(为了逐步解决这个问题)。写功能也不起作用,事实上这是因为WREN位未设置。我虽然(错误的一个),写入状态寄存器的事实并没有要求也设置WREN像WRITE功能进入内存要求。其实,这也是必要的。

感谢您的帮助!

+0

前段时间我为STM32 + SPI EEPROM写了lib。 STM技术支持也对此进行了检查。目前我在大约十个项目中使用这个lib,它运行良好。看看[STM32-EEPROM-SPI](https://github.com/firebull/STM32-EEPROM-SPI) – Bulkin