开发平台
- 野火开发板 F429
- 标准库
一提到I2C就会想到是通信协议,两个设备遵守这个协议便可以进行通讯 - 一个I2C总线上可以挂在多个I2C设备,一个I2C总线上有SCL(时钟线)和SDA(数据线)
I2C时序
- I2C的时序,如下图:
1.SCL(时钟线)高电平有效。
在SCL高电平时,SDA(数据线)由高电平被拉低,表示已经有了起始信号,可以开始通讯
2.数据在SCL为高电平时有效,SCL为低电平时无效,在SCL为低电平时,SDA可切换高低电平。每次传输八位数据
3收发数据后等待应答
4.在SCL高电平时,SDA由低电平被拉高,表示通讯停止
I2C通讯过程
- 主发送器序列
STM32作为主设备,每完成一个动作后都会产生相应的事件
1.STM32发送起始信号
2.发送I2C从设备地址
3.发送I2C从设备内存地址
4.发送数据(可多个)
5.停止信号 - 主接收器序列
1.STM32发送起始信号
2.发送I2C从设备地址
3.发送I2C从设备内存地址
4.第二次发送起始信号
5.发送I2C从设备地址(告知从设备要读取他的数据)
6.读取数据(可多个)
7.停止信号
I2C架构框图
直接操作寄存器,要看架构框图
1.时钟线和数据线
2.时钟控制寄存器(I2C主模式选择、快速模式占空比、CCR的值)
控制寄存器(使能应答、产生停止位、产生起始位等)
状态寄存器(通讯过程产生事件标志位)
3.传输数据会用到(DR寄存器、OAR寄存器)
4.逻辑控制(涉及到中断、使用DMA等)
I2C读写EEPROM
EEPROM设备地址为7位,前4位地址固定为:1010,后三位看原理图000,最后一位由读操作或写操作决定,读为1,写为0。读地址为:0xA1,写地址为;0xA0
1.配置引脚,复用为I2C,注意一定是开漏输出
2.配置I2C的参数
3.编写接收、发送数据函数(要用到上述的通讯过程)
- 注意:通讯过程产生的事件要看清,很多时候会写错事件标志而导致I2C不通
代码如下:
#include "i2c.h"
void I2C_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/*使能时钟*/
RCC_AHB1PeriphClockCmd(I2C_CLK_CLOCK|
I2C_SDA_CLOCK,ENABLE);
/*引脚复用为I2C1*/
GPIO_PinAFConfig(I2C_CLK_PORT,I2C_CLK_PINSOURCE,GPIO_AF_I2C1);
GPIO_PinAFConfig(I2C_SDA_PORT,I2C_SDA_PINSOURCE,GPIO_AF_I2C1);
/*
**复用模式
**开漏输出
**不上拉不下拉
**100MHZ
**PB6 PB7
*/
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType=GPIO_OType_OD;
GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Speed=GPIO_High_Speed;
GPIO_InitStruct.GPIO_Pin=I2C_CLK_PIN;
GPIO_Init(I2C_CLK_PORT,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin=I2C_SDA_PIN;
GPIO_Init(I2C_SDA_PORT,&GPIO_InitStruct);
}
void I2C_Config(void)
{
I2C_InitTypeDef I2C_InitStruct;
/*使能时钟*/
RCC_APB1PeriphClockCmd(I2C_CLOCK,ENABLE);
I2C_GPIO_Config();
/*
**I2C模式
**通信速率400K
**STM32的I2C设备地址
**占空比16:9
**应答使能
**地址长度7位
*/
I2C_InitStruct.I2C_Mode=I2C_Mode_I2C;
I2C_InitStruct.I2C_ClockSpeed=I2C_CLOCK_SPEED;
I2C_InitStruct.I2C_OwnAddress1=I2C_OWNADDRESS;
I2C_InitStruct.I2C_DutyCycle=I2C_DutyCycle_16_9;
I2C_InitStruct.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;
I2C_InitStruct.I2C_Ack=I2C_Ack_Enable;
I2C_Init(I2C_PORT,&I2C_InitStruct);
/*使能I2C*/
I2C_Cmd(I2C_PORT,ENABLE);
}
uint8_t I2C_Writebyte(uint8_t addr,uint8_t *data)
{
/*I2C起始信号*/
I2C_GenerateSTART(I2C_PORT,ENABLE);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);
/*I2C设备地址*/
I2C_Send7bitAddress(I2C_PORT,I2C_ADDRESS_WRITE1,I2C_Direction_Transmitter);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=SUCCESS);
/*发送内存地址*/
I2C_SendData(I2C_PORT,addr);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=SUCCESS);
/*写入数据*/
I2C_SendData(I2C_PORT,*data);
/*I2C结束信号*/
I2C_GenerateSTOP(I2C_PORT,ENABLE);
return 1;
}
uint8_t I2C_Readbyte(uint8_t addr)
{
uint8_t data;
/*I2C起始信号*/
I2C_GenerateSTART(I2C_PORT,ENABLE);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);
/*I2C设备地址写*/
I2C_Send7bitAddress(I2C_PORT,I2C_ADDRESS_WRITE1,I2C_Direction_Transmitter);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=SUCCESS);
/*发送内存地址*/
I2C_SendData(I2C_PORT,addr);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=SUCCESS);
/*重新发送起始信号*/
I2C_GenerateSTART(I2C_PORT,ENABLE);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);
/*I2C设备地址读*/
I2C_Send7bitAddress(I2C_PORT,I2C_ADDRESS_READ1,I2C_Direction_Receiver);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)!=SUCCESS);
/*读取数据*/
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_BYTE_RECEIVED)!=SUCCESS);
data=I2C_ReceiveData(I2C_PORT);
/*失能应答*/
I2C_AcknowledgeConfig(I2C_PORT,DISABLE);
/*停止信号*/
I2C_GenerateSTOP(I2C_PORT,ENABLE);
/*使能应答,为下一次读取做准备*/
I2C_AcknowledgeConfig(I2C_PORT,ENABLE);
return data;
}
uint8_t I2C_Writepbuffer(uint8_t addr,uint8_t *data,uint8_t num)
{
/*I2C起始信号*/
I2C_GenerateSTART(I2C_PORT,ENABLE);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);
/*I2C设备地址*/
I2C_Send7bitAddress(I2C_PORT,I2C_ADDRESS_WRITE1,I2C_Direction_Transmitter);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=SUCCESS);
/*发送内存地址*/
I2C_SendData(I2C_PORT,addr);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=SUCCESS);
while(num)
{
/*写入数据*/
I2C_SendData(I2C_PORT,*data);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=SUCCESS);
data++;
num--;
}
/*停止信号*/
I2C_GenerateSTOP(I2C_PORT,ENABLE);
return 1;
}
uint8_t I2C_Readpbuffer(uint8_t addr,uint8_t num,uint8_t *pbuffer)
{
/*起始信号*/
I2C_GenerateSTART(I2C_PORT,ENABLE);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);
/*设备地址*/
I2C_Send7bitAddress(I2C_PORT,I2C_ADDRESS_WRITE1,I2C_Direction_Transmitter);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=SUCCESS);
/*内存地址*/
I2C_SendData(I2C_PORT,addr);
/*第二次起始信号*/
I2C_GenerateSTART(I2C_PORT,ENABLE);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);
/*发送设备地址为读*/
I2C_Send7bitAddress(I2C_PORT,I2C_ADDRESS_READ1,I2C_Direction_Receiver);
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)!=SUCCESS);
while(num)
{
if(num==1)
{
I2C_AcknowledgeConfig(I2C_PORT,DISABLE);
I2C_GenerateSTOP(I2C_PORT,ENABLE);
}
while(I2C_CheckEvent(I2C_PORT,I2C_EVENT_MASTER_BYTE_RECEIVED)!=SUCCESS);
{
*pbuffer=I2C_ReceiveData(I2C_PORT);
pbuffer++;
num--;
}
I2C_AcknowledgeConfig(I2C_PORT,ENABLE);
}
return 1;
}