본문 바로가기
Study/STM32F

SPI 로 M25PXX (Flash,eeprom) 사용하기

by Answer Choi 2015. 2. 12.
반응형



 M25Pxx 시리즈 flash는 SPI를 사용하는데, 막상 하려면 조금 까다롭습니다.


참고할만한 소스가 ST에서 제공하는 STM32F1 개발보드용 소스가 있습니다.


첨부로 넣어두었는데, ST에 가셔도 받을 수 있는 자료이고요, 압축을 푸셔서 Examples\SPI\M25P64_FLASH\


에 가시면 예제소스가 있습니다. main.c와 spi_flash.c ,spi_flash.h 파일을 자신의 보드에 맞게 수정하시면 됩니다.


우선 헤더파일인 spi_flash.h 파일만 수정해주시면 될 것같아요.


개발보드에 따라 포트 바뀌게 되어있는데 아래와 같이바꾸시면 개발보드 상관없이 쓸 수 있습니다.


헤더파일 수정


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __SPI_FLASH_H
#define __SPI_FLASH_H
 
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
 
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
 
 
 #define GPIO_CS                  GPIOA
 #define RCC_APB2Periph_GPIO_CS   RCC_APB2Periph_GPIOA
 #define GPIO_Pin_CS              GPIO_Pin_4
 
 
/* Exported macro ------------------------------------------------------------*/
/* Select SPI FLASH: Chip Select pin low  */
#define SPI_FLASH_CS_LOW()       GPIO_ResetBits(GPIO_CS, GPIO_Pin_CS)
/* Deselect SPI FLASH: Chip Select pin high */
#define SPI_FLASH_CS_HIGH()      GPIO_SetBits(GPIO_CS, GPIO_Pin_CS)
 
/* Exported functions ------------------------------------------------------- */
/*----- High layer function -----*/
void SPI_FLASH_Init(void);
void SPI_FLASH_SectorErase(u32 SectorAddr);
void SPI_FLASH_BulkErase(void);
void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite);
void SPI_FLASH_BufferWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite);
void SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead);
u32 SPI_FLASH_ReadID(void);
void SPI_FLASH_StartReadSequence(u32 ReadAddr);
 
/*----- Low layer function -----*/
u8 SPI_FLASH_ReadByte(void);
u8 SPI_FLASH_SendByte(u8 byte);
u16 SPI_FLASH_SendHalfWord(u16 HalfWord);
void SPI_FLASH_WriteEnable(void);
void SPI_FLASH_WaitForWriteEnd(void);
 
#endif /* __SPI_FLASH_H */
 
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/
cs


전 SPI1번을 사용하니깐 SPI1로 설정했습니다.


초기화!!


초기화는 별다른 것 없습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
void SPI_FLASH_Init(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
 
  /* Enable SPI1 and GPIO clocks */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA |
                         RCC_APB2Periph_GPIO_CS, ENABLE);
 
  /* Configure SPI1 pins: SCK, MISO and MOSI */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
 
  /* Configure I/O for Flash Chip select */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_CS;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIO_CS, &GPIO_InitStructure);
 
  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH();
 
  /* SPI1 configuration */
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI1, &SPI_InitStructure);
 
  /* Enable SPI1  */
  SPI_Cmd(SPI1, ENABLE);
}
cs


SPI1을 사용하시면 위와같이 아니면 포트를 바꿔주시면 됩니다.


플래시 쓰기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
  /* Enable the write access to the FLASH */
  SPI_FLASH_WriteEnable();
 
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW();
  /* Send "Write to Memory " instruction */
  SPI_FLASH_SendByte(WRITE);
  /* Send WriteAddr high nibble address byte to write to */
  SPI_FLASH_SendByte((WriteAddr & 0xFF0000>> 16);
  /* Send WriteAddr medium nibble address byte to write to */
  SPI_FLASH_SendByte((WriteAddr & 0xFF00>> 8);
  /* Send WriteAddr low nibble address byte to write to */
  SPI_FLASH_SendByte(WriteAddr & 0xFF);
 
  /* while there is data to be written on the FLASH */
  while (NumByteToWrite--)
  {
    /* Send the current byte */
    SPI_FLASH_SendByte(*pBuffer);
    /* Point on the next byte to be written */
    pBuffer++;
  }
 
  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH();
 
  /* Wait the end of Flash writing */
  SPI_FLASH_WaitForWriteEnd();
}
cs


플래시에 쓰는건 SPI_FLASH_PageWrite 함수를 쓰시면 됩니다.


파라메터값은 각각 플래시에 쓸 버퍼,쓸 주소, 쓸 길이 입니다.


예제에는 main.c에 SPI_FLASH_PageWrite(Tx_Buffer, FLASH_WriteAddress, BufferSize); 가 제공됩니다.


FLASH_WriteAddress만 수정해서 그대로 사용하시면 결과를 보실 수 있습니다.


플래시 읽기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
{
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW();
 
  /* Send "Read from Memory " instruction */
  SPI_FLASH_SendByte(READ);
 
  /* Send ReadAddr high nibble address byte to read from */
  SPI_FLASH_SendByte((ReadAddr & 0xFF0000>> 16);
  /* Send ReadAddr medium nibble address byte to read from */
  SPI_FLASH_SendByte((ReadAddr& 0xFF00>> 8);
  /* Send ReadAddr low nibble address byte to read from */
  SPI_FLASH_SendByte(ReadAddr & 0xFF);
 
  while (NumByteToRead--/* while there is data to be read */
  {
    /* Read a byte from the FLASH */
    *pBuffer = SPI_FLASH_SendByte(Dummy_Byte);
    /* Point to the next location where the byte read will be saved */
    pBuffer++;
  }
 
  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH();
}
cs


플래시읽기 역시 SPI_FLASH_BufferRead(Rx_Buffer, FLASH_ReadAddress, BufferSize); 를 제공합니다.


플래시 ID


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
u32 SPI_FLASH_ReadID(void)
{
  u32 Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
 
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW();
 
  /* Send "RDID " instruction */
  SPI_FLASH_SendByte(0x9F);
 
  /* Read a byte from the FLASH */
  Temp0 = SPI_FLASH_SendByte(Dummy_Byte);
 
  /* Read a byte from the FLASH */
  Temp1 = SPI_FLASH_SendByte(Dummy_Byte);
 
  /* Read a byte from the FLASH */
  Temp2 = SPI_FLASH_SendByte(Dummy_Byte);
 
  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH();
 
  Temp = (Temp0 << 16| (Temp1 << 8| Temp2;
 
  return Temp;
}
cs


플래시 ID 또한 FLASH_ID = SPI_FLASH_ReadID();를 쓰셔서 읽어오시면 됩니다.


반응형

'Study > STM32F' 카테고리의 다른 글

CAN baudrate 설정하기  (0) 2020.12.03
ds1338용 HEX <-> DEC 변환  (0) 2015.02.12
I2C로 DS1338 (RTC) 사용하기  (2) 2015.02.12
timestamp 변환하기  (0) 2015.02.12
코드개발을 쉽게 STM32CubeMx  (0) 2015.02.12

인기글