1.不废话,上干货
本文主要驱动是由以色列工程师在github上提供,https://github.com/folibis/M25L_SPI
修改成STM32版本的供大家直接使用,不要再费劲编写驱动了,感谢。原作者。
2.头文件
/*
* The MIT License (MIT)
*
* Copyright (c) 20014 Moukhlynin Ruslan <ruslan@khvmntk.ru>
*
* MX25L.h
* This file is part of the MX25L SPI memory library.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef MX25L_H_
#define MX25L_H_
#ifndef bool
#define bool unsigned short
#endif
#ifndef byte
#define byte unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
#ifndef ulong
#define ulong unsigned long
#endif
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
void SPI_Init();
byte SPI_Transfer(byte data);
void Get_Identification(byte data[3]);
byte GetStatus();
void SetWriteEnable(bool enable);
void SetStatus(byte status);
void SectorErase(ulong address);
void BlockErase(ulong address);
void ChipErase();
void SetAddress(ulong address);
void Write(ulong address, const char * data, uint length);
void Read(ulong address, char * data, uint length);
void FastRead(ulong address, char * data, uint length);
void ProtectBlock(bool bp0, bool bp1, bool bp2, bool bp3);
#endif /* MX25L_H_ */
3.c文件
/*
* The MIT License (MIT)
*
* Copyright (c) 20014 Moukhlynin Ruslan <ruslan@khvmntk.ru>
*
* MX25L.c
* This file is part of the MX25L SPI memory library.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "main.h"
#include "spi.h"
#include "MX25L.h"
#define SLAVESELECT HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);
#define SLAVEDESELECT HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);
#define COMMAND_WREN 0x06
#define COMMAND_WRDI 0x04
#define COMMAND_RDSR 0x05
#define COMMAND_WRSR 0x01
#define COMMAND_READ 0x03
#define COMMAND_FREAD 0x0B
#define COMMAND_WRITE 0x02
#define COMMAND_RDID 0x9F
#define COMMAND_SE 0x20
#define COMMAND_BE 0x52
#define COMMAND_CE 0x60
#define STATUS_WIP 0x01
#define STATUS_WEL 0x02
#define STATUS_BP0 0x04
#define STATUS_BP1 0x08
#define STATUS_BP2 0x10
#define STATUS_BP3 0x20
#define STATUS_RES 0x40
#define STATUS_SWRD 0x80
#define DUMMY 0xFF
void SPI_Init()
{
}
byte SPI_Transfer(byte data)
{
uint8_t RxData = 0X00;
if (HAL_SPI_TransmitReceive(&hspi1, &data, &RxData, 1, 10) != HAL_OK)
{
RxData = 0XFF;
}
return RxData;
}
void Get_Identification(byte data[3])
{
SLAVESELECT;
SPI_Transfer(COMMAND_RDID);
data[0] = SPI_Transfer(DUMMY);
data[1] = SPI_Transfer(DUMMY);
data[2] = SPI_Transfer(DUMMY);
SLAVEDESELECT;
}
byte GetStatus()
{
byte status;
SLAVESELECT;
SPI_Transfer(COMMAND_RDSR);
status = SPI_Transfer(DUMMY);
SLAVEDESELECT;
return status;
}
void SetWriteEnable(bool enable)
{
SLAVESELECT;
SPI_Transfer(enable ? COMMAND_WREN : COMMAND_WRDI);
SLAVEDESELECT;
}
void SetStatus(byte status)
{
SetWriteEnable(true);
SLAVESELECT;
SPI_Transfer(COMMAND_WRSR);
SPI_Transfer(status);
SLAVEDESELECT;
}
void Erase(byte command, ulong address)
{
}
void SectorErase(ulong address)
{
SetWriteEnable(true);
SLAVESELECT;
SPI_Transfer(COMMAND_SE);
SetAddress(address);
SLAVEDESELECT;
while((GetStatus())&(STATUS_WIP));
}
void BlockErase(ulong address)
{
SetWriteEnable(true);
SLAVESELECT;
SPI_Transfer(COMMAND_BE);
SetAddress(address);
SLAVEDESELECT;
while(GetStatus() & STATUS_WIP);
}
void ChipErase()
{
SetWriteEnable(true);
SLAVESELECT;
SPI_Transfer(COMMAND_CE);
SLAVEDESELECT;
while(GetStatus() & STATUS_WIP);
}
void SetAddress(ulong address)
{
SPI_Transfer( (byte) (address >> 16) );
SPI_Transfer( (byte) (address >> 8) );
SPI_Transfer( (byte) address );
}
void Write(ulong address, const char * data, uint length)
{
SetWriteEnable(true);
SLAVESELECT;
SPI_Transfer(COMMAND_WRITE);
SetAddress(address);
for(uint i = 0;i < length;i ++)
{
SPI_Transfer(*(data + i));
}
SLAVEDESELECT;
while(GetStatus() & STATUS_WIP);
}
void Read(ulong address, char * data, uint length)
{
SLAVESELECT;
SPI_Transfer(COMMAND_READ);
SetAddress(address);
for(uint i = 0;i < length;i ++)
{
*(data + i) = SPI_Transfer(DUMMY);
}
SLAVEDESELECT;
while(GetStatus() & STATUS_WIP);
}
void FastRead(ulong address, char * data, uint length)
{
SLAVESELECT;
SPI_Transfer(COMMAND_READ);
SetAddress(address);
SPI_Transfer(DUMMY);
for(uint i = 0;i < length;i ++)
{
*(data + i) = SPI_Transfer(DUMMY);
}
SLAVEDESELECT;
while(GetStatus() & STATUS_WIP);
}
void ProtectBlock(bool bp0, bool bp1, bool bp2, bool bp3)
{
byte status = GetStatus();
if(bp0)
{
status |= STATUS_BP0;
}
if(bp1) status |= STATUS_BP1;
if(bp2) status |= STATUS_BP2;
if(bp3) status |= STATUS_BP3;
SetStatus(status);
}
4.调用主函数
/* USER CODE BEGIN PV */
I2C_StatusTypeDef eeStatus=I2C_ERROR;
uint8_t wrEE[256]={0x01};
uint8_t rdEE[256]={0x00};
uint8_t wrEE2[256]={0x01};
uint8_t rdEE2[256]={0x00};
uint8_t flashID[3];
uint8_t wrData[]="1234567890";
uint8_t rdData[10]={0x00};
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */
SetStatus(0x00);
byte status = GetStatus();
Get_Identification(flashID);
HAL_Delay(1000);
Write(0,(char *)wrData,10);
HAL_Delay(100);
Read(0,(char *)rdData,10);
if(memcmp(wrData,rdData,10)==0)
{
for(int i=0;i<3;i++)
{
HAL_GPIO_WritePin(RUN_LED_GPIO_Port, RUN_LED_Pin, GPIO_PIN_SET);
HAL_Delay(200);
HAL_GPIO_WritePin(RUN_LED_GPIO_Port, RUN_LED_Pin, GPIO_PIN_RESET);
HAL_Delay(200);
}
}
ChipErase();
HAL_Delay(200);
Read(0,(char *)rdData,10);
if(memcmp(wrData,rdData,10)!=0)
{
for(int i=0;i<3;i++)
{
HAL_GPIO_WritePin(RUN_LED_GPIO_Port, RUN_LED_Pin, GPIO_PIN_SET);
HAL_Delay(200);
HAL_GPIO_WritePin(RUN_LED_GPIO_Port, RUN_LED_Pin, GPIO_PIN_RESET);
HAL_Delay(200);
}
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}