STM32 SPI SD card

DongHee Lim·2022년 3월 28일
1

STM32

목록 보기
3/11

사용 보드 : F429ZI
프로그램 : CubeIDE

서론

SD 카드 리더기로
핀이 9개가 있는 제품과
핀이 6개가 있는 제품이 있다.

SDIO 기능을 사용할 때 쓰려고 샀는데 보니까 [알리익스프레스 제품 9핀 링크]
SPI 통신으로 데이터를 주고 받는 것이였다.    [알리익스프레스 제품 6핀 링크]

참고 자료
[STM32 SPI SD 카드 블로그]
[위 블로그 자료 사용 Youtube]

Setup

먼저 RCC 를 HSE 로 설정한다.

HSE Clock 설정은 아래와 같이 했다.

SD카드를 읽고 쓸 예정이기 때문에 Full-Duplex Master로 설정한다.
속도는 일단 테스트를 하기위해 11.25MBits/s 로 맞췄다.

파일 읽고 쓰는 과정을 확인하기 위해 UART3 설정을 한다.

FATFS 설정
USE_LFN 은 8 Bytes 이상의 파일 이름을 위해서 설정하였고
섹터 사이즈는 최대로 올렸다. [Sector : FAT32 관련 블로그 링크]

전체 핀
PB10 : USART3_TX
PB11 : USART3_RX
PB13 : SPI2_SCK
PB14 : SPI2_MISO
PB15 : SPI2_MOSI
PD8 : GPIO_OUTPUT (SD_CS, HIGH)
PD10 : GPIO_EXTI10 (인터럽트 용 버튼)

SDIO 할 때는 핀을 알아서 해줬는데
SPI 통신을 할 때는 장치마다 CS (Chip Select) 를 설정해줘야 한다.
GPIO_OUTPUT을 하나 고르고
초기 GPIO output level 을 HIGH로 해준다.
Maximum output speed => Medium
이름은 굳이 바꿀 필요는 없다. (SD카드 Chip Select 라서 SD_CS)



Code

  1. Github 에서 fatfs_sd.h 와 fatfs_sd.c 파일을 가져온다. [SPI_SD Github 링크]

1. fatfs_sd.h

빨간 테두리를 자신이 선택한 설정으로 바꾼다. (본인 : SPI2, SD_CS->PD8)

2. user_diskio.c

위에서 파란색 네모를 복사해서 user_diskio.c 파일의 return 값에 넣는다.
경로 : FATFS -> Target -> user_diskio.c

return SD_disk_initialize (pdrv);

return SD_disk_status (pdrv);

return SD_disk_read (pdrv, buff, sector, count);

return SD_disk_write (pdrv, buff, sector, count);

return SD_disk_ioctl (pdrv, cmd, buff);

3. stm32f1xx_it.c

경로 : Core -> Src -> stm32f1xx_it.c

  • fatfs_sd.c -> uint16_t Timer1, Timer2
  • stm32f4xx_hal_dma.h -> DMA_HandleTypeDef
  • spi.c -> SPI_HandleTypeDef hspi2

추가 해야할 코드

extern uint16_t Timer1, Timer2;
extern DMA_HandleTypeDef hdma_spi2_tx;
extern SPI_HandleTypeDef hspi2;

추가 해야할 코드 2

if(Timer1 > 0)
	Timer1--;
if(Timer2 > 0)
	Timer2--;
HAL_SYSTICK_IRQHandler();

4. main.c


include 와 전역변수 설정이다.

CubeIDE 에서 printf 를 사용하기 위해서는 UART와 위 함수를 재정의 해줘야한다.
또한, 아래에서 만든 함수도 선언해줬다.


f_mount 같은 함수를 좌클릭을 하고 F3을 누르면 ff.c 파일로 들어가진다
내부가 궁금하면 찾아보자. 리턴값 자료형이 FRESULT 로 enum(열거형) 으로 둬서 여러가지 상태를 나타낼 수 있다.


USER CODE BEGIN 2 사이에 넣는 코드

▶ f_mount

SD 카드를 마운트, 언마운트하는 함수이다. 이것을 안하면 SD카드 메모리에 접근이 불가능

▶ f_open and f_close

특정 파일을 열고 닫는 함수이다.

▶ f_getfree

클러스터 개수와 크기를 연산하여 파일 사이즈를 계산해준다.

▶ f_write and f_puts

파일의 처음 처음 위치로 커서를 옮기고 데이터 한 줄을 쓰는 함수이다.
f_write 는 정해진 크기를 쓰기 때문에 여러 줄을 쓰기 위해서는 여러가지르 신경 써야한다.

◆   f_write 여러줄 작성

	sprintf((char*)buffer, "%s\r\n", text);
	uint16_t length = (uint16_t)strlen(text) + 2;	// +2 는 \r\n 추가
	for (uint8_t i = 0; i < 3; i++) {
		fres = f_write(&fil, buffer, length, (void*)&bw);
	}

\r\n 를 추가하여 나중에 파일시스템에서 읽을 때나 메모장에서 열 때 우리가 원하는 3줄을 얻을 수 있다.
그리고 f_write 의 크기를 버퍼의 크기[sizeof(buffer)]가 아니라 TEXT의 크기(length)로 변경해야 한다는 것을 꼭 기억해야 한다.
\r (carriage return) 을 쓴 이유는 f_read 를 사용할 때 똑같이 보이게 하기 위해서다.

	sprintf((char*)buffer, "%s\n", text);
	for (uint8_t i = 0; i < 3; i++) {
		fres = f_puts(buffer, &fil);
	}

만약 f_write 를 말고 f_puts 를 사용한다면 \0 (NULL) 까지 쓰기 때문에 크기를 따로 입력할 필요가 없다.


▶ f_read and f_gets

Read 함수는 길어서 코드블럭으로 작성
한줄을 읽어오는 코드인데
파일을 fres = f_open(&fil, fileName, FA_READ); 의 FA_READ 를 안하면
읽어온 바이트의 크기를 읽어오지 못해서 Flag를 통해서
먼저 열려있던 파일을 닫고 다시 열었다.

void ReadFile(char* fileName)
{
     if (closedFlag == 0) CloseFile();

     fres = f_open(&fil, fileName, FA_READ);
     if (fres == FR_OK) {
         printf("File opened for reading.\r\n");
     } else if (fres != FR_OK) {
         printf("File was not opened for reading!\r\n");
     }

     fres = f_read(&fil, buffer, sizeof(buffer), (void*)&br);
     char mRd[100];

     if (fres == FR_OK)
     {
         sprintf((char*)mRd, "%s", buffer);
         printf("-----------READING_TEXT----------\r\n");
         printf("%s", mRd);	// already existed \r\n
         printf("-----------READING_TEXT---------\r\n");
         sprintf((char*)str, "%3d bytes Read", (int)br);
         printf("%s\r\n", str);
     }
     else if (fres != FR_OK || br == 0)
     {
         printf("Can't read~!\r\n");
     }

}


f_gets 는 \n (Line Feed) 또는 \0 까지 읽는다. 그 리턴값을 버퍼의 포인터를 반환하는데
버퍼 길이 끝까지 다 읽은 경우 0을 반환하여 while문에 넣어서 자주 사용한다.


위의 saveFile()은
위 Youtube 의 연습 자료를 함수로 만든 것이다. [Code 링크]


# 해결 하고 싶은 것

EXTI 외부 인터럽트를 통해서 FATFS 에 접근하는 것을 하고싶다.

예) 버튼을 누르면 파일이 저장되는 기능

잘 안되어서 고민 중.

profile
하고 싶은 것, 소유하고 싶은 것, 좋아하는 것

0개의 댓글