我把iic通信的代码给你吧
/
/
//
void delay(unsigned int k)
{
unsigned int i,j;
for(i=0;i<k;i++)
{
for(j=0;j<121;j++)
{;}}
}
/
延时5微秒(STC90C52RC@12M)
不同的工作环境,需要调整此函数,注意时钟过快时需要修改
当改用1T的MCU时,请调整此延时函数
/
void Delay5us()
{
_nop_();_nop_();_nop_();_nop_();
_nop_();/_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_(); /
}
/
延时5毫秒(STC90C52RC@12M)
不同的工作环境,需要调整此函数
当改用1T的MCU时,请调整此延时函数
/
void Delay5ms()
{
WORD n = 1000;
while (n--)
{
_nop_();_nop_();_nop_();_nop_();
};
}
void MMA8452_SendByte(BYTE dat)
{
BYTE i;
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1; //移出数据的最高位
SDA = CY; //送数据口
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
MMA8452_RecvACK();
}
/
从IIC总线接收一个字节数据
/
BYTE MMA8452_RecvByte()
{
BYTE i;
BYTE dat = 0;
SDA = 1; //使能内部上拉,准备读取数据,
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1;
SCL = 1; //拉高时钟线
Delay5us(); //延时
dat |= SDA; //读数据
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
return dat;
}
这是我以前读取传感器信息时候用的。正好是iic通信的那部分,你自己学一下iic吧,我的程序是没问题的哦。
对于疑问1:for循环已经把数据从主器件发送到从器件,没错,后面加那几句是为了释放数据总线,这是芯片协议已经规定了的,为什么是scl=0;而sda=1呢,应该总线SCL与SDA都是线与关系,任意一个器件输出低电平,都使该总线的信号变低,你可能会这么想:为什么不是scl=1;delay();sda=1;delay();呢?那是因为当scl=1;sda=1;这是终止信号。对吧,这样写的话IIC将会停止工作。
对于疑问2:加这几句也一样,是芯片现已规定:无论是写数据还是读数据,写完读完之后需释放总线,for循环语句的意思是:
for(i=0;i<8;i++)
{
scl=1; //拉高时钟总线,开始读数据
delay();
k=(k<<1)|sda; // 将读取到的sda数据存放到k中,这里你可能有点无法理解,我举个例子:刚开始k=0x00(系统默认),当读取到的sda数据为1时,k=0x01;对吧,反之当读取到的sda数据为0时,k=0x00;
scl=0;// 读取完一个数据,拉低时钟总线
delay();
}
就这样循环8次,这样一个字节的数据就从主器件读到了从器件了。对吧。
如果那个释放总线你理解不了,你就记住,这是芯片协议规定,读完或写完都必须释放总线。iic协议都是如此。
希望能帮助到你。
他由3根线组成分别叫SDA,SCL,GND,SDA为数据线,SCL为时钟线,GND为参考电平,就是0电平
通信原理是通过对SCL和SDA线高低电平时序的控制,来产生I2C总线协议所需要的信号进行数据的传递。在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平
I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址(可以从I2C器件的数据手册得知),主从设备之间就通过这个地址来确定与哪个器件进行通信,在通常的应用中,我们把CPU带I2C总线接口的模块作为主设备,把挂接在总线上的其他设备都作为从设备。
I2C总线上的主设备与从设备之间 以字节(8位)为单位 进行双向的数据传输
总线上数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件
数据的传输
主设备在传输有效数据之前要先指定从设备的地址,地址指定的过程和上面数据传输的过程一样,只不过大多数从设备的地址是7位的,然后协议规定再给地址添加一个最低位用来表示接下来数据传输的方向,0表示主设备向从设备写数据,1表示主设备向从设备读数据
第一,主设备往从设备中写数据。数据传输格式如下:
第二,主设备从从设备中读数据。数据传输格式如下:
第三,主设备往从设备中写数据,然后重启起始条件,紧接着从从设备中读取数据;或者是主设备从从设备中读数据,然后重启起始条件,紧接着主设备往从设备中写数据。数据传输格式如下:
第三种 *** 作在单个主设备系统中,重复的开启起始条件机制要比用STOP终止传输后又再次开启总线更有效率。
Arduino的IIC通信使用wire库,该库包含以下方法:
begin()
requestFrom()
beginTransmission()
endTransmission()
write()
available()
read()
onReceive()
onRequest()
Wirebegin() 建立连接
(1)要在 setup( ) 内用Wirebegin( ) 加入 IIC 通讯
(A)Master 只要这样Wirebegin( );
(B)Slave 要用一个 1 到 127 的整数当作参数, 代表 Slave 的address,
例如
Wirebegin(2); // 我是2 号地址
(2)要由 Master 下命令要求Slave 送数据过来,
例如:
WirerequestFrom(2,6); // 要求 2号透过Wire 送 6 个char 过来
但是, 请注意, 这里的 6 其实只是一个byte 的命令, 只是"希望"从机送 6 byte (最多只可要求32 byte)
这里的 6 到底是啥意思是由Master 和 Slave 的程序设计者自己约定好即可
WirerequestFrom(); 只是送个命令(一个 byte)给某个Slave,
然后等着,直到至少一个char 送过来或 time out 才会往下做下一行
所以, 这时 Master 在这句下方要用Wireread( ) 读取数据
WirerequestFrom(); 会回传一个整数, intkkk = WirerequestFrom(2, 6);
然后检查实际收到几个 byte 的kkk 是否为 0, 是表示 timeout 都没收到任何 byte
(3) Slave 应该如何响应主人Master的命令
官网的范例不管 Master 送过来是啥, 直接用 requestEvent() 函数送回6 bytes
比较正确的方法应该是:
(A) Master 在下达命令requestFrom(从机地址, 几byte); 之前:
(B)在Slave 这边相对应于 (A)Master 的动作如下:
(C)在 Master 这边于requestFrom( ); 之后用 while 检查Wireavailable( ) 并用 Wireread( ) 接收数据
一般情况下,要进行I2C通讯,你最起码其中有一个芯片要本身就带有I2C通讯接口,用这个带有I2C接口的芯片来作从器件,这样就相对好处理一点。你要是两个都不带这个接口,来模拟的话,很有难度。除非你对I2C协议很清楚,不过从楼主的提问来看,估计就不怎么熟悉这种协议。
所以建议还是用别的通讯方式吧,比如用SPI,相对会好处理一点,用其中一个芯片的INTx来模拟CS接口,作为从器件在中断中来处理,另外一个就模拟主器件来控制从器件,这样或许会好弄点。如果楼主确实需要通讯,还是赶快换个思路吧,要是卡在一个地方动不了,会耽误你的进程的,祝你好运!
以上就是关于51单片机IIC总线通信全部的内容,包括:51单片机IIC总线通信、如何实现双单片机模拟iic通信、Arduino IIC协议笔记等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)