본문 바로가기

SW 개발 공부/STM8

STM8 I2C

1. 개요

STM8에서 I2C 기능을 구현한다.

 

2. 개념

- SCL, SDA 두개의 선을 통하여 통신하는 프로토콜

- SCL은 clk을 , SDA는 데이터를 전송하는 버스이다.

- 1:N 통신이 가능하며 Master : n Slave로 동작한다.

 

- 데이터를 송수신할때 bit를 shift하여 전송하고 수신함으로, 데이터를 수신받기 위해선 addr를 전송후 2번 수신해야한다.( 원하는 데이터가 2byte일때)

 

** 몰랐던 사실

- i2c는 1byte 통신을 수행한다.

 

3. 함수

 

1) 초기화

I2C_Init(uint32_t OutputClockFrequencyHz, uint16_t OwnAddress, 
              I2C_DutyCycle_TypeDef I2C_DutyCycle, I2C_Ack_TypeDef Ack, 
              I2C_AddMode_TypeDef AddMode, uint8_t InputClockFrequencyMHz )

 

para 1) OutputClockFrequencyHz 

- clk ? 자체적으로 정해줘야함? 

=> stm8s003 기준 100kHz ~400kHz

 

para 2) OwnAddress

 

para 3) I2C_DutyCycle

- duty cycle

para 4) Ack

- ? 어떤식으로 동작하는지>?

para 5) AddMode

- 7bit or 10bit

para 6) InputClockFrequencyMHz 

- 입력 clk

 

 

4. 동작 흐름도

1) slave

마스터가 start 신호를 전송하면  Ack 신호(이는 I2c AcknowlegeConfig를 통해 확인가능)와 event를 생성한다.

 

2) address 매칭

 i) Non General Call

 - 하나의 slave를 갖고있어서, Master가 전송한 address와 slave의 address가 일치하면 EVENT_SLAVE_XXX_ADDRESS_MATCHED 이벤트를 발생

 

TRA, BUSY, TXE and ADDR flags

 

 ii) General Call

 - slave가 General Call에 표시된 address와 동일하다면 

I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED 이벤트를 발생

 

 

I2C 레지스터

 

1. BRR(Bit Rate Register )

 - 전송속도를 설정하는 레지스터

 

2. CR ( Control Register )

TWINT (TWI Interrupt Flag) : 작업을 끝마쳤을때 1로 플래그 한다. 

TWEA (TWI Enable Acknowledge Bit) : 수신했다는 신호를 알리는 ACK신호를 만드는 역할을 한다.

1로 세트되어있고, 수신이 완료되었을때 ACK신호를 보내게 된다.

TWSTA (TWI START Condition Bit) : START 조건을 만들어주는 비트로,

TWI버스가 not busy상태일때 조건을 만들고 busy상태이면 기다리는 역할을 한다.

TWSTO (TWI STOP Condition Bit) : TWI 버스 사용이 끝나면 다른 디바이스를 위해 STOP조건을 만들어 전송.

TWWC (TWI Write Collision Flag) : 충돌 플래그로 작업중일때 쓰기를 시도하면 플래그가 성립된다.

TWEN (TWI Enable Bit) : 말그대로 TWI를 활성화하는 비트이다

TWIE (TWI Interrupt Enable Bit) : TWI 인터럽트를 활성화 하는 비트이다.

 

3. SR(Status Register)

TWS3...7 (TWI Status) : 5개의 비트로 TWI의 로직, 상태를 나타낸다.

TWPS0...1 (TWI Prescaler Bit) : TWI 속도를 계산할때 쓰이는 Prescaler 값을 설정하는 비트.

 

4. DR( Data Register )

TWD0...7 (TWI Data) : 다음 전송할 데이터를 저장하며, 수신일때는 이전 데이터를 갖는다.

 

5. AR( Address Register )

TWA0...6 (TWI slave Address Register) : 7개의 비트로 보낼 slave의 주소를 나타낸다.

 

TWGCE (TWI General Call Enable) : 1일때 general call을 인식하게 한다.

마스터에서 START신호를 발생하고 TWDR에 0x00을 넣으면 general을 의미하며,

TWGCE가 1인 slave들이 응답하게 된다.

 

이벤트 설명

EV1

- master로부터 start signal이 수신될시, Event 발생하고 Ack가 전송된다.

- master로부터 전송된 slave addr과 통신방향에 맞게 Event가 생성

 

< slave Receiver mode >

- EV2:  데이터가 수신될때 발생되는 이벤트
- EV4:  master로부터 stop bit가 전송될때 발생되는 이벤트

 

< slave Transmitter mode>

- EV3: 데이터를 송신할때 발생되는 이벤트 ( 언제 발생하는지>?)
    *      The two events I2C_EVENT_SLAVE_BYTE_TRANSMITTED and I2C_EVENT_SLAVE_BYTE_TRANSMITTING
    *      are similar. The second one can optionally be used when the user software
    *      doesn't guarantee the EV3 is managed before the current byte end of transfer.
- EV3_2: When the master sends a NACK in order to tell slave that data transmission
 shall end (before sending the STOP condition).
 In this case slave has to stop sending data bytes and expect a Stop
    *      condition on the bus.

 

 

 

< Master mode>

EV5

- start bit set 후 전송

- start bit가 정상적으로 bus에 올라갔을시 발생

 

EV6

- EV5 이후, master는 slave address와 통신 방향을 전송함.

- slave는 ack를 전송함.

 

< Master Transmitter mode>

EV8

- data register에 데이터가 써지고 shift register로 데이터 shift 되었을때의 이벤트

 

EV8-2

- shift register에서 물리적 bus로 shift 되었을때의 이벤트

 

 

< Master Receiver mode >

EV7

- 데이터 수신 이벤트

 

 

 

 

 

각 레지스터와 플래그

/* SR1 register flags */
  I2C_FLAG_TXEMPTY             = (uint16_t)0x0180,  /*!< Transmit Data Register Empty flag */
  I2C_FLAG_RXNOTEMPTY          = (uint16_t)0x0140,  /*!< Read Data Register Not Empty flag */
  I2C_FLAG_STOPDETECTION       = (uint16_t)0x0110,  /*!< Stop detected flag */
  I2C_FLAG_HEADERSENT          = (uint16_t)0x0108,  /*!< 10-bit Header sent flag */
  I2C_FLAG_TRANSFERFINISHED    = (uint16_t)0x0104,  /*!< Data Byte Transfer Finished flag */
  I2C_FLAG_ADDRESSSENTMATCHED  = (uint16_t)0x0102,  /*!< Address Sent/Matched (master/slave) flag */
  I2C_FLAG_STARTDETECTION      = (uint16_t)0x0101,  /*!< Start bit sent flag */

  /* SR2 register flags */
  I2C_FLAG_WAKEUPFROMHALT      = (uint16_t)0x0220,  /*!< Wake Up From Halt Flag */
  I2C_FLAG_OVERRUNUNDERRUN     = (uint16_t)0x0208,  /*!< Overrun/Underrun flag */
  I2C_FLAG_ACKNOWLEDGEFAILURE  = (uint16_t)0x0204,  /*!< Acknowledge Failure Flag */
  I2C_FLAG_ARBITRATIONLOSS     = (uint16_t)0x0202,  /*!< Arbitration Loss Flag */
  I2C_FLAG_BUSERROR            = (uint16_t)0x0201,  /*!< Misplaced Start or Stop condition */

  /* SR3 register flags */
  I2C_FLAG_GENERALCALL         = (uint16_t)0x0310,  /*!< General Call header received Flag */
  I2C_FLAG_TRANSMITTERRECEIVER = (uint16_t)0x0304,  /*!< Transmitter Receiver Flag */
  I2C_FLAG_BUSBUSY             = (uint16_t)0x0302,  /*!< Bus Busy Flag */
  I2C_FLAG_MASTERSLAVE         = (uint16_t)0x0301   /*!< Master Slave Flag */

typedef struct I2C_struct
{
  __IO uint8_t CR1;       /*!< I2C control register 1 */
  __IO uint8_t CR2;       /*!< I2C control register 2 */
  __IO uint8_t FREQR;     /*!< I2C frequency register */
  __IO uint8_t OARL;      /*!< I2C own address register LSB */
  __IO uint8_t OARH;      /*!< I2C own address register MSB */
  uint8_t RESERVED1;      /*!< Reserved byte */
  __IO uint8_t DR;        /*!< I2C data register */
  __IO uint8_t SR1;       /*!< I2C status register 1 */
  __IO uint8_t SR2;       /*!< I2C status register 2 */
  __IO uint8_t SR3;       /*!< I2C status register 3 */
  __IO uint8_t ITR;       /*!< I2C interrupt register */
  __IO uint8_t CCRL;      /*!< I2C clock control register low */
  __IO uint8_t CCRH;      /*!< I2C clock control register high */
  __IO uint8_t TRISER;    /*!< I2C maximum rise time register */
  uint8_t RESERVED2;      /*!< Reserved byte */
}

 

 

----------------------의문점

- i2c는 풀업저항을 달아야한다?

 

duty cycle

- 1 clk에서 1이 차지하는 비율

 

각 레지스터의 비트를 아는게 목적? ㄴㄴ 동작이해가 목적

 

1) I2C의 각 인터럽트들이 감지하는 동작은 무엇인가?

I2C_IT_BUF, I2C_IT_EVT, I2C_IT_ERR

=> 버퍼를 감지하여 인터럽트를 바꾸는것을 해제한다.

 

2) 가장 최근 이벤트와 현재 이벤트 

 

pending bit란?

- 인터럽트 동작은 인터럽트가 발생시 인터럽트 플래그가 set되고, 인터럽트 루틴에 들어가며 해당 플래그를 clear 시켜준다.

- 이때, 더 높은 순위의 인터럽트 루틴이 동작되고 있거나 해당 인터럽트가 금지되어있으면 인터럽트 루틴을 대기하는데, 이때 pending bit 가 set 되고 이러한 상태를 interrupt pendding된 상태라고 한다.

 

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=kiatwins&logNo=221153029568

'SW 개발 공부 > STM8' 카테고리의 다른 글

STM8 STVP & STVD 사용법  (0) 2022.03.10