Study/STM32F
I2C로 DS1338 (RTC) 사용하기
Answer Choi
2015. 2. 12. 10:44
반응형
DS1337과 DS1338은 I2C를 이용한 RTC 입니다.
동작전압만 다르고, 똑같다고 생각하시면 됩니다.
DS1337은 RTC를 이용한 시계(윤교수님 stm32f103 보드) 에서 사용했었구요.
이번에는 DS1338을 사용하게 되었습니다.
DS1338이나 DS1337은 I2C를 사용하기 때문에 처음에 초기화를 해주셔야 합니다.
초기화
초기화는 아래 코드에 RTC의 DEVICE ADDRESS를 넣어주시면 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | void I2c_init(u8 addr) { I2C_InitTypeDef I2C_InitStruct; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(I2C_SCL_GPIO_CLK | I2C_SDA_GPIO_CLK, ENABLE); RCC_APB1PeriphClockCmd(I2C_CLK, ENABLE); GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_Init(I2C_SDA_GPIO_PORT, &GPIO_InitStructure); I2C_InitStruct.I2C_Mode = I2C_Mode_I2C; I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; I2C_InitStruct.I2C_ClockSpeed = I2C_SPEED; I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStruct.I2C_OwnAddress1 = addr; I2C_Cmd(I2C, ENABLE); I2C_Init(I2C, &I2C_InitStruct); } | cs |
DS1338이나 DS1337 모두 DEVICE ADDRESS 는 0xD0입니다.
위의 코드는 STM32F103의 I2C1을 사용한 것이구요.
속도는 풀업저항값에따라 바꿀 수 있지만 무난하게 100kHz를 사용하시면 될 것 같습니다.
RTC에 시간을 설정하거나 시간값을 가져올 때도 I2C의 Read / Write 동작을 이용하시면 되는데 RTC 안의
register address를 알아야 합니다.
위의 레지스터 주소를 i2c를 이용하여 값을 가져오거나 쓰면 됩니다.
I2C read 입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | s16 I2C_read(u8 dev_addr,u8 reg_addr) { s16 data=0; I2C_Cmd(I2C, DISABLE); //clear PE I2C_Cmd(I2C, ENABLE); //set PE /* Enable I2C1 acknowledgement if it is already disabled by other function */ I2C_AcknowledgeConfig(I2C, ENABLE); /*----- Transmission Phase -----*/ /* Send I2C1 START condition */ I2C_GenerateSTART(I2C,ENABLE); //start /* Test on I2C1 EV5 and clear it */ while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_MODE_SELECT)); // EV5 /* Test on I2C1 EV5 and clear it */ I2C_Send7bitAddress(I2C, dev_addr, I2C_Direction_Transmitter); // device addr-write mode /* Test on I2C1 EV6 and clear it */ while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // EV6 /* Send the specified register data pointer */ I2C_SendData(I2C, reg_addr); // internel ADDR /* Test on I2C1 EV8_2 and clear it */ while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // EV8_2 /*----- Reception Phase -----*/ /* Send Re-STRAT condition */ I2C_GenerateSTART(I2C, ENABLE); //restart /* Test on EV5 and clear it */ while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_MODE_SELECT)); // EV5 /* Send slave address for read */ I2C_Send7bitAddress(I2C, dev_addr, I2C_Direction_Receiver); // DEVICE ADDR-read mode /* Test on EV6 and clear it */ while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); // EV6(Read) /* Test on EV7 and clear it */ while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_BYTE_RECEIVED)); // EV7 /* Store I2C1 received data */ data = I2C_ReceiveData(I2C); //save data /* Disable I2C1 acknowledgement */ I2C_AcknowledgeConfig(I2C, DISABLE); /* Send I2C1 STOP Condition */ I2C_GenerateSTOP(I2C, ENABLE); //stop Delay_us(100); return data; } | cs |
그리고 I2C write입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | void I2C_write(u8 dev_addr,u8 reg_addr,u8 data) { I2C_Cmd(I2C, DISABLE); //clear PE I2C_Cmd(I2C, ENABLE); //set PE I2C_AcknowledgeConfig(I2C, ENABLE); /*----- Transmission Phase -----*/ /* Send I2C1 START condition */ I2C_GenerateSTART(I2C,ENABLE); // START /* Test on I2C1 EV5 and clear it */ while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_MODE_SELECT)); // EV5 /* Send slave address for write */ I2C_Send7bitAddress(I2C, dev_addr, I2C_Direction_Transmitter); // DEVICE ADDR-write mode /* Test on I2C1 EV6 and clear it */ while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // EV6(Write) /* Send the specified register data pointer */ I2C_SendData(I2C,reg_addr); // internel ADDR /* Test on I2C1 EV8 and clear it */ while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); //EV8 /* Send I2C1 data */ I2C_SendData(I2C,data); // data /* Test on I2C1 EV8_2 and clear it */ while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // EV8_2 /* Disable I2C1 acknowledgement */ I2C_AcknowledgeConfig(I2C, DISABLE); /* Send I2C1 STOP Condition */ I2C_GenerateSTOP(I2C, ENABLE); //stop Delay_us(100); } | cs |
단, 주의하실 점은 DS1337이나 DS1338의 경우 데이터 값이 DEC로 보이는 HEX값으로 저장되어 있습니다.
예를 들어 30분인 경우 0x30으로 저장이 되기 때문에 쓸때나 불러올때 변환을 해줘야 합니다.
반응형