Home » Post » STM » STM32F103 SPI 통신 코드 작성하기

STM32F103 SPI 통신 코드 작성하기

STM32F103 SPI 통신 목차

  1. STM32F103 SPI 통신 CUBEMX로 초기 설정하기
  2. STM32F103 SPI 통신 코드 작성하기 (현재 포스팅)

 

SPI 통신의 기본 원리는 데이터를 쓴 만큼 데이터를 받는다. 이 말은 즉 데이터를 받고 싶으면 그 만큼 더미데이터를 보내야 한다는 뜻이다. 이번 포스팅은 SPI를 사용하는 ADC 칩과 통신하고자 한다.

 

처음 SPI를 시작할 때 ADC 칩을 초기화 해야한다. 이전에 어떤 데이터를 받아 그 일부가 남아있거나, 통신에 실패해 문제가 생겼을 수도 있기 때문이다. 따라서 칩에서 서술하는 초기화 방법을 숙지하고, 코드로 작성하기로 한다.

 

데이터 시트에서는 초기화 방법을 서술하고 있다.

 

ADC 칩에서는 DIN핀으로 1의 값을 32번 연속으로 주면 초기화가 된다고 서술하고 있다. 이전 포스팅에서 데이터 비트수를 8로 설정하였으므로, 0xFF 값을 4번 연속으로 호출하도록 한다.

 

따라서 먼저 SPI 통신을 시작한 후에, Chip Select 핀 출력을 Low로 준 다음 리셋을 시작한다. 그리고 안정시간으로 1ms를 준다. 데이터시트에서는 500us이지만, 맘 편이 1ms를 주었다.

 

따라서 작성한 코드는 아래와 같아진다.

  1. SPI를 동작시킴
  2. GPIO A라인에서 4번째 핀의 출력을 LOW로 설정한다. (PA4포트 출력 LOW)
  3. SPI1에서 RESET DATA( = 0xFF)를 4번 호출해 1의 값을 연속으로 32번 준다.
  4. GPIO A라인에서 4번째 핀의 출력을 HIGH로 설정한다. (PA4포트 출력 HIGH)
  5. 칩 안정화 시간을 준다.

 

겁먹지 마시라. SPI 통신 방식은 생각보다 간단하니. 데이터 전송과 수신을 동시에 하고 싶다면 HAL_SPI_TransmitReceive함수를 사용하도록 한다.

 

HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)

 

어떤 spi를 사용하는지, 전송할 데이터 값과, 수신받을 데이터, 데이터의 길이와 타임오버 값을 주도록 한다.

 

P.S)

만약에 로직애널라이저로 찍었을 때 클럭 타이밍을 놓친다면 Timeout을 5정도로 늘려보시라.

 

“STM32F103 SPI 통신 코드 작성하기”의 12개의 댓글

  1. 정리가 잘 돼 있어서 STM32 코드 테스트 하는데 큰 도움이 되었습니다. 감사합니다.

    그런데 HAL_SPI_Transmit이 끝나고 난 후 chip select는 high로 돌아가야 하므로 HAL_GPIO_WritePin에서는 GPIO_PIN_SET으로 설정해야 정상 동작을 하지 않을까 합니다. 혹시 GPIO_PIN_RESET을 하신 이유가 있는지 여쭤봐도 될까요?

    1. 죄송합니다. 요즘 애달픈 일이 많아서 블로그 관리를 통 못했습니다. SET이 맞습니다. 혼선을 드려서 죄송합니다.

    1. 안녕하세요. 답글로 공개하기 다소 여하하여 남겨주신 이메일로 메세지를 드렸습니다.
      Slave는 통신해 볼 경험은 없으나, 문의글을 남겨주시면 관련 레퍼런스를 찾아보고 답변 드리겠습니다.

  2. 저도 SPI 슬레이브 통신을 구현하고 싶은데 항상 마스터로만 해봐서 어떻게 접근해야할까요?

    1. 너무 오래전이라 기억이 잘 안나는군요
      레퍼런스 메뉴얼상에는 큰 차이가 없어보입니다.
      맨처음 cubemx에서 슬레이브 모드로 설정하고 핀 결선만 다르지 않으면 그 이후 동신은 동일할 거라고 생각합니다

  3. STM32G474 모델을 MASTER로 SPI FRAM을 SLAVE로 해서
    SPI 통신으로 FRAM에 데이터를 보낸 후
    그 데이터를 읽어드리는 작업을 하고 싶습니다.
    uint8_t T_buffer[] = {0x0,0x1,0x2,0x3};
    uint8_t R_buffer[] = {0x9,0x9,0x9,0x9};
    선언을하고
    HAL_SPI_TransmitReceive(&hspi1, T_buffer, R_buffer, 8, 500);
    명령을 하면
    T_buffer와 R_buffer에 모두 0,0,0,0이 들어옵니다
    하여 Trasmit으로 Tbuffer를 보내고
    다시 Tbuffer에 Recieve를 받아도 0,0,0,0이 들어옵니다.
    문제가 뭘까요??

    1. 안녕하세요 데이터 길이는 4로 설정하는 것이 맞을 것 같습니다. Fram은 사용하는 모델에따라 적용이 다를 수 있으니 사용하는 칩 데이터시트에 opcode가 있는지 자주 사용되는 칩이라면 arduino로는 어떻게 코드구성이 되어있는지 참고해서 작성해주세요.
      아마 opcode가 있다면 tranmitreceive함수만으로는 구현이 힘들수도 있습니다.

    1. 어떤 목적으로 회로가 연결되어있는지 모릅니다. 아날로그 회로도 문제일 수도 있구요.
      단순 펌웨어가 궁금하신거라면, 1채널만 쓰는경우 42~3p에 있는 Manual Channel n Select 모드로 채널 지정 후, 다음 통신부터 0x00h를 지속해서 입력해서 데이터를 취득하세요.
      문제가 생기면 스테이트 머신 확인해보시구요. Input Range 세팅도 확인도 해보시구요.
      좋은 결과 얻으시길 바랍니다.

댓글 남기기

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.