안녕하세요?
오늘은 I2C통신을 다뤄보겠습니다.
I2C(Inter-Intergrated Circuit)은 TWI(Two Wire Interface)로도 불리며, 2개의 선을 이용하여 여러대의 기기와 연결할 수 있는 통신입니다.
위 그림과 같이 I2C통신에서 Master는 다수의 Slave와 연결되며, Master의 기준으로 클럭(SCL)을 생성합니다.
이 클럭(SCL)에 맞춰 데이터(SDA)를 전송 및 수신합니다.
I2C통신은 송신과 수신이 동시에 이뤄지지 않는 반이중(Half-Duplex)방식을 사용합니다.
I2C통신을 사용방법에 따라 통신 프로토콜이 달라질 수 있습니다.
위에 통신 프로토콜은 1Byte 데이터 전송을 하는 프로토콜 입니다.
이 때 유의해야할 점은 전송 프로토콜에서 Address부분을 유의 해야합니다.
Slave Address는 7bit로 사용되어 집니다. 실제로 데이터를 전송할때 R/W를 정하는 bit와 합쳐 1Byre로 전송하기 떄문에 이 부분을 유의하여야 합니다.
자세한 설명은 위 그림에 설명이 되어있고 밑에 코드 작성 부분에 다시 한번 자세히 설명하겠습니다.
저는 I2C끼리 통신을 하여 Loop Back으로 사용하기 위해 I2C1, I2C2를 활성화 시켰습니다.
I2C2를 Slave로 사용하기 위해 Address를 0x01로 설정하였습니다.
그다음 TIM6를 이용하여 1초 타이머를 만들어서 초당 I2C통신을 사용하기 위해 TIM6를 설정합니다.(타이머 설정은 Basic Timer 부분을 참고해 주세요.)
또한 I2C통신으로 LED를 제어 할 것 이기 떄문에 GPIO_Output으로 2핀을 설정해줍니다.
STM32CubeMX를 설정 했으니 저는 위와같이 변수 및 매크로 정의를 해주도록 합니다.
여기서 유의해서 봐야할 점은 Slave주소 입니다.
분명 위에서 STM32CubeMX에서 0x01로 설정했지만 Coding으로 작성을 할 때는 0x02로 설정을 해야합니다.
이유는 위에 언급한것처럼 데이터를 8bit로 보내기 때문에 Slave Address(7 bit) + R/W(1 bit)를 합쳐 1Byte로 데이터를 전송하기 떄문입니다.
그렇기 떄문에 Slave Adress는 1bit씩 오른쪽으로 쉬프트되는 것입니다.
TIM6는 매초마다 인터럽트를 발생시키도로 STM32CubeMX를 통하여 설정을 하였습니다.
그러므로 HAL_TIM_PeriodElapsedCallback 함수는 1초마다 호출합니다.
위에 Coding을 통해 정해진 문자열을 HAL_I2C_Master_Transmit_IT와 HAL_I2C_Slave_IT를 통해 송/수신을 합니다.
I2C2의 수신 인터럽트 콜백함수를 통해 문자열이 매초마다 송신한 문자열이 제대로 들어오는지 printf를 통해 확인합니다.
그 다음 Main문 안에 Tim6 인터럽트 활성화 함수로 Tim6를 활성화 시킵니다.
다음 While문 안에 strcmp로 수신한 문자열을 비교하여 각 상태에 맞는 led를 제어합니다.
처음 PD8_LED_ON -> PD9_LED_ON -> PD8_LED_OFF -> PD9_LED_OFF 순서로 반복되는것을 확인하실 수 있습니다.
읽어주셔서 감사합니다.