51单片机模拟IIC总线问题

51单片机模拟IIC总线问题,第1张

IIC的地址你可以自己定义的

在硬件上提供过IIC地址的你可以直接选择他的地址进行发送

像你这种情况的话可以自己定义地址:

假设你有两台或者以上的S3C2410,单片机作为主机,然后单片机发送数据,所有S3C接收(接收的前提是他的接收端口上获得IIC的开始信号,你可以选择利用中断进行检测),然后你在软件里可以预先设置好每台S3C的地址,即接收单片机的前8BIT,然后对照地址,一样的话就开始接收接下来的信息,没有就放弃这个通信,这样的话8BIT就可以控制256台S3C了

其实IIC也只是一种通信方式,你可以选择自己的协议,以IIC为基础,比如地址位选择16BIT甚至更多,如果从机是S3C这种32位的RAM9的话,数据位的传输可以32位的传。所谓的开始信号跟终止信号也只是双方默认的方式而已,就像是“点头YES,摇头NO”,你也可以选择相反的方式,只要两台通信的机子能懂就好。

不过最好是采用大家一起的,这样在软件移植的时候会有帮助,也方便别人看懂。当大家在某一领域都用一种方式的时候也就形成所谓的协议,比如TCP/IP,UART,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( ) 接收数据

IIC总线在没有总裁模式的前提下,只能实现主从通信。也就是主机可以随时向从机发送数据,但只能等主机访问才能从机才能应答。这个是标准IIC协议。不知道符不符合你对双机通信的要求。电路图很简单,只用连上2条上,上拉个电阻就可以啦。IIC通信的原理参考飞利浦的标准,两线特定的状态实现数据传输开始,应答,结束等等,多看看时序图就了解啦。

但是大多数的51单片机不带硬件IIC模块,我们可以用软件来模拟。我只写过主机的模拟IIC程序,从机的没写过。从机程序51实现难度很大,也不实用。机制问题,从机响应如不能用中断实现,只能一直让程序在查询,实现起来没什么意义。如果你的51带管脚电平变化中断,可以去尝试下。

;

;AT24C04测试程序 供参考

;工作频率: 12000MHz

;

SCL BIT P20 ;AT24C04的时钟线

SDA BIT P21 ;AT24C04的数据线

BUF EQU 30H ;数据缓存区

;

ORG 0

JMP Reset

ORG 100H

Reset:

CALL AT24C04_WritePage ;写一页数据

CALL Delay5ms ;写一页数据需延时5ms

CALL AT24C04_ReadPage ;读一页数据

JMP $

;

;向AT24C04写1页(16字节)数据

;将TESTDATA开始的16个测试数据写如设备的00~0F地址中

;入口参数:无

;出口参数:无

;

AT24C04_WritePage:

CALL AT24C04_Start ;起始信号

MOV A,#0A0H ;发送设备地址+写信号

CALL AT24C04_SendByte ;发送

MOV A,#00H ;发送存储单元地址

CALL AT24C04_SendByte ;发送

MOV R0,#16 ;16字节计数器

MOV DPTR,#TESTDATA ;测试数据首地址

WriteNext:

CLR A ;读取测试数据

MOVC A,@A+DPTR

CALL AT24C04_SendByte ;写入设备

INC DPTR ;准备下一个数据的地址

DJNZ R0,WriteNext ;判断16字节是否完成

CALL AT24C04_Stop ;停止信号

RET

TESTDATA:

DB 000H,011H,022H,033H,044H,055H,066H,077H

DB 088H,099H,0AAH,0BBH,0CCH,0DDH,0EEH,0FFH

;

;从AT24C04读取1页(16字节)数据

;将设备的00~0F地址中的数据读出存放在DATA区的BUF中

;入口参数:无

;出口参数:无

;

AT24C04_ReadPage:

CALL AT24C04_Start ;起始信号

MOV A,#0A0H ;发送设备地址+写信号

CALL AT24C04_SendByte ;发送

MOV A,#00H ;发送存储单元地址

CALL AT24C04_SendByte ;发送

CALL AT24C04_Start ;起始信号

MOV A,#0A1H ;发送设备地址+读信号

CALL AT24C04_SendByte ;发送

MOV R0,#16 ;16字节计数器

MOV R1,#BUF ;数据缓冲区首地址

ReadNext:

CALL AT24C04_RecvByte ;读取数据

MOV @R1,A ;保存数据

CJNE R0,#2,$+3 ;判断回应ACK还是NAK

CALL AT24C04_SendACK ;发送应答信号

INC R1 ;缓冲区地址加1

DJNZ R0,ReadNext ;判断16字节是否完成

CALL AT24C04_Stop ;停止信号

RET

;

;延时5微秒

;不同的工作环境,需要调整此函数

;入口参数:无

;出口参数:无

;

Delay5us: ;2 当改用1T的MCU时,请调整此延时函数

NOP ;1

RET ;2

;

;延时5毫秒

;不同的工作环境,需要调整此函数

;入口参数:无

;出口参数:无

;

Delay5ms: ;2 当改用1T的MCU时,请调整此延时函数

PUSH ACC ;2

PUSH DPL ;2

PUSH DPH ;2

MOV DPTR,#-500 ;2

Delay5ms1:

NOP ;1

NOP ;1

NOP ;1

NOP ;1

INC DPTR ;2

MOV A,DPL ;1

ORL A,DPH ;1

JNZ Delay5ms1 ;2

POP DPH ;2

POP DPL ;2

POP ACC ;2

RET ;2

;

;起始信号

;入口参数:无

;出口参数:无

;

AT24C04_Start:

SETB SDA

SETB SCL ;拉高时钟线

CALL Delay5us ;延时

CLR SDA ;产生下降沿

CALL Delay5us ;延时

CLR SCL ;拉低时钟线

RET

;

;停止信号

;入口参数:无

;出口参数:无

;

AT24C04_Stop:

CLR SDA

SETB SCL ;拉高时钟线

CALL Delay5us ;延时

SETB SDA ;产生上升沿

CALL Delay5us ;延时

RET

;

;发送应答信号

;入口参数:C (0:ACK 1:NAK)

;出口参数:无

;

AT24C04_SendACK:

MOV SDA,C ;写应答信号

SETB SCL ;拉高时钟线

CALL Delay5us ;延时

CLR SCL ;拉低时钟线

CALL Delay5us ;延时

RET

;

;接收应答信号

;入口参数:无

;出口参数:C

;

AT24C04_RecvACK:

SETB SCL ;拉高时钟线

CALL Delay5us ;延时

MOV C,SDA ;读应答信号

CLR SCL ;拉低时钟线

CALL Delay5us ;延时

RET

;

;向IIC总线发送一个字节数据

;入口参数:ACC

;出口参数:无

;

AT24C04_SendByte:

PUSH 0

MOV 0,#8 ;8位计数器

SendNext:

RLC A ;移出数据的最高位

MOV SDA,C ;送数据口

SETB SCL ;拉高时钟线

CALL Delay5us ;延时

CLR SCL ;拉低时钟线

CALL Delay5us ;延时

DJNZ 0,SendNext ;判断8位数据是否发送完成

POP 0

JMP AT24C04_RecvACK ;接收应答信号

; RET

;

;从IIC总线接收一个字节数据

;入口参数:无

;出口参数:ACC

;

AT24C04_RecvByte:

SETB SDA ;使能内部上拉,准备读取数据

PUSH 0

MOV 0,#8 ;8位计数器

RecvNext:

SETB SCL ;拉高时钟线

CALL Delay5us ;延时

MOV C,SDA ;读数据口

RLC A ;保存数据

CLR SCL ;拉低时钟线

CALL Delay5us ;延时

DJNZ 0,RecvNext ;判断8位数据是否接收完成

POP 0

RET

;

END

这个其实就是状态机。

I2C 主机 *** 作有9 个状态分别是空闲、启动、发送地址、等待应答、发送数据、再等待应答、接收数据、发送无应答、停止。利用状态切换就可以了

以上就是关于51单片机模拟IIC总线问题全部的内容,包括:51单片机模拟IIC总线问题、Arduino IIC协议笔记、iic总线实现双机通信,求接线图和原理等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10634168.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-10
下一篇 2023-05-10

发表评论

登录后才能评论

评论列表(0条)

保存