首先我们看到F1系列单片机引脚的截图,可以看到PB7,PB8可以复用为I2C1接口。PB10,PB11可以复用为I2C2接口。
在后面i2c产生起始位,以及使能的时候,会填入参数:i2cX,这时候要和复用的GPIO口对应的通讯线路一致
从51单片机学习的时候可以知道,I2C接口需要配置上拉电阻。保证通讯,在这里上拉电阻配置在外面,所以说GPIO口复用的时候配置为开漏输出模式。
I2C通讯的软件架构和之前的51单片机也略微有些不同:
总体而言就是增加了官方的固件库:stm32f10x_i2c 用于配置底层的功能寄存器,寄存器进一步管理硬件电路,而实现功能。所以自然i2c总线驱动函数中调用stm32f10x_i2c的库函数是不可少的。
其中着重说一下这个I2C_CheckEvent()函数,在后面的函数中,多次嵌套在while循环中进行判断,这个相当于是51单片机里面,每次发送数据后都要等一个Ack,具体等待的是什么发来的应答就要到库函数里面去看了,基本掌握运用就行。
通过对库函数的重新封装,组合成新的驱动函数,具体可以见下面的.h文件,定义的5个基本函数
(下面的代码注释紊乱是编码的问题,复制到Keil5里选择ANSI编码就没问题了)
#define I2CPORT GPIOB //¶¨ÒåIO½Ó¿Ú
#define I2C_SCL GPIO_Pin_6 //¶¨ÒåIO½Ó¿Ú
#define I2C_SDA GPIO_Pin_7 //¶¨ÒåIO½Ó¿Ú
#define HostAddress 0xc0 //×ÜÏßÖ÷»úµÄÆ÷¼þµØÖ·
#define BusSpeed 200000 //×ÜÏßËÙ¶È£¨²»¸ßÓÚ400000£©
void I2C_Configuration(void);
void I2C_SAND_BUFFER(u8 SlaveAddr, u8 WriteAddr, u8* pBuffer, u16 NumByteToWrite);
void I2C_SAND_BYTE(u8 SlaveAddr,u8 writeAddr,u8 pBuffer);
void I2C_READ_BUFFER(u8 SlaveAddr,u8 readAddr,u8* pBuffer,u16 NumByteToRead);
u8 I2C_READ_BYTE(u8 SlaveAddr,u8 readAddr);
看到下面的初始化结构体函数中
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;我们定义的是7位地址模式,十位地址定义如下:
#define I2C_AcknowledgedAddress_7bit ((uint16_t)0x4000)
#define I2C_AcknowledgedAddress_10bit ((uint16_t)0xC000)
#include "i2c.h"
void I2C_GPIO_Init(void){ //I2C½Ó¿Ú³õʼ»¯(ÅäÖýӿڣ¬ÄÚǶÓÚvoid I2C_Configuration(void)£¬ÉÏÀµç×èÔÚµ¥Æ¬»úÍ⣬ËùÒÔÓø´ÓÿªÂ©Êä³ö)
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); //Æô¶¯I2C¹¦ÄÜ
GPIO_InitStructure.GPIO_Pin = I2C_SCL | I2C_SDA; //Ñ¡Ôñ¶Ë¿ÚºÅ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //Ñ¡ÔñIO½Ó¿Ú¹¤×÷·½Ê½
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //ÉèÖÃIO½Ó¿ÚËÙ¶È£¨2/10/50MHz£©
GPIO_Init(I2CPORT, &GPIO_InitStructure);
}
void I2C_Configuration(void){ //I2C³õʼ»¯
I2C_InitTypeDef I2C_InitStructure;//¶¨Òå½á¹¹Ì壬½øÐгõʼ»¯
I2C_GPIO_Init(); //ÏÈÉèÖÃGPIO½Ó¿ÚµÄ״̬
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//ÉèÖÃΪI2Cģʽ
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = HostAddress; //Ö÷»úµØÖ·£¨´Ó»ú²»µÃÓô˵ØÖ·£©(Ò»°ãΪ0xc0ÔÚ.hÎļþÀïÃæ¶¨ÒåµÄÓÐ)
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//ÔÊÐíÓ¦´ð
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //7λµØÖ·Ä£Ê½
I2C_InitStructure.I2C_ClockSpeed = BusSpeed; //×ÜÏßËÙ¶ÈÉèÖÃ
I2C_Init(I2C1,&I2C_InitStructure);
I2C_Cmd(I2C1,ENABLE);//¿ªÆôI2C1(¸ù¾ÝÒý½Å¸´ÓÃÊÓͼ£¬F1ϵÁеĵ¥Æ¬»úÓÐ2×éi2c½Ó¿Ú£¬ÕâÀïÓõÄÊǵÚÒ»×é)
}
void I2C_SAND_BUFFER(u8 SlaveAddr,u8 WriteAddr,u8* pBuffer,u16 NumByteToWrite){ //I2C·¢ËÍÊý¾Ý´®£¨Æ÷¼þµØÖ·£¬¼Ä´æÆ÷£¬ÄÚ²¿µØÖ·£¬ÊýÁ¿£©
I2C_GenerateSTART(I2C1,ENABLE);//²úÉúÆðʼλ
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)); //Çå³ýEV5
I2C_Send7bitAddress(I2C1,SlaveAddr,I2C_Direction_Transmitter);//·¢ËÍÆ÷¼þµØÖ·
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//Çå³ýEV6
I2C_SendData(I2C1,WriteAddr); //ÄÚ²¿¹¦ÄܵØÖ·
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));//ÒÆÎ»¼Ä´æÆ÷·Ç¿Õ£¬Êý¾Ý¼Ä´æÆ÷Òѿգ¬²úÉúEV8£¬·¢ËÍÊý¾Ýµ½DR¼ÈÇå³ý¸Ãʼþ
while(NumByteToWrite--){ //Ñ»··¢ËÍÊý¾Ý
I2C_SendData(I2C1,*pBuffer); //·¢ËÍÊý¾Ý
pBuffer++; //Êý¾ÝÖ¸ÕëÒÆÎ»
while (!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));//Çå³ýEV8
}
I2C_GenerateSTOP(I2C1,ENABLE);//²úÉúÍ£Ö¹ÐźÅ
}
void I2C_SAND_BYTE(u8 SlaveAddr,u8 writeAddr,u8 pBuffer){ //I2C·¢ËÍÒ»¸ö×Ö½Ú£¨´ÓµØÖ·£¬ÄÚ²¿µØÖ·£¬ÄÚÈÝ£©
I2C_GenerateSTART(I2C1,ENABLE); //·¢ËÍ¿ªÊ¼ÐźÅ
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)); //µÈ´ýÍê³É
I2C_Send7bitAddress(I2C1,SlaveAddr, I2C_Direction_Transmitter); //·¢ËÍ´ÓÆ÷¼þµØÖ·¼°×´Ì¬£¨Ð´È룩
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //µÈ´ýÍê³É
I2C_SendData(I2C1,writeAddr); //·¢ËÍ´ÓÆ÷¼þÄÚ²¿¼Ä´æÆ÷µØÖ·
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //µÈ´ýÍê³É
I2C_SendData(I2C1,pBuffer); //·¢ËÍҪдÈëµÄÄÚÈÝ
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //µÈ´ýÍê³É
I2C_GenerateSTOP(I2C1,ENABLE); //·¢ËͽáÊøÐźÅ
}
void I2C_READ_BUFFER(u8 SlaveAddr,u8 readAddr,u8* pBuffer,u16 NumByteToRead){ //I2C¶ÁÈ¡Êý¾Ý´®£¨Æ÷¼þµØÖ·£¬¼Ä´æÆ÷£¬´¢´æÆ÷µØÖ·£¬×Ö½Ú³¤¶È£©
while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));
I2C_GenerateSTART(I2C1,ENABLE);//¿ªÆôÐźÅ
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)); //Çå³ý EV5
I2C_Send7bitAddress(I2C1,SlaveAddr, I2C_Direction_Transmitter); //дÈëÆ÷¼þµØÖ·
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//Çå³ý EV6
I2C_Cmd(I2C1,ENABLE);
I2C_SendData(I2C1,readAddr); //·¢ËͶÁµÄµØÖ·
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //Çå³ý EV8
I2C_GenerateSTART(I2C1,ENABLE); //¿ªÆôÐźÅ
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)); //Çå³ý EV5
I2C_Send7bitAddress(I2C1,SlaveAddr,I2C_Direction_Receiver); //½«Æ÷¼þµØÖ·´«³ö£¬Ö÷»úΪ¶Á
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); //Çå³ýEV6
while(NumByteToRead){
if(NumByteToRead == 1){ //ֻʣÏÂ×îºóÒ»¸öÊý¾Ýʱ½øÈë if Óï¾ä
I2C_AcknowledgeConfig(I2C1,DISABLE); //×îºóÓÐÒ»¸öÊý¾Ýʱ¹Ø±ÕÓ¦´ðλ
I2C_GenerateSTOP(I2C1,ENABLE); //×îºóÒ»¸öÊý¾ÝʱʹÄÜֹͣλ
}
if(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)){ //¶ÁÈ¡Êý¾Ý
*pBuffer = I2C_ReceiveData(I2C1);//µ÷Óÿ⺯Êý½«Êý¾ÝÈ¡³öµ½ pBuffer
pBuffer++; //Ö¸ÕëÒÆÎ»
NumByteToRead--; //×Ö½ÚÊý¼õ 1
}
}
I2C_AcknowledgeConfig(I2C1,ENABLE);
}
u8 I2C_READ_BYTE(u8 SlaveAddr,u8 readAddr){ //I2C¶Áȡһ¸ö×Ö½Ú
u8 a;
while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));//È·¶¨i2c×ÜÏßûÓÐÆäËûÉ豸ռÏß
I2C_GenerateSTART(I2C1,ENABLE);//i2c¿ªÊ¼Ìõ¼þ
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1,SlaveAddr, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_Cmd(I2C1,ENABLE);//ÆôÓÃi2c
I2C_SendData(I2C1,readAddr);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTART(I2C1,ENABLE);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1,SlaveAddr, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
I2C_AcknowledgeConfig(I2C1,DISABLE); //×îºóÓÐÒ»¸öÊý¾Ýʱ¹Ø±ÕÓ¦´ðλ
I2C_GenerateSTOP(I2C1,ENABLE); //×îºóÒ»¸öÊý¾ÝʱʹÄÜֹͣλ
a = I2C_ReceiveData(I2C1);
return a;
}