반응형

본인은 STM32F103 시리즈 MCU를 사용하고 있으며, Interrupt 기능을 사용하기 위해 GPIOA Pin 4번을 이용하여 인터럽트 관련 설정 코드를 아래와 같이 하였다.

 

void STM32_Interrupt_initial(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA  | RCC_APB2Periph_AFIO, ENABLE);

	// GPIOA Pin 4 Interrupt
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	// Connect EXTI Line to gpio pin
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource4);

	// Configure EXTI Line to generate an interrupt
	EXTI_InitStructure.EXTI_Line    = EXTI_Line4;
	EXTI_InitStructure.EXTI_Mode    = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);

	// Configure the NVIC Preemption Priority Bits
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

	// Enable the EXTI4 Interrupt
	NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

EXTI 및 NVIC 관련 설정은 구글링을 하면 많은 자료가 검색 되므로, 굳이 설명을 하지 않기로 한다.

참고로 "EXTI1_IRQHandler" ~ "EXTI4_IRQHandler", "EXTI9_5_IRQHandler", "EXTI15_10_IRQHandler"의 IRQ 핸들러를 설정할 수 있는데, Pin0 부터 Pin4까지는 지정된 IRQHandler를 사용해야 하고, Pin5 부터 Pin9는 EXTI9_5_IRQHandler를 사용해야 한다. 마찬가지로 Pin10 부터 Pin15는 EXTI15_10_IRQHandler를사용해야한다.

 

/*******************************************************************************
* Function Name  : EXTI4_IRQHandler
* Description    : This function handles External interrupt Line 4 request.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void EXTI4_IRQHandler(void)
{
	if(EXTI_GetITStatus(GPIO_Pin_4) != RESET)
	{
		printf("Interrupt OK\n");

		// Clear the Interrupt EXTI line pending bit
		EXTI_ClearITPendingBit(GPIO_Pin_4);		
	}
}

이렇게 하여, 해당 GPIO Pin에 Failling Signal을 전달하면, 아래와 같이 debug message가 나타난다.

 

 

반응형
반응형

보다 많은 number의 범위를 보장하는 signed extend number funtion 함수이다. 최대 32자리까지 지원하는 unsigned bit number를 부호있는 숫자로 형변환을 할 때에 유용하게 쓰일 함수다.

 

참고로 "1L"의 의미는 여러 종류의 데이터 타입 중에 long type 이 있는데, 이는 int type 보다 큰 memory size를 차지하며, 일반적으로 4bytes(32bit)의 memory size를 가지는 unsigned, signed type으로 형변환을 할 때에 이를 모두 표현할 수 있는 long type 이 제격이다.

/* To convert the sing extension number from the target number */  
long SignExtensionRedunction(uint32_t number, int length)  
{  
     long extend_number = (long)number;  
     long mask = 1L<<(length-1);  

     if (length<32) {  
          // fill the zero bit unless the same bit after the AND bit operation 
          extend_number = extend_number&((1<<length)-1); 
         }  
     return (long)((extend_number^mask)-mask);  
}

 

반응형
반응형

STM32F103 series로 maximum 72Mhz system clock를 사용하려면 외부 12Mhz oscillator를 실장하여 HSE (High Speed External) crystal output clock frequency mode로 PLL multiplication factor 제어하여 6배 (PLL input clock x 6) 곱하여 72Mhz PLLCLK source로 사용하고 있었다.

 

그러나 external crystal 사용에 따른 부품 단가로 인하여 비용 절감(?)을 위해 internal 8Mhz RC Oscillator를 사용하여 HSI (High Speed Internal) crystal output clock frequency mode에서 아래 그림을 참고하면 2 분주 후, 16배 곱하여 maximum 64Mhz system clock를 사용할 수가 있다. 

 

(8Mhz / 2) x 16 = 64Mhz

 

그리고 internal 8Mhz RC Oscillator에 따른 HSI crystral output clock frequency mode의 장단점은 아래와 같다. 단지 main system clock frequency의 accuracy가 저하된다고 하는데, 과연 MCU 시스템에 큰 영향을 끼칠까?

 

The HSI RC oscillator has the advantage of providing a clock source at low cost (no external components). It also has a faster startup time than the HSE crystal oscillator however, even with calibration the frequency is less accurate than an external crystal oscillator or ceramicresonator.

 

참고로 STM32F103은 다음과 같이 3가지 종류의 clock source를 제공하고 있다.

 

- HSI Oscillator clock

- HSE Oscillator clock

- PLL clock

 

그리고 다음과 같이 maximum clock frequeny가 정의되어 있으므로, 적절하게 선정하여 사용 하도록 하자.

 

The maximum frequency of the AHB and the APB2 domains is 72 MHz. The maximum allowed frequency of the APB1 domain is 36 MHz.

 

위의 내용을 토대로 HSI mode를 사용하여 main 64Mhz system clock frequency를 출력하는 예제 코드는 아래와 같다.

 

void RCC_Configuration_HSI_64Mhz_without_USBclock(void)
{
    ErrorStatus HSIStartUpStatus;

    /* RCC system reset(for debug purpose) */
    RCC_DeInit();

    /* activate HSI (Internal High Speed oscillator) */
    RCC_HSICmd(ENABLE);

    /* Wait until RCC_FLAG_HSIRDY is ready */
    while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);

    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);

    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1);// HCLK = 64 MHz, AHB

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2); // APB1 = 32 MHz

    /* PCLK2 = HCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1); // APB2 = 64 MHz

    /* PLLCLK = (8MHz/2) * 16 = 64MHz */
    RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_16); // 64 MHz

    /* Enable PLL */ 
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08);
 
}

 

그러나 위의 과정을 거쳐서 USB clock를 사용하게 되면 문제가 발생되는데, 다음과 같이 USB clock를 사용하려면 48Mhz clock이 필요로하다. 그래서 PLL clock은 72Mhz 및 48Mhz의 output clock frequency가 필요하다.

 

The USB OTG FS 48 MHz clock which is derived from the PLL VCO clock (2 × PLLCLK), followed by a programmable prescaler (divide by 3 or 2). 

This selection is  made through the OTGFSPRE bit in the RCC_CFGR register. 

For proper USB OTG FSoperation, the PLL should be configured to output 72 MHz or 48 MHz.

 

위의 내용을 토대로 HSI mode를 사용하여 main 48Mhz system clock frequency로 설정하고 48Mhz USB clock 출력하는 예제 코드는 아래와 같다.

 

void RCC_Configuration_HSI_48Mhz_with_USBclock(void)
{
    ErrorStatus HSIStartUpStatus;

    /* RCC system reset(for debug purpose) */
    RCC_DeInit();

    /* activate HSI (Internal High Speed oscillator) */
    RCC_HSICmd(ENABLE);

    /* Wait until RCC_FLAG_HSIRDY is ready */
    while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);

    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);

    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1);// HCLK = 48 MHz, AHB

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2); // APB1 = 24 MHz

    /* PCLK2 = HCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1); // APB2 = 48 MHz

    /* PLLCLK = (8MHz/2) * 12 = 48MHz */
    RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_12); // 48 MHz

    /* Enable PLL */ 
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08);
 
}

 

참고로 USB clock 관련 설정은 아래와 같이 code 분리하여 프로그래밍을 하여도 된다.

 

/******************************************************************************* 
* Function Name  : Set_USBClock 
* Description    : Configures USB Clock input (48MHz) 
* Input          : None. 
* Return         : None. 
*******************************************************************************/ 
void Set_USBClock(void) 
{ 
    // Select USBCLK source 
    RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1); 

    // Enable the USB clock 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE); 
}

/*******************************************************************************
* Function Name  : USB_Interrupts_Config
* Description    : Configures the USB interrupts
* Input          : None.
* Return         : None.
*******************************************************************************/
void USB_Interrupts_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;

    // 2 bit for pre-emption priority, 2 bits for subpriority
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    // Enable the USB interrupt
    NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // Enable the USB Wake-up interrupt
    NVIC_InitStructure.NVIC_IRQChannel = USBWakeUp_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // Enable the DMA1 Channel1 Interrupt
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

/********************** main.c ***********************/
Set_USBClock();
USB_Interrupts_Config();
USB_Init(); // STM32 USB library at 'usb_init.c'

 

[부록]

System clock frequency를 48Mhz로 설정하고 나니, 문득 드는 생각이 있는데 GPIO_Speed_2MHz, GPIO_Speed_10MHz, GPIO_Speed_50MHz 의 설정값들이 있는데 GPIO Speed 50Mhz 설정에 따른 GPIO speed 관련 내용을 수집하여 보니, 해당 GPIO speed는 system clock과 관계없이 ARM core의 bus line speed에 대한 의미로 이해하면 된다. 어차피 아래 STM32F103 datasheet 내용을 참조하면 maximum 72Mhz system clock frequency 설정에 따른 maximum GPIO toggling speed는 18Mhz 이다. (GPIO speed 2Mhz의 장점은 EMI noise가 작아진다. 거꾸로 GPIO speed 50Mhz로 설정하면 EMI noise가 높아질 확률이다.)

 

GPIOs (general-purpose inputs/outputs)
Each of the GPIO pins can be configured by software as output (push-pull or open-drain), as input (with or without pull-up or pull-down) or as peripheral alternate function. Most of the GPIO pins are shared with digital or analog alternate functions. All GPIOs are high currentcapable. The I/Os alternate function configuration can be locked if needed following a specific sequence in order to avoid spurious writing to the I/Os registers. I/Os on APB2 with up to 18 MHz toggling speed. 

 

마지막으로 혹시 몰라서 HSE (High Speed External) crystal output clock frequency mode 관련 예제 코드도 공유한다.

 

void RCC_Configuration_HSE(void)
{
    ErrorStatus HSEStartUpStatus;

    /* RCC system reset(for debug purpose) */
    RCC_DeInit();

    /* Enable HSE */
    RCC_HSEConfig(RCC_HSE_ON);

    /* Wait till HSE is ready */
    HSEStartUpStatus = RCC_WaitForHSEStartUp();

    if(HSEStartUpStatus == SUCCESS)
    {
        /* Enable Prefetch Buffer */
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

        /* Flash 2 wait state */
        FLASH_SetLatency(FLASH_Latency_2);

        /* HCLK = SYSCLK */
        RCC_HCLKConfig(RCC_SYSCLK_Div1); 

        /* PCLK1 = HCLK/2 */
        RCC_PCLK1Config(RCC_HCLK_Div2);

        /* PCLK2 = HCLK */
        RCC_PCLK2Config(RCC_HCLK_Div1); 

        /* ADCCLK = PCLK2/4 */
        RCC_ADCCLKConfig(RCC_PCLK2_Div6); 

        /* PLLCLK = 12MHz * 6 = 72 MHz */
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_6);

        /* Enable PLL */ 
        RCC_PLLCmd(ENABLE);

        /* Wait till PLL is ready */
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

        /* Select PLL as system clock source */
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

        /* Wait till PLL is used as system clock source */
        while(RCC_GetSYSCLKSource() != 0x08);
    }    
}

 

반응형
반응형

STM32F10x series MCU를 사용하면서 제공되는 stm32f10x_i2c.h / stm32f10x_i2c.c 관련 STM32 library를 사용한 hardware I2C example code를 공유한다.

 

# i2c_hw.h

#ifndef __I2C_HW_H
#define __I2C_HW_H

/* includes */
#include "stm32f10x.h"
#include "hw_config.h"
/* defines */
/* functions */
void HW_I2C_master_initial(void);

uint8_t HW_I2C_Read(I2C_TypeDef* I2Cx, uint8_t DeviceAddr, uint8_t RegisterAddr, uint16_t NumByteToRead, uint8_t* pBuffer);
uint8_t HW_I2C_Write(I2C_TypeDef* I2Cx, uint8_t DeviceAddr, uint8_t RegisterAddr, uint16_t NumByteToWrite, uint8_t* pBuffer);
uint8_t I2C_Check_SlaveAddr(I2C_TypeDef* I2Cx, uint8_t DeviceAddr);

uint8_t HW_I2C_UTIL_Write(I2C_TypeDef* I2Cx, uint8_t DeviceAddr, uint8_t RegisterAddr, uint8_t pBuffer);
uint8_t HW_I2C_UTIL_Read(I2C_TypeDef* I2Cx, uint8_t DeviceAddr, uint8_t RegisterAddr);
void HW_I2C_UTIL_Write_Multi(I2C_TypeDef* I2Cx, uint8_t DeviceAddr, uint8_t RegisterAddr, uint16_t NumByteToWrite, uint8_t* pBuffer);
uint8_t HW_I2C_UTIL_Read_Multi(I2C_TypeDef* I2Cx, uint8_t DeviceAddr, uint8_t RegisterAddr, uint8_t ReadCount, uint8_t (*pReadData));
uint8_t HW_I2C_UTIL_Check_SlaveAddr(I2C_TypeDef* I2Cx);

#endif  /* __I2C_HW_H */

 

# i2c_hw.c

#include "i2c_hw.h"

#define MAX_COMMUNICATION_FREQ   ((uint32_t) 400000)	// 100khz
#define FLAG_TIMEOUT             ((uint32_t)0x1000)
#define LONG_TIMEOUT             ((uint32_t)(10 * FLAG_TIMEOUT))

#define GPIO_I2C_HW        GPIOB

#define GPIO_I2C1_SCL	GPIO_Pin_6
#define GPIO_I2C1_SDA	GPIO_Pin_7
#define GPIO_I2C2_SCL	GPIO_Pin_10
#define GPIO_I2C2_SDA	GPIO_Pin_11

__IO uint32_t  UTIL_Timeout = LONG_TIMEOUT;
__IO uint16_t  UTIL_Address = 0;

void HW_I2C_master_initial(void)
{
	I2C_InitTypeDef 	I2C_InitStructure;
	GPIO_InitTypeDef	GPIO_InitStructure;

	// I2C_SCL_GPIO_CLK and I2C_SDA_GPIO_CLK Periph clock enable
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	// I2C Periph clock enable
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);

	// Configure I2C pins: SCL , SDA
	GPIO_InitStructure.GPIO_Pin = GPIO_I2C1_SCL | GPIO_I2C1_SDA | GPIO_I2C2_SCL | GPIO_I2C2_SDA;;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_Init(GPIO_I2C_HW, &GPIO_InitStructure);

	// Free all used resources
	I2C_DeInit(I2C1);
	I2C_DeInit(I2C2);

	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	I2C_InitStructure.I2C_OwnAddress1 = 0x00;
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	I2C_InitStructure.I2C_ClockSpeed = MAX_COMMUNICATION_FREQ;
	I2C_Init(I2C1, &I2C_InitStructure);
	I2C_Init(I2C2, &I2C_InitStructure);

	I2C_Cmd(I2C1, ENABLE);
	I2C_Cmd(I2C2, ENABLE);
}

uint8_t HW_I2C_Read(I2C_TypeDef* I2Cx, uint8_t DeviceAddr, uint8_t RegisterAddr, uint16_t NumByteToRead, uint8_t* pBuffer)
{
  __IO uint32_t UTIL_Timeout = LONG_TIMEOUT;
  __IO uint32_t temp;

  (void)(temp);

restart:

  UTIL_Timeout = LONG_TIMEOUT;
/* Send START condition */
  I2C_GenerateSTART(I2Cx, ENABLE);
  /* Test on EV5 and clear it */
  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
  {
    if (UTIL_Timeout-- == 0)
      return ERROR;
  }

  UTIL_Timeout = LONG_TIMEOUT;
  /* Send slave address for read */
  I2C_Send7bitAddress(I2Cx, DeviceAddr, I2C_Direction_Transmitter);

  while (!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  {
    if (UTIL_Timeout-- == 0)
    {
      I2C_ClearFlag(I2Cx,I2C_FLAG_BUSY|I2C_FLAG_AF);
      goto restart;
    }
  }
  /* Clear EV6 by setting again the PE bit */
  I2C_Cmd(I2Cx, ENABLE);

  I2C_SendData(I2Cx, RegisterAddr);

  /* Test on EV8 and clear it */
  UTIL_Timeout = LONG_TIMEOUT;
  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    if (UTIL_Timeout-- == 0)
     return ERROR;
  }

  if (NumByteToRead == 0x01)
  {
    restart3:
    /* Send START condition */
    I2C_GenerateSTART(I2Cx, ENABLE);
    while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
    /* Send Slave address for read */
    I2C_Send7bitAddress(I2Cx, DeviceAddr, I2C_Direction_Receiver);
    /* Wait until ADDR is set */
    UTIL_Timeout = LONG_TIMEOUT;
    while (!I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR))
    {
      if (UTIL_Timeout-- == 0)
      {
        I2C_ClearFlag(I2Cx,I2C_FLAG_BUSY|I2C_FLAG_AF);
        goto restart3;
      }
    }
    /* Clear ACK */
    I2C_AcknowledgeConfig(I2Cx, DISABLE);
    __disable_irq();
    /* Clear ADDR flag */
    temp = I2Cx->SR2;
    /* Program the STOP */
    I2C_GenerateSTOP(I2Cx, ENABLE);
    __enable_irq();
    while ((I2C_GetLastEvent(I2Cx) & 0x0040) != 0x000040); /* Poll on RxNE */
    /* Read the data */
    *pBuffer = I2C_ReceiveData(I2Cx);
    /* Make sure that the STOP bit is cleared by Hardware before CR1 write access */
    while ((I2Cx->CR1&0x200) == 0x200);
    /* Enable Acknowledgement to be ready for another reception */
    I2C_AcknowledgeConfig(I2Cx, ENABLE);

    return SUCCESS;
  }
  else
    if(NumByteToRead == 0x02)
    {
      restart4:
      /* Send START condition */
      I2C_GenerateSTART(I2Cx, ENABLE);
      while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
      /* Send EEPROM address for read */
      I2C_Send7bitAddress(I2Cx, DeviceAddr, I2C_Direction_Receiver);
      I2Cx->CR1 = 0xC01; /* ACK=1; POS =1 */
      UTIL_Timeout = LONG_TIMEOUT;
      while (!I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR))
      {
        if (UTIL_Timeout-- == 0)
        {
          I2C_ClearFlag(I2Cx,I2C_FLAG_BUSY|I2C_FLAG_AF);
          goto restart4;
        }
      }
      __disable_irq();
      /* Clear ADDR */
      temp = I2Cx->SR2;
      /* Disable ACK */
      I2C_AcknowledgeConfig(I2Cx, DISABLE);
      __enable_irq();
      while ((I2C_GetLastEvent(I2Cx) & 0x0004) != 0x00004); /* Poll on BTF */

       __disable_irq();
      /* Program the STOP */
      I2C_GenerateSTOP(I2Cx, ENABLE);
      /* Read first data */
      *pBuffer = I2Cx->DR;
      pBuffer++;
      /* Read second data */
      *pBuffer = I2Cx->DR;
      __enable_irq();
      I2Cx->CR1 = 0x0401; /* POS = 0, ACK = 1, PE = 1 */

      return SUCCESS;
    }
  else
  {
restart2:
    UTIL_Timeout = LONG_TIMEOUT;
    /* Send START condition */
    I2C_GenerateSTART(I2Cx, ENABLE);
    /* Test on EV5 and clear it */
    while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
    {
      if (UTIL_Timeout-- == 0) return ERROR;
    }
    UTIL_Timeout = LONG_TIMEOUT;
    /* Send slave address for read */
    I2C_Send7bitAddress(I2Cx,  DeviceAddr, I2C_Direction_Receiver);
    while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
    {

      if (UTIL_Timeout-- == 0)
      {
        I2C_ClearFlag(I2Cx,I2C_FLAG_BUSY|I2C_FLAG_AF);
        goto restart2;
      }
    }

    /* While there is data to be read; here the safe procedure is implemented */
    while (NumByteToRead)
    {

      if (NumByteToRead != 3) /* Receive bytes from first byte until byte N-3 */
      {
        while ((I2C_GetLastEvent(I2Cx) & 0x00004) != 0x000004); /* Poll on BTF */
        /* Read data */
        *pBuffer = I2C_ReceiveData(I2Cx);
        pBuffer++;
        /* Decrement the read bytes counter */
        NumByteToRead--;
      }

      if (NumByteToRead == 3)  /* it remains to read three data: data N-2, data N-1, Data N */
      {

        /* Data N-2 in DR and data N -1 in shift register */
        while ((I2C_GetLastEvent(I2Cx) & 0x000004) != 0x0000004); /* Poll on BTF */
        /* Clear ACK */
        I2C_AcknowledgeConfig(I2Cx, DISABLE);
        __disable_irq();
        /* Read Data N-2 */
        *pBuffer = I2C_ReceiveData(I2Cx);
        pBuffer++;
        /* Program the STOP */
        I2C_GenerateSTOP(I2Cx, ENABLE);
        /* Read DataN-1 */
        *pBuffer = I2C_ReceiveData(I2Cx);
        __enable_irq();
        pBuffer++;
        while ((I2C_GetLastEvent(I2Cx) & 0x00000040) != 0x0000040); /* Poll on RxNE */
        /* Read DataN */
        *pBuffer = I2Cx->DR;
        /* Reset the number of bytes to be read by master */
        NumByteToRead = 0;
      }
    }
    /* Make sure that the STOP bit is cleared by Hardware before CR1 write access */
    while ((I2Cx->CR1&0x200) == 0x200);
    /* Enable Acknowledgement to be ready for another reception */
    I2C_AcknowledgeConfig(I2Cx, ENABLE);

    return SUCCESS;
  }
}

uint8_t HW_I2C_Write(I2C_TypeDef* I2Cx, uint8_t DeviceAddr, uint8_t RegisterAddr,
                               uint16_t NumByteToWrite,
                               uint8_t* pBuffer)
{

 restart1:
  UTIL_Timeout = LONG_TIMEOUT;
  /* Send START condition */
  I2C_GenerateSTART(I2Cx, ENABLE);
  /* Test on EV5 and clear it */
  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
  {
    if (UTIL_Timeout-- == 0) return ERROR;
  }
  /* Send slave address for write */
  I2C_Send7bitAddress(I2Cx, DeviceAddr, I2C_Direction_Transmitter);

  UTIL_Timeout = LONG_TIMEOUT;
  /* Test on EV6 and clear it */
  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  {

    if (UTIL_Timeout-- == 0)
    {
      I2C_ClearFlag(I2Cx,I2C_FLAG_BUSY|I2C_FLAG_AF);
      goto restart1;
    }
  }

  UTIL_Timeout = LONG_TIMEOUT;

  /* Transmit the first address for r/w operations */
  I2C_SendData(I2Cx, RegisterAddr);

  /* Test on EV8 and clear it */
  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    if (UTIL_Timeout-- == 0)
      return ERROR;
  }
  if (NumByteToWrite == 0x01)
  {
    UTIL_Timeout = LONG_TIMEOUT;
    /* Prepare the register value to be sent */
    I2C_SendData(I2Cx, *pBuffer);

    /* Test on EV8 and clear it */
    while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
    {
      if (UTIL_Timeout-- == 0)
        return ERROR;
    }

    /* End the configuration sequence */
    I2C_GenerateSTOP(I2Cx, ENABLE);
    return SUCCESS;
  }
  I2C_SendData(I2Cx, *pBuffer);
  pBuffer++;
  NumByteToWrite--;
  /* While there is data to be written */
  while (NumByteToWrite--)
  {
    while ((I2C_GetLastEvent(I2Cx) & 0x04) != 0x04);  /* Poll on BTF */
    /* Send the current byte */
    I2C_SendData(I2Cx, *pBuffer);
    /* Point to the next byte to be written */
    pBuffer++;

  }
  UTIL_Timeout = LONG_TIMEOUT;
  /* Test on EV8_2 and clear it, BTF = TxE = 1, DR and shift registers are
   empty */
  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    if (UTIL_Timeout-- == 0) return ERROR;
  }
  /* Send STOP condition */
  I2C_GenerateSTOP(I2Cx, ENABLE);
  return SUCCESS;
}

uint8_t I2C_Check_SlaveAddr(I2C_TypeDef* I2Cx, uint8_t DeviceAddr)
{
	uint8_t   returnack = SUCCESS;

	UTIL_Timeout = FLAG_TIMEOUT;
	/* Send START condition */
	I2C_GenerateSTART(I2Cx, ENABLE);
	/* Test on EV5 and clear it */
	while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
	{
		if (UTIL_Timeout-- == 0) return ERROR;
	}
	/* Send slave address for write */
	I2C_Send7bitAddress(I2Cx, DeviceAddr, I2C_Direction_Transmitter);

	UTIL_Timeout = FLAG_TIMEOUT;
	/* Test on EV6 and clear it */
	while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
	{

		if (UTIL_Timeout-- == 0)
		{
		  I2C_ClearFlag(I2Cx,I2C_FLAG_BUSY|I2C_FLAG_AF);
		  returnack = ERROR;
		  break;
		}
	}
	I2C_GenerateSTOP(I2Cx, ENABLE);

	return returnack;
}

uint8_t HW_I2C_UTIL_Write(I2C_TypeDef* I2Cx, uint8_t DeviceAddr, uint8_t RegisterAddr, uint8_t pBuffer)
{
	return HW_I2C_Write(I2Cx, DeviceAddr<<1,RegisterAddr,1,&pBuffer);
}

uint8_t HW_I2C_UTIL_Read(I2C_TypeDef* I2Cx, uint8_t DeviceAddr, uint8_t RegisterAddr)
{
	uint8_t	pBuffer;

	HW_I2C_Read(I2Cx, DeviceAddr<<1,RegisterAddr,1,&pBuffer);

	return pBuffer;
}

void HW_I2C_UTIL_Write_Multi(I2C_TypeDef* I2Cx, uint8_t DeviceAddr, uint8_t RegisterAddr, uint16_t NumByteToWrite, uint8_t* pBuffer)
{
	HW_I2C_Write(I2Cx, DeviceAddr<<1,RegisterAddr,NumByteToWrite,pBuffer);
}

uint8_t HW_I2C_UTIL_Read_Multi(I2C_TypeDef* I2Cx, uint8_t DeviceAddr, uint8_t RegisterAddr, uint8_t ReadCount, uint8_t (*pReadData))
{
	HW_I2C_Read(I2Cx, DeviceAddr<<1,RegisterAddr,ReadCount,pReadData);

	return 1;
}

uint8_t HW_I2C_UTIL_Check_SlaveAddr(I2C_TypeDef* I2Cx)
{
	uint8_t i = 0x00;

	for(i = 0; i < 255; i++)
	{
		if(I2C_Check_SlaveAddr(I2Cx, i) == SUCCESS)
		{
			return i;
		}
	}
	return i;
}
반응형
반응형

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);
}
반응형

+ Recent posts