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 |
---|