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

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

  

posted @ 2014-04-19 10:20  子航  阅读(3350)  评论(0编辑  收藏  举报