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. 安装 GraphicsMagick

    yum -y install GraphicsMagick GraphicsMagick-devel 实际试了试,上面yum的方式不好使,下面是我实际安装过程: 1.下载最新版 wget ftp:// ...

  2. sql join实例图解

    https://blog.codinghorror.com/a-visual-explanation-of-sql-joins/ 1. inner join: 所有满足join条件的两个table对应 ...

  3. APRoundedButton

    APRoundedButton https://github.com/elpsk/APRoundedButton 效果: 源码: APRoundedButton.h // // Created by ...

  4. Compare DML To Both REDO And UNDO Size

    SUMMARY you can remember undo rule  the same to redo if you want demo rule that you can look up the ...

  5. Android启动外部应用的方法

    1.根据package的名称获取应用的Launch Intent Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage ...

  6. [Assignment] C++2

    作业要求:PAT1025 翻转链表 代码在这里

  7. codeforces 388D Fox and Perfect Sets(线性基+数位dp)

    #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define mp mak ...

  8. 《java编程思想》有必要买吗

    <java编程思想>有必要买吗 1.看到过好多个这样的提问,其实我一般真的不那么容易分享自己的这点心得的,这是第一次回答这样的“推荐书籍”方面的问题. 我买编程方面的书籍,有一个非常清晰. ...

  9. Codeforces Round #439 (Div. 2)【A、B、C、E】

    Codeforces Round #439 (Div. 2) codeforces 869 A. The Artful Expedient 看不透( #include<cstdio> in ...

  10. POJ3347 Kadj Squares

    嘟嘟嘟 题意:给出一堆正方形的边长,且这些正方形都是\(45 ^ {\circ}\)斜放着并且紧挨着的,求从上往下看能看到几个正方形. 真是一道好题--跟计算几何关系不大. 想一下,如果我们能求出正方 ...