当前位置: 代码迷 >> 单片机 >> 关于STM32系列单片机I2C通信的有关问题,求教各位大牛
  详细解决方案

关于STM32系列单片机I2C通信的有关问题,求教各位大牛

热度:65   发布时间:2016-04-28 14:59:51.0
关于STM32系列单片机I2C通信的问题,求教各位大牛
最近再做一个关于STM32F103系列单片机I2C通信的项目,因为以前没有玩过单片机所以有一些东西实在搞不懂,也没人可以咨询,所以来求教各位大牛了
先贴我的第一个问题:下面是一个简单的I2C写数据以及读数据的函数
void I2C_WriteByte(unsigned char write_address,unsigned char byte)
{
I2C_GenerateSTART(I2C2,ENABLE);
//产生起始条件
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));
//等待ACK
I2C_Send7bitAddress(I2C2,EEPROM_ADDR,I2C_Direction_Transmitter);
//向设备发送设备地址
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
//等待ACK
I2C_SendData(I2C2, write_address);
//寄存器地址
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
//等待ACK
I2C_SendData(I2C2, byte);
//发送数据
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
//发送完成
I2C_GenerateSTOP(I2C2, ENABLE);
//产生结束信号
}

void I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)//将EEPROM的数据读入缓冲器


I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));//检查最近一次 I2C事件是否是输入的事件

/* In the case of a single data transfer disable ACK before reading the data */
if(NumByteToRead==1) 
{
I2C_AcknowledgeConfig(I2C1, DISABLE);//使能或者失能指定 I2C的应答功能
}
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的从 I2C设备传送地址字,选择发送方向
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//检查最近一次 I2C事件是否是输入的事件
I2C_Cmd(I2C1, ENABLE);//使能或者失能 I2C外设
I2C_SendData(I2C1, ReadAddr); //通过外设 I2Cx发送读取地址()
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检查最近一次 I2C事件是否是输入的事件
I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));//检查最近一次 I2C事件是否是输入的事件
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver);//向指定的从 I2C设备传送地址字,选择接收方向
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//检查最近一次 I2C事件是否是输入的事件
/* While there is data to be read */
while(NumByteToRead) 
{
/* Test on EV7 and clear it */
if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) //检查最近一次 I2C事件是否是输入的事件
{
if(NumByteToRead == 2)
{
I2C_AcknowledgeConfig(I2C1, DISABLE);//使能或者失能指定 I2C的应答功能
}
if(NumByteToRead == 1)
{
I2C_GenerateSTOP(I2C1, ENABLE);//产生 I2Cx传输 STOP条件
}
*pBuffer = I2C_ReceiveData(I2C1);//返回通过 I2Cx最近接收的数据
pBuffer++; 
NumByteToRead--; 

}
/* Enable Acknowledgement to be ready for another reception */
I2C_AcknowledgeConfig(I2C1, ENABLE);//使能或者失能指定 I2C的应答功能

}

我查资料说STM32和器件通信有以下步骤:
写:检测SDA是否空闲;
->按I2C协议发出起始讯号;
->发出7位器件地址和写模式;
->要写入的存储区首地址;
->用页写入方式或字节写入方式写入数据;
 
读:检测SDA是否空闲;
->按I2C协议发出起始讯号;
->发出7位器件地址和写模式(伪写);
->发出要读取的存储区首地址;
->重发起始讯号;
->发出7位器件地址和读模式;
->接收数据;
无论读和写在发送完要写入或者读取的器件地址后都要再发送一个要写入或者读取的存储区地址,我的疑问是,这个地址读和写分别如何确定的呢?
还有一个疑问是:STM32有I2C1和I2C2两个I2C,如果我想做一下自回环,即I2C1给I2C2发送一个数据,I2C2收到后在传给I2C1一个数据,其中I2C1做主设备,I2C2做从设备,那么I2C1给I2C2发数据的时候器件地址是什么呢,I2C2给I2C1回数据的时候器件地址又是什么呢
东西有点多,跪求大神给解答!谢谢了
------解决方案--------------------
没用过,给2个参考

STM32硬件I2C读写AT24Cxx http://download.csdn.net/detail/xiaoxia711/6411779

http://download.csdn.net/detail/sjxabc123/3716906

http://bbs.ednchina.com/BLOG_ARTICLE_152425.HTM
------解决方案--------------------
你照着单片机datasheet上的操作去配置寄存器就是你贴出来的程序。你说的EEPROM的地址,是因为这些器件内部已经有了通讯协议,你只需按照通讯协议去操作就会读/写对应地址的值。你如果想用单片机模拟这种协议,只需在地址后再加一条命令(即寄存器地址),就是你看到的EEPROM的操作。 你说的循环会有问题,估计是你的开始或停止信号时序有问题。