STM32F4XX中断方式通过IO模拟I2C总线Master模式

时间:2021-11-09 01:58:34

STM32的I2C硬核为了规避NXP的知识产权,使得I2C用起来经常出问题,因此ST公司推出了CPAL库,CPAL库在中断方式工作下仅支持无子地址

的器件,无法做到中断方式完成读写大部分I2C器件。同时CPAL库在多个I2C同时使用时,经测试也有问题,因此我们项目中放弃了使用ST公司的CPAL库以及标准外设库

访问I2c器件,用IO模拟I2c总线,同时也是支持中断方式完成I2C读写。

目前网上绝大部分IO模拟I2c总线的程序都是查询方式,浪费大量CPU周期用于循环等待,本文的程序使用定时器中断推动状态机来模拟I2C总线的操作,

中断方式使用,请定义回调函数,本程序将在读写完成或出错时自动调用回调函数

当然此程序也可以通过查询方式读写I2c总线,仅需查询IIC_BUSY.

本程序仅模拟主模式(Master)

i2c_sim.h

#ifndef __I2C_SIM_H__
#define __I2C_SIM_H__ #include <stm32f4xx.h> #define MAXFREQ 500000 extern uint8_t I2C_Read7(uint8_t IIC, uint8_t device, uint8_t Addr, uint8_t *Buf, uint8_t Count); extern uint8_t I2C_Read16(uint8_t IIC, uint8_t device, uint16_t Addr, uint8_t *Buf, uint8_t Count); extern uint8_t I2C_WriteByte7(uint8_t IIC, uint8_t device, uint8_t Addr, uint8_t Data); extern uint8_t I2C_Write16(uint8_t IIC, uint8_t device, uint16_t Addr, uint8_t *Buf, uint8_t Count); extern void IIC_Init(uint8_t IIC, uint16_t MicroSecond); extern void IIC_DeInit(uint8_t IIC); extern void IIC_SetCallback(uint8_t IIC, void(*OnTx)(void), void(*OnRx)(void) ,void(*OnErr)(void)); #endif

  

i2c_sim.c

#include "stm32f4xx_conf.h"
#include <string.h> #define IIC_COUNT 2 #if (IIC_COUNT>3)
Error! To many IIC
#endif /*----------- I2C1 Device -----------*/ #define I2C1_SCL_GPIO_PORT GPIOB
#define I2C1_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB
#define I2C1_SCL_GPIO_PIN GPIO_Pin_6
#define I2C1_SCL_GPIO_PINSOURCE GPIO_PinSource6 #define I2C1_SDA_GPIO_PORT GPIOB
#define I2C1_SDA_GPIO_CLK RCC_AHB1Periph_GPIOB
#define I2C1_SDA_GPIO_PIN GPIO_Pin_7
#define I2C1_SDA_GPIO_PINSOURCE GPIO_PinSource7 /*-----------I2C2 Device -----------*/ #define I2C2_SCL_GPIO_PORT GPIOA
#define I2C2_SCL_GPIO_CLK RCC_AHB1Periph_GPIOA
#define I2C2_SCL_GPIO_PIN GPIO_Pin_8
#define I2C2_SCL_GPIO_PINSOURCE GPIO_PinSource8 #define I2C2_SDA_GPIO_PORT GPIOC
#define I2C2_SDA_GPIO_CLK RCC_AHB1Periph_GPIOC
#define I2C2_SDA_GPIO_PIN GPIO_Pin_9
#define I2C2_SDA_GPIO_PINSOURCE GPIO_PinSource9 /*-----------I2C3 Device -----------*/ #define I2C3_SCL_GPIO_PORT GPIOH
#define I2C3_SCL_GPIO_CLK RCC_AHB1Periph_GPIOH
#define I2C3_SCL_GPIO_PIN GPIO_Pin_7
#define I2C3_SCL_GPIO_PINSOURCE GPIO_PinSource7 #define I2C3_SDA_GPIO_PORT GPIOH
#define I2C3_SDA_GPIO_CLK RCC_AHB1Periph_GPIOH
#define I2C3_SDA_GPIO_PIN GPIO_Pin_8
#define I2C3_SDA_GPIO_PINSOURCE GPIO_PinSource8 GPIO_TypeDef* I2C_SCL_GPIO_PORT[3] = {I2C1_SCL_GPIO_PORT, I2C2_SCL_GPIO_PORT, I2C3_SCL_GPIO_PORT};
const uint16_t I2C_SCL_GPIO_PIN[3] = {I2C1_SCL_GPIO_PIN, I2C2_SCL_GPIO_PIN, I2C3_SCL_GPIO_PIN};
const uint32_t I2C_SCL_GPIO_CLK[3] = {I2C1_SCL_GPIO_CLK, I2C2_SCL_GPIO_CLK, I2C3_SCL_GPIO_CLK};
const uint16_t I2C_SCL_GPIO_PINSOURCE[3] = {I2C1_SCL_GPIO_PINSOURCE, I2C2_SCL_GPIO_PINSOURCE, I2C3_SCL_GPIO_PINSOURCE}; GPIO_TypeDef* I2C_SDA_GPIO_PORT[3] = {I2C1_SDA_GPIO_PORT,I2C2_SDA_GPIO_PORT,I2C3_SDA_GPIO_PORT};
const uint16_t I2C_SDA_GPIO_PIN[3] = {I2C1_SDA_GPIO_PIN,I2C2_SDA_GPIO_PIN,I2C3_SDA_GPIO_PIN};
const uint32_t I2C_SDA_GPIO_CLK[3] = {I2C1_SDA_GPIO_CLK,I2C2_SDA_GPIO_CLK,I2C3_SDA_GPIO_CLK};
const uint16_t I2C_SDA_GPIO_PINSOURCE[3] = {I2C1_SDA_GPIO_PINSOURCE,I2C2_SDA_GPIO_PINSOURCE,I2C3_SDA_GPIO_PINSOURCE}; TIM_TypeDef* Timer[3] = {TIM5, TIM6, TIM7};
const IRQn_Type TimerIRQ[3] = {TIM5_IRQn, TIM6_DAC_IRQn, TIM7_IRQn}; const uint32_t RCC_APB1Periph_TIM[3] ={RCC_APB1Periph_TIM5, RCC_APB1Periph_TIM6, RCC_APB1Periph_TIM7}; #define SDA_Clear(IIC) I2C_SDA_GPIO_PORT[IIC]->BSRRH=I2C_SDA_GPIO_PIN[IIC]
#define SDA_Set(IIC) I2C_SDA_GPIO_PORT[IIC]->BSRRL=I2C_SDA_GPIO_PIN[IIC] #define SCL_Clear(IIC) I2C_SCL_GPIO_PORT[IIC]->BSRRH=I2C_SCL_GPIO_PIN[IIC]
#define SCL_Set(IIC) I2C_SCL_GPIO_PORT[IIC]->BSRRL=I2C_SCL_GPIO_PIN[IIC] #define En_SDA_Input(IIC) I2C_SDA_GPIO_PORT[IIC]->MODER&=~(I2C_SDA_GPIO_PIN[IIC]<<I2C_SDA_GPIO_PINSOURCE[IIC])
#define En_SDA_Output(IIC) I2C_SDA_GPIO_PORT[IIC]->MODER|=(I2C_SDA_GPIO_PIN[IIC]<<I2C_SDA_GPIO_PINSOURCE[IIC]) #define SDA_Read(IIC) ((I2C_SDA_GPIO_PORT[IIC]->IDR&I2C_SDA_GPIO_PIN[IIC])!=0)?1:0 typedef struct {
__IO uint8_t StartState;
__IO uint8_t StopState;
__IO int8_t ReadByteState;
__IO uint8_t TransferByte;
__IO uint8_t ReadStop;
__IO uint8_t WriteByteState;
__IO uint8_t WriteACK;
__IO uint8_t Command; //1-Read, 0=Write;
__IO uint8_t Device;
__IO uint32_t SubAddr;
__IO uint8_t SubAddrLen;
__IO uint8_t *TransferBuf;
__IO uint16_t TransferCount;
__IO uint8_t ReadState;
__IO uint8_t WriteState; __IO uint8_t dat;
__IO uint8_t bit;
__IO uint8_t IIC_BUSY;
__IO uint8_t ERROR;
} IIC_State; static IIC_State iic_state[IIC_COUNT]; typedef struct {
void(*OnTx)(void);
void(*OnRx)(void);
void(*OnErr)(void);
} IIC_Callback; __IO IIC_Callback iic_callback[IIC_COUNT]; #define IN 1
#define OUT 0 void __INLINE SetIicSdaDir(uint8_t IIC, uint8_t x) {
if (x) En_SDA_Input(IIC);
else En_SDA_Output(IIC);
} void IIC_GPIOInit(uint8_t IIC)
{
GPIO_InitTypeDef GPIO_InitStructure; /* Enable I2Cx SCL and SDA Pin Clock */
RCC_AHB1PeriphClockCmd((I2C_SCL_GPIO_CLK[IIC] | I2C_SDA_GPIO_CLK[IIC]), ENABLE); /* Set GPIO frequency to 50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /* Select Alternate function mode */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//????? /* Select output Open Drain type */
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; /* Disable internal Pull-up */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; /* Initialize I2Cx SCL Pin */
GPIO_InitStructure.GPIO_Pin = I2C_SCL_GPIO_PIN[IIC]; GPIO_Init((GPIO_TypeDef*)I2C_SCL_GPIO_PORT[IIC], &GPIO_InitStructure); /* Initialize I2Cx SDA Pin */
GPIO_InitStructure.GPIO_Pin = I2C_SDA_GPIO_PIN[IIC]; GPIO_Init((GPIO_TypeDef*)I2C_SDA_GPIO_PORT[IIC], &GPIO_InitStructure);
} static void IIC_DelayTimer_Init(uint8_t IIC)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = TimerIRQ[IIC];
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0 ;
NVIC_Init(&NVIC_InitStructure);
memset((void *)&iic_state[IIC], 0, sizeof(IIC_State));
memset((void *)&iic_callback[IIC], 0, sizeof(IIC_Callback));
} static void IIC_DelayTimer_DeInit(uint8_t IIC)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = TimerIRQ[IIC];
NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0 ;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(Timer[IIC], DISABLE);
memset(&iic_state[IIC], 0, sizeof(IIC_State));
} static void IIC_SetDelay(uint8_t IIC, uint16_t MicroSecond)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_ClocksTypeDef rccClocks;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM[IIC],ENABLE); RCC_GetClocksFreq(&rccClocks); TIM_DeInit(Timer[IIC]);
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
if (Timer[IIC]==TIM2||Timer[IIC]==TIM3||Timer[IIC]==TIM4||Timer[IIC]==TIM5||Timer[IIC]==TIM6||Timer[IIC]==TIM7||
Timer[IIC]==TIM12||Timer[IIC]==TIM13||Timer[IIC]==TIM14) TIM_TimeBaseStructure.TIM_Prescaler=rccClocks.PCLK1_Frequency*2/1000000;
else TIM_TimeBaseStructure.TIM_Prescaler=rccClocks.PCLK2_Frequency*2/1000000;
TIM_TimeBaseStructure.TIM_ClockDivision=0;
TIM_TimeBaseStructure.TIM_Period=MicroSecond;
TIM_TimeBaseInit(Timer[IIC], &TIM_TimeBaseStructure); TIM_ClearFlag(Timer[IIC], TIM_FLAG_Update); TIM_ITConfig(Timer[IIC],TIM_FLAG_Update, ENABLE);
} void IIC_Init(uint8_t IIC, uint16_t MicroSecond)
{
IIC_GPIOInit(IIC);
SDA_Set(IIC);
SCL_Set(IIC);
IIC_DelayTimer_Init(IIC);
IIC_SetDelay(IIC, MicroSecond);
}
#define p iic_state[IIC]
#define q iic_callback[IIC] void IIC_SetCallback(uint8_t IIC, void(*OnTx)(void), void(*OnRx)(void) ,void(*OnErr)(void))
{
q.OnErr=OnErr;
q.OnTx=OnTx;
q.OnRx=OnRx;
} void IIC_DeInit(uint8_t IIC)
{
IIC_DelayTimer_DeInit(IIC);
} static uint8_t IIC_StartStateMachine(uint8_t IIC)
{
switch(p.StartState) {
case 0:
SDA_Set(IIC);
SCL_Set(IIC);
p.StartState++;
break;
case 1:
SDA_Clear(IIC);
//SoftDelay(0);
p.StartState++;
break;
case 2:
SCL_Clear(IIC);
p.StartState=0;
break;
}
return p.StartState;
} static uint8_t IIC_StopStateMachine(uint8_t IIC)
{
switch(p.StopState) {
case 0:
SCL_Set(IIC);
SDA_Clear(IIC);
//SoftDelay(1);
p.StopState++;
break;
case 1:
SDA_Set(IIC);
p.StopState=0;
break;
}
return p.StopState;
} static uint8_t IIC_ReadByteStateMachine(uint8_t IIC)
{
switch(p.ReadByteState) {
case 0:
SetIicSdaDir(IIC, IN);
p.bit=0;
p.ReadByteState++;
break;
case 1:
p.dat <<= 1;
SCL_Set(IIC);
p.ReadByteState++;
break;
case 2:
if(SDA_Read(IIC))
{
p.dat |= 1;
}
SCL_Clear(IIC);
p.bit++;
if (p.bit==8) p.ReadByteState++;
else {
p.ReadByteState--;
break;
}
case 3:
p.TransferByte=p.dat;
SetIicSdaDir(IIC, OUT);
if (p.ReadStop) SDA_Set(IIC); else SDA_Clear(IIC); // ReadStop = 0; ask, ReadStop = 1,stop
p.ReadByteState++;
break;
case 4:
SCL_Set(IIC);
p.ReadByteState++;
break;
case 5:
SCL_Clear(IIC);
p.ReadByteState++;
case 6:
p.ReadByteState=0;
break;
}
return p.ReadByteState;
} static uint8_t IIC_WriteByteStateMachine(uint8_t IIC)
{
switch(p.WriteByteState) {
case 0:
p.dat=p.TransferByte;
p.bit=8;
p.WriteByteState++;
case 1:
if(p.dat & 0x80)
{
SDA_Set(IIC);
}
else
{
SDA_Clear(IIC);
}
p.WriteByteState++;
break;
case 2:
SCL_Set(IIC);
p.WriteByteState++;
break;
case 3:
p.dat <<= 1;
SCL_Clear(IIC);
p.bit--;
if (p.bit) {
p.WriteByteState=1;
break;
}
else p.WriteByteState++;
case 4:
SetIicSdaDir(IIC, IN);
p.WriteByteState++;
break;
case 5:
SCL_Set(IIC);
p.WriteByteState++;
break;
case 6:
p.WriteACK = SDA_Read(IIC);
SCL_Clear(IIC);
SetIicSdaDir(IIC, OUT);
p.WriteByteState++;
break;
case 7:
p.WriteByteState=0;
break;
}
return p.WriteByteState;
} static uint8_t IIC_ReadStateMachine(uint8_t IIC)
{
switch(p.ReadState) {
case 0:
p.ReadState++;
case 1:
if (IIC_StartStateMachine(IIC)==0) p.ReadState++;
break;
case 2:
p.TransferByte=p.Device;
p.ReadState++;
case 3:
if (IIC_WriteByteStateMachine(IIC)==0) {
if (p.WriteACK==1) {
p.ReadState=14; //Stop
}
else {
if (p.SubAddrLen) p.ReadState++; //Send Access Address
else p.ReadState+=3; //No Address
}
}
break;
case 4: //Send Address
switch(p.SubAddrLen) {
case 4: p.TransferByte=(p.SubAddr >> 24)&0x000000FF; break;
case 3: p.TransferByte=(p.SubAddr >> 16)&0x000000FF; break;
case 2: p.TransferByte=(p.SubAddr >> 8)&0x000000FF; break;
case 1: p.TransferByte=p.SubAddr&0x000000FF; break;
}
p.SubAddrLen--;
p.ReadState++;
case 5:
if (IIC_WriteByteStateMachine(IIC)==0) {
if (p.WriteACK==1) {
p.ReadState=14; //Stop
}
else {
if (p.SubAddrLen==0) p.ReadState++;
else p.ReadState--;
}
}
break;
case 6:
if (IIC_StartStateMachine(IIC)==0) p.ReadState++;
break;
case 7: //Send Device Read
p.TransferByte=p.Device|0x01;
p.ReadState++;
case 8:
if (IIC_WriteByteStateMachine(IIC)==0) {
if (p.WriteACK==1) {
p.ReadState=14;
}
else {
if (p.TransferCount==1) p.ReadState+=3;
else p.ReadState++;
}
}
break;
case 9: //Read Bytes
p.ReadStop=0;
p.ReadState++;
case 10:
if (IIC_ReadByteStateMachine(IIC)==0) {
*p.TransferBuf=p.TransferByte;
p.TransferBuf++;
p.TransferCount--;
if (p.TransferCount==1) p.ReadState++;
}
break;
case 11: //Read Last Byte
p.ReadStop=1;
p.ReadState++;
case 12: //Read Last Byte
if (IIC_ReadByteStateMachine(IIC)==0) {
*p.TransferBuf=p.TransferByte;
p.TransferCount=0;
p.ReadState++;
}
break;
case 13:
if (IIC_StopStateMachine(IIC)==0) {
p.ReadState=0;
p.IIC_BUSY=0;
p.ERROR=0;
if (q.OnRx) q.OnRx();
}
break;
case 14:
if (IIC_StopStateMachine(IIC)==0) {
p.ReadState=0;
p.IIC_BUSY=0;
p.ERROR=1;
if (q.OnErr) q.OnErr();
}
break;
}
return p.ReadState;
} static uint8_t IIC_WriteStateMachine(uint8_t IIC)
{
switch(p.WriteState) {
case 0:
p.WriteState++;
case 1:
if (IIC_StartStateMachine(IIC)==0) p.WriteState++;
break;
case 2:
p.TransferByte=p.Device;
p.WriteState++;
case 3:
if (IIC_WriteByteStateMachine(IIC)==0) {
if (p.WriteACK==1) {
p.WriteState=11; //Stop
}
else {
if (p.SubAddrLen) p.WriteState++; //Send Access Address
else {
if (p.TransferCount) p.WriteState+=5; //Multi-Bytes;
else p.WriteState+=3; //Single Byte
}
}
}
break;
case 4: //Send Address
switch(p.SubAddrLen) {
case 4: p.TransferByte=(p.SubAddr >> 24)&0x000000FF; break;
case 3: p.TransferByte=(p.SubAddr >> 16)&0x000000FF; break;
case 2: p.TransferByte=(p.SubAddr >> 8)&0x000000FF; break;
case 1: p.TransferByte=p.SubAddr&0x000000FF; break;
}
p.SubAddrLen--;
p.WriteState++;
case 5:
if (IIC_WriteByteStateMachine(IIC)==0) {
if (p.WriteACK==1) {
p.WriteState=11; //Stop
}
else {
if (p.SubAddrLen==0) {
if (p.TransferCount) p.WriteState+=3; //Multi-Bytes;
else p.WriteState++; //Single Byte
}
else p.WriteState--;
}
}
break;
case 6: //Send Only One Byte
p.TransferByte=(uint32_t)p.TransferBuf;
p.WriteState++;
case 7:
if (IIC_WriteByteStateMachine(IIC)==0) {
if (p.WriteACK==1) {
p.WriteState=11; //Stop
}
else {
p.WriteState+=3;
}
}
break;
case 8: //Send Multi-Bytes Data
p.TransferByte=*p.TransferBuf; p.TransferBuf++; p.TransferCount--;
p.WriteState++;
case 9:
if (IIC_WriteByteStateMachine(IIC)==0) {
if (p.WriteACK==1) {
p.WriteState=11; //Stop
}
else {
if (p.TransferCount==0) p.WriteState++;
else p.WriteState--;
}
}
break;
case 10:
if (IIC_StopStateMachine(IIC)==0) {
p.WriteState=0;
p.IIC_BUSY=0;
p.ERROR=0;
if (q.OnTx) q.OnTx();
}
break;
case 11:
if (IIC_StopStateMachine(IIC)==0) {
p.WriteState=0;
p.IIC_BUSY=0;
p.ERROR=1;
if (q.OnErr) q.OnErr();
}
break;
}
return p.WriteState;
} static uint8_t IIC_StateMachine(uint8_t IIC)
{
if (p.Command) return IIC_ReadStateMachine(IIC);
return IIC_WriteStateMachine(IIC);
} uint8_t I2C_Read7(uint8_t IIC, uint8_t device, uint8_t Addr, uint8_t *Buf, uint8_t Count)
{
if (p.IIC_BUSY==0) {
memset(&p, 0, sizeof(IIC_State));
p.Command=1; //1-Read, 0=Write;
p.Device=device;
p.SubAddr=Addr;
p.SubAddrLen=1;
p.TransferBuf=Buf;
p.TransferCount=Count;
p.IIC_BUSY=1;
TIM_Cmd(Timer[IIC], ENABLE);
return 1;
}
else return 0;
} uint8_t I2C_Read16(uint8_t IIC, uint8_t device, uint16_t Addr, uint8_t *Buf, uint8_t Count)
{
if (p.IIC_BUSY==0) {
memset(&p, 0, sizeof(IIC_State));
p.Command=1; //1-Read, 0=Write;
p.Device=device;
p.SubAddr=Addr;
p.SubAddrLen=2;
p.TransferBuf=Buf;
p.TransferCount=Count;
p.IIC_BUSY=1;
TIM_Cmd(Timer[IIC], ENABLE);
return 1;
}
else return 0;
} uint8_t I2C_WriteByte7(uint8_t IIC, uint8_t device, uint8_t Addr, uint8_t Data)
{
if (p.IIC_BUSY==0) {
memset(&p, 0, sizeof(IIC_State));
p.Command=0; //1-Read, 0=Write;
p.Device=device;
p.SubAddr=Addr;
p.SubAddrLen=1;
p.TransferBuf=(uint8_t *)Data;
p.TransferCount=0;
p.IIC_BUSY=1;
TIM_Cmd(Timer[IIC], ENABLE);
return 1;
}
else return 0;
} uint8_t I2C_Write16(uint8_t IIC, uint8_t device, uint16_t Addr, uint8_t *Buf, uint8_t Count)
{
if (p.IIC_BUSY==0) {
memset(&p, 0, sizeof(IIC_State));
p.Command=0; //1-Read, 0=Write;
p.Device=device;
p.SubAddr=Addr;
p.SubAddrLen=2;
p.TransferBuf=Buf;
p.TransferCount=Count;
p.IIC_BUSY=1;
TIM_Cmd(Timer[IIC], ENABLE);
return 1;
}
else return 0;
} #if (IIC_COUNT>=1)
void TIM5_IRQHandler(void)
{
if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM5, TIM_IT_Update);
if (IIC_StateMachine(0)==0) {
if (iic_state[0].IIC_BUSY==0) TIM_Cmd(TIM5, DISABLE);
}
}
}
#endif #if (IIC_COUNT>=2)
void TIM6_DAC_IRQHandler(void)
{
if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
if (IIC_StateMachine(1)==0) {
if (iic_state[1].IIC_BUSY==0) TIM_Cmd(TIM6, DISABLE);
}
}
}
#endif #if (IIC_COUNT>=3)
void TIM7_IRQHandler(void)
{
if (TIM_GetITStatus(TIM7, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM7, TIM_IT_Update);
if (IIC_StateMachine(2)==0) {
if (iic_state[2].IIC_BUSY==0) TIM_Cmd(TIM7, DISABLE);
}
}
}
#endif