• 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
    

      

  • 相关阅读:
    svn版本控制器在vs2013中的使用
    在本地环境用虚拟机win2008 sever搭建VS2013 + SVN 代码版本控制环境
    luogu 2422 良好的感觉
    loj 10181 绿色通道
    luogu 2569 [SCOI2010]股票交易
    luogu 3946 ことりのおやつ(小鸟的点心)
    luogu 2865 [USACO06NOV]路障Roadblocks
    luogu 4554 小明的游戏
    luogu 2411 白银莲花池 && luogu 1606 Lilypad Pond
    luogu 2850 [USACO06DEC]虫洞Wormholes
  • 原文地址:https://www.cnblogs.com/hezihang/p/3674657.html
Copyright © 2020-2023  润新知