개요: I²C(inter-integrated circuit)는 IC 간의 양방향 통신을 가능하게 하는 2-wire 인터페이스이다. 이 애플리케이션 노트에서는 마이크로컨트롤러의 GPIO 핀을 이용해 100kHz 또는 400kHz로 I²C 통신이 가능한 MAXQ2000 마이크로컨트롤러용 소프트웨어 I²C 드라이버에 대해 설명한다. MAXQ 마이크로컨트롤러 제품군은 높은 속도, 유연한 GPIO 모듈, 별도의 I/O 전원 전압을 특징으로 하므로 비트뱅잉(bit-banging) 애플리케이션에 적합하다.
개요
I²C(inter-integrated circuit)는 IC 간에 양방향 통신을 가능하게 하는 2-wire 인터페이스이다. 이 애플리케이션 노트에서는 MAXQ2000 마이크로컨트롤러(µC)용 소프트웨어 I²C 드라이버인 maxqi2c 라이브러리에 대해 설명한다.
maxqi2c 라이브러리는 C로 작성되었으며, MAXQ용 IAR Embedded Workbench를 이용해 컴파일하는 확장을 이용한다. 이 라이브러리는 maxqi2c.h 및 maxqi2c.c의 2개 파일로 구성된다. MAXQ2000 펌웨어 프로젝트에 이 파일을 포함시킴으로써, 마이크로컨트롤러의 GPIO 핀 중 어느 것이든 이용하여 100kHz 또는 400kHz로 유연한 I²C 통신이 가능하다.
MAXQ 마이크로컨트롤러 제품군은 높은 속도, 유연한 GPIO 모듈, 별도의 I/O 전원 전압을 특징으로 하므로 비트뱅잉 애플리케이션에 적합하다.
이 애플리케이션 노트에서 설명하는 프로젝트 예의 파일은 Maxim Integrated Products 웹사이트에서 다운로드할 수 있다.
maxqi2c 라이브러리의 구성
사용자는 maxqi2c 라이브러리 파일(maxqi2c.h 및 maxqi2c.c)을 MAXQ2000 프로젝트 디렉토리로 복사하고 이 파일을 구성해서 원하는 I²C 인터페이스를 생성해야 한다. 다음 코드(Listing 1)의 편집을 통해 모든 구성이 가능하며, maxqi2c.h 소스 파일 상단에서 이 코드를 찾을 수 있다.
Listing 1. maxi2c.h 맞춤화 코드
/* USER MUST CUSTOMIZE THE FOLLOWING DEFINE STMTS - START */
// Enter the port used for SDA and SCL
#define SDA_PORT 0
#define SCL_PORT 0
// Enter the pin used for SDA and SCL
#define SDA_PORT_BIT 0
#define SCL_PORT_BIT 1
// Uncomment one of these define statements to select I²C bus speed
#define I2C_400_KHZ
//#define I2C_100_KHZ
// Comment out the following define statement to disable clock
// stretching in i2cRecv()
#define I2C_CLOCK_STRETCHING
/* USER MUST CUSTOMIZE THE FOLLOWING DEFINE STMTS - END */
참고: 맞춤화는 컴파일 때 구현되므로 런타임 때는 동작하지 않는다.
SCL 및 SDA 핀 선택
SCL 및 SDA의 이용을 위해서는 GPIO 핀 두 개가 선택되어야 한다. SCL 및 SDA를 위한 I/O를 선택한 다음에는, 바람직한 SDA 및 SCL 포트를 반영하기 위해 SDA_PORT 및 SCL_PORT 정의문을 편집해야 한다. 또한 SDA 및 SCL에 대해 원하는 핀을 반영하기 위해 SDA_PORT_BIT 및 SCL_PORT_BIT 정의문을 편집해야 한다.
위의 Listing 1에서 소스 코드는 I/O 포트 0의 핀 0을 SDA로 동작하도록 지정하고 I/O 포트 0의 핀 1을 SCL로 동작하도록 지정했다.
통신 속도 선택
통신 속도 선택은 I2C_400_KHZ 및 I2C_100_KHZ의 2개 문의 하나를 이용해서 이루어진다.
Listing 1의 소스 코드는 400kHz I²C 버스를 이용해 maxqi2c 라이브러리를 통신으로 초기화한다. I²C 인터페이스가 비트뱅잉되므로 실제로는 이 통신이 400kHz(또는 100kHz)에 조금 못미친다. 온전히 400kHz 통신을 달성하기 위해서는 펌웨어 설계자가 maxqi2c 라이브러리를 검토하여 이 라이브러리의 고유의 유연성을 제공하는 일부 소스 코드를 제거해야 한다.
참고:maxqi2c 라이브러리에는 I²C 규격을 충족시키기 위해 지연이 발생된다. maxqi2c.c 파일 상단의 이 지연은 MAXQ2000이 20MHz 시스템 클록을 이용한다는 것을 가정하는 것이다. 이보다 낮은 클록 속도를 이용하면 이 지연을 단축할 수 있다.
클록 스트레칭 이용
maxqi2c 라이브러리의 클록 스트레칭은 i2cRecv() 함수에 대한 호출이 이루어지는 동안 전송 시작 부분에서만 허용된다(어드레스를 전송하는 경우에는 어드레스 확인응답 후에, 혹은 전송을 시작할 때). 그러므로 다음과 같은 형식을 이용해 I²C 전송에 클록 스트레칭을 이용할 수 있다.
maxqi2c 사용법 부분의 i2cRecv()에 대한 설명과 maxqi2c 라이브러리 용례 부분의 코드 예에서 이 형식을 이용해 I²C 명령을 생성하는 방법을 설명하고 있다.
클록 스트레칭을 인에이블하기 위해서는 I2C_CLOCK_STRETCHING 정의문에 주석을 기술하지 않아야 한다. 클록 스트레칭이 필요없으면 I2C_CLOCK_STRETCHING 정의문에 주석을 기술해서 클록 스트레칭을 디스에이블한다. 클록 스트레칭을 디스에이블하면 maxqi2c 라이브러리의 i2cRecv() 함수의 속도가 다소 높아진다.
위 Listing 1의 소스 코드는 클록 스트레칭을 인에이블시킨다.
maxqi2c의 이용
maxqi2c 라이브러리를 이용해 소프트웨어 I²C 드라이버로 데이터를 전송하고 수신하는 것은 i2cInit(), i2cIsAddrPresent(), i2cSend() 및 i2cRecv()의 4개 함수에 의해 이루어진다. 이 함수에 대한 자료가 maxqi2c.h 파일 안에 포함되어 있다.
이 함수는 형식적 파라미터를 필요로 하지 않는다. 대신에 i2cData (부호 없는 문자 *), i2cDataLen (부호 없는 문자), i2cDataAddr (부호 없는 문자) 및 i2cDataTerm 부호 없는 문자)의 4개 전역 변수를 이용해 이 함수의 파라미터를 저장한다. 이 기법은 함수 호출 때 데이터를 복사하지 않음으로써 펌웨어가 더 빠르게 실행될 수 있게 해준다. maxqi2c 라이브러리에 대한 파라미터로 사용되는 4개 전역 변수는 i2cData (부호 없는 문자 *), i2cDataLen (부호 없는 문자), i2cDataAddr (부호 없는 문자) 및 i2cDataTerm (부호 없는 문자)이다.
i2cInit()
어떤 maxqi2c 함수보다도, 이 함수가 먼저 호출되어야 한다. 이 함수가 maxqi2c.h 파일의 맞춤화 코드에서 선택한 포트 핀을 초기화한다. 이 함수는 파라미터(로컬 또는 전역)를 필요로 하지 않으며 값을 리턴하지 않는다.
i2cIsAddrPresent()
이 함수는 MAXQ2000이 I²C 버스를 질의해서 특정 어드레스의 장치가 존재하는지 확인할 수 있도록 한다. 이 함수가 하나의 파라미터 전역 변수 i2cDataAddr을 이용하며, I²C 버스 상에 존재하는지 질의한 장치의 어드레스로 이 변수가 로드되어야 한다. 또한 이 함수는 값(부호 없는 문자 타입)을 리턴한다. 특정 어드레스의 장치가 식별되었으면 이 값은 I2C_XMIT_OK와 동일하고, 특정 어드레스의 장치가 식별되지 않았으면 I2C_XMIT_FAILED와 동일하다.
I²C 버스 상에 특정 장치가 존재하는지 확인하기 위해 i2cIsAddrPresent()가 다음 형식으로 I²C 명령을 전송한다.
[S] [ADDR] [W] [A] [P]
i2cSend()
이 함수는 MAXQ2000이 소프트웨어 I²C 드라이버를 이용해 특정 장치로 데이터를 전송할 수 있도록 한다. i2cSend()가 초기화되려면 다음과 같은 4개 파라미터(모두 전역 변수)를 필요로 한다.
i2cData (부호 없는 문자 *): 전송하려는 바이트 어레이의 첫 번째 바이트 포인터
i2cDataLen (부호 없는 문자): I²C 버스로 전송하려는 바이트 수 (장치 어드레스 포함하지 않음)
i2cDataAddr (부호 없는 문자): 데이터를 전송하려는 장치의 어드레스. 이 변수가 0으로 설정되면 I²C 데이터가 어드레스를 포함하지 않고 전송된다.
i2cDataTerm (부호 없는 문자): I²C 전송이 어떻게 종료되는지를 나타낸다. 이 변수가 i2cSend(): I2C_TERM_NONE이나 I2C_TERM_STOP을 호출해서 2가지 값을 취할 수 있다.
I²C 버스 상의 장치로 데이터를 전송하기 위해 이용되는 형식은 파라미터로 이용되는 4개 전역 변수 값에 따라 결정된다. 표 1은 이 전역 변수의 값에 따른 I²C 명령 형식이다.
표 1. i2cSend()가 전송하는 I²C 명령
i2cDataLen(hex)
i2cDataAddr(hex)
i2cDataTerm
I²C Command Format
0x0002
0x7E
I2C_TERM_STOP
[S] [ADDR] [W] [A] [DATA0] [A] [DATA1] [P]
0x0002
0x7E
I2C_TERM_NONE
[S] [ADDR] [W] [A] [DATA0] [A] [DATA1] [A]
0x0002
0x00
I2C_TERM_NONE
[DATA0] [A] [DATA1] [A]
0x0002
0x00
I2C_TERM_STOP
[DATA0] [A] [DATA1] [A] [P]
참고: 표 1의 마지막 3개 형식은 i2cSend()가 어떻게 I²C 버스 상의 동일 장치로 연속적으로 데이터를 전송하는지 보여준다.
지정된 어드레스의 장치가 모든 바이트를 확인응답하면 i2cSend() 함수가 I2C_XMIT_OK에 해당되는 값(부호 없는 문자 타입)을 리턴하고, 지정된 어드레스의 장치가 바이트를 확인응답하지 않으면 I2C_XMIT_FAILED에 해당되는 값을 리턴한다. 한 바이트라도 확인응답되지 않으면 이 함수가 곧바로 값을 리턴한다.
i2cRecv()
이 함수는 MAXQ2000이 소프트웨어 I²C 드라이버를 이용해 특정 장치로부터 데이터를 수신할 수 있도록 한다. i2cRecv() 함수는 초기화를 위해 다음 4개 파라미터(모두 전역 변수)를 필요로 한다.
i2cData (부호 없는 문자 *): 수신한 값을 저장하려는 바이트 어레이의 첫 번째 바이트 포인터
i2cDataLen (부호 없는 문자): I²C 버스에서 수신하려는 바이트 수 (장치 어드레스 포함하지 않음)
i2cDataAddr (부호 없는 문자): 데이터를 수신할 장치의 어드레스. 이 변수를 0으로 설정하면 어드레스를 전송하지 않고 I²C 데이터가 수신된다.
i2cDataTerm (부호 없는 문자): I²C 전송이 어떻게 종료되는지를 나타낸다. 이 변수는 i2cRecv(): I2C_TERM_NONE, I2C_TERM_ACK 또는 I2C_TERM_NACK_AND_STOP을 호출해서 3가지 값을 취할 수 있다.
I²C 버스 상의 장치로부터 데이터를 수신하기 위해 이용되는 형식은 파라미터로 이용하는 4개 전역 변수의 값에 따라 결정된다. 표 2는 이 전역 변수의 값에 따른 I²C 명령 형식이다.
표 2. 클록 스트레칭이 디스에이블되었을 때 i2cRecv()가 전송하는 I²C 명령
i2cDataLen(hex)
i2cDataAddr(hex)
i2cDataTerm
I²C Command Format
0x0002
0x7E
I2C_TERM_NACK_AND_STOP
[S] [ADDR] [R] [A] [DATA0] [A] [DATA1] [N] [P]
0x0002
0x7E
I2C_TERM_ACK
[S] [ADDR] [R] [A] [DATA0] [A] [DATA1] [A]
0x0002
0x00
I2C_TERM_ACK
[DATA0] [A] [DATA1] [A]
0x0002
0x00
I2C_TERM_NACK_AND_STOP
[DATA0] [A] [DATA1] [N] [P]
참고: 표 2의 마지막 3개 형식은 i2cRecv()가 어떻게 I²C 버스 상의 동일 장치로부터 데이터를 수신하는지를 보여준다.
어드레스가 I²C 명령에 포함되어 전송되고 확인응답되지 않으면 i2cRecv() 함수가 I2C_XMIT_FAILED에 해당되는 값(부호 없는 문자 타입)을 리턴하고, 그렇지 않으면 I2C_XMIT_OK를 리턴한다.
클록 스트레칭이 가능한 maxqi2c 라이브러리 용례
다음 예에서는 maxqi2c 라이브러리를 이용해 MAX1169 ADC로부터 16비트 샘플을 수신하고, 이를 MAXQ의 RS-232 포트를 이용해 PC로 전송하는 것을 설명하고 있다.
회로도
이 예는 MAX1169 ADC EV 킷 및 MAXQ2000 EV 킷(Rev B)을 이용해 구현되었다. 그림 1은 두 EV 킷이 어떻게 연결되었는지를 보여준다. MAXQ2000의 I/O 포트 0의 핀 0 및 핀 1(각각 J2-30 및 J2-28에서 이용 가능)이 I²C 버스 상의 마스터 SDA 및 SCL 라인으로 동작한다.
그림 1. MAX1169 EV 킷과 MAXQ2000 EV 킷(Rev B)이 어떻게 연결되고 maxqi2c 라이브러리가 이용할 수 있도록 준비되었는지 보여준다.
참고: MAXQ2000 EV 킷의 MAXQ2000 고주파 크리스털(Y1)을 20MHz 크리스털로 대체했다. MAX1169 EV 킷의 점퍼 설정과 MAXQ2000 EV 킷의 스위치 설정이 표 3 및 표 4와 같아야 한다.
표 3. MAX1169 EV 킷의 점퍼 설정
Jumper
Shunt Position
JU1
Shunt on pins 1 and 2
JU2
Shunt on pins 1 and 2
JU3
Shunt on pins 1 and 2
JU4
No shunt
JU5
No shunt
표 4. MAXQ2000 EV 킷(Rev B)의 스위치 설정
Switch
Position
SW1-1
OFF
SW1-2
OFF
SW1-3
OFF
SW1-4
ON
SW1-5
OFF
SW1-6
OFF
SW1-7
ON
SW1-8
OFF
SW6-1
OFF
SW6-2
OFF
SW6-3
OFF
SW6-4
OFF
SW6-5
OFF
SW6-6
OFF
SW6-7
OFF
SW6-8
ON
펌웨어
이 예의 펌웨어 파일(max1169.c)은 부록 A와 같다. Maxim MAXQ2000 웹페이지에서 전체 프로젝트를 다운로드할 수 있으며 MAXQ용 IAR Embedded Workbench를 이용해 컴파일할 수 있다. 이 예에서는 maxqi2c 라이브러리의 코드 맞춤화(maxqi2c.h 파일 상단)가 Listing 1의 소스 코드와 동일하다.
max1169.c 파일은 iomaxq200x.h 및 maxqi2c.h의 2개 헤더 파일을 포함한다. 이 예의 iomaxq200x.h 파일이 MAXQ include 패스에서 IAR Embedded Workbench의 iomaxq200x.h 파일을 오버라이드한다. iomaxq200x.h 파일은 maxqi2c 라이브러리에 필요한 모든 포트의 모든 핀에 대한 정의를 생성한다. maxqi2c.h 파일을 포함시킴으로써 펌웨어는 maxqi2c 라이브러리의 함수를 호출할 수 있다.
이 펌웨어는 max1169.c 파일에서 표기한 5단계로 구성된다(부록 A 참조).
1단계는 UART0을 초기화해서 19200bps로 비동기 통신한다. MAXQ2000 시스템 클록이 20MHz가 아니면 레지스터 PR0에 대한 지정을 변경해서 원하는 보(Baud) 속도를 획득하도록 해야 한다.
단계는 MAXQ2000에서 I²C 버스에 이용되는 핀의 초기화를 담당한 i2cInit() 함수를 호출한다.
3단계는 파라미터를 초기화하고 i2cRecv() 함수를 호출한다. 그러면 파라미터가 초기화되고 다음과 같은 형식으로 I²C 명령을 전송한다.
5단계는 무한 반복하는 루프이다. 이 루프가 i2cRecv()를 호출하고 (4단계의 형식으로) MAX1169로부터 16비트 샘플을 수신한다. 이 16비트 샘플이 UART0을 이용해 PC로 전송된다 (MSB 먼저). 종료 파라미터 i2cDataTerm은 언제나 I2C_TERM_ACK와 동일하므로, 루프는 무한 반복하며 MAX1169는 정지 조건을 만나지 않는다.
부록 A: max1169.c
/*
* DEMO of maxqi2c Software I²C Driver
* (uses evkits for the MAX1169 and MAXQ2000)
*
* by: Paul Holden - MAXIM INTEGRATED PRODUCTS
*
*
* DESC: Test program for the maxqi2c.c/maxqi2c.h I²C
* driver for the MAXQ2000. The program reads
* 16-bit samples from the MAX1169 (running in
* continuous conversion mode) and transmits them
* using the UART0 port.
*
* NOTE - THE FOLLOWING CODE ASSUMES THE MAXQ2000 HAS
* A Fsysclk=20MHz.
*/
#include "iomaxq200x.h"
#include "maxqi2c.h"
void main()
{
unsigned char data[2];
// 1. Init UART0
PD7_bit.bit0 = 1; // Set TX0 pin as output
SCON0 = 0x42;
SMD0 = 0x02;
PR0 = 0x07DD; // 19200bps
// 2. Init bit-banged I²C port
i2cInit();
// 3. Send initial I²C request
// [S] [ADDR+R] [A] [clock_stretch] [DATA0] [A] [DATA1] [A (termination)]
i2cData = (unsigned char *)(&data); // cast needed!
i2cDataAddr = 0x7E;
i2cDataLen = 0x0002;
i2cDataTerm = I2C_TERM_ACK;
i2cRecv();
// 4. Init continuous conversion
// [clock_stretch] [DATA0] [A] [DATA1] [A (termination)]
i2cDataAddr = 0x00;
// 5. Receive a 16-bit sample and transfer it to the UART0 port
// one byte at a time. Repeat forever...
while (1)
{
i2cRecv();
while(!SCON0_bit.TI); // Wait for UART0 Buffer to be empty
SCON0_bit.TI = 0; // Reset TI flag
SBUF0 = data[0]; // Send data byte 0
while(!SCON0_bit.TI); // Wait for UART0 Buffer to be empty
SCON0_bit.TI = 0; // reset TI flag
SBUF0 = data[1]; // Send data byte 1
}
}
의견을 보내주세요! 위 내용이 도움이 되셨나요? 여러분의 의견을 기다립니다 — Maxim은 보내주신 정정이나 제안사항을 반영하고 있습니다.
이 페이지를 평가하고 의견을 보내주십시오.