2017-04-11 102 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