STM32 I2C - FabLabSeoul/WingProject GitHub Wiki
μ΄ κΈμ Stm32 Value line discovery보λ μ μ© μ€λͺ μ΄λ€.
I2C μ°κ²°. ( !!μμ§λ§μ. SCL, SDA νμ Pull-Up μ νμ κΌ λ¬μμ€μΌ νλ€. )
I2C(inter integrated circuit)λ μ λκ°λ₯λ§ μ°κ²°νλ©΄ μ 보λ₯Ό μ£Όκ³ λ°μ μ μλ ν΅μ νλ‘ν μ½μ λ§νλ€. λ μ μ κ°κ° SCL(Serial CLock), SDA(Serial DAta)λΌκ³ λ§νλ€. ν΅μ μ μμνκ³ λλ Masterμ μ 보λ₯Ό μ£Όκ³ λ°μ μ μλ Slave μν μ΄ μλ€. (λ¬Όλ‘ λ§μ€ν°λ μ 보λ₯Ό μ£Όκ³ λ°μ μ μλ€.) λ§μ€ν° νλμ λ κ°μ΄μμ μ¬λμ΄λΈκ° λΆμ μ μκΈ° λλ¬Έμ, μ μκΈ°κΈ°μ λ΄λΆ μ₯μΉλ€κ°μ ν΅μ μ λ§μ΄ μ°μΈλ€.
νλμ λ§μ€ν°μ λ κ°μ΄μμ μ¬λμ΄λΈκ° λΆμ μ μκΈ° λλ¬Έμ, λκ° μ 보λ₯Ό λ°μμ§μ λν μ 보(Address)λ₯Ό μ‘μ ν΄μΌ νλ€. λν ν΅μ μ μ λ’°μ±μ λμ΄κΈ°μν΄ HandShake λ°©μμ νλ‘ν μ½μ μ¬μ©νκ³ μλ€. λ€μλ§ν΄, μ 보λ₯Ό μ‘μ νκ³ λ ν, ACKμ΄λ²€νΈλ₯Ό λ°μμΌ, λ€μ μ 보λ₯Ό μ‘μ ν μ μλ€. μ μμ μμνκ³ , μ μμ λλ κ²λ λ§μ°¬κ°μ§λ€. (νΈλμΈμ΄νΉ λ°©μ λλ¬Έμ μ½λκ° λ³΅μ‘νλ€.)
κΈμ κ³μ μ½μ΄λκ°κΈ° μ μ λ¨Όμ λ€μ λ¬Έμλ€μ μ½μ΄λ³΄μ.
- stm32f103μμ©.pdf, i2c
- http://lemonkenya.egloos.com/3442831
I2C κΈ°λ³Έ μμ
μμΌλ‘ μ€λͺ ν μμ λ STM32\stm32vldiscovery_package\Project\Examples\I2C ν΄λμ μλ€.
Stm32 MCUμ I2C ν¬νΈ λ κ°λ₯Ό μ¬μ©νμ¬ μλ‘ ν΅μ νλ μμ λ₯Ό 보μ¬μ€λ€. I2C1μ λ§μ€ν°κ° λκ³ , I2C2λ μ¬λμ΄λΈκ° λλ€. (I2Cλ₯Ό μ½κ² μ€λͺ νκΈ° μν μμ μ΄μ§, κ°μ MCUμμ I2C ν΅μ νλ κ²½μ°λ μλ€.)
- PB6 : I2C1_SCL (λ§μ€ν°)
- PB7 : I2C1_SDA (λ§μ€ν°)
- PB10 : I2C2_SCL (μ¬λμ΄λΈ)
- PB11 : I2C2_SDA (μ¬λμ΄λΈ)
κ° ν¬νΈλ λ€μκ³Ό μ°κ²°νλ€.
- PB6 - PB10
- PB7 - PB11
μ¦, SCLμ SCLλΌλ¦¬, SDAλ SDAλΌλ¦¬ μ°κ²°νλ€. I2C1 μμ I2C2λ‘ λ°μ΄νλ₯Ό μ μ‘ν΄μ, μ¬λ°λ‘ μ μ‘λμλμ§ κ²μ¬νλ μμ λ€. μ μ‘νλ μ 보λ 1λ°μ΄νΈ ν¬κΈ°μ΄κ³ , {1,2,3,4} 4κ°μ μ 보λ₯Ό μμλλ‘ λ³΄λΈλ€.
ν΄λ μ΄κΈ°ν
I2Cλ ν΄λμ μ€μ ν΄μ€μΌ νλ€. PB6,7,10,11 ν¬νΈλ₯Ό μ¬μ©νκΈ° λλ¬Έμ, GPIOB ν¬νΈ ν΄λλ μ€μ νλ€.
void RCC_Configuration(void)
{
/* Enable peripheral clocks ------------------------------------------------*/
/* GPIOB Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* I2C1 and I2C2 Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 | RCC_APB1Periph_I2C2, ENABLE);
}
GPIO μ€μ
I2Cλ₯Ό μ¬μ©ν ν¬νΈ PB6,7,10,11 μ μ€μ νλ€. I2C ν¬νΈλ μ ν΄μ Έ μλ€. ν μ΄λΈμ λ€μκ³Ό κ°λ€.
(Stm32f103μμ©.pdf, page 220)
PB6,7(I2C1), PB10,11(I2C2) ν¬νΈλ₯Ό Alternate-Function λͺ¨λλ‘ μ€μ νλ€.
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure I2C1 pins: SCL and SDA ----------------------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure I2C2 pins: SCL and SDA ----------------------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
I2C μ€μ
I2C1,2 λ κ°μ I2Cλͺ¨λμ΄ μλ€. μ΄λ€ λͺ¨λμ μ¬μ©ν μ§ μ ννκ³ , I2Cμ£Όμλ₯Ό μ€μ νλ€. μ£Όμκ° μμΌλ©΄ μ 보λ₯Ό λ°μ μ μλ€. 7λΉνΈμ 10λΉνΈ μ£Όμ νμ μ€ νλλ₯Ό μ ννμ. μ£Όμ νμ μ λ°λΌ μ μ‘ νλ‘ν μ½μ΄ λ°λκΈ° λλ¬Έμ μ£Όμν΄μΌ νλ€.
I2C μ€μ μ κ΄ν μμΈν λ΄μ©μ 맀λ΄μΌμ μ°Έκ³ νμ.
#define I2C1_SLAVE_ADDRESS7 0x30
#define I2C2_SLAVE1_ADDRESS7 0x30
#define ClockSpeed 200000
I2C_InitTypeDef I2C_InitStructure;
/* Enable I2C1 and I2C2 ----------------------------------------------------*/
I2C_Cmd(I2C1, ENABLE);
I2C_Cmd(I2C2, ENABLE);
/* I2C1 configuration ------------------------------------------------------*/
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = ClockSpeed;
I2C_Init(I2C1, &I2C_InitStructure);
/* I2C2 configuration ------------------------------------------------------*/
I2C_InitStructure.I2C_OwnAddress1 = I2C2_SLAVE1_ADDRESS7;
I2C_Init(I2C2, &I2C_InitStructure);
I2Cλ₯Ό μ΄μ©ν λ°μ΄ν μ μ‘
I2Cλ λ§μ€ν° λͺ¨λμΌ λμ μ¬λμ΄λΈ λͺ¨λμΌ λμ λ°λΌ μ 보λ₯Ό μ‘μμ νλ λ°©μμ΄ λ€λ₯΄λ€. μ΄ μμ μμ λ§μ€ν°λ μ‘μ (Transmitter)λ§ νλ€. μ¬λμ΄λΈλ μ 보λ₯Ό μμ (Receiver)λ§ νλ€. I2C νλ‘ν μ½μ λ€μμ κ³Όμ μ κ±°μ³ μ 보λ₯Ό μ‘μμ νκ² λλ€. λ§μ€ν°, μ¬λμ΄λΈ λͺ¨λ 7bit-address λͺ¨λλ€. μμΈν λ΄μ©μ 맀λ΄μΌμ μ°Έκ³ νμ.
I2C νλ‘ν μ½μ λ°μ΄ν° μ μ‘ κ³Όμ μ λ€μκ³Ό κ°λ€.
- λ§μ€ν°κ° μ¬λ μ΄λΈμ μ μ‘μ μμνλ€λ νν - Start
- μ μ‘ λͺ©μ μ§μ μ£Όμ νν - Address
- μ μ‘ λͺ©μ νν(μ½κΈ°μ©μΈκ° λλ μ°κΈ°μ©μΈκ°) - R/W
- μ μ‘ λ°μ΄ν° νν - Data
- μ¬λ μ΄λΈκ° μ μμ μΌλ‘ λ°μ΄ν°λ₯Ό μμ νλ€λ μλ΅ νν - Ack
- μ μ‘ μ’ λ£ νν - Stop
I2C ν΅μ μμ, I2C1-2κ° ν΅μ μ μ°κ²°νλ€.
I2C1 μμ Startλ₯Ό μμνκ³ , I2C2λ‘λΆν° μλ΅μ΄ μ¬ λκΉμ§ λκΈ°νλ€. μ΄ κ³Όμ μ μμ μλ μνμ€ λ€μ΄μ΄κ·Έλ¨μ κ·Έλλ‘ λ°λ₯Έλ€. (μμ€μμ λμ€λ EV1μ μνμ€ λ€μ΄μ΄κ·Έλ¨μ EV8_1 κ³Ό κ°λ€.)
/* Send I2C1 START condition */
I2C_GenerateSTART(I2C1, ENABLE);
/* Test on I2C1 EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
/* Send I2C2 slave Address for write */
I2C_Send7bitAddress(I2C1, I2C2_SLAVE1_ADDRESS7, I2C_Direction_Transmitter);
/* Test on I2C2 EV1 and clear it */
while(!I2C_CheckEvent(I2C2, I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED));
/* Test on I2C1 EV6 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C λ°μ΄ν μ‘μμ
I2C1μμ λ°μ΄νλ₯Ό 보λ΄κ³ , I2C2λ λ°μ΄νλ₯Ό λ°λλ€. 7bit address master transmitterμΈ I2C1μ I2C1_Buffer1_Tx[] λ°°μ΄μ μ μ₯λ μ 보λ₯Ό νλμ© μ‘μ νλ€. 7bit address slave receiverμΈ I2C2λ λ§μ€ν°λ‘λΆν° λμ΄μ¨ μ 보λ₯Ό νλμ© λ°μμ I2C2_Buffer1_Rx[] λ°°μ΄μ μ μ₯νλ€. μ΄ κ³Όμ μ μμ μλ μνμ€ λ€μ΄μ΄κ·Έλ¨μ κ·Έλλ‘ λ°λ₯Έλ€.
uint8_t I2C1_Buffer1_Tx[BufferSize] = {1,2,3,4};
uint8_t I2C2_Buffer1_Rx[BufferSize];
uint8_t Tx_Idx = 0, Rx_Idx = 0;
/* Send data */
while (Rx_Idx < BufferSize)
{
/* Send I2C1 data */
I2C_SendData(I2C1, I2C1_Buffer1_Tx[Tx_Idx++]);
/* Test on I2C2 EV2 and clear it */
while(!I2C_CheckEvent(I2C2, I2C_EVENT_SLAVE_BYTE_RECEIVED));
/* Store received data on I2C2 */
I2C2_Buffer1_Rx[Rx_Idx++] = I2C_ReceiveData(I2C2);
/* Test on I2C1 EV8 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}
I2C ν΅μ μ’ λ£
λ§μ€ν°μΈ I2C1μμ Stop λ©μΈμ§λ₯Ό 보λ΄κ³ μ μμ λλλ€. μ¬λμ΄λΈλ μ μμ΄ λκ²Όλμ§ νμΈνκ³ ν΅μ μ μ’ λ£νλ€.
/* Send I2C1 STOP Condition */
I2C_GenerateSTOP(I2C1, ENABLE);
/* Test on I2C2 EV4 and clear it */
while(!I2C_CheckEvent(I2C2, I2C_EVENT_SLAVE_STOP_DETECTED));
/* Clear I2C2 STOPF flag: read operation to I2C_SR1 followed by a
write operation to I2C_CR1 */
(void)(I2C_GetFlagStatus(I2C2, I2C_FLAG_STOPF));
I2C_Cmd(I2C2, ENABLE);
μμ μ½λ μ 체
μ΄ μμ λ STM32\stm32vldiscovery_package\Project\Examples\I2C ν΄λμ μλ€.
I2C ν¬νΈ λ κ°λ₯Ό μ¬μ©νμ¬ μλ‘ ν΅μ νλ μμ λ₯Ό 보μ¬μ€λ€. ν¬νΈ PB6,7(I2C1)μ λ§μ€ν°κ° λκ³ , ν¬νΈ PB10,11(I2C2)μ μ¬λμ΄λΈκ° λλ€. κ°κ°μ SCL, SDAν¬νΈλ₯Ό μ°κ²°ν΄μ ν μ€νΈ ν΄λ³΄μ. κ·Έλ¦¬κ³ SCL, SDA ν¬νΈμ νμ μ νμ λ¬μμΌ μ λλ‘ λμνλ€.
νλ‘ꡬμ±μ https://harinadha.wordpress.com/2012/07/24/i2c_problem-mpu6050/ λ₯Ό μ°Έμ‘°νμ.
(I2Cλ₯Ό μ½κ² μ€λͺ νκΈ° μν μμ μ΄μ§, κ°μ MCUμμ I2C ν΅μ νλ κ²½μ°λ μλ€.)
(while
λ¬ΈμΌλ‘ ACKλ₯Ό κΈ°λ€λ¦¬κΈ° λλ¬Έμ λ§μ½ I2Cμ μ΄ λκΈ΄λ€λ©΄, μμν λκΈ°ν κ°λ₯μ±μ΄ λλ€. μ€μ μμλ μ΄λ° μ½λλ₯Ό μ°λ©΄μλλ€.)
//
// I2C Test
//
#include "stm32f10x.h"
#include "stm32f10x_i2c.h"
/* Private typedef -----------------------------------------------------------*/
typedef enum { FAILED = 0, PASSED = !FAILED} TestStatus;
/* Private define ------------------------------------------------------------*/
#define I2C1_SLAVE_ADDRESS7 0x30
#define I2C2_SLAVE1_ADDRESS7 0x30
#define BufferSize 4
#define ClockSpeed 200000
I2C_InitTypeDef I2C_InitStructure;
uint8_t I2C1_Buffer1_Tx[BufferSize] = {1,2,3,4};//, I2C1_Buffer2_Tx[BufferSize] = {5,6,7,8};
uint8_t I2C2_Buffer1_Rx[BufferSize];//, I2C2_Buffer2_Rx[BufferSize];
uint8_t Tx_Idx = 0, Rx_Idx = 0;
volatile TestStatus TransferStatus1 = FAILED;//, TransferStatus2 = FAILED;
/* Private functions ---------------------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);
/**
* @brief Main program
* @param None
* @retval None
*/
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
/* Enable I2C1 and I2C2 ----------------------------------------------------*/
I2C_Cmd(I2C1, ENABLE);
I2C_Cmd(I2C2, ENABLE);
/* I2C1 configuration ------------------------------------------------------*/
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = ClockSpeed;
I2C_Init(I2C1, &I2C_InitStructure);
/* I2C2 configuration ------------------------------------------------------*/
I2C_InitStructure.I2C_OwnAddress1 = I2C2_SLAVE1_ADDRESS7;
I2C_Init(I2C2, &I2C_InitStructure);
/*----- First transmission Phase -----*/
/* Send I2C1 START condition */
I2C_GenerateSTART(I2C1, ENABLE);
/* Test on I2C1 EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
/* Send I2C2 slave Address for write */
I2C_Send7bitAddress(I2C1, I2C2_SLAVE1_ADDRESS7, I2C_Direction_Transmitter);
/* Test on I2C2 EV1 and clear it */
while(!I2C_CheckEvent(I2C2, I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED));
/* Test on I2C1 EV6 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
/* Send data */
while (Rx_Idx < BufferSize)
{
/* Send I2C1 data */
I2C_SendData(I2C1, I2C1_Buffer1_Tx[Tx_Idx++]);
/* Test on I2C2 EV2 and clear it */
while(!I2C_CheckEvent(I2C2, I2C_EVENT_SLAVE_BYTE_RECEIVED));
/* Store received data on I2C2 */
I2C2_Buffer1_Rx[Rx_Idx++] = I2C_ReceiveData(I2C2);
/* Test on I2C1 EV8 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}
/* Send I2C1 STOP Condition */
I2C_GenerateSTOP(I2C1, ENABLE);
/* Test on I2C2 EV4 and clear it */
while(!I2C_CheckEvent(I2C2, I2C_EVENT_SLAVE_STOP_DETECTED));
/* Clear I2C2 STOPF flag: read operation to I2C_SR1 followed by a
write operation to I2C_CR1 */
(void)(I2C_GetFlagStatus(I2C2, I2C_FLAG_STOPF));
I2C_Cmd(I2C2, ENABLE);
/* Check the corectness of written data */
TransferStatus1 = Buffercmp(I2C1_Buffer1_Tx, I2C2_Buffer1_Rx, BufferSize);
/* TransferStatus1 = PASSED, if the transmitted and received data
are equal */
/* TransferStatus1 = FAILED, if the transmitted and received data
are different */
while (1)
{
}
}
/**
* @brief Configures the different system clocks.
* @param None
* @retval None
*/
void RCC_Configuration(void)
{
/* Enable peripheral clocks ------------------------------------------------*/
/* GPIOB Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* I2C1 and I2C2 Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 | RCC_APB1Periph_I2C2, ENABLE);
}
/**
* @brief Configures the different GPIO ports.
* @param None
* @retval None
*/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure I2C1 pins: SCL and SDA ----------------------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure I2C2 pins: SCL and SDA ----------------------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/**
* @brief Compares two buffers.
* @param pBuffer1, pBuffer2: buffers to be compared.
* @param BufferLength: buffer's length
* @retval PASSED: pBuffer1 identical to pBuffer2
* FAILED: pBuffer1 differs from pBuffer2
*/
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
{
while(BufferLength--)
{
if(*pBuffer1 != *pBuffer2)
{
return FAILED;
}
pBuffer1++;
pBuffer2++;
}
return PASSED;
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
λ νΌλ°μ€
- http://cafe.daum.net/_c21_/bbs_search_read?grpid=1CJLD&fldid=NRrD&datanum=1
- http://nexp.tistory.com/866
- https://harinadha.wordpress.com/2012/07/24/i2c_problem-mpu6050/
- μμ STM32\STM32F10x_StdPeriph_Lib_V3.3.0\Project\STM32F10x_StdPeriph_Examples\I2C\DualAddress
- μμ STM32\STM32F10x_StdPeriph_Lib_V3.3.0\Project\STM32F10x_StdPeriph_Examples\I2C\10bitAddress
- stm32f103μμ©.pdf, i2c
- http://lemonkenya.egloos.com/3442831
- stm32_i2c.pdf