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 통신 코드 작성하기”에 대한 14개의 생각

  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 세팅도 확인도 해보시구요.
      좋은 결과 얻으시길 바랍니다.

  4. 안녕하세요. f103보드사용해서 슬레이브 모드로 SPI2로 수신만 받고자 합니다.
    Full_Duplex_slave모드로 해두고 NSS disable로 하여 PB10을 GPIO_output설정하여
    MSIO 에 max speed HIGH, PB10도 output level과 max speed 둘 다 HIGH로 해놓은 상태입니다.
    이제 저 HAL_SPI_ENABLE 코드를 (&hspi2)로 한 후 transmit을 전부 receive로 바꾸어 while문에 넣으면 슬레이브 모드로 정상 작동하는게 맞을까요? 물론 master STM IDE코드는 이 글의 내용대로 다 맞춘 상태입니다.
    많이 배우고있습니다. 답장 부탁드립니다.

    1. na님, 안녕하세요.
      chip을 사용하는 입장에서, chip을 디자인 하는 쪽으로 업을 바꾼지 오래되어서요. 답변이 정확하지 않을 수 있습니다.
      UM1850 레퍼런스 문서를 기준으로 답변 드립니다.
      while문으로 처리한다면 interrupt mode나, dma mode 등은 사용하지 않는 것으로 보이는군요.
      지금은 tool이 없어서 정확하게 알지는 못하지만, PB10을 chip select mode pin이라고 하면 output이 아니고 input이 맞을 것으로 보입니다.
      master mode에서 output으로 설정한 것은 반대로 slave mode일 때 input이 되어야 합니다.
      driver가 아니고 chip에 대한 것이라면 st32f103 reference manual을 참고하세요.
      SPI 모드를 사용하려면 GPIO의 input/output 설정 / phase & polarity 등이 맞아야 하는데요. 이걸 먼저 확인해보세요.
      모든 세팅이 맞다면 manual 상에 Procedure는 아래와 같습니다.

      Procedure
      1. Set the DFF bit to define 8- or 16-bit data frame format
      2. Select the CPOL and CPHA bits to define one of the four relationships between the
      data transfer and the serial clock (see Figure 240). For correct data transfer, the CPOL
      and CPHA bits must be configured in the same way in the slave device and the master
      device.
      3. The frame format (MSB-first or LSB-first depending on the value of the LSBFIRST bit in
      the SPI_CR1 register) must be the same as the master device.
      4. In Hardware mode (refer to Slave select (NSS) pin management), the NSS pin must be
      connected to a low level signal during the complete byte transmit sequence. In NSS
      software mode, set the SSM bit and clear the SSI bit in the SPI_CR1 register.
      5. Clear the MSTR bit and set the SPE bit (both in the SPI_CR1 register) to assign the
      pins to alternate functions.

      그리고 이에 대한 read procedure는 아래와 같습니다.
      Receive sequence
      For the receiver, when data transfer is complete:
       The Data in shift register is transferred to Rx Buffer and the RXNE flag (SPI_SR
      register) is set
       An Interrupt is generated if the RXNEIE bit is set in the SPI_CR2 register

      Receive sequence에 해당하는 함수는 질문 주신 것과 같이 receive 함수로 대체 가능할 것 같은데요.(blocking / pulling 방식)
      동작하지 않는다면 메뉴얼을 다시 참고하시길 바랍니다.

댓글 남기기

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