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

  

STM32F4XX中断方式通过IO模拟I2C总线Master模式的更多相关文章

  1. C51单片机模拟I2C总线驱动程序设计

    /********************************** I2C总线驱动 ******************************** 模块名:I2C总线驱动 型号:I2C 功能描述 ...

  2. 51单片机模拟I2C总线的C语言实现

    电路原理图   EEPROM为ATMEL公司的AT24C01A.单片机为ATMEL公司的AT89C51. 软件说明 C语言为Franklin C V3.2.将源程序另存为testi2c.c,用命令 C ...

  3. 51单片机 | 基于I2C总线的秒表模拟应用

    ———————————————————————————————————————————— 参考地址: http://blog.csdn.net/junyeer/article/details/4648 ...

  4. I2C总线完全版——I2C总线的结构、工作时序与模拟编程

    I2C总线的结构.工作时序与模拟编程 I2C总线的结构.工作时序与模拟编程I2C总线(Inter Integrated Circuit)是飞利浦公司于上个世纪80年代开发的一种"电路板级&q ...

  5. MSP430的IO口模拟I2C总线对AT24C25进行读写程序

    功能: 实现MSP430口线模拟I2C总线协议与24C04通信.                                           ** 描述: 主系统工作时钟为12MHz,I2C工 ...

  6. I2C总线协议的软件模拟实现方法

    I2C总线协议的软件模拟实现方法 在上一篇博客中已经讲过I2C总线通信协议,本文讲述I2C总线协议的软件模拟实现方法. 1. 简述 所谓的I2C总线协议的软件模拟实现方法,就是用软件控制GPIO的输入 ...

  7. 【转载】GPIO模拟i2c通信

    I2C总线的通信过程(见图4-8)主要包含三个主要阶段:起始阶段.数据传输阶段和终止阶段. 1. 起始阶段 在I2C总线不工作的情况下,SDA(数据线)和SCL(时钟线)上的信号均为高电平.如果此时主 ...

  8. I2C总线以及GPIO模拟I2C

    ·I2C总线的一些特征: 1. 只要求两条总线,一条串行数据线(SDA),一条串行时钟线(SCL) 2. 两个连接到总线的器件都可以通过唯一的地址和一直存在的简单的主机/从机系统软件设定的地址:主机可 ...

  9. Linux+I2C总线分析(主要是probe的方式)

    Linux I2C 总线浅析 ㈠ Overview Linux的I2C体系结构分为3个组成部分: ·I2C核心: I2C核心提供了I2C总线驱动和设备驱动的注册.注销方法,I2C通信方法(即“algo ...

随机推荐

  1. 毕向东_Java基础视频教程第20天_IO流(7~10)

    第20天-07-IO流(递归) package bxd; import java.io.File; public class FileDemo3 { // 非递归打印 public static vo ...

  2. maven(13)-安装nexus私服

     环境 nexus最新3.x版需要java1.8,2.x版需要1.7以上.我之前一直用2.x,现在偿试在centos7和window10上分别安装nexus3.x,首先确保系统中已经配好了JDK1 ...

  3. LoadRunner简单培训相关笔记

    学校花了20万买了LoadRunner,因此作为幸运的一届,赶上了这场培训.以下为笔记以及培训后制作的简易思维导图. Loadrunner思维导图源码(Xmind): http://pan.baidu ...

  4. python的enumerate函数

    python的enumerate函数用于循环索引和元素 例如 foo = 'abc' for i , ch in enumerate(foo): print ch, '(%d)' % i 输出结果: ...

  5. 一些很酷的.Net技巧 .

    一..Net Framework 1.  如何获得系统文件夹 使用System.Envioment类的GetFolderPath方法:例如: Environment.GetFolderPath( En ...

  6. [翻译] WZFlashButton

    WZFlashButton This is a custom button with flash-like effect. Inspired by Ripple Effect. 这是一个自定义的按钮, ...

  7. Python super执行基类的构造方法

    有一个需求是这样的,先有一个Machine的类,有通用的name.position.date属性,然后又出现了一个Server的类继承Machine类,但是Server类多出一个ipaddr的属性,所 ...

  8. ZT Android Debuggerd的分析及使用方法

    Android Debuggerd的分析及使用方法 分类: 移动开发 android framework 2012-12-28 12:00 983人阅读 评论(0) 收藏 举报 目录(?)[+] An ...

  9. Python中根据提供的日期,返回是一年中的第几天

    # coding = utf-8 import datetime dd = raw_input("Please enter date , format is YYYYMMDD:") ...

  10. 阿里嘉年华ADC Workshop PPT分享

    前段时间在阿里嘉年华的workshop做了一些关于memcache高可用和MMM Mod的分享. 下面是相关的PPT,特此分享. ADC官网直接在线查看:http://adc.alibabatech. ...