반응형

STM32F10x series MCU를 사용하면서 device의 slave address가 겹치는 2개 이상의 여러 개의 I2C를 제어할 필요가 있을 때 100kHz to 400kHz clock speed 수준의 software I2C example code를 공유한다.

 

참고로 only GPIO으로만 control 하기 때문에 stm32f10x_i2c.h / stm32f10x_i2c.c 관련 STM32 library는 없어도 된다. 그리고 software I2C channel별 GPIO 설정(GPIOC PIN0 , GPIOC PIN14 등)은 user가 임의로 설정하면 된다.

 

# i2c_sw.h

#ifndef __I2C_SW_H
#define __I2C_SW_H

/* includes */
#include "stm32f10x.h"
#include "stdio.h"

/* defines */
#define GPIO_SW_I2C1_SCL           GPIOC
#define GPIO_SW_I2C1_SCL_PIN   GPIO_Pin_0
#define GPIO_SW_I2C1_SDA           GPIOB
#define GPIO_SW_I2C1_SDA_PIN   GPIO_Pin_14

#define GPIO_SW_I2C2_SCL           GPIOB
#define GPIO_SW_I2C2_SCL_PIN   GPIO_Pin_1
#define GPIO_SW_I2C2_SDA           GPIOC
#define GPIO_SW_I2C2_SDA_PIN   GPIO_Pin_1

#define GPIO_SW_I2C3_SCL           GPIOB
#define GPIO_SW_I2C3_SCL_PIN   GPIO_Pin_6
#define GPIO_SW_I2C3_SDA           GPIOB
#define GPIO_SW_I2C3_SDA_PIN   GPIO_Pin_7

#define GPIO_SW_I2C4_SCL GPIOB
#define GPIO_SW_I2C4_SCL_PIN GPIO_Pin_10
#define GPIO_SW_I2C4_SDA GPIOB
#define GPIO_SW_I2C4_SDA_PIN GPIO_Pin_11

#define GPIO_SW_I2C5_SCL           GPIOC
#define GPIO_SW_I2C5_SCL_PIN   GPIO_Pin_6
#define GPIO_SW_I2C5_SDA           GPIOC
#define GPIO_SW_I2C5_SDA_PIN   GPIO_Pin_5

#define GPIO_SW_I2C6_SCL           GPIOA
#define GPIO_SW_I2C6_SCL_PIN   GPIO_Pin_6
#define GPIO_SW_I2C6_SDA           GPIOC
#define GPIO_SW_I2C6_SDA_PIN   GPIO_Pin_8

#define GPIO_SW_I2C7_SCL           GPIOC
#define GPIO_SW_I2C7_SCL_PIN   GPIO_Pin_10
#define GPIO_SW_I2C7_SDA           GPIOA
#define GPIO_SW_I2C7_SDA_PIN   GPIO_Pin_1

#define GPIO_SW_I2C8_SCL           GPIOC
#define GPIO_SW_I2C8_SCL_PIN   GPIO_Pin_12
#define GPIO_SW_I2C8_SDA           GPIOC
#define GPIO_SW_I2C8_SDA_PIN   GPIO_Pin_11

#define GPIO_SW_I2C9_SCL           GPIOB
#define GPIO_SW_I2C9_SCL_PIN   GPIO_Pin_12
#define GPIO_SW_I2C9_SDA           GPIOA
#define GPIO_SW_I2C9_SDA_PIN   GPIO_Pin_5

#define GPIO_SW_I2C10_SCL           GPIOB
#define GPIO_SW_I2C10_SCL_PIN   GPIO_Pin_12
#define GPIO_SW_I2C10_SDA           GPIOA
#define GPIO_SW_I2C10_SDA_PIN   GPIO_Pin_5

#define SW_I2C1		1
#define SW_I2C2		2
#define SW_I2C3		3
#define SW_I2C4		4
#define SW_I2C5		5
#define SW_I2C6		6
#define SW_I2C7		7
#define SW_I2C8		8
#define SW_I2C9		9
#define SW_I2C10	10

/* functions */
void SW_I2C_initial(void);

void i2c_port_initial(uint8_t sel);		

uint8_t SW_I2C_ReadVal_SDA(uint8_t sel);

void SW_I2C_Write_Data(uint8_t sel, uint8_t data);
uint8_t SW_I2C_Read_Data(uint8_t sel);

uint8_t SW_I2C_WriteControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t data);
uint8_t SW_I2C_WriteControl_8Bit_OnlyRegAddr(uint8_t sel, uint8_t IICID, uint8_t regaddr);
uint8_t SW_I2C_WriteControl_16Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint16_t data);

uint8_t SW_I2C_ReadControl_8Bit_OnlyRegAddr(uint8_t sel, uint8_t IICID, uint8_t regaddr);
uint8_t SW_I2C_ReadControl_8Bit_OnlyData(uint8_t sel, uint8_t IICID);
uint16_t SW_I2C_ReadControl_16Bit_OnlyData(uint8_t sel, uint8_t IICID);
uint8_t SW_I2C_ReadControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr);
uint16_t SW_I2C_ReadControl_16Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr);

uint8_t SW_I2C_ReadnControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t rcnt, uint8_t (*pdata));
uint8_t SW_I2C_Multi_ReadnControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t rcnt, uint8_t (*pdata));
uint8_t SW_I2C_Check_SlaveAddr(uint8_t sel, uint8_t IICID);

uint8_t SW_I2C_UTIL_WRITE(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t data);
uint8_t SW_I2C_UTIL_Read(uint8_t sel, uint8_t IICID, uint8_t regaddr);
uint8_t SW_I2C_UTIL_Read_Multi(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t rcnt, uint8_t (*pdata));

#endif  /* __I2C_SW_H */

 

# i2c_sw.c

#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "hw_config.h"

//#define  SW_I2C_WAIT_TIME  26	//100Khz(11.4us)
//#define  SW_I2C_WAIT_TIME  25	//(11.0us)
//#define  SW_I2C_WAIT_TIME  23	//(10.4us)
#define  SW_I2C_WAIT_TIME  22	//100Khz(10.0us)	100Khz	==	10us
//#define  SW_I2C_WAIT_TIME  10	//195Khz
//#define  SW_I2C_WAIT_TIME  9	//205Khz	200Khz	==	5us
//#define  SW_I2C_WAIT_TIME  8	//237Khz
//#define  SW_I2C_WAIT_TIME  7	//240Khz	250Khz	==	4us
//#define  SW_I2C_WAIT_TIME  6	//275Khz
//#define  SW_I2C_WAIT_TIME  5	//305Khz
//#define  SW_I2C_WAIT_TIME  4	//350Khz(3.84us)
//#define  SW_I2C_WAIT_TIME  3	//400Khz(3.44us)
//#define  SW_I2C_WAIT_TIME  2	//425Khz(3.04us)	333Khz	==	3us
//#define  SW_I2C_WAIT_TIME  1	//425Khz(2.64us)	400Khz	==	2.5us

#define  I2C_READ       0x01
#define  READ_CMD       1
#define  WRITE_CMD      0

#define SW_I2C1_SCL_GPIO  GPIO_SW_I2C1_SCL
#define SW_I2C1_SDA_GPIO  GPIO_SW_I2C1_SDA
#define SW_I2C1_SCL_PIN   GPIO_SW_I2C1_SCL_PIN
#define SW_I2C1_SDA_PIN   GPIO_SW_I2C1_SDA_PIN

#define SW_I2C2_SCL_GPIO  GPIO_SW_I2C2_SCL
#define SW_I2C2_SDA_GPIO  GPIO_SW_I2C2_SDA
#define SW_I2C2_SCL_PIN   GPIO_SW_I2C2_SCL_PIN
#define SW_I2C2_SDA_PIN   GPIO_SW_I2C2_SDA_PIN

#define SW_I2C3_SCL_GPIO  GPIO_SW_I2C3_SCL
#define SW_I2C3_SDA_GPIO  GPIO_SW_I2C3_SDA
#define SW_I2C3_SCL_PIN   GPIO_SW_I2C3_SCL_PIN
#define SW_I2C3_SDA_PIN   GPIO_SW_I2C3_SDA_PIN

#define SW_I2C4_SCL_GPIO  GPIO_SW_I2C4_SCL
#define SW_I2C4_SDA_GPIO  GPIO_SW_I2C4_SDA
#define SW_I2C4_SCL_PIN   GPIO_SW_I2C4_SCL_PIN
#define SW_I2C4_SDA_PIN   GPIO_SW_I2C4_SDA_PIN

#define SW_I2C5_SCL_GPIO  GPIO_SW_I2C5_SCL
#define SW_I2C5_SDA_GPIO  GPIO_SW_I2C5_SDA
#define SW_I2C5_SCL_PIN   GPIO_SW_I2C5_SCL_PIN
#define SW_I2C5_SDA_PIN   GPIO_SW_I2C5_SDA_PIN

#define SW_I2C6_SCL_GPIO  GPIO_SW_I2C6_SCL
#define SW_I2C6_SDA_GPIO  GPIO_SW_I2C6_SDA
#define SW_I2C6_SCL_PIN   GPIO_SW_I2C6_SCL_PIN
#define SW_I2C6_SDA_PIN   GPIO_SW_I2C6_SDA_PIN

#define SW_I2C7_SCL_GPIO  GPIO_SW_I2C7_SCL
#define SW_I2C7_SDA_GPIO  GPIO_SW_I2C7_SDA
#define SW_I2C7_SCL_PIN   GPIO_SW_I2C7_SCL_PIN
#define SW_I2C7_SDA_PIN   GPIO_SW_I2C7_SDA_PIN

#define SW_I2C8_SCL_GPIO  GPIO_SW_I2C8_SCL
#define SW_I2C8_SDA_GPIO  GPIO_SW_I2C8_SDA
#define SW_I2C8_SCL_PIN   GPIO_SW_I2C8_SCL_PIN
#define SW_I2C8_SDA_PIN   GPIO_SW_I2C8_SDA_PIN

#define SW_I2C9_SCL_GPIO  GPIO_SW_I2C9_SCL
#define SW_I2C9_SDA_GPIO  GPIO_SW_I2C9_SDA
#define SW_I2C9_SCL_PIN   GPIO_SW_I2C9_SCL_PIN
#define SW_I2C9_SDA_PIN   GPIO_SW_I2C9_SDA_PIN

#define SW_I2C10_SCL_GPIO  GPIO_SW_I2C10_SCL
#define SW_I2C10_SDA_GPIO  GPIO_SW_I2C10_SDA
#define SW_I2C10_SCL_PIN   GPIO_SW_I2C10_SCL_PIN
#define SW_I2C10_SDA_PIN   GPIO_SW_I2C10_SDA_PIN

void TIMER__Wait_us(__IO u32 nCount)
{
    for (; nCount != 0;nCount--);
}

/* internal static functions */
void SW_I2C_initial(void)
{
	GPIO_InitTypeDef			GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;

    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C1_SCL_PIN;
    GPIO_Init(GPIO_SW_I2C1_SCL, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C1_SDA_PIN;
    GPIO_Init(GPIO_SW_I2C1_SDA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C2_SCL_PIN;
    GPIO_Init(GPIO_SW_I2C2_SCL, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C2_SDA_PIN;
    GPIO_Init(GPIO_SW_I2C2_SDA, &GPIO_InitStructure);
	
    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C3_SCL_PIN;
    GPIO_Init(GPIO_SW_I2C3_SCL, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C3_SDA_PIN;
    GPIO_Init(GPIO_SW_I2C3_SDA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C4_SCL_PIN;
    GPIO_Init(GPIO_SW_I2C4_SCL, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C4_SDA_PIN;
    GPIO_Init(GPIO_SW_I2C4_SDA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C5_SCL_PIN;
    GPIO_Init(GPIO_SW_I2C5_SCL, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C5_SDA_PIN;
    GPIO_Init(GPIO_SW_I2C5_SDA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C6_SCL_PIN;
    GPIO_Init(GPIO_SW_I2C6_SCL, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C6_SDA_PIN;
    GPIO_Init(GPIO_SW_I2C6_SDA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C7_SCL_PIN;
    GPIO_Init(GPIO_SW_I2C7_SCL, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C7_SDA_PIN;
    GPIO_Init(GPIO_SW_I2C7_SDA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C8_SCL_PIN;
    GPIO_Init(GPIO_SW_I2C8_SCL, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C8_SDA_PIN;
    GPIO_Init(GPIO_SW_I2C8_SDA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C9_SCL_PIN;
    GPIO_Init(GPIO_SW_I2C9_SCL, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin   = GPIO_SW_I2C9_SDA_PIN;
    GPIO_Init(GPIO_SW_I2C9_SDA, &GPIO_InitStructure);

}

// SDA High
void sda_high(uint8_t sel)
{
    if(sel == 1)
        GPIO_SetBits(SW_I2C1_SDA_GPIO, SW_I2C1_SDA_PIN);
    else if(sel == 2)
        GPIO_SetBits(SW_I2C2_SDA_GPIO, SW_I2C2_SDA_PIN);		
    else if(sel == 3)
        GPIO_SetBits(SW_I2C3_SDA_GPIO, SW_I2C3_SDA_PIN);
    else if(sel == 4)
        GPIO_SetBits(SW_I2C4_SDA_GPIO, SW_I2C4_SDA_PIN);
    else if(sel == 5)
        GPIO_SetBits(SW_I2C5_SDA_GPIO, SW_I2C5_SDA_PIN);
    else if(sel == 6)
        GPIO_SetBits(SW_I2C6_SDA_GPIO, SW_I2C6_SDA_PIN);		
    else if(sel == 7)
        GPIO_SetBits(SW_I2C7_SDA_GPIO, SW_I2C7_SDA_PIN);
    else if(sel == 8)
        GPIO_SetBits(SW_I2C8_SDA_GPIO, SW_I2C8_SDA_PIN);
    else if(sel == 9)
        GPIO_SetBits(SW_I2C9_SDA_GPIO, SW_I2C9_SDA_PIN);
    else if(sel == 10)
        GPIO_SetBits(SW_I2C10_SDA_GPIO, SW_I2C10_SDA_PIN);
}

// SDA low
void sda_low(uint8_t sel)
{
    if(sel == 1)
        GPIO_ResetBits(SW_I2C1_SDA_GPIO, SW_I2C1_SDA_PIN);
    else if(sel == 2)
	GPIO_ResetBits(SW_I2C2_SDA_GPIO, SW_I2C2_SDA_PIN);	
    else if(sel == 3)
	GPIO_ResetBits(SW_I2C3_SDA_GPIO, SW_I2C3_SDA_PIN);
    else if(sel == 4)
	GPIO_ResetBits(SW_I2C4_SDA_GPIO, SW_I2C4_SDA_PIN);
    else if(sel == 5)
	GPIO_ResetBits(SW_I2C5_SDA_GPIO, SW_I2C5_SDA_PIN);
    else if(sel == 6)
	GPIO_ResetBits(SW_I2C6_SDA_GPIO, SW_I2C6_SDA_PIN);	
    else if(sel == 7)
	GPIO_ResetBits(SW_I2C7_SDA_GPIO, SW_I2C7_SDA_PIN);
    else if(sel == 8)
	GPIO_ResetBits(SW_I2C8_SDA_GPIO, SW_I2C8_SDA_PIN);
    else if(sel == 9)
	GPIO_ResetBits(SW_I2C9_SDA_GPIO, SW_I2C9_SDA_PIN);
    else if(sel == 10)
	GPIO_ResetBits(SW_I2C10_SDA_GPIO, SW_I2C10_SDA_PIN);
}

// SCL High
void scl_high(uint8_t sel)
{
    if(sel == 1)
        GPIO_SetBits(SW_I2C1_SCL_GPIO, SW_I2C1_SCL_PIN);
    else if(sel == 2)
        GPIO_SetBits(SW_I2C2_SCL_GPIO, SW_I2C2_SCL_PIN);
    else if(sel == 3)
        GPIO_SetBits(SW_I2C3_SCL_GPIO, SW_I2C3_SCL_PIN);
    else if(sel == 4)
        GPIO_SetBits(SW_I2C4_SCL_GPIO, SW_I2C4_SCL_PIN);
    else if(sel == 5)
        GPIO_SetBits(SW_I2C5_SCL_GPIO, SW_I2C5_SCL_PIN);
    else if(sel == 6)
        GPIO_SetBits(SW_I2C6_SCL_GPIO, SW_I2C6_SCL_PIN);
    else if(sel == 7)
        GPIO_SetBits(SW_I2C7_SCL_GPIO, SW_I2C7_SCL_PIN);
    else if(sel == 8)
        GPIO_SetBits(SW_I2C8_SCL_GPIO, SW_I2C8_SCL_PIN);
    else if(sel == 9)
        GPIO_SetBits(SW_I2C9_SCL_GPIO, SW_I2C9_SCL_PIN);
    else if(sel == 10)
        GPIO_SetBits(SW_I2C10_SCL_GPIO, SW_I2C10_SCL_PIN);
}

// SCL low
void scl_low(uint8_t sel)
{
    if(sel == 1)
        GPIO_ResetBits(SW_I2C1_SCL_GPIO, SW_I2C1_SCL_PIN);
    else if(sel == 2)
        GPIO_ResetBits(SW_I2C2_SCL_GPIO, SW_I2C2_SCL_PIN);
    else if(sel == 3)
        GPIO_ResetBits(SW_I2C3_SCL_GPIO, SW_I2C3_SCL_PIN);
    else if(sel == 4)
        GPIO_ResetBits(SW_I2C4_SCL_GPIO, SW_I2C4_SCL_PIN);
    else if(sel == 5)
        GPIO_ResetBits(SW_I2C5_SCL_GPIO, SW_I2C5_SCL_PIN);
    else if(sel == 6)
        GPIO_ResetBits(SW_I2C6_SCL_GPIO, SW_I2C6_SCL_PIN);
    else if(sel == 7)
        GPIO_ResetBits(SW_I2C7_SCL_GPIO, SW_I2C7_SCL_PIN);
    else if(sel == 8)
        GPIO_ResetBits(SW_I2C8_SCL_GPIO, SW_I2C8_SCL_PIN);
    else if(sel == 9)
        GPIO_ResetBits(SW_I2C9_SCL_GPIO, SW_I2C9_SCL_PIN);
    else if(sel == 10)
        GPIO_ResetBits(SW_I2C10_SCL_GPIO, SW_I2C10_SCL_PIN);
}

void sda_out(uint8_t sel, uint8_t out)
{
    if (out)
    {
        sda_high(sel);
    }
    else
    {
        sda_low(sel);
    }
}

void sda_in_mode(uint8_t sel)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;	//IPD->IPU
		
    if(sel == 1)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C1_SDA_PIN;
        GPIO_Init(SW_I2C1_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 2)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C2_SDA_PIN;
        GPIO_Init(SW_I2C2_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 3)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C3_SDA_PIN;
        GPIO_Init(SW_I2C3_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 4)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C4_SDA_PIN;
        GPIO_Init(SW_I2C4_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 5)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C5_SDA_PIN;
        GPIO_Init(SW_I2C5_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 6)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C6_SDA_PIN;
        GPIO_Init(SW_I2C6_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 7)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C7_SDA_PIN;
        GPIO_Init(SW_I2C7_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 8)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C8_SDA_PIN;
        GPIO_Init(SW_I2C8_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 9)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C9_SDA_PIN;
        GPIO_Init(SW_I2C9_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 10)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C10_SDA_PIN;
        GPIO_Init(SW_I2C10_SDA_GPIO, &GPIO_InitStructure);
    }
}

void sda_out_mode(uint8_t sel)
{
        GPIO_InitTypeDef GPIO_InitStructure;

        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_OD;		// error point GPIO_Mode_Out_PP
		
    if(sel == 1)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C1_SDA_PIN;
        GPIO_Init(SW_I2C1_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 2)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C2_SDA_PIN;
        GPIO_Init(SW_I2C2_SDA_GPIO, &GPIO_InitStructure);
    }		
    else if(sel == 3)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C3_SDA_PIN;
        GPIO_Init(SW_I2C3_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 4)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C4_SDA_PIN;
        GPIO_Init(SW_I2C4_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 5)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C5_SDA_PIN;
        GPIO_Init(SW_I2C5_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 6)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C6_SDA_PIN;
        GPIO_Init(SW_I2C6_SDA_GPIO, &GPIO_InitStructure);
    }		
    else if(sel == 7)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C7_SDA_PIN;
        GPIO_Init(SW_I2C7_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 8)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C8_SDA_PIN;
        GPIO_Init(SW_I2C8_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 9)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C9_SDA_PIN;
        GPIO_Init(SW_I2C9_SDA_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 10)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C10_SDA_PIN;
        GPIO_Init(SW_I2C10_SDA_GPIO, &GPIO_InitStructure);
    }
}

void scl_in_mode(uint8_t sel)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;	//IPD->IPU
		
    if(sel == 1)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C1_SCL_PIN;
        GPIO_Init(SW_I2C1_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 2)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C2_SCL_PIN;
        GPIO_Init(SW_I2C2_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 3)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C3_SCL_PIN;
        GPIO_Init(SW_I2C3_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 4)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C4_SCL_PIN;
        GPIO_Init(SW_I2C4_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 5)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C5_SCL_PIN;
        GPIO_Init(SW_I2C5_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 6)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C6_SCL_PIN;
        GPIO_Init(SW_I2C6_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 7)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C7_SCL_PIN;
        GPIO_Init(SW_I2C7_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 8)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C8_SCL_PIN;
        GPIO_Init(SW_I2C8_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 9)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C9_SCL_PIN;
        GPIO_Init(SW_I2C9_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 10)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C10_SCL_PIN;
        GPIO_Init(SW_I2C10_SCL_GPIO, &GPIO_InitStructure);
    }
}

void scl_out_mode(uint8_t sel)
{
        GPIO_InitTypeDef GPIO_InitStructure;

        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_OD;		// error point GPIO_Mode_Out_PP
		
    if(sel == 1)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C1_SCL_PIN;
        GPIO_Init(SW_I2C1_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 2)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C2_SCL_PIN;
        GPIO_Init(SW_I2C2_SCL_GPIO, &GPIO_InitStructure);
    }		
    else if(sel == 3)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C3_SCL_PIN;
        GPIO_Init(SW_I2C3_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 4)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C4_SCL_PIN;
        GPIO_Init(SW_I2C4_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 5)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C5_SCL_PIN;
        GPIO_Init(SW_I2C5_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 6)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C6_SCL_PIN;
        GPIO_Init(SW_I2C6_SCL_GPIO, &GPIO_InitStructure);
    }		
    else if(sel == 7)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C7_SCL_PIN;
        GPIO_Init(SW_I2C7_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 8)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C8_SCL_PIN;
        GPIO_Init(SW_I2C8_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 9)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C9_SCL_PIN;
        GPIO_Init(SW_I2C9_SCL_GPIO, &GPIO_InitStructure);
    }
    else if(sel == 10)
    {
        GPIO_InitStructure.GPIO_Pin   = SW_I2C10_SCL_PIN;
        GPIO_Init(SW_I2C10_SCL_GPIO, &GPIO_InitStructure);
    }
}

void i2c_clk_data_out(uint8_t sel)
{
    scl_high(sel);
    TIMER__Wait_us(SW_I2C_WAIT_TIME);
    scl_low(sel);
//    TIMER__Wait_us(SW_I2C_WAIT_TIME>>2);
}

void i2c_port_initial(uint8_t sel)
{
    sda_high(sel);
    scl_high(sel);
}

void i2c_start_condition(uint8_t sel)
{
    sda_high(sel);
    scl_high(sel);

    TIMER__Wait_us(SW_I2C_WAIT_TIME);
    sda_low(sel);
    TIMER__Wait_us(SW_I2C_WAIT_TIME);
    scl_low(sel);

    TIMER__Wait_us(SW_I2C_WAIT_TIME << 1);
}

void i2c_stop_condition(uint8_t sel)
{
    sda_low(sel);
    scl_high(sel);

    TIMER__Wait_us(SW_I2C_WAIT_TIME);
    sda_high(sel);
    TIMER__Wait_us(SW_I2C_WAIT_TIME);
}

uint8_t i2c_check_ack(uint8_t sel)
{
    uint8_t         ack;
    int             i;
    unsigned int    temp;

    sda_in_mode(sel);

    scl_high(sel);

    ack = FALSE;
    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    for (i = 10; i > 0; i--)
    {
        temp = !(SW_I2C_ReadVal_SDA(sel));	//0=ack , 1=nack
        if (temp)	// if ack, enter
        {
            ack = TRUE;
            break;
        }
    }
    scl_low(sel);
    sda_out_mode(sel);	//during setting, sda signal high

    TIMER__Wait_us(SW_I2C_WAIT_TIME);
    return ack;
}

void i2c_check_not_ack(uint8_t sel)
{
    sda_in_mode(sel);
    i2c_clk_data_out(sel);
    sda_out_mode(sel);
    TIMER__Wait_us(SW_I2C_WAIT_TIME);
}

void i2c_check_not_ack_continue(uint8_t sel)
{
//    sda_in_mode();
    i2c_clk_data_out(sel);
//    sda_out_mode();
    TIMER__Wait_us(SW_I2C_WAIT_TIME);
}

void i2c_slave_address(uint8_t sel, uint8_t IICID, uint8_t readwrite)
{
    int x;

    if (readwrite)
    {
        IICID |= I2C_READ;
    }
    else
    {
        IICID &= ~I2C_READ;
    }

    scl_low(sel);

    for (x = 7; x >= 0; x--)
    {
        sda_out(sel, IICID & (1 << x));
        TIMER__Wait_us(SW_I2C_WAIT_TIME);
        i2c_clk_data_out(sel);
//        TIMER__Wait_us(SW_I2C_WAIT_TIME);
    }
}

void i2c_register_address(uint8_t sel, uint8_t addr)
{
    int  x;

    scl_low(sel);

    for (x = 7; x >= 0; x--)
    {
        sda_out(sel, addr & (1 << x));
        TIMER__Wait_us(SW_I2C_WAIT_TIME);
        i2c_clk_data_out(sel);
//        TIMER__Wait_us(SW_I2C_WAIT_TIME);
    }
}

void i2c_send_ack(uint8_t sel)
{
    sda_out_mode(sel);
    sda_low(sel);

    TIMER__Wait_us(SW_I2C_WAIT_TIME);
    scl_high(sel);

    TIMER__Wait_us(SW_I2C_WAIT_TIME << 1);

    sda_low(sel);
    TIMER__Wait_us(SW_I2C_WAIT_TIME << 1);

    scl_low(sel);

    sda_out_mode(sel);

    TIMER__Wait_us(SW_I2C_WAIT_TIME);
}

/* external functions */
uint8_t SW_I2C_ReadVal_SDA(uint8_t sel)
{
    if(sel == 1)
        return GPIO_ReadInputDataBit(SW_I2C1_SDA_GPIO, SW_I2C1_SDA_PIN);
    else if(sel == 2)
        return GPIO_ReadInputDataBit(SW_I2C2_SDA_GPIO, SW_I2C2_SDA_PIN);
    else if(sel == 3)
        return GPIO_ReadInputDataBit(SW_I2C3_SDA_GPIO, SW_I2C3_SDA_PIN);
    else if(sel == 4)
        return GPIO_ReadInputDataBit(SW_I2C4_SDA_GPIO, SW_I2C4_SDA_PIN);
    else if(sel == 5)
        return GPIO_ReadInputDataBit(SW_I2C5_SDA_GPIO, SW_I2C5_SDA_PIN);
    else if(sel == 6)
        return GPIO_ReadInputDataBit(SW_I2C6_SDA_GPIO, SW_I2C6_SDA_PIN);
    else if(sel == 7)
        return GPIO_ReadInputDataBit(SW_I2C7_SDA_GPIO, SW_I2C7_SDA_PIN);
    else if(sel == 8)
        return GPIO_ReadInputDataBit(SW_I2C8_SDA_GPIO, SW_I2C8_SDA_PIN);
    else if(sel == 9)
        return GPIO_ReadInputDataBit(SW_I2C9_SDA_GPIO, SW_I2C9_SDA_PIN);
    else if(sel == 10)
        return GPIO_ReadInputDataBit(SW_I2C10_SDA_GPIO, SW_I2C10_SDA_PIN);
    return 0;
}

uint8_t SW_I2C_ReadVal_SCL(uint8_t sel)
{
    if(sel == 1)
        return GPIO_ReadInputDataBit(SW_I2C1_SCL_GPIO, SW_I2C1_SCL_PIN);
    else if(sel == 2)
        return GPIO_ReadInputDataBit(SW_I2C2_SCL_GPIO, SW_I2C2_SCL_PIN);
    else if(sel == 3)
        return GPIO_ReadInputDataBit(SW_I2C3_SCL_GPIO, SW_I2C3_SCL_PIN);
    else if(sel == 4)
        return GPIO_ReadInputDataBit(SW_I2C4_SCL_GPIO, SW_I2C4_SCL_PIN);
    else if(sel == 5)
        return GPIO_ReadInputDataBit(SW_I2C5_SCL_GPIO, SW_I2C5_SCL_PIN);
    else if(sel == 6)
        return GPIO_ReadInputDataBit(SW_I2C6_SCL_GPIO, SW_I2C6_SCL_PIN);
    else if(sel == 7)
        return GPIO_ReadInputDataBit(SW_I2C7_SCL_GPIO, SW_I2C7_SCL_PIN);
    else if(sel == 8)
        return GPIO_ReadInputDataBit(SW_I2C8_SCL_GPIO, SW_I2C8_SCL_PIN);
    else if(sel == 9)
        return GPIO_ReadInputDataBit(SW_I2C9_SCL_GPIO, SW_I2C9_SCL_PIN);
    else if(sel == 10)
        return GPIO_ReadInputDataBit(SW_I2C10_SCL_GPIO, SW_I2C10_SCL_PIN);
    return 0;
}

void SW_I2C_Write_Data(uint8_t sel, uint8_t data)
{
    int  x;

    scl_low(sel);

    for (x = 7; x >= 0; x--)
    {
        sda_out(sel, data & (1 << x));
        TIMER__Wait_us(SW_I2C_WAIT_TIME);
        i2c_clk_data_out(sel);
//        TIMER__Wait_us(SW_I2C_WAIT_TIME);
    }
}

uint8_t SW_I2C_Read_Data(uint8_t sel)
{
    int      x;
    uint8_t  readdata = 0;

    sda_in_mode(sel);

    for (x = 8; x--;)
    {
        scl_high(sel);

        readdata <<= 1;
        if (SW_I2C_ReadVal_SDA(sel))
            readdata |= 0x01;

        TIMER__Wait_us(SW_I2C_WAIT_TIME);
        scl_low(sel);

        TIMER__Wait_us(SW_I2C_WAIT_TIME);
    }

    sda_out_mode(sel);
    return readdata;
}

uint8_t SW_I2C_WriteControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t data)
{
    uint8_t   returnack = TRUE;

    i2c_start_condition(sel);

    i2c_slave_address(sel, IICID, WRITE_CMD);
    if (!i2c_check_ack(sel))
    {
        returnack = FALSE;
    }

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    i2c_register_address(sel, regaddr);
    if (!i2c_check_ack(sel))
    {
        returnack = FALSE;
    }

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    SW_I2C_Write_Data(sel, data);
    if (!i2c_check_ack(sel))
    {
        returnack = FALSE;
    }

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    i2c_stop_condition(sel);

    return returnack;
}

uint8_t SW_I2C_WriteControl_8Bit_OnlyRegAddr(uint8_t sel, uint8_t IICID, uint8_t regaddr)
{
    uint8_t   returnack = TRUE;

    i2c_start_condition(sel);

    i2c_slave_address(sel, IICID, WRITE_CMD);
    if (!i2c_check_ack(sel))
    {
        returnack = FALSE;
    }

    i2c_register_address(sel, regaddr);
    if (!i2c_check_ack(sel))
    {
        returnack = FALSE;
    }

//    i2c_stop_condition(sel);

    return returnack;
}

uint8_t SW_I2C_WriteControl_16Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint16_t data)
{
    uint8_t   returnack = TRUE;

    i2c_start_condition(sel);

    i2c_slave_address(sel, IICID, WRITE_CMD);
    if (!i2c_check_ack(sel))
    {
        returnack = FALSE;
    }

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    i2c_register_address(sel, regaddr);
    if (!i2c_check_ack(sel))
    {
        returnack = FALSE;
    }

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    SW_I2C_Write_Data(sel, (data >> 8) & 0xFF);
    if (!i2c_check_ack(sel))
    {
        returnack = FALSE;
    }

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    SW_I2C_Write_Data(sel, data & 0xFF);
    if (!i2c_check_ack(sel))
    {
        returnack = FALSE;
    }

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    i2c_stop_condition(sel);

    return returnack;
}

uint8_t SW_I2C_ReadControl_8Bit_OnlyRegAddr(uint8_t sel, uint8_t IICID, uint8_t regaddr)
{
    uint8_t   returnack = TRUE;

    i2c_start_condition(sel);

    i2c_slave_address(sel, IICID, WRITE_CMD);
    if (!i2c_check_ack(sel))
    {
        returnack = FALSE;
    }

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    i2c_register_address(sel, regaddr);
    if (!i2c_check_ack(sel))
    {
        returnack = FALSE;
    }

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    i2c_stop_condition(sel);

    return returnack;
}

uint8_t SW_I2C_ReadControl_8Bit_OnlyData(uint8_t sel, uint8_t IICID)
{
    uint8_t  readdata = 0;

    i2c_port_initial(sel);

    i2c_start_condition(sel);

    i2c_slave_address(sel, IICID, READ_CMD);
    i2c_check_ack(sel);

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    readdata = SW_I2C_Read_Data(sel);

    i2c_check_not_ack(sel);

    i2c_stop_condition(sel);

    return readdata;
}

uint16_t SW_I2C_ReadControl_16Bit_OnlyData(uint8_t sel, uint8_t IICID)
{
    uint8_t  readimsi = 0;
    uint16_t  readdata = 0;

    i2c_start_condition(sel);

    i2c_slave_address(sel, IICID, READ_CMD);
    i2c_check_not_ack(sel);

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    readimsi = SW_I2C_Read_Data(sel);
    i2c_check_not_ack_continue(sel);

    readdata = readimsi<<8;

    readimsi = SW_I2C_Read_Data(sel);
    i2c_check_not_ack(sel);


    readdata |= readimsi;

    i2c_stop_condition(sel);

    return readdata;
}

uint8_t SW_I2C_ReadControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr)
{
    uint8_t  readdata = 0;

    i2c_port_initial(sel);

    i2c_start_condition(sel);

    i2c_slave_address(sel, IICID, WRITE_CMD);
    i2c_check_ack(sel);

    i2c_register_address(sel, regaddr);
    i2c_check_ack(sel);

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    i2c_start_condition(sel);

    i2c_slave_address(sel, IICID, READ_CMD);
    i2c_check_ack(sel);

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    readdata = SW_I2C_Read_Data(sel);

    i2c_check_not_ack(sel);

    i2c_stop_condition(sel);

    return readdata;
}

uint16_t SW_I2C_ReadControl_16Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr)
{
    uint16_t  readdata = 0;

    i2c_port_initial(sel);

    i2c_start_condition(sel);

    i2c_slave_address(sel, IICID, WRITE_CMD);
    i2c_check_ack(sel);

    i2c_register_address(sel, regaddr);
    i2c_check_ack(sel);

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    i2c_start_condition(sel);

    i2c_slave_address(sel, IICID, READ_CMD);
    i2c_check_ack(sel);

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    readdata = SW_I2C_Read_Data(sel);
    i2c_send_ack(sel);
    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    readdata = ((readdata << 8) | SW_I2C_Read_Data(sel));

    i2c_check_not_ack(sel);

    i2c_stop_condition(sel);

    return readdata;
}

uint8_t SW_I2C_ReadnControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t rcnt, uint8_t (*pdata))
{
    uint8_t   returnack = TRUE;
    uint8_t  index;

    i2c_port_initial(sel);

    i2c_start_condition(sel);

    i2c_slave_address(sel, IICID, WRITE_CMD);
    if (!i2c_check_ack(sel)) { returnack = FALSE; }

    TIMER__Wait_us(SW_I2C_WAIT_TIME);
	
    i2c_register_address(sel, regaddr);
    if (!i2c_check_ack(sel)) { returnack = FALSE; }

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    i2c_start_condition(sel);

    i2c_slave_address(sel, IICID, READ_CMD);
    if (!i2c_check_ack(sel)) { returnack = FALSE; }

    for ( index = 0 ; index < rcnt ; index++){
    	TIMER__Wait_us(SW_I2C_WAIT_TIME);
    	pdata[index] = SW_I2C_Read_Data(sel);
    }

    pdata[rcnt-1] = SW_I2C_Read_Data(sel);
	
    i2c_check_not_ack(sel);

    i2c_stop_condition(sel);

    return returnack;
}

uint8_t SW_I2C_Multi_ReadnControl_8Bit(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t rcnt, uint8_t (*pdata))
{
    uint8_t   returnack = TRUE;
    uint8_t  index;

    i2c_port_initial(sel);

    i2c_start_condition(sel);

    i2c_slave_address(sel, IICID, WRITE_CMD);
    if (!i2c_check_ack(sel)) { returnack = FALSE; }

    TIMER__Wait_us(SW_I2C_WAIT_TIME);
	
    i2c_register_address(sel, regaddr);
    if (!i2c_check_ack(sel)) { returnack = FALSE; }

    TIMER__Wait_us(SW_I2C_WAIT_TIME);

    i2c_start_condition(sel);

    i2c_slave_address(sel, IICID, READ_CMD);
    if (!i2c_check_ack(sel)) { returnack = FALSE; }

    for ( index = 0 ; index < (rcnt-1) ; index++){
    	TIMER__Wait_us(SW_I2C_WAIT_TIME);
    	pdata[index] = SW_I2C_Read_Data(sel);
	i2c_send_ack(sel);
	//if (!i2c_check_ack(sel)) { returnack = FALSE; }
    }

    pdata[rcnt-1] = SW_I2C_Read_Data(sel);
	
    i2c_check_not_ack(sel);

    i2c_stop_condition(sel);

    return returnack;
}

uint8_t SW_I2C_Check_SlaveAddr(uint8_t sel, uint8_t IICID)
{
    uint8_t   returnack = TRUE;

    i2c_start_condition(sel);

    i2c_slave_address(sel, IICID, WRITE_CMD);
    if (!i2c_check_ack(sel))
    {
        returnack = FALSE;
    }
	
    return returnack;
}

uint8_t SW_I2C_UTIL_WRITE(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t data)
{
	return SW_I2C_WriteControl_8Bit(sel, IICID<<1, regaddr, data);
}

uint8_t SW_I2C_UTIL_Read(uint8_t sel, uint8_t IICID, uint8_t regaddr)
{
	return SW_I2C_ReadControl_8Bit(sel, IICID<<1, regaddr);
}

uint8_t SW_I2C_UTIL_Read_Multi(uint8_t sel, uint8_t IICID, uint8_t regaddr, uint8_t rcnt, uint8_t (*pdata))
{
	return SW_I2C_Multi_ReadnControl_8Bit(sel, IICID<<1, regaddr, rcnt, pdata);
}
반응형
반응형

청주 테크노폴리스 푸르지오에 입주한지 벌써 1년이 흘러 지나갔다.

그 와중에 동네 상권 활성화에 일조하기 위해 동네 맛집을 하나둘씩 찾아 다니면서 식도락 투어를 하고 있는 와중에 그동안 개인적으로 맛있었던 식당은 블로그에 포스팅을 하고 있었는데, '그림바위'라는 쭈꾸미 철판 구이 식당을 맛집 포스팅 하게 되었다.

 

'그림바위' 식당은 도심지 및 대로변에 위치한 곳이 아니고, 꾸불꾸불한 시골길(?)을 일부러 찾아가야 할 정도로 한적한 곳에 있는데, 아래 사진처럼 조용한 분위기 속에서 레트로 감성을 느끼면서 여유롭게 식사를 하고 싶다면 추천을 하고자 한다.

 

식당을 방문하게 되면 마주하게 될 홀
기본적으로 나오는 밑반찬
쭈꾸미 2인분이 올려진 철판
점점 맛있게 익어가는 귀여운 쭈꾸미들
좀더 맛있게 먹기 위해 콩나물 추가
김과 무쌈, 콩나물 그리고 쭈꾸미와 함께 싸먹으면 고소하고 담백하게 맛있다!

아쉽게도 쭈꾸미 철판 구이의 끝판왕인 철판 볶음밥 사진이 빠뜨렸다. 다음번에 방문하게 되면 내용 업데이트를 해야겠다.

 

마지막으로 '그림바위' 찾아가는 길은 아래와 같다. 식당 방문 전에 주인장에게 미리 연락하고 방문하는 것을 권장한다.

 

  • 식당 : 그림바위
  • 주소 : 충북 청주시 흥덕구 문암로 177번길 7
  • 예약 전화번호 : 010-9418-2209

 

반응형
반응형

1. 개발 환경 설치

1.1. JDK (Java Development Kit) 설치

1.2. GNU Arm Embedded Toolchain 설치

1.3. 이클립스 (Eclipse) IDE 설치

1.3.1. Eclipse CDT용 플러그인 설치

1.3.2. GNU MCU Eclipse 설치 – STM32F series firmware compile 

1.3.3.  cygwin 설치 - 내용 추가

 

1.1. JDK (Java Development Kit)

(1) Java platform으로 구동되는 이클립스 (Eclipse) 통합 개발 환경에서 GCC compile 관련 개발 및 실행하기 위해 JDK (Java Development Kit) 설치를 필요로 하며, 기존에 설치 되어 있을 경우 생략하여도 된다.

 

(2) 아래 경로에 접속을 하여서 JDK 관련 Setup 파일을 다운로드 한다.

https://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html#javasejdk

 

(3)  Accept License Agreement 라디오 버튼을 클릭 후, “jdk-13.0.1_windows-x64_bin.exe”를  다운로드 한 후에 해당 파일을 실행하여 설치 프로세스를 진행한다.

 

(4) 위와 같이 정상적으로 설치 프로세스를 진행하여 JDK 관련 설치를 종료한다. 

 

1.2. GNU Arm Embedded Toolchain 설치

 (1) Windows 환경에서 GCC 컴파일을 하기 위해 GNU Arm Embedded Toolchain 관련 설치를 진행해야 하며, 아래 경로에서 해당 다운로드를 하여 관련 GCC 컴파일 환경 설정을 한다.
[GNU Arm Embedded Toolchain : ARM
용 compiler, Linker, Debugger 등이 포함된 Toolchain]

https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm

 

(2) 해당 경로의 web page에서 “GNU-RM” 리스트 박스를 선택하여 ‘Downloads’ page로 이동을 한다.

(3) ‘Downloads’ page에서 가장 최신 versionGNU Arm Embedded Toolchain을 다운로드한다.
※ 작성 시점의 version : GNU Arm Embedded Toolchain: 9-2019-q4-major November 06, 2019

(4) Windows 32-bit installer typeWindows 32-bit ZIP package type를 선택하여 Toolchain 환경을 설치할 수가 있는데, ‘gcc-arm-none-eabi-9-2019-q4-major-win32.zip’를 선택하여 관련 설정을 하도록 한다.

 

(5) Windows 32-bit ZIP package을 원하는 폴더에 다운로드 하고 압축 해제를 한다.

(6) GNU Arm Embedded Toolchain 경로 설정을 위해 사용자 PC의 시스템 속성의 환경변수 탭을 선택한다.

 

 (7) 환경변수의 시스템 변수(S)’ 항목에서 새로 만들기(W)’을 선택하여 변수 이름에는 ‘gcc-arm-none-eabi’를 입력하고, 변수 값에는 아래와 같이 GNU Arm Embedded Toolchain을 압축 해제한 경로를 입력하고 확인 버튼을 누른다.

 

(8) 이어서 환경변수의 시스템 변수(S) -> Path 변수항목의 편집을 선택하고, Path 환경변수 편집 창에서 새로 만들기를 누른 후에 ‘%gcc-arm-none-eabi%\bin’를 입력한다.

 

(9) 위와 같이 환경변수 관련 설정을 마치면, 아래와 같이 Command Window에서 ‘arm-none-eabi-gcc --version’를 실행하여 정상적으로 GNU Arm Embedded toolchain이 설정되어 있는지 확인할 수가 있다.

 

 

1.3. 클립스 (Eclipse) IDE 설치

 (1) GNU Arm Embedded Toolchain 환경에서 STM32F series firmwaregcc compiler 환경에서 compile를 하기위해 이클립스 (Eclipse) IDE를 설치해야 한다. 아래 경로에서 이클립스 IDE 설치 파일을 다운로드 한다.

https://www.eclipse.org/downloads/packages/release/2019-12/r
 

(2) 위의 사이트에서 ‘Eclipse IDE for C/C++ Developers’ 설치 파일을 다운 받는다.

 

(3) 위의 Eclipse portable 실행 파일을 원하는 디렉토리에 다운로드를 하고 ‘eclipse.exe’를 실행하면 아래와 같은 화면이 나타나며, 사용자 임의 ‘workspace’를 설정한다.

 

(4) 아래 그림은 정상적으로 Eclipse IDE 환경이 실행된 화면이다.

 

 

1.3.1.      Eclipse CDT용 플러그인 설치

Eclipse C/C++뿐만 아니라 다양한 프로그래밍 언어 및 대상 플랫폼 개발 환경을 지원하며, ARM GCC를 위한 플러그-인을 추가로 설치한다. 참고로 Install New software 및 Eclipse marketplace에서 아래 플러그인들을 추가설치 하면, 대부분의 사이트에서 안내하는 ‘GNU MCU Eclipse - window build tool 설치’ 절차를 생략하여도 된다.

 

(1) Eclipse를 실행 후,

(2) 메뉴 항목, Help > Install New Software 선택 하면 ‘Install’ 창이 나타난다.

 

(3) ‘Work with’ 탭박스의 ‘Available Software Site’를 누르면 여러 사이트 주소창이 나오는데 아래 항목 선택

 

     "CDT - http://download.eclipse.org/tools/cdt/releases/9.10"

 

(4) 잠시 기다리면 CDT Main Features CDT Optional Features가 나오는데 순차적으로 선택을 한다.

 

# CDT Main Features     

▣ C/C++ Development Tools SDK 9.10.0.201912051559

 

# CDT Optional Features

▣ C/C++ Autotools support Developer Resources   9.10.0.201911192140

▣ C/C++ C99 LR Parser  9.10.0.201910281707

▣ C/C++ GCC Cross Compiler Support Developer Resources 9.10.0.201910171407

▣ C/C++ GDB Hardware Debugging Developer Resources   9.10.0.201911010936

▣ C/C++ Memory View Enhancements Developer Resources 9.10.0.201910171407

 

(5) ‘I accept the terms of the license agreement’를 선택하고 ‘Finish’를 누르면 Eclipse software 실행 화면 우측 하단에 아래와 같이 install progress bar를 확인할 수가 있다.

 

(6) 정상적으로 Eclipse IDE Install software 설치 완료 되었으면, 아래와 같은 창이 나타나는데 ‘Restart Now’를 선택해서 재시작을 한다.

 

 

1.3.2.      GNU MCU Eclipse 설치 – STM32F series firmware compile

(1) C/C++ Development Tools SDK 플러그인 설치 완료 후, GNU MCU Eclipse 관련 설치가 필요하며, 이를 설치하기 위해 메뉴 항목의 Help > Eclipse Marketplace를 선택한다.

(2) ‘Eclipse Marketplace’ 창의 ‘Search-Find’ 항목에 ‘GNU-MCU’를 입력하면 다음과 같이 검색이 된다.

 

(3)   ‘GNU MCU Eclipse 4.7.1’ 설치 항목은 대부분 설치를 하는 것을 권장하며 모두 선택한 후에 ‘Confirm’을 선택한다.

 

(4) ‘I accept the terms of the license agreement’를 선택하고 ‘Finish’를 누르고 정상적으로 설치가 되면 다음과 같은 창이 나타나는데 ‘Restart Now’를 선택하면 된다.

 

 

1.3.3.      Cygwin 설치

새로운 PC에 위의 과정(To. 1.3.2)을 최신 version 설치하면서, 기존 프로젝트를 불러온 후에, 아래와 같은 에러 메세지가 나타나면서 compile이 안되는 문제가 있었다.

 

C / C++ IDE (CDT) » "make" is not found in PATH hello( "make" is not found in PATH hello)

 

아래와 같은 프로그램으로 리눅스 관련 명령어가 실행되도록 해야한다. 아래 사이트에 가서 설치하고, 환경설정을 하여주면된다.

https://www.cygwin.com/

 

Cygwin

Cygwin Get that Linux feeling - on Windows This is the home of the Cygwin project What... ...is it? Cygwin is: a large collection of GNU and Open Source tools which provide functionality similar to a Linux distribution on Windows. a DLL (cygwin1.dll) which

www.cygwin.com

 글을 남기는 시점에서 개발환경의 Version 은 아래와 같다.

 

반응형
반응형

Eclipse IDE 환경에서 printf() 함수 사용시에는 아래와 같이 hwconfig.c 에서 정의해야 한다.

 

#ifdef __GNUC__
	/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
	 set to 'Yes') calls __io_putchar() */
	#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
	#define GETCHAR_PROTOTYPE int __io_getchar(int ch)
#else
	#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
	#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
#endif /* __GNUC__ */

PUTCHAR_PROTOTYPE		// for printf use USART1
{
	// Write a character to the USART
	if( ch == '\n')
	{
		USART_SendData(USART1, '\r');
		while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
		USART_SendData(USART1, '\n');
	}
	else
	{
		USART_SendData(USART1, (uint8_t) ch);
	}

	// Loop until the end of transmission
	while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

	return ch;
}

GETCHAR_PROTOTYPE		// for printf use USART1
{
	while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET){}; 
	return USART_ReceiveData(USART1);
}

그리고 특정 source file에 printf() 함수를 추가하고 build를 진행하면 아래와 같이 compile error가 발생하는데, 이 부분은 gcc compile system의 standard I/O function call에 따른 이슈로 인하여 발생되는 문제이며, 해결 방안은 syscalls.c 파일을 프로젝트에 추가하여 함께 build 하면 된다. (참고로 IAR compiler 환경에서는 해당 printf() 함수 사용 할 경우 optimization linking 및 compile 되어 build image가 생성된다.)

 

# compile error case

/usr/lib/gcc/arm-none-eabi/4.9.1/../../../../arm-none-eabi/lib/libc.a(lib_a-exit.o): In function `exit':
/build/arm-none-eabi-gcc/src/gcc-4.9.1/build/arm-none-eabi/newlib/libc/stdlib/../../../../../newlib/libc/stdlib/exit.c:70: undefined reference to `_exit'
/usr/lib/gcc/arm-none-eabi/4.9.1/../../../../arm-none-eabi/lib/libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
/build/arm-none-eabi-gcc/src/gcc-4.9.1/build/arm-none-eabi/newlib/libc/reent/../../../../../newlib/libc/reent/sbrkr.c:58: undefined reference to `_sbrk'
/usr/lib/gcc/arm-none-eabi/4.9.1/../../../../arm-none-eabi/lib/libc.a(lib_a-writer.o): In function `_write_r':
/build/arm-none-eabi-gcc/src/gcc-4.9.1/build/arm-none-eabi/newlib/libc/reent/../../../../../newlib/libc/reent/writer.c:58: undefined reference to `_write'
/usr/lib/gcc/arm-none-eabi/4.9.1/../../../../arm-none-eabi/lib/libc.a(lib_a-closer.o): In function `_close_r':
/build/arm-none-eabi-gcc/src/gcc-4.9.1/build/arm-none-eabi/newlib/libc/reent/../../../../../newlib/libc/reent/closer.c:53: undefined reference to `_close'
/usr/lib/gcc/arm-none-eabi/4.9.1/../../../../arm-none-eabi/lib/libc.a(lib_a-fstatr.o): In function `_fstat_r':
/build/arm-none-eabi-gcc/src/gcc-4.9.1/build/arm-none-eabi/newlib/libc/reent/../../../../../newlib/libc/reent/fstatr.c:62: undefined reference to `_fstat'
/usr/lib/gcc/arm-none-eabi/4.9.1/../../../../arm-none-eabi/lib/libc.a(lib_a-isattyr.o): In function `_isatty_r':
/build/arm-none-eabi-gcc/src/gcc-4.9.1/build/arm-none-eabi/newlib/libc/reent/../../../../../newlib/libc/reent/isattyr.c:58: undefined reference to `_isatty'
/usr/lib/gcc/arm-none-eabi/4.9.1/../../../../arm-none-eabi/lib/libc.a(lib_a-lseekr.o): In function `_lseek_r':
/build/arm-none-eabi-gcc/src/gcc-4.9.1/build/arm-none-eabi/newlib/libc/reent/../../../../../newlib/libc/reent/lseekr.c:58: undefined reference to `_lseek'
/usr/lib/gcc/arm-none-eabi/4.9.1/../../../../arm-none-eabi/lib/libc.a(lib_a-readr.o): In function `_read_r':
/build/arm-none-eabi-gcc/src/gcc-4.9.1/build/arm-none-eabi/newlib/libc/reent/../../../../../newlib/libc/reent/readr.c:58: undefined reference to `_read'
collect2: error: ld returned 1 exit status

# syscall.c 새로 정의

#include <_ansi.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>
#include <errno.h>
#include <reent.h>
#include <unistd.h>
#include <sys/wait.h>

#define FreeRTOS
#define MAX_STACK_SIZE 0x2000

extern int __io_putchar(int ch) __attribute__((weak));
extern int __io_getchar(void) __attribute__((weak));

#ifndef FreeRTOS
  register char * stack_ptr asm("sp");
#endif

caddr_t _sbrk(int incr)
{
  extern char end asm("end");
  static char *heap_end;
  char *prev_heap_end,*min_stack_ptr;

  if (heap_end == 0)
    heap_end = &end;

  prev_heap_end = heap_end;

#ifdef FreeRTOS
  /* Use the NVIC offset register to locate the main stack pointer. */
  min_stack_ptr = (char*)(*(unsigned int *)*(unsigned int *)0xE000ED08);
  /* Locate the STACK bottom address */
  min_stack_ptr -= MAX_STACK_SIZE;

  if (heap_end + incr > min_stack_ptr)
#else
  if (heap_end + incr > stack_ptr)
#endif
  {
//    write(1, "Heap and stack collision\n", 25);
//    abort();
    errno = ENOMEM;
    return (caddr_t) -1;
  }

  heap_end += incr;

  return (caddr_t) prev_heap_end;
}

/*
 * _gettimeofday primitive (Stub function)
 * */
int _gettimeofday (struct timeval * tp, struct timezone * tzp)
{
  /* Return fixed data for the timezone.  */
  if (tzp)
    {
      tzp->tz_minuteswest = 0;
      tzp->tz_dsttime = 0;
    }

  return 0;
}
void initialise_monitor_handles()
{
}

int _getpid(void)
{
  return 1;
}

int _kill(int pid, int sig)
{
  errno = EINVAL;
  return -1;
}

void _exit (int status)
{
  _kill(status, -1);
  while (1) {}
}

int _write(int file, char *ptr, int len)
{
  int DataIdx;

    for (DataIdx = 0; DataIdx < len; DataIdx++)
    {
       __io_putchar( *ptr++ );
    }
  return len;
}

int _close(int file)
{
  return -1;
}

int _fstat(int file, struct stat *st)
{
  st->st_mode = S_IFCHR;
  return 0;
}

int _isatty(int file)
{
  return 1;
}

int _lseek(int file, int ptr, int dir)
{
  return 0;
}

int _read(int file, char *ptr, int len)
{
  int DataIdx;

  for (DataIdx = 0; DataIdx < len; DataIdx++)
  {
    *ptr++ = __io_getchar();
  }

   return len;
}

int _open(char *path, int flags, ...)
{
  /* Pretend like we always fail */
  return -1;
}

int _wait(int *status)
{
  errno = ECHILD;
  return -1;
}

int _unlink(char *name)
{
  errno = ENOENT;
  return -1;
}

int _times(struct tms *buf)
{
  return -1;
}

int _stat(char *file, struct stat *st)
{
  st->st_mode = S_IFCHR;
  return 0;
}

int _link(char *old, char *new)
{
  errno = EMLINK;
  return -1;
}

int _fork(void)
{
  errno = EAGAIN;
  return -1;
}

int _execve(char *name, char **argv, char **env)
{
  errno = ENOMEM;
  return -1;
}

결론적으로 상용 컴파일러를 사용하지 않고, Eclipse IDE와 같은 무료 프로그램으로 충분히 compile를 할 수 있다는 것에 고무적인 결과이다. 조만간 STM32F103x processor를 사용한 hardware platform 기반 Eclipse IDE 환경에서의 setup guide post를 남겨보도록 하겠다.

 

참고로 일반적으로 잘 알려진 디버깅용 printf() 함수 사용과 비슷한 구현을 아래와 같이 공유한다.

 

void zPrintf(USART_TypeDef* usart_p, char *fmt, ...)
{
	va_list	arg_ptr;
	char		LocalText[64];
	uint8_t	cnt;
	
	for(cnt=0 ; cnt<64 ; cnt++) 
	{
		LocalText[cnt] = 0x00;
	}

	va_start(arg_ptr, fmt);
	vsprintf(LocalText, fmt, arg_ptr);
	va_end(arg_ptr);

	for(cnt=0 ; cnt<64 ; cnt++) 
	{
		if(LocalText[cnt] != 0)
		{
			USART_SendData(usart_p, LocalText[cnt]);
			while(USART_GetFlagStatus(usart_p, USART_FLAG_TXE) == RESET);
			
			if(LocalText[cnt] == KEYBOARD_LineFeed)
			{
				USART_SendData(usart_p, KEYBOARD_CarryRet);
				while(USART_GetFlagStatus(usart_p, USART_FLAG_TXE) == RESET);
			}
		}
		else		break;
	}	
}
반응형
반응형

세상에서 가장 소중한 우리 아기의 성장 과정을 한눈에 보기 위해 50일, 100일, 돌에 대한 성장 앨범을 촬영하게 되었다.

사실 성장 앨범 촬영 스튜디오를 선택하기 위해서는 꽤 많은 고민을 하게 되는데, 대부분 입소문 및 인터넷 검색을 통해서 업체를 만나게 된다.

하지만, 천안 근방에서 아기 성장 앨범을 촬영하기 위해 고민을 하고 있다면, 필자의 글과 실제 촬영 사진들을 보고 선택의 고민에 조금이나마 도움이 되길 바란다. 

 

그리고 성장 앨범 업체를 선택하는 데에 있어서 가장 요인은 아래와 같지 않을까?

 

1. 지역적인 접근성

2. 다양한 스튜디오 씬(테마 촬영)

3. 실력있는 전문적인 사진 촬영 기사와 작가

4. 깔끔한 건물과 인테리어

5. 친절한 사후처리 여부

6. 대내외적인 서비스

 

그리고 아래 촬영 사진의 카메라 EXIF 정보를 보면 꽤 좋은 카메라 Body와 렌즈를 사용하고 있다는 것을 알 수가 있다.

 

필자의 경우, 위의 체크 리스트를 검토한 결과 양호한 평가 결과를 내린 끝에 "스튜디오 아이처럼"을 선택하고 성장 앨범을 촬영하게 되었다.

 

자, 이제 본격적으로 필자의 소중한 딸인 예서의 성장 앨범을 하나씩 살펴볼까?

(참고로, 50일 100일 돌사진 등 원본파일 450장 가량 받았다. 그만큼 많은 촬영 사진들을 제공하여 준다. 그리고 무료 촬영이었던 만삭 촬영 사진은 생략 하였다.)

 

50일 사진 (4가지 베이비 촬영신)

 

 

 

 

 

 

 

100일 사진 (4가지 베이비 촬영신)

 

 

 

 

 

 

돌 사진 (3가지 베이비 촬영신+가족 촬영신)

 

 

 

 

 

 

여기까지 성장 앨범 사진들을 살펴 보았는데, 스튜디오에 방문을 하면,

직원들이 보여주는 태블릿으로 정말 다양한 테마를 접할 수 있으므로 어떤 촬영을 해야할 지에 대해 행복한 고민을 하길 바란다.

 

그럼 필자가 촬영한 스튜디오에 대해 짤막하게 안내하기로 한다. 

 

 

네비게이션에 "충남 천안시 동남구 신방동 1009 스튜디오 아이처럼" 를 찾아서,

경로탐색을 하고 찾아 오면 위와 같은 건물들을 볼 수가 있다.

건물 바로 앞에 주차장이 완비되어 있으니 편안하게 주차를 하고 직원들의 안내를 받으면 된다.

 

 

위의 사진들은 스튜디오 내부 모습이다.

각 층별로 안내실, 만삭 사진 촬영, 베이비 촬영, 가족 사진 촬영 등 촬영 컨셉마다 다르게 촬영을 하고 있다.

 

반응형

+ Recent posts