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. Python套接字

    1.客户端/服务器架构 什么是客户端/服务器架构?对于不同的人来说,它意味着不同的东西,这取决于你问谁以及描述的是软件还是硬件系统.在这两种情况中的任何一种下,前提都很简单:服务器就是一系列硬件或软件 ...

  2. Mycat中间件

    数据库中间件Mycat自我介绍 一.mycat概述 1.功能介绍 mycat一个开源的分布式数据库系统,是一个实现了mysql协议的server前端用户可以把它看成一个数据库代理,用mysql客户端工 ...

  3. ExpressRoute 概述

    使用 Azure ExpressRoute 可通过连接服务提供商所提供的专用连接,将本地网络扩展到 Azure 云.使用 ExpressRoute 可与 Azure云服务建立连接. 可以从任意位置之间 ...

  4. SQL 常用语法

    一.SQL分类 DDL—数据定义语言(CREATE,ALTER,DROP,DECLARE) DML—数据操纵语言(SELECT,DELETE,UPDATE,INSERT) DCL—数据控制语言(GRA ...

  5. 主存储器与CPU的连接

    半导体存储器的读写时间一般在十几至几百毫微秒之间,其芯片集成度高,体积小,片内含有译码器和寄存器等电路.常用的半导体存储器芯片有多字一位片和多字多位片,如16M位容量的芯片可以有16M×1位和4M×4 ...

  6. August 04th 2017 Week 31st Friday

    Love is a vine that grows into our hearts. 爱是长在我们心里的藤蔓. What is love? Maybe no one can explain it cl ...

  7. PhoneGap的通知

    一.通知类型列表 1.notification.alert         提示警告框 2.notification.confirm                  确认对话框 3.notifica ...

  8. win10 系统下获取系统版本号为6.2的问题

    近期赶时髦升级了win10,用着挺爽.但是某天在测试一个bug时发现要对win10做特殊处理,于是直接调用了GetVersionEx,并取出版本号进行判断,但是发现得到的版本竟然是6.2.当时就被雷到 ...

  9. Extjs自定义验证介绍

    表单验证实例(空验证,密码确认验证,email验证) 我们可以用单独的js写表单验证,但是extjs已经为我们想到了(自己单独写反而不方便). 在验证之前,我不得不提两个小知识点: //大家在很多的e ...

  10. PHP面试系列之Linux(一) ----- Linux基础

    一.系统安全 sudo:以系统管理者的身份执行指令,也就是说,经由 sudo 所执行的指令就好像是 root 亲自执行. su:用于变更为其他使用者的身份,除 root 外,需要键入该使用者的密码. ...