TODO : GPIO를 이용하여 RTC 디바이스를 사용하기 위해 RTC와 I2C통신을 한다.(즉, 실제 I2C통신을 사용할 땐 주어진 함수를 이용한다.)
*SDA: data, SCL : 디바이스 간 신호 동기화에 사용되는 클럭.
*SCL이 high일 때 data를 읽고 Low일 때 SDA 바뀐다. 이런식으로 통신
(i2c 데이터 통신 중에는 클럭이 high 시그널일 때에는 데이터(SDA) 시그널이 변경되면 안된다. 이러한 규칙으로 인해 클럭이 high인 상태에서는 데이터를 안정적으로 읽는 것을 보장한다.)
*Master 는 cpu, slave는 디바이스들
*Ack는 응답 Ack : 0, 무응답 Ack :1(? – Need to check)
1. 회로도 분석
2. Data Sheet를 보고 set configuration
DDKIomuxSetPinMux DDKGpioSetConfig 등등
3.RTC chip DataSheet 분석
=> Slave address를 알 수 있다.
=> data를 보낼 때 여러개의 data를 연달아 보낼 수 있다. 단 1 < 1s 조건 ->1s이상 해본 결과 처음Write 할때 만 이상하게 들어가고 다시 Write하면 제대로잘 들어감
=> R/W mode 방식
=> data를 보낼 때 여러개의 data를 연달아 보낼 수 있다. 단 1 < 1s 조건
=> Lasty data byte는 지금은 쓰지 않았지만 레지스터에 여러 데이터를 넣는 경우도 있는 것 같다.
그리고 Read mode에서 set register과 read data 사이에 Start, Stop이 존재 해야하며 약 10초정도의
시간이 지나도 읽을 수 있더라.(자세히 모르겟다)
**주요 이슈
1. DataPin을 Read할 수 없었음
-> DDK_GPIO_DIR_IN을 설정하지 않았음, R/W할 때 마다 신경 써야한다…
2. Data Read하는 부분 여러 번 Read하는데 방법을 잘모르겠으며 처음 한번만 잘나오고 뒤에는 쓰래기값이 나온다.
- 문제점 1 :
int bin[8]={0,};
=>bin 배열이 clear 되지 않아서 전에 쓰던 값이 들어가는 문제, 전역변수에서 지역변수로 바꿔줌
- 문제점 2 : Write와 Read의 Data를 읽을 때 Regiter의 주소는 시작하는 주소 하나만 넣어서 8bit씩 읽으면 순차적으로 읽거나 쓸 수 있다.
#define myd_speed (10)
void Start()
{
DDKGpioWriteDataPin(DDK_GPIO_PORT4, 13, 0);
Sleep(myd_speed);
DDKGpioWriteDataPin(DDK_GPIO_PORT4, 12, 0);
Sleep(myd_speed);
//Start 신호-> SCL이High 상태일때, SDA이Low로변하면Start
}
void Stop()
{
DDKGpioWriteDataPin(DDK_GPIO_PORT4, 12, 1);
Sleep(myd_speed);
DDKGpioWriteDataPin(DDK_GPIO_PORT4, 13, 1);
Sleep(myd_speed);
//Stop 신호-> SCL이High 상태일때, SDA이High로변하면Stop
}
void SCL_Clock()
{
DDKGpioWriteDataPin(DDK_GPIO_PORT4, 12, 1);
Sleep(myd_speed);
DDKGpioWriteDataPin(DDK_GPIO_PORT4, 12, 0);
Sleep(myd_speed);
}
//SDA 8bit Data
void Clock_data(int data)
{
int bin[8]={0,}; //주소를역순으로보내기위한배열
int position = 7;
while(data != 0){//bin 배열Clear후저장
bin[position] = data %2;
data /= 2;
position--;
}
for(int i=0;i<8;i++){
DDKGpioWriteDataPin(DDK_GPIO_PORT4, 13, bin[i]);
SCL_Clock();
}
}
void Read_data(int reg_addr)
{
UINT32 pinVal;
RETAILMSG(1, (L"[ I2C Read !!! ] "));
Start();
Clock_data(0xD0);//1101000 (Slave address + Write bit)(7bit + 1bit)
SCL_Clock();//Ack
Clock_data(reg_addr);//input data(data address)
SCL_Clock();//Ack
Stop();
for(int i=0;i<3;i++){//03h ~ 05h만읽는다.
Start();
Clock_data(0xD1);//1101001 (Slave address + Read bit)
SCL_Clock();//Ack
/* print */
RETAILMSG(1, (L"Read Data : ["));
for(int i=0;i<8;i++){
DDKGpioWriteDataPin(DDK_GPIO_PORT4, 12, 1);
Sleep(myd_speed);
DDKGpioSetConfig(DDK_GPIO_PORT4, 13, DDK_GPIO_DIR_IN, DDK_GPIO_INTR_NONE);
//Set DDK_GPIO_DIR_IN For Read mode enable
DDKGpioReadDataPin(DDK_GPIO_PORT4, 13, &pinVal);
RETAILMSG(1, (L"%d",pinVal));
DDKGpioSetConfig(DDK_GPIO_PORT4, 13, DDK_GPIO_DIR_OUT, DDK_GPIO_INTR_NONE);
DDKGpioWriteDataPin(DDK_GPIO_PORT4, 12, 0);
Sleep(myd_speed);
}
RETAILMSG(1, (L"]"));
SCL_Clock();//Ack
Stop();
}
}
BOOL MYD_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn,
DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,
PDWORD pdwActualOut)
{
BOOL bRet = FALSE;
switch(dwCode){
case 1:
/* Init */
DDKIomuxSetPinMux(DDK_IOMUX_PIN_KEY_COL3, DDK_IOMUX_PIN_MUXMODE_ALT5, DDK_IOMUX_PIN_SION_REGULAR);
//datasheet -> IOMUXC_SW_MUX_CTL_PAD_KEY_COL3 의gpio4_12(SCL)( ALT5) 설정(enable)
DDKIomuxSetPinMux(DDK_IOMUX_PIN_KEY_ROW3, DDK_IOMUX_PIN_MUXMODE_ALT5, DDK_IOMUX_PIN_SION_REGULAR);
//datasheet -> IOMUXC_SW_MUX_CTL_PAD_KEY_ROW3 의gpio4_13(SDA)( ALT5) 설정(enable)
DDKGpioSetConfig(DDK_GPIO_PORT4, 12, DDK_GPIO_DIR_OUT, DDK_GPIO_INTR_NONE);
DDKGpioSetConfig(DDK_GPIO_PORT4, 13, DDK_GPIO_DIR_OUT, DDK_GPIO_INTR_NONE);
//12, 13 bit Write mode enable
RETAILMSG(1, (L"[ I2C Write !!! ] "));//Slave address : 1101000(RTC -> Chip : PCF8523TS/1 ) , Read : 1 Write : 0
Start();
Clock_data(0xD0);//1101000 (Slave address + Write bit)(7bit + 1bit)
SCL_Clock();//Ack
/*
03h : Seconds(data address)
04h : Minutes(data address)
05h : Hours(data address)
*/
Clock_data(0x03);
SCL_Clock();//Ack
Clock_data(0x00);//0초[7]:clock integrity is guaranteed, [6-0]
SCL_Clock();//Ack
Clock_data(0x10);//10분[7]: unused, [6-4]: ten's place, [3-0]: unit place
SCL_Clock();//Ack
Clock_data(0x13);//13시[7-6]: unused, 12mode [5] : 0-AM,1-PM, [4]: ten's place,[3-0]: unit place
SCL_Clock();//Ack 24mode [5-4]: ten's place,[3-0]: unit place
Stop();
break;
case 2:
Read_data(0x03);
break;
case 3:
break;
}
return bRet;
}
'kernel Driver' 카테고리의 다른 글
[Atmega128]Character LCD (0) | 2019.04.30 |
---|---|
[Atmega128]PWM(Buzzer) (0) | 2019.04.30 |