您的当前位置:首页正文

AT25M01使用说明 SPI EEPROM STM32

2020-07-27 来源:欧得旅游网


1.芯片访问规则符合AT25系列原则,可以找相关的例子,但是25M01目前没有

2.芯片工作原则,不考虑写保护问题,所有操作的第一步都是要发送写允许指令,然后重新片选有效,发送下一步的命令。

注意问题:SPI的EEPROM的数据输出的原理是,在输入一个字节的同时输出一个字节,没有输入字节,就输出,所以,所谓的读数据,其实质是先发送一个数据,然后在接收一个数据。操作如下: (1)寄存器读

1)先片选,在发送写允许指令,片选无效

2)片选,发送读寄存器指令,读寄存器,片选无效 (2)寄存器写

1)先片选,在发送写允许指令,片选无效

2)片选,发送写寄存器指令,写数据,片选无效 (3)写数据 1)先片选,在发送写允许指令,片选无效 2)片选,发送写数据指令,写数据,片选无效 (4)读数据 1)先片选,在发送写允许指令,片选无效 2)片选,发送读数据指令,读数据,片选无效 注意:STM32的SPI需要,每次都开启 void SPI_EEPROM_Init(void) {

SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; /* Enable SPI1 and GPIO clocks */ /*!< SPI_FLASH_SPI_CS_GPIO, SPI_FLASH_SPI_MOSI_GPIO, SPI_FLASH_SPI_MISO_GPIO, SPI_FLASH_SPI_DETECT_GPIO and SPI_FLASH_SPI_SCK_GPIO Periph clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE); /*!< SPI_FLASH_SPI Periph clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); /*!< Configure SPI_FLASH_SPI pins: SCK */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /*!< Configure SPI_FLASH_SPI pins: MOSI */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_Init(GPIOA, &GPIO_InitStructure); /*!< Configure SPI_FLASH_SPI pins: MISO */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;

//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure);

//选通 采用 软件 模式-------------------------

/*!< Configure SPI_FLASH_SPI_CS_PIN pin: SPI_FLASH Card CS pin */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

——仅供参考

GPIO_Init(GPIOA, &GPIO_InitStructure); //NSS1 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &GPIO_InitStructure); //NSS2 /* Deselect the FLASH: Chip Select high */ NSS1_HIGH(); NSS1_HIGH();

/* SPI1 configuration */

// W25X16: data input on the DIO pin is sampled on the rising edge of the CLK. // Data on the DO and DIO pins are clocked out on the falling edge of CLK. SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //SPI模式3 //SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //SPI模式0 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //软件 片选 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //硬件 片选 //SPI_InitStructure.SPI_NSS =SPI_NSS_Hard; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; //72M/8=9Mhz,供电 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure); /* Enable SPI1 */ SPI_Cmd(SPI1, DISABLE); }

/*********************************************END OF FILE**********************/ void NSS_CS_ENABLE(uint8_t NSS) {

if(NSS==1) { NSS1_LOW();NSS2_HIGH();} else if(NSS==2) { NSS2_LOW();NSS1_HIGH();} }

void NSS_CS_DISABLE() {

NSS1_HIGH(); NSS2_HIGH(); }

void SPI_WREN(uint8_t nss) {

NSS_CS_ENABLE(nss); SPI_WriteByte(WREN); NSS_CS_DISABLE(); ——仅供参考

// Delay_ms(1); }

void SPI_WRDI(uint8_t nss) {

NSS_CS_ENABLE(nss); SPI_WriteByte(WRDI); NSS_CS_DISABLE(); // Delay_ms(1); }

void SPI_EEPROM_WRITE_Start(void) {

SPI_Cmd(SPI1, ENABLE); SPI_WREN(1); NSS_CS_ENABLE(1); SPI_WriteByte(WRSR); SPI_WriteByte(0X02); NSS_CS_DISABLE( ); SPI_WREN(2); NSS_CS_ENABLE(2); SPI_WriteByte(WRSR); SPI_WriteByte(0X02); NSS_CS_DISABLE( ); SPI_Cmd(SPI1, DISABLE); }

void SPI_EEPROM_WRITE_END(void) {

SPI_Cmd(SPI1, ENABLE); SPI_WRDI(1); SPI_WRDI(2); SPI_Cmd(SPI1, DISABLE); }

uint8_t SPI_WriteByte(uint8_t data) {

/* Loop while DR register in not emplty */ while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); /* Send byte through the SPI1 peripheral */ SPI_I2S_SendData(SPI1, data); /* Wait to receive a byte */

while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); /* Return the byte read from the SPI bus */ return SPI_I2S_ReceiveData(SPI1); }

uint8_t SPI_ReadByte(void) {

return (SPI_WriteByte(Dummy_Byte));

//while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) == RESET); ——仅供参考

// return SPI_I2S_ReceiveData(SPI1); }

uint8_t AT25_GetStatus(uint8_t NSS) {

uint8_t tmp=0; SPI_WREN(NSS);

NSS_CS_ENABLE(NSS); SPI_WriteByte(RDSR); tmp = SPI_ReadByte(); NSS_CS_DISABLE(); return tmp; }

void AT25_WaitReady(uint8_t NSS) {

while((0x01 & AT25_GetStatus(NSS))!=0); } /*

单字节操作,读和写 */

uint8_t AT25_ReadByte(uint32_t addr) {

uint8_t tmp; uint8_t nss=1; if(addr >=(uint32_t)(1024*128*2)) return 0; if(addr>=(uint32_t)(1024*128)) {addr=addr-(uint32_t)(1024*128);nss=2;} else nss=1; SPI_Cmd(SPI1,ENABLE); AT25_WaitReady(nss); SPI_WREN(nss); NSS_CS_ENABLE(nss); SPI_WriteByte(READ); SPI_WriteByte((uint8_t)((addr & 0x010000)>>16));/* A16*/ SPI_WriteByte((uint8_t)((addr & 0x00FF00)>>8));/* A15-A8*/ SPI_WriteByte((uint8_t)(addr & 0x0000FF));/* A7-A0*/ tmp = SPI_ReadByte(); NSS_CS_DISABLE( );

SPI_Cmd(SPI1,DISABLE); return tmp; }

void AT25_WriteByte(uint8_t data, uint32_t addr) {

uint8_t nss=1;

uint32_t tt=1024*128*2; if(addr >= tt) ——仅供参考

return ;

if(addr>=(uint32_t)(1024*128))

{addr=addr-(uint32_t)(1024*128);nss=2;} else nss=1;

SPI_Cmd(SPI1,ENABLE); AT25_WaitReady(nss); SPI_WREN(nss); NSS_CS_ENABLE(nss); SPI_WriteByte(WRITE);

SPI_WriteByte((uint8_t)((addr & 0x010000)>>16));/* A16*/ SPI_WriteByte((uint8_t)((addr & 0x00FF00)>>8));/* A15-A8*/ SPI_WriteByte((uint8_t)(addr & 0x0000FF));/* A7-A0*/ SPI_WriteByte(data); NSS_CS_DISABLE( ); SPI_Cmd(SPI1,DISABLE); }

////////////多字节操作 /**

* @brief 将缓冲区中的数据写到I2C EEPROM中 * @param * @arg pBuffer:缓冲区指针 * @arg WriteAddr:写地址 * @arg NumByteToWrite:写的字节数 * @retval 无 */

void SPI_EE_BufferWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite,uint8_t NSS) {

u32 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0; Addr = WriteAddr % I2C_PageSize; count = I2C_PageSize - Addr; NumOfPage = NumByteToWrite / I2C_PageSize; NumOfSingle = NumByteToWrite % I2C_PageSize; /* If WriteAddr is I2C_PageSize aligned */ if(Addr == 0) {

/* If NumByteToWrite < I2C_PageSize */ if(NumOfPage == 0) {

SPI_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle,NSS); }

/* If NumByteToWrite > I2C_PageSize */ else {

while(NumOfPage--) {

SPI_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize,NSS); ——仅供参考

WriteAddr += I2C_PageSize; pBuffer += I2C_PageSize; }

if(NumOfSingle!=0) {

SPI_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle,NSS); } } }

/* If WriteAddr is not I2C_PageSize aligned */ else {

/* If NumByteToWrite < I2C_PageSize */ if(NumOfPage== 0) {

SPI_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle,NSS); }

/* If NumByteToWrite > I2C_PageSize */ else {

NumByteToWrite -= count; NumOfPage = NumByteToWrite / I2C_PageSize; NumOfSingle = NumByteToWrite % I2C_PageSize; if(count != 0) { SPI_EE_PageWrite(pBuffer, WriteAddr, count,NSS); WriteAddr += count; pBuffer += count; }

while(NumOfPage--) {

SPI_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize,NSS); WriteAddr += I2C_PageSize; pBuffer += I2C_PageSize; }

if(NumOfSingle != 0) {

SPI_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle,NSS); } } } } /**

* @brief 在EEPROM的一个写循环中可以写多个字节,但一次写入的字节数 * 不能超过EEPROM页的大小,AT24C02每页有8个字节 * @param ——仅供参考

* @arg pBuffer:缓冲区指针 * @arg WriteAddr:写地址

* @arg NumByteToWrite:写的字节数 * @retval 无 */

void SPI_EE_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite,uint8_t NSS) {

SPI_Cmd(SPI1,ENABLE); AT25_WaitReady(NSS); SPI_WREN(NSS);

NSS_CS_ENABLE(NSS); SPI_WriteByte(WRITE); SPI_WriteByte((uint8_t)((WriteAddr & 0x010000)>>16));/* A16*/ SPI_WriteByte((uint8_t)((WriteAddr & 0x00FF00)>>8));/* A15-A8*/ SPI_WriteByte((uint8_t)(WriteAddr & 0x0000FF));/* A7-A0*/ /* While there is data to be written */ while(NumByteToWrite--) {

/* Send the current byte */ SPI_WriteByte(*pBuffer); /* Point to the next byte to be written */ pBuffer++; }

/* Send STOP condition */ NSS_CS_DISABLE(); SPI_Cmd(SPI1,DISABLE); } /**

* @brief 从EEPROM里面读取一块数据 * @param * @arg pBuffer:存放从EEPROM读取的数据的缓冲区指针 * @arg WriteAddr:接收数据的EEPROM的地址 * @arg NumByteToWrite:要从EEPROM读取的字节数 * @retval 无 */

void SPI_EE_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead,uint8_t NSS) {

uint8_t nss=NSS;

SPI_Cmd(SPI1,ENABLE); AT25_WaitReady(nss); SPI_WREN(NSS); NSS_CS_ENABLE(nss); SPI_WriteByte(READ);

SPI_WriteByte((uint8_t)((ReadAddr & 0x010000)>>16));/* A16*/ SPI_WriteByte((uint8_t)((ReadAddr & 0x00FF00)>>8));/* A15-A8*/ SPI_WriteByte((uint8_t)(ReadAddr & 0x0000FF));/* A7-A0*/ ——仅供参考

/* While there is data to be read */ while(NumByteToRead) {

*pBuffer = SPI_ReadByte(); pBuffer++;

NumByteToRead--; }

/* Enable Acknowledgement to be ready for another reception */ NSS_CS_DISABLE( ); SPI_Cmd(SPI1,DISABLE); }

//*****wdz*******// void SPI_EE_BufferWrite2(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite) {

u32 temp=WriteAddr+NumByteToWrite-1; u32 number=WriteAddr+NumByteToWrite-1024*128; if(temp<1024*128) {

SPI_EE_BufferWrite(pBuffer,WriteAddr,NumByteToWrite,1); }

else if(WriteAddr<1024*128 && temp>=1024*128 ) {

SPI_EE_BufferWrite(pBuffer,WriteAddr,NumByteToWrite-number,1); SPI_EE_BufferWrite(pBuffer+NumByteToWrite-number,0,number,2); }

else if(WriteAddr>=1024*128) {

SPI_EE_BufferWrite(pBuffer,WriteAddr-1024*128,NumByteToWrite,2); } }

void SPI_EE_BufferRead2(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead) {

u32 temp=ReadAddr+NumByteToRead-1; u32 number=ReadAddr+NumByteToRead-1024*128; if(temp<1024*128) {

SPI_EE_BufferRead(pBuffer,ReadAddr,NumByteToRead,1); }

else if(ReadAddr<1024*128 && temp>=1024*128 ) {

SPI_EE_BufferRead(pBuffer,ReadAddr,NumByteToRead-number,1); SPI_EE_BufferRead(pBuffer+NumByteToRead-number,0,number,2); }

else if(ReadAddr>=1024*128) {

SPI_EE_BufferRead(pBuffer,ReadAddr-1024*128,NumByteToRead,2); ——仅供参考

} }

void SPI_Read_status(void) {

uint8_t mygetbyte; SPI_Cmd(SPI1,ENABLE); SPI_WREN(1); NSS1_LOW();

SPI_WriteByte(RDSR);

mygetbyte=SPI_ReadByte();

USART_printf(USART3,\"\\r\\n ST1=%d\SPI_WREN(2); NSS2_LOW(); SPI_WriteByte(RDSR); mygetbyte=SPI_ReadByte(); USART_printf(USART3,\"\\r\\n ST2=%d\}

——仅供参考

因篇幅问题不能全部显示,请点此查看更多更全内容