STM32F4 LL I2C 레지스터 및 코드 작성하기

STM32F4 LL I2C 레지스터 및 코드 작성하기

STM32F4 LL I2C 설정 및 코드 작성 프로젝트입니다.

  1. STM32F4 LL I2C 설정 및 ADXL345 레지스터 살펴보기
  2. STM32F4 LL I2C 레지스터 및 코드 작성하기

STM32F4 LL I2C INTRO

LL드라이버를 작성해보는 사람이라면 모두 알겠지만, 레퍼런스 메뉴얼을 참고하지 않고서는 코드를 작성할 수 없다. 더군다나 아트메가로 먼저 i2c를 제어해봤지만, 이건 그것보다 더 복잡하다고 해야하나, 골때리는 것들이 있다.

레퍼런스 메뉴얼 찾아보기

레퍼런스 메뉴얼을 찾아보면 초장부터 기분나쁘게 I2C 는 슬레이브 모드로 동작하는 것이 기본 모드란다. 허허

START비트를 생성 시켜야만 마스터 모드로 동작한단다. 여튼 레퍼런스 메뉴얼에서 제공하는 도식표는 아래와 같이 나왔다.

위 도식표를 순서대로 정리하면 아래와 같을 것이다.

  1. 맨처음 START 신호를 땅땅 내리고 SB가 1이 될때까지 기다린다.
  2. 슬레이브 주소를 써주고 ADDR이 1이 된다.
  3. SR2레지스터를 읽어서 ADDR이 저장된 SR1 레지스터를 초기화 해준다
  4. 데이터를 써준다.
  5. TxE = 1이 될때까지 기다린다.
  6. 보낼만큼 4,5를 반복해준다.
  7. 마지막 데이터를 보낼때 TxE가 1이되고 BTF가 1이될때까지 기다린다.

이상하다 ADXL345를 할땐 쉬워보였는데 이렇게 보니 어려워 보인다. 읽을 때는 어떤지 한번 보자.

위 도식도를 아래 처럼 순서대로 써볼 수 있다.

  1. 시작 신호 땅땅
  2. SB=1이 될때까지 기다린다
  3. 슬레이브 주소 땅땅
  4. ADDR=1이 되고 SR2 레지스터를 읽어서 ADDR을 0으로 초기화해줌
  5. 데이터를 수신하고 RxNE가 0으로 초기화 된다.
  6. 마지막 데이터를 수신하면 ACK과 STOP 리퀘스트를 보낸다.

레지스터를 읽어서 하나하나 보여주는 것이 타당하나, 레퍼런스 메뉴얼을 읽을 줄 안다면 굳이 서술하는 것도 시간낭비일 듯 하다. 여기에서 서술된 레지스터 비트를 바탕으로 LL 드라이버 코드를 찾아보자.

LL 드라이버 코드 찾아보기

위에서 언급 했듯이 I2C를 마스터로 사용하려면 START 컨디션을 생성해줘야한다. LL 드라이버에서 해당 코드를 찾으면 아래와 같다.

공통

void LL_I2C_GenerateStartCondition (I2C_TypeDef * I2Cx)

나는 I2C1 을 사용하니까 입력인자로 I2C1 을 적어주면 된다.

시작 신호를 보냈으면 SB플래그가 선다고 적혀있다. 그러면 SB 관련 LL 드라이버 코드를 찾아보자.

uint32_t LL_I2C_IsActiveFlag_SB (I2C_TypeDef * I2Cx)

START BIT가 1이 되었는지를 확인하는 비트다. 이게 1이 되었다면 마스터 모드로 동작 중이라는 사실을 알 수 있게 되는 것이다. START 컨디션이 1이 되었다면 I2C 를 마스터로 동작할 준비가 된다.

그다음에 주소를 보내거나, 데이터를 보내거나, 레지스터의 값을 보낼 때 사용하는 코드를 찾아보자.

LL_I2C_TransmitData8 (I2C_TypeDef * I2Cx, uint8_t Data)

I2C와 보낼 데이터를 입력 인자로 넣어주면 된다.

주소를 넣어 준 다음에 주소가 제대로 보내졌는지를 확인하는 레지스터를 확인해보자.

uint32_t LL_I2C_IsActiveFlag_ADDR (I2C_TypeDef * I2Cx)

만약 주소를 올바르게 보냈다고 하면 ADDR 비트가 1이 될 것이다. 해당 비트가 1이 되는지를 확인하면 다음 라인으로 진행되도록 코드를 작성하면 될 것이다. 위에서 살펴본 것과 같이 ADDR 비트를 초기화 해줘야 할 것이다. 해당 LL 드라이버 코드를 찾아보자.

void LL_I2C_ClearFlag_ADDR (I2C_TypeDef * I2Cx)

사실 이 함수 말고도 SR2 레지스터에 있는 아무거나 읽어도 ADDR 비트는 초기화 되지만, 굳이 살펴보고 싶지도 않아서 해당 함수를 사용했다.

데이터를 보내고 난 뒤에, 데이터 레지스터가 비워졌는지 확인하기 위해서는 TXE가 1이 되는지를 확인하면 된다고 적혀있으니 TXE 상태 비트를 확인하는 함수도 찾아보자.

송신 파트

uint32_t LL_I2C_IsActiveFlag_TXE (I2C_TypeDef * I2Cx)

Transmit 데이터 레지스터가 비워지면 해당 플래그가 세워지니 이 함수를 잘 사용하면 될 것이다. 계속 데이터를 보내고 이 TXE상태를 확인하면 될 것이다. 마지막 데이터를 보냈다고 하면 모든 데이터가 비워지고 Transfer Finished 플래그가 세워지면 통신을 종료하면 된다. 그럼 BTF플래그도 살펴보자.

uint32_t LL_I2C_IsActiveFlag_BTF (I2C_TypeDef * I2Cx)

그럼 수신의 경우도 살펴보자. 수신의 경우 RXNE가 되서 수신 데이터가 도착했는지를 살펴보고, 수신하면 된다. 해당 레지스터를 살펴보자.

수신 파트

uint32_t LL_I2C_IsActiveFlag_RXNE (I2C_TypeDef * I2Cx)

수신 데이터가 도착하면 해당 플래그가 서는 것을 확인할 수 있다. 모든 데이터를 수신하고 NACK 신호를 발생해야하면 아래 레지스터를 확인하면 될 것이다.

void LL_I2C_AcknowledgeNextData (I2C_TypeDef * I2Cx, uint32_t TypeAcknowledge)

어드레스 매치 코드 다음이나 수신되고 난 다음에ACK이나 NACK 신호를 발생하도록 하는 함수이다. 수신되기 전에 이 함수를 써야하는 것 같지만, 수신하고 난 다음에 해도 뭐 잘 된다.

– LL_I2C_ACK

– LL_I2C_NACK

둘 중 하나의 인자를 넣어주면 된다.

모든 통신이 완료가 되었다면 STOP CONDITION 을 발생해야한다. 그건 아래와 같을 것이다.

void LL_I2C_GenerateStopCondition (I2C_TypeDef * I2Cx)

여튼 이 함수까지 다 봤다면 코드를 짤 수 있다. 이전 포스팅에서 배운 내용을 적용시켜보자.

코드 짜기

송신 예제

코드를 짜는거야 위에 있는 함수를 이해했다면 어렵지 않을 것이다.

수신 예제의 경우도 그리 복잡하지는 않다.

수신 예제

수신 예제는 x, y, z의 데이터를 수신 하는 방법을 적어두겠다. 해석은 따로 해두지 않을테니 전체적인 시퀀스를 이해하고 음미해 보시라.

오늘 포스팅은 여기서 끝!

댓글 남기기

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

%d 블로거가 이것을 좋아합니다: