Profile
总线一般是可以接2个以上用户相互通讯的硬件通讯系统。协议一般是传输信号的事先约定的信号结构,比如速率、电平、数据字节、数据包结构。
当各种同类动物之间沟通的时候,空气组成了总线,动物间的声音(语言)就是协议。只有同类才听得懂。
BACnet与Lonwork协议已经被大家所熟知,那么行业所涉及的其他协议又有哪些呢?这里为大家编辑整理了一些协议,供大家学习与参考。下面向大家介绍一下其他协议:(1)OPC
OPC(用于过程控制的OLE)是一个工业标准。它由一些世界上占领先地位的自动化系统和硬件、软件公司与微软(Microsoft)紧密合作而建立的。这个标准定义了应用Microsoft操作系统在基于PC的客户机之间交换自动化实时数据的方法。它是在Microsoft COM、DCOM和Active X技术的功能规程基础上开发一个开放的和互操作的接口标准,这个标准的目标是促使自动化/控制应用、现场系统/设备和商业/办公室应用之间具有更强大的互操作能力。
(2)ODBC
开放数据库互连(ODBC)是Microsoft引进的一种早期数据库接口技术。它实际上是ADO的前身。Microsoft引进这种技术的一个主要原因是,以非语言专用的方式,提供给程序员一种访问数据库内容的简单方法。换句话说,访问 DBF文件或Access Basic以得到MDB 文件中的数据时,无需懂得Xbase程序设计语言。事实上,Visual C++就是这样一个程序设计平台,即Microsoft最初是以ODBC为目标的。ODBC的确能履行承诺,提供对数据库内容的访问,并且没有太多的问题。它没有提供数据库管理器和C之间尽可能最好的数据转换,这种情况是有的,但它多半能像广告所说的那样去工作。唯一影响ODBC前程的是,它的速度极低,至少较早版本的产品是这样。ODBC最初面世时,一些开发者曾说,因为速度问题,ODBC 永远也不会在数据库领域产生太大的影响。然而,以 Microsoft的市场影响力,ODBC毫无疑问是成功了。今天,只要有两种ODBC驱动程序的一种,那么几乎每一个数据库管理器的表现都会很卓越。
(3)Socket
一个完整的socket有一个本地唯一的socket号,由操作系统分配。最重要的是,socket 是面向客户/服务器模型而设计的,针对客户和服务器程序提供不同的socket系统调用。客户随机申请一个socket (相当于一个想打电话的人可以在任何一台入网电话上拨号呼叫),系统为之分配一个socket号;服务器拥有全局公认的 socket ,任何客户都可以向它发出连接请求和信息请求(相当于一个被呼叫的电话拥有一个呼叫方知道的电话号码)。Socket利用客户/服务器模式巧妙地解决了进程之间建立通信连接的问题。服务器socket 半相关为全局所公认非常重要。读者不妨考虑一下,两个完全随机的用户进程之间如何建立通信?假如通信双方没有任何一方的socket 固定,就好比打电话的双方彼此不知道对方的电话号码,要通话是不可能的。
在Internet上有很多这样的主机,这些主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原意那样,象一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电,有的提供110伏交流电,有的则提供有线电视节目。客户软件将插头插到不同编号的插座,就可以得到不同的服务。
(4)RS232
计算机与计算机或计算机与终端之间的数据传送可以采用串行通讯和并行通讯二种方式。由于串行通讯方式具有使用线路少、成本低,特别是在远程传输时,避免了多条线路特性的不一致而被广泛采用。在串行通讯时,要求通讯双方都采用一个标准接口,使不同的设备可以方便地连接起来进行通讯。RS-232-C接口(又称 EIA RS-232-C)是目前最常用的一种串行通讯接口。它是在1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。它的全名是“数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准”该标准规定采用一个25个脚的 DB25连接器,对连接器的每个引脚的信号内容加以规定,还对各种信号的电平加以规定。
(5) RS-485
RS-485是双向、半双工通信协议,允许多个驱动器和接收器挂接在总线上,其中每个驱动器都能够脱离总线。该规范满足所有RS-422的要求,而且比RS-422稳定性更强。具有更高的接收器输入阻抗和更宽的共模范围(-7V至+12V)。
接收器输入灵敏度为±200mV,这就意味着若要识别符号或间隔状态,接收端电压必须高于+200mV或低于-200mV。最小接收器输入阻抗为12k,驱动器输出电压为±1.5V(最小值)、±5V(最大值)。
驱动器能够驱动32个单位负载,即允许总线上并联32个12k的接收器。对于输入阻抗更高的接收器,一条总线上允许连接的单位负载数也较高。RS-485接收器可随意组合,连接至同一总线,但要保证这些电路的实际并联阻抗不高于32个单位负载(375)。
(6) EtherNet/IP协议
EtherNet/IP是ODVA发起的基于以太网传输的协议标准,全称为“以太网工业协议”。现在这个协议受到三大组织的支持:ControlNet International(CI),the Industrial Ethernet Association(IEA),the Open DeviceNet Vender Association (ODVA)。这个协议旨在应用层建立一个开放的网络协议,以构建开放式的工业控制网络。我个人理解,以太网也就是IEEE802.3只是定义了网络下两层的规范,对于网络层,是由IP协议规范的,运输层由TCP和UDP,会话层向上由包含TFTP、SMTP、FTP、 DNS、NFS等协议的应用程序来构成。这就象现场总线CAN协议规范底层传输,DeviceNet基于CAN定义应用层一样。现在EtherNet/IP和DeviceNet一样,都是在传输层以上寻找结合二者特点的规范,也就是建立一种基于以太网上的,具有DeviceNet协议扩展特性的协议,那就是EtherNet/IP。
这个协议对于原有DeviceNet产品的供应商来说,具有以较少投资换来以太网接入方案的实惠,根据前面的分析,是混合型网络结构方案的一种。
(7)Modbus协议
Modbus协议最初由Modicon公司开发出来,在1979年末该公司成为施耐德自动化(Schneider Automation)部门的一部分,现在Modbus已经是工业领域全球最流行的协议。此协议支持传统的RS-232、RS-422、RS-485和以太网设备。许多工业设备,包括PLC,DCS,智能仪表等都在使用Modbus协议作为他们之间的通讯标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。当在网络上通信时,Modbus协议决定了每个控制器须要知道它们的设备地址,识别按地址发来的消息,决定要产生何种行动。如果需要回应,控制器将生成应答并使用Modbus协议发送给询问方。
Modbus协议包括ASCII、RTU、TCP等,并没有规定物理层。此协议定义了控制器能够认识和使用的消息结构,而不管它们是经过何种网络进行通信的。标准的Modicon控制器使用RS232C实现串行的Modbus。Modbus的ASCII、RTU协议规定了消息、数据的结构、命令和就答的方式,数据通讯采用Maser/Slave方式,Master端发出数据请求消息,Slave端接收到正确消息后就可以发送数据到Master端以响应请求;Master端也可以直接发消息修改Slave端的数据,实现双向读写。
Modbus协议需要对数据进行校验,串行协议中除有奇偶校验外,ASCII模式采用LRC 校验,RTU模式采用16位CRC校验,但TCP模式没有额外规定校验,因为TCP协议是一个面向连接的可靠协议。另外,Modbus采用主从方式定时收发数据,在实际使用中如果某Slave 站点断开后(如故障或关机),Master端可以诊断出来,而当故障修复后,网络又可自动接通。因此,Modbus协议的可靠性较好。
I2C(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。I2C总线产生于在80年代,最初为音频和视频设备开发,如今主要在服务器管理中使用,其中包括单个组件状态的通信。例如管理员可对各个组件进行查询,以管理系统的配置或掌握组件的功能状态,如电源和系统风扇。可随时监控内存、硬盘、网络、系统温度等多个参数,增加了系统的安全性,方便了管理。
一、I2C总线特点
I2C总线最主要的优点是其简单性和有效性。由于接口直接在组件之上,因此I2C总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件。I2C总线的另一个优点是,它支持多主控(multimastering), 其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。
二、I2C总线工作原理
2.1、总线的构成及信号类型
I2C总线是一种串行数据总线,只有二根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。在CPU与被控IC之间、IC与IC之间进行双向传送,最高传送速率100kbps。各种被控制电路均并联在这条总线上,但就像电话机一样只有拨通各自的号码才能工作,所以每个电路和模块都有唯一的地址,在信息的传输过程中,I2C总线上并接的每一模块电路既是主控器(或被控器),又是发送器(或接收器),这取决于它所要完成的功能。CPU发出的控制信号分为地址码和控制量两部分,地址码用来选址,即接通需要控制的电路,确定控制的种类;控制量决定该调整的类别(如对比度、亮度等)及需要调整的量。这样,各控制电路虽然挂在同一条总线上,却彼此独立,互不相关。
2.2、位的传输
SDA 线上的数据必须在时钟的高电平周期保持稳定数据线的高或低电平状态只有在SCL 线的时钟信号是低电平时才能改变。
2.3、开始信号
SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
2.4、结束信号
SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。
2.5、应答信号
接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收
到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。
2.6、总线基本操作
I2C规程运用主/从双向通讯。器件发送数据到总线上,则定义为发送器,器件接收数据则定义为接收器。主器件和从器件(本文为AT24C01)都可以工作于接收和发送状态。总线必须由主器件(通常为微控制器CPU)控制,主器件产生串行时钟(SCL)控制总线的传输方向,并产生起始和停止条件。SDA线上的数据状态仅在SCL为低电平的期间才能改变,SCL为高电平的期间,SDA状态的改变被用来表示起始和停止条件。
三、单片机模拟I2C总线C语言代码
/*************************************
单片机模拟I2C总线C语言代码
*************************************/
#include
#include
#include
#define DELAY_TIME 60 /*只有不小于50!才不会造成时序混乱*/
#define TRUE 1
#define FALSE 0
sbit SCL=P1^7; /*串行时钟*/
sbit SDA=P1^6; /*串行数据*/
/********** Function Definition 函数定义 ************/
void DELAY(unsigned int t) /*延时函数*/
{
while(t!=0)
t--;
}
/*启动I2C总线的函数,当SCL为高电平时使SDA产生一个负跳变*/
void I2C_Start(void)
{
SDA=1;
SCL=1;
DELAY(DELAY_TIME);
SDA=0;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
/*终止I2C总线,当SCL为高电平时使SDA产生一个正跳变*/
void I2C_Stop(void)
{
SDA=0;
SCL=1;
DELAY(DELAY_TIME);
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
/*发送0,在SCL为高电平时使SDA信号为低*/ void SEND_0(void) /* SEND ACK */
{
SDA=0;
SCL=1;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
/*发送1,在SCL为高电平时使SDA信号为高*/ void SEND_1(void)
{
SDA=1;
SCL=1;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
/*发送完一个字节后检验设备的应答信号*/
bit Check_Acknowledge(void)
{
SDA=1;
SCL=1;
DELAY(DELAY_TIME/2);
F0=SDA;
DELAY(DELAY_TIME/2);
SCL=0;
DELAY(DELAY_TIME);
if(F0==1)
return FALSE;
return TRUE;
}
/*向I2C总线写一个字节*/
void WriteI2CByte(char b)reentrant
{
char i;
for(i=0;i<8;i++)
if((b<
SEND_1();
SEND_0();
}
/*从I2C总线读一个字节*/
char ReadI2CByte(void)reentrant {
char b=0,i;
for(i=0;i<8;i++)
{
SDA=1; /*释放总线*/
SCL=1; /*接受数据*/
DELAY(10);
F0=SDA;
DELAY(10);
SCL=0;
if(F0==1)
{
b=b<<1;
b=b|0x01;
}
else
b=b<<1;
}
return b;
}
# include
# include
# define uchar unsigned char # define uint unsigned int sbit SO=P0^3;/*25045输出*/ sbit SI=P0^2;/*25045输入*/ sbit SCK=P0^1;/*25045时钟*/ sbit CS=P0^0;/*25045片选*/ uchar code WREN_INST=0X06;
/* Write enable latch instruction (WREN)*/
uchar code WRDI_INST=0X04;
/* Write disable latch instruction (WRDI)*/
uchar code WRSR_INST=0X01;
/* Write status register instruction (WRSR)*/
uchar code RDSR_INST=0X05;
/* Read status register instruction (RDSR)*/
uchar code WRITE_INST=0X02;
/* Write memory instruction (WRITE)*/
/*写入25045的先导字,应当为0000A010,其中的A为写入25045的高位地址
将此WRITE_INST和写入高位地址相或后即为正确的写先导字*/
uchar code READ_INST=0X03;
/* Read memory instruction (READ)*/
/*读出25045的先导字,应当为0000A011,其中的A为读出25045的高位地址
将此READ_INST和读出高位地址相或后即为正确的读先导字*/
uint code BYTE_ADDR=0X55;
/* Memory address for byte mode operations*/
uchar code BYTE_DATA=0X11;
/*Data byte for byte write operation*/
uint code PAGE_ADDR=0X1F;
/* Memory address for page mode operations*/
/*页面写入的其始地址*/
uchar code PAGE_DATA1=0X22;
/* 1st data byte for page write operation*/
uchar code PAGE_DATA2=0X33;
/* 2nd data byte for page write operation*/
uchar code PAGE_DATA3=0X44;
/* 3rd data byte for page write operation*/
uchar code STATUS_REG=0X20;
/* Status register,设置DOG时间设置为200毫秒,无写保护*/
/*这是状态寄存器的值,他的意义在于第5,第4位为WDI1,WDI0代表DOG的时间,00为1.4秒,01为600毫秒,10为200毫秒,00为disabled
第3位和第2位为BL1,BL0,是写保护设置位,00为无保护,01为保护180-1FF,10为保护100-1FF,11为保护000-1FF.第1位为WEL,
当他为1时代表已经"写使能"设置了,现在可以写了,只读位.第0位为WIP,当他为1时代表正在进行写操作,是只读*/
uchar code MAX_POLL=0x99;
/* Maximum number of polls*/
/*最大写过程时间,确定25045的最大的写入过程的时间*/
uchar code INIT_STATE=0x09;
/* Initialization value for control ports*/
uint code SLIC=0x30;
/* Address location of SLIC*/
void wren_cmd(void);/*写使能子程序*/
void wrdi_cmd(void);/*写使能复位*/
void wrsr_cmd(void);/*复位时间位和数据保护位写入状态寄存器*/
uchar rdsr_cmd(void);/*读状态寄存器*/
void byte_write(uchar aa,uint dd);/*字节写入,aa为写入的数据,dd为写入的地址*/ uchar byte_read(uint dd);/*字节读出,dd为读出的地址,返回读出的数据*/
void page_write(uchar aa1,uchar aa2,uchar aa3,uchar aa4,uint dd);/*页写入*/ void sequ_read(void);/*连续读出*/
void rst_wdog(void);/*DOG复位*/
void outbyt(uchar aa);/*输出一个字节到25045中,不包括先导字等*/
uchar inputbyt();/*由25045输入一个字节,不包括先导字等额外的东西*/
void wip_poll(void);/*检查写入过程是否结束*/
/*25045操作子程序集*/
/*;***************************************************************************** **************
*
;* Name: WREN_CMD
;* Description: Set write enable latch
;* Function: This routine sends the command to enable writes to the EEPROM memory array or
;* status register
;* Calls: outbyt
;* Input: None
;* Outputs: None
;* Register Usage: A
;******************************************************************************* ************
*/
/*写使能子程序*/
void wren_cmd(void)
{
uchar aa;
SCK=0;/* Bring SCK low */
CS=0;/* Bring /CS low */
aa=WREN_INST;
outbyt(aa);/* Send WREN instruction */
SCK=0;/* Bring SCK low */
CS=1;/* Bring /CS high */
}
/*;***************************************************************************** **************
*
;* Name: WRDI_CMD
;* Description: Reset write enable latch
;* Function: This routine sends the command to disable writes to the EEPROM memory array or
;* status register
;* Calls: outbyt
;* Input: None
;* Outputs: None
;* Register Usage: A
;*******************************************************************************
************
*/
/*写使能复位子程序*/
void wrdi_cmd(void)
{
uchar aa;
SCK=0;/* Bring SCK low */
CS=0;/* Bring /CS low */
aa=WRDI_INST;
outbyt(aa);/* Send WRDI instruction */
SCK=0;/* Bring SCK low */
CS=1;/* Bring /CS high */
}
/*;*****************************************************************************
**************
*
;* Name: WRSR_CMD
;* Description: Write Status Register
;* Function: This routine sends the command to write the WD0, WD1, BP0 and BP0 EEPROM ;* bits in the status register
;* Calls: outbyt, wip_poll
;* Input: None
;* Outputs: None
;* Register Usage: A
;*******************************************************************************
************
*/
/*写状态寄存器子程序*/
void wrsr_cmd(void)
{
uchar aa;
SCK=0;/* Bring SCK low */
CS=0;/* Bring /CS low */
aa=WRSR_INST;
outbyt(aa) ;/* Send WRSR instruction */
aa=STATUS_REG;
outbyt(aa);/* Send status register */
SCK=0;/* Bring SCK low */
CS=1;/* Bring /CS high */
wip_poll();/* Poll for completion of write cycle */
}
/*;*****************************************************************************
**************
*
;* Name: RDSR_CMD
;* Description: Read Status Register
;* Function: This routine sends the command to read the status register
;* Calls: outbyt, inputbyt
;* Input: None
;* Outputs: A = status registerXicor Application Note AN21
;* Register Usage: A
;*******************************************************************************
************
*/
/*读状态寄存器,读出的数据放入到aa中*/
uchar rdsr_cmd (void)
{
uchar aa;
SCK=0;
CS=0;
aa=RDSR_INST;
outbyt(aa);
aa=inputbyt();
SCK=0;
CS=1;
return aa;
}
/*;*****************************************************************************
**************
*
;* Name: BYTE_WRITE
;* Description: Single Byte Write
;* Function: This routine sends the command to write a single byte to the EEPROM memory array
;* Calls: outbyt, wip_poll
;* Input: None
;* Outputs: None
;* Register Usage: A, B
;******************************************************************************* ************
*/
/*字节写入,aa为写入的数据,dd为写入的地址,对于25045而言为000-1FF*/
void byte_write(aa,dd)
uchar aa;
uint dd;
{
SCK=0;
CS=0;
outbyt((((uchar)(dd-0XFF))<<3)|WRITE_INST);/* Send WRITE instruction including MSB of address */
/*将高位地址左移3位与写入先导字相或,得到正确的先导字写入25045*/
outbyt((uchar)(dd));
/*输出低位地址到25045*/
outbyt(aa);
/*写入数据到25045的对应单元*/
SCK=0;
CS=1;
wip_poll();
/*检测是否写完*/
}
/*;***************************************************************************** **************
*
;* Name: BYTE_READ
;* Description: Single Byte Read
;* Function: This routine sends the command to read a single byte from the EEPROM memory
array
;* Calls: outbyt, inputbyt
;* Input: None
;* Outputs: A = read byte
;* Register Usage: A, BXicor Application Note AN21
;******************************************************************************* ************
*/
/*字节读出,其中dd为读出的地址,返回的值为读出的数据*/
uchar byte_read(dd)
uint dd;
{
uchar cc;
SCK=0;
CS=0;
outbyt((((uchar)(dd-0XFF))<<3)|READ_INST);/* Send READ_INST instruction including MSB of address */
/*将高位地址左移3位与读出先导字相或,得到正确的先导字写入25045*/
outbyt((uchar)(dd));
/*输出低位地址到25045*/
cc=inputbyt();/*得到读出的数据*/
SCK=0;
CS=1;
return cc;
}
/*;***************************************************************************** **************
*
;* Name: PAGE_WRITE
;* Description: Page Write
;* Function: This routine sends the command to write three consecutive bytes to the EEPROM
;* memory array using page mode
;* Calls: outbyt, wip_poll
;* Input: None
;* Outputs: None
;* Register Usage: A, B
;******************************************************************************* ************
*/
/*页面写入,其中aa1,aa2,aa3,aa4为需要写入的4个数据(最大也就只能一次写入4个字,dd 为写入的首地址*/
void page_write(aa1,aa2,aa3,aa4,dd)
uchar aa1,aa2,aa3,aa4;
uint dd;
{
SCK=0;
CS=0;
outbyt((((uchar)(dd-0XFF))<<3)|WRITE_INST);/* Send WRITE instruction including MSB of address */
/*将高位地址左移3位与写入先导字相或,得到正确的先导字写入25045*/
outbyt((uchar)(dd));
/*写入低位地址到25045*/
outbyt(aa1);
/*写入数据1到25045的对应单元*/
outbyt(aa2);
/*写入数据2到25045的对应单元*/
outbyt(aa3);
/*写入数据3到25045的对应单元*/
outbyt(aa4);
/*写入数据4到25045的对应单元*/
SCK=0;
CS=1;
wip_poll();
}
/*;***************************************************************************** **************
*
;* Name: SEQU_READ
;* Description: Sequential Read
;* Function: This routine sends the command to read three consecutive bytes from the EEPROM
;* memory array using sequential mode
;* Calls: outbyt, inputbyt
;* Input: None
;* Outputs: A = last byte read
;* Register Usage: A, B
;******************************************************************************* ************
*/
/*连续读出,由于函数的返回值只能为1个,对于连续读出的数据只能使用指针作为函数的返回值才能做到返回一系列的数组*/
/*sequ_read:*/
unsigned int *page_read(n,dd)
uchar n;/*n是希望读出的数据的个数,n<=11*/
unsigned int dd;/*dd是读出数据的首地址*/
{
uchar i;
uchar pp[10];
unsigned int *pt=pp;
SCK=0;
CS=0;
outbyt((((uchar)(dd-0XFF))<<3)|READ_INST);
for (i=0;i { pp[i]=inputbyt(); } return (pt); } /*调用的方法如下*/ /*unsigned int *p;*/ /*p=page_read(4,100);*/ /*a=*(p)*/ /*b=*(p+1)*/ /*c=*(p+2)*/ /*d=*(p+3)*/ /*abcd中存放25045中由100地址开始的4个数据*/ /* Send WRITE */ /*mov DPTR, #PAGE_ADDR ; Set address of 1st byte to be read clr sck ; Bring SCK low clr cs ; Bring /CS low mov A, #READ_INST mov B, DPH mov C, B.0 mov ACC.3, C lcall outbyt ; Send READ instruction with MSB of address mov A, DPL lcall outbyt ; Send low order address byte lcall inputbyt ; Read 1st data byte lcall inputbyt ; Read 2nd data byte lcall inputbyt ; Read 3rd data byte clr sck ; Bring SCK low setb cs ; Bring /CS high ret*/ /*;***************************************************************************** ************** * ;* Name: RST_WDOG ;* Description: Reset Watchdog Timer ;* Function: This routine resets the watchdog timer without sending a command ;* Calls: None ;* Input: None ;* Outputs: None ;* Register Usage: None ;******************************************************************************* ************ */ /*复位DOG*/ void rst_wdog (void) { CS=0; CS=1; } /*;***************************************************************************** ************** * ;* Name: WIP_POLL ;* Description: Write-In-Progress Polling ;* Function: This routine polls for completion of a nonvolatile write cycle by examining the ;* WIP bit of the status register ;* Calls: rdsr_cmdXicor Application Note AN21 ;* Input: None ;* Outputs: None ;* Register Usage: R1, A ;******************************************************************************* ************ */ /*检测写入的过程是否结束*/ void wip_poll(void) { uchar aa; uchar idata my_flag; for (aa=1;aa>MAX_POLL;aa++) { my_flag=rdsr_cmd(); if ((my_flag&&0x01)==0) {aa=MAX_POLL;}/*判断是否WIP=0,即判断是否写入过程已经结束,若结束就跳出,否则继续等待直到达到最大记数值*/ } } /*;***************************************************************************** ************** * ;* Name: OUTBYT ;* Description: Sends byte to EEPROM ;* Function: This routine shifts out a byte, starting with the MSB, to the EEPROM ;* Calls: None ;* Input: A = byte to be sent ;* Outputs: None ;* Register Usage: R0, A ;******************************************************************************* ************ */ /*输出一个数据到25045,此数据可能为地址,先导字,写入的数据等*/ void outbyt(aa) uchar aa; { uchar my_flag1,i; for (i=0;i>7;i++) { my_flag1=aa; SCK=0; SI=(my_flag1>>i); SCK=1; } SI=0;/*使SI处于确定的状态*/ } /*;***************************************************************************** ************** * ;* Name: INPUTBYT ;* Description: Recieves byte from EEPROM ;* Function: This routine recieves a byte, MSB first, from the EEPROM ;* Calls: None ;* Input: None ;* Outputs: A = recieved byte ;* Register Usage: R0, A ;******************************************************************************* ************ */ /*得到一个数据,此数据可能为状态寄存器数据,读出的单元数据等*/ uchar inputbyt(void) { uchar aa,my_flag; char i; for (i=7;i<0;i--) { SCK=0; my_flag=(uchar)(SO); SCK=1; aa=(aa||(my_flag< my_flag=0x00; } return aa; } 1.#include 2.#include 3.sbit?SCK=P1^0;//将p1口摸仪时钟输出??? 4.sbit?MOSI=P1^1;//将P1.1口模拟主机输出??? 5.sbit?MISO=P1^2;//将p1.2口模拟主机输入??? 6.sbit?CS1=P1^3;//将P1.3模拟片选??? 7.#define?delayNOP();{_nop_();_nop_();_nop_();_nop_();};??? 8.//---------------------------------------------------------??? 9.//函数名称:SPISENDBYTE??? 10.//入口参数:CH??? 11.//函数功能:发送一个字符??? 12.//-----------------------------------------------------------??? 13.void?SPISendByte(unsigned?char?ch)??? 14.{unsigned?char?idata?n=8;//向SDA上发送一位数据字节,共8位??? 15.SCK=1;//时钟置高??? 16.CS1=0;//选择从机??? 17.while(n--)??? 18.??{delayNOP();??? 19.???SCK=0;//时钟置低??? 20.??if((ch&0x80)==0x80)//若发送的数据等于1,则发送位1??? 21.????{MOSI=1;//传送位1??? 22.????}??? 23.??else??? 24.????{MOSI=0;//否则传送0??? 25.????}??? 26.??delayNOP();??? 27.??ch=ch<<1;//数据左移一位??? 28.??SCK=1;//时钟置高??? 29.??}??? 30.}??? 31.//-------------------------------------------------------------------??? 32.//函数名称SPIreceiveByte??? 33.//返回接收的数据??? 34.//函数功能:接受1BYTE子程序??? 35.//--------------------------------------------------------------------??? 36.unsigned?char?SPIreceiveByte()??? 37.{??? 38.??unsigned?char?idata?n=8;//从MISO线上读取上一字节,共8位??? 39.??unsigned?char?tdata;??? 40.??SCK=1;//时钟为高??? 41.??CS1=0;//选择从机??? 42.??while(n--)??? 43.??{??delayNOP();??? 44.?????SCK=0;//时钟为低??? 45.?????delayNOP();??? 46.?????tdata=tdata<<1;//左移一位,或_crol_(temp,1)??? 47.?????if(MISO==1)??? 48.????????tdata=tdata|0x01;//若接收到的位为1,则数据的最后的一位置1??? 49.?????else??? 50.????????tdata=tdata&0xfe;//否则数据的最后一位置0??? 51.?????SCK=1;??? 52.??}??? 53.??return(tdata);??? 54.}??? 55.//---------------------------------------------------------------------------??? 56.//函数名称:SPIsend-receiveByte??? 57.//入口参数:CH??? 58.//返回接收的数据??? 59.//函数功能:串行输入/输出子程序??? 60.//--------------------------------------------------------------------------- -??? 61.//unsigned?char?SPIsendByte(unsigned?char?ch)??? 62.//{???? 63.?//?unsigned?char?idata?n=8;//从MISO线上读取上一数据字节,共8位??? 64.?//?unsigned?char?tdata;??? 65.??//SCK=1;//时钟为高??? 66.??//CS1=0;//选择从机??? 67.?//?while(n--)??? 68.?//?{delayNOP();??? 69.???//??SCK=0;//时钟为低??? 70.????//?delayNOP();??? 71.????//?tdata=tdata<<1;//左移一位??? 72.?????//?if(MISO==1)??? 73.???????//?tdata=tdata|0x01;//若接收到的位为1,则数据的最后一位置1??? 74.??????//else??? 75.???????//?tdata=tdata&0xfe;//否则数据的最后一位置0??? 76.??????//if((ch&0x80)==0x80)??? 77.??????//{?MOSI=1;//传送位1??? 78.??????//}??? 79.????//?else??? 80.?????//?{MOSI=0;//否则传送位0??? 81.?????//?}??? 82.???????//?ch=ch<<1;//数据左移1位??? 83.???????//?SCK=1;??? 84.?//?}??? 85.//return(tdata);??? 86.//}? DS18B20 以单总线协议工作,测温分机首先发送复位脉冲命令,使信号线上所有的 DS18B20 芯片都被复位,接着发送ROM 操作命令,使序列号编码匹配的DS18B20 被激活进入接收内存访问命令状态;内存访问命令完成温度转换、温度读取等工作(单总线在ROM 命令发送之前存储命令和控制命令不起作用)。DS18B20 工作流程见图3 所示。 图3 DS18B20 工作流程图 系统以ROM 命令和存储器命令的形式对DS18B20 操作。ROM 操作命令均为8 位,命令代码分别为:读ROM(0x33H)、匹配ROM(0x55H)、跳过ROM(0xCCH) 、搜索ROM(0xF0H) 和告警搜索(0xECH) 命令;存储器操作命令为:写暂存存储器(0x4EH) 、读暂存存储器(0xBEH)、复制暂存存储器(0x48H)、温度变换(0x44H)、重新调出EERAM(0xB8H)以及读电源供电方式(0xB4H)命令。其对时序及电特性参数要求较高,必须严格按照它的时序要求去操作。DS18B20 的数据读写由测温分机来完成,包括初始化、读数据和写数据。 系统软件采用模块化程序设计,主从式结构通信方式。规定总线上有一个测温主机和64台分机,分机地址唯一。初始化完成后各分机均处于监听状态,采用中断方式工作,测温分机接受上位机命令,向DS18B20发出地址匹配命令帧,进入等待状态,每一帧数据位都对应着不同意义,若地址匹配成功则进行响应分机,否则继续等待,直到等待超时而重发命令。温度采集模块负责数据的采集工作。 当缓冲区有数据时产生中断,程序转向中断服务子程序入口,中断子程序如下: void SerialInterrupt() interrupt 4 //中断服务子程序 {loop0:if(RI);SlaveNo=SBUF; RI=0; while (! RI); //等待下一个命令 loop1:RI=0; SensorNo=SBUF; if(SlaveNo==0x81&SensorNo<0x80) //判别数据是否合法 {while(1) 单总线协议详解 单总线即one-wire总线,是美国DALLAS公司推出的外围串行扩展总线技术。与SPI、IC串行数据通信方式不同.它采用单根信号线,既传输时钟又传输数据,而且数据传输是双向的,具有节省I/O口线、资源结构简单、成本低廉、便于总线扩展和维护等诸多优点。 单总线是DALLAS公司研制开发的种协议由一个总线主节点、或多个从节点组成系统,通过根信号线对从芯片进行数据的读取。每一个符合OneWire协议的从芯片都有一个唯一的地址,包括48位的序列号、8位的家族代码和8位的CRC代码。主芯片对各个从芯片的寻址依据这64位的不同来进行。单总线利用一根线实现双向通信。因此其协议对时序的要求较严格,如应答等时序都有明确的时间要求。,基本的时序包括复位及应答时序、写一位时序、读一位时序。在复位及应答时序中,主器件发出复位信号后,要求从器件在规定的时间内送回应答信号;在位读和位写时序中,主器件要在规定的时间内读固或写出数据。 单总线适用于单主机系统,能够控制一个或多个从机设备。主机可以是微控制器,从机可以是单总线器件,它们之间的数据交换只通过一条信号线。当只有一个从机设备时,系统可按单节点系统操作;当有多个从设备时,系统则按多节点系统操作。 单总线工作原理单总线器件内部设置有寄生供电电路(Parasite Power Circuit)。当单总线处于高电平时,一方面通过二极管VD向芯片供电,另方面对内部电容C(约800pF)充电;当单总线处于低电平时,二极管截止,内部电容c向芯片供电。由于电容c的容量有限,因此要求单总线能间隔地提供高电平以能不断地向内部电容C充电、维持器件的正常工作。这就是通过网络线路窃取电能的寄生电源的工作原理。要注意的是,为了确保总线上的某些器件在工作时(如温度传感器进行温度转换、E2PROM写人数据时)有足够的电流供给,除了上拉电阻之外,还需要在总线上使用MOSFET(场效应晶体管)提供强上拉供电。 单总线的数据传输速率一般为16.3Kbit/s,最大可达142 Kbit/s,通常情况下采用100Kbit/s 1. 讲废话 小弟最近做了一个项目(用Lattice的CPLD),话说前面还算顺利,就在即将完工的时候,发现(TMD)I/O不够用,有一功能需要CPLD传输8bit数据到另一个控制器做进一步处理,but现在仅剩下一个I/O,好吧,我被卡死在这里了。终于,在一个月黑风高的夜晚(本人喜欢把气氛营造的悲壮一点,嘎嘎。。),突然想到DS18B20的单总线传输协议,以前也了解过其他的协议,心想,为嘛自己不整一个类似的东东出来yy 一下呢,所以有了此贴。 解释一下,本次原创单总线传输协议命名为b2s(不才,取了个类似I2C的名,由于本人有一个贱贱的英文名Bob,所以用了b,各位轻喷啊;s代表single,意为单线传输),本协议含传送端(transmitter)和接收端(receiver)两部分,基于verilog语言,仅使用单个I/O口进行多位数据的传输,传输方向为单向,用于I/O不够用的情况,亲测绝对可用,如果大家以后有用得到的时候,可以直接拿来使用。 本人拥抱开源,所有源码能贴出来尽量贴出来,为大家节省积分,攒RP。 废话完毕,下面为各位客官准备干货。 2. 晒干货 ps. 带★号处可根据需要进行修改. 发送端源码: /*********************************************************************** ******************* Author: Bob Liu E-mail:shuangfeiyanworld@http://biz.doczj.com/doc/137439876.html, File Name: b2s_transmitter.v Function: b2s发送端, 默认发送32bit数据,数据宽度可更改 Version: 2013-5-13 v1.0 ************************************************************************ ********************/ module b2s_transmitter ( clk, //时钟基准,不限频率大小,但必须与接收端一致 din, //待发送数据 b2s_dout //b2s数据输出端口 ); parameter WIDTH=32; //★设定b2s发送数据的位宽,可根据需要进行更改input clk; input [WIDTH-1:0] din; 单总线协议 与其他所有的数据通信传输方式一样,单总线芯片在数据传输过程要求采用严格的通信协议,以保证数据的完整性。单总线芯片在数据传输过程中,每个单总线芯片都拥有唯一的地址,系统主机一旦选中某个芯片,就会保证通信连接直到复位,其他器件则全部脱离总线,在下次复位之前不参与任何通信。 为了说明单总线数据传输的过程,以下将分4个部分对单总线数据通信传输过程进行介绍,它们分别是单总线通信信号类型,单总线通信初始化,单总线通信的ROM命令以及单总线通信的功能命令。 1.1单总线通信信号类型 单总线通信协议定义了如下几种类型,即复位脉冲、应答脉冲、写0、写1、读0和读1,除了应答脉冲外,所有的信号都由主机发出同步信号,并且发送的所有的命令和数据都是字节的低位在前。 单总线通信协议中不同类型的信号都采用一种类似脉宽调制的波形表示,逻辑0用较长的低电平持续周期表示,逻辑1用较长的高电平持续周期表示。在单总线通信协议中,读写时隙的概念十分重要,当系统主机向从设备输出数据时产生写时隙,当主机从从机设备读取数据时产生读时隙,每一个时隙总线只能传输一位数据。无论是在读时隙还是写时隙,它们都以主机驱动数据线位低电平开始,数据线的下降沿是从设备触发其内部的延时电路,使之与主机同步。在写时隙内,该延迟电路决定从设备采样数据线的时间窗口。 单总线通信协议中存在两种写时隙:写1和写0。主机采用写1时隙向从机写入1,而采用写0时隙向从机写入0,。所有写时隙至少要60us,且在两次独立的写时隙之间至少需要1us的恢复时间。两种写时隙均起始于主机拉低数据总线。产生1时隙的方式:主机拉低总线后,接着必须在15us之内释放总线,由上拉电阻将总线拉至高电平;产生写0时隙的方式为在主机拉低后,只需要在整个时隙间保持低电平即可(至少60us)。在写时隙开始后15us~60us期间,单总线器件采样总电平状态。如果在此期间采样值为高电平,则逻辑1被写入器件;如果为0,写入逻辑0。 图1-1给出了写时隙(包括1和0)时序的图形解释。 竭诚为您提供优质文档/双击可除 1,wire,协议 篇一:单总线(1-wiRebus)技术及其应用 单总线(1-wirebus)技术及其应用摘要:介绍了美dallas公司推出的单总线技术的原理和信号传输方式,说明了单总线通信协议,最后以单总线器件ibutton在安防系统中的应用为例,给出了单总线的数据传输方法。关键词:单总线单总线协议ibutton1引言目前常用的微机与外设之间进行数据传输的串行总线主要有i2c总线、spi总线和sci 总线。其中i2c总线以同步串行2线方式进行通信(一条时钟线,一条数据线),spi总线则以同步串行3线方式进行通信(一条时钟线,一条数据输入线,一条数据输出线),而sci总线是以异步方式进行通信(一条数据输入线,一条数据输出线)的。这些总线至少需要两条或两条以上的信号线。近年来,美国的达拉斯半导体公司(dallassemiconductoR)推出了一项特有的单总线(1-wirebus)技术。该技术与上述总线不同,它采用单根信号线,既可传输时钟,又能传输数据,而且数据传输是双向的,因而这种单总线技术具有线路简单,硬件开销少,成本低廉,便于总线扩展和维护等优 点。单总线适用于单主机系统,能够控制一个或多个从机设备。主机可以是微控制器,从机可以是单总线器件,它们之间的数据交换只通过一条信号线。当只有一个从机设备时,系统可按单节点系统操作;当有多个从设备时,系统则按多节点系统操作。图1所示是单总线多节点系统的示意图。2单总线的工作原理顾名思义,单总线即只有一根数据线,系统中的数据交换、控制都由这根线完成。设备(主机或从机)通过一个漏极开路或三态端口连至该数据线,以允许设备在不发送数据时能够释放总线,而让其它设备使用总线,其内部等效电路如图2所示。单总线通常要求外接一个约为4.7k Ω的上拉电阻,这样,当总线闲置时,其状态为高电平。主机和从机之间的通信可通过3个步骤完成,分别为初始化 1-wire器件、识别1-wire器件和交换数据。由于它们是主从结构,只有主机呼叫从机时,从机才能应答,因此主机访问1-wire器件都必须严格遵循单总线命令序列,即初始化、Rom、命令功能命令。如果出现序列混乱,1-wire器件将不响应主机(搜索Rom命令,报警搜索命令除外)。表1是列为ΔΙΩ命令的说明,而功能命令则根据具体1-wire器件所支持的功能来确定。表1Rom命令说明Rom命令说明搜索Rom(F0h)识别单总线上所有的1-wire器件的Rom编码读Rom(33h)(仅适合单节点)直接读1-wire器件的序列号匹配Rom(55h)寻找与指定序列号相匹配的1-wire器件跳跃 单总线通信协议中存在两种写时隙:写0写1。主机采用写1时隙向从机写入1,而写0时隙向从机写入0。所有写时隙至少要60us,且在两次独立的写时隙之间至少要1us的恢复时间。两种写时隙均起始于主机拉低数据总线。产生1时隙的方式:主机拉低总线后,接着必须在15us之内释放总线,由上拉电阻将总线拉至高电平;产生写0时隙的方式为在主机拉低后,只需要在整个时隙间保持低电平即可(至少60us)。在写时隙开始后15~60us期间,单总线器件采样总电平状态。如果在此期间采样值为高电平,则逻辑1被写入器件;如果为0,写入逻辑0。 下图为写时隙(包括1和0)时序 上图中黑色实线代表系统主机拉低总线,黑色虚线代表上拉电阻将总线拉高。 对于读时隙,单总线器件仅在主机发出读时隙时,才向主机传输数据。所有主机发出读数据命令后,必须马上产生读时隙,以便从机能够传输数据。所有读时隙至少需要60us,且在两次独立的读时隙之间至少需要1us恢复时间。每个读时隙都由主机发起,至少拉低总线1us。在主机发出读时隙后,单总线器件才开始在总线上发送1或0。若从机发送1,则保持总线为高电平;若发出0,则拉低总线。 当发送0时,从机在读时隙结束后释放总线,由上拉电阻将总线拉回至空闲高电平状态。从机发出的数据在起始时隙之后,保持有效时间15us,因此主机在读时隙期间必须释放总线,并且在时隙起始后的15us之内采样总线状态。 下图给出读时隙(包括0或1)时序 图中黑色实线代表系统主机拉低总线,灰色实线代表总局拉低总线,而黑色的虚线则代表上 拉电阻总线拉高。 单总线通信的初始化 单总线上所有的通信都是以初始化序列开始的,初始化序列包括主机发出的复位脉冲及从机的应答脉冲,这一过程如图所示,黑色实线代表系统主机拉低总线,灰色实线代表从机拉低总线,而黑色的虚线则代表上拉电阻将总线拉高。 系统主设备发送端发出的复位脉冲是一个480~960us的低电平,然后释放总线进入接收状态。此时系统总线通过4.7K的上拉电阻接至vcc高电平,时间约为15~60us,接在接受端的设备就开始检测io引脚上的下降沿以及监视在脉冲的到来。主设备处于这种状态下的时间至少480us。 作为从设备在接收到系统主设备发出的复位脉冲之后,向总线发出一个应答脉冲,表示从设备已准备好,可根据各种命令发送或接收数据。通常情况下,器件等待15~60us即可发送应答脉冲 单总线协议-以DS18B20举例 一、概述 1-wire 单总线是Maxim 全资子公司Dallas 的一项专有技术。与目前多数标准串行数据通信方式,如SPI/I2C/MICROWIRE 不同,它采用单根信号线,既传输时钟,又传输数据,而且数据传输是双向的。它具有节省I/O 口线资源、结构简单、成本低廉、便于总线扩展和维护等诸多优点。 1-wire 单总线适用于单个主机系统,能够控制一个或多个从机设备。当只有一个从机位于总线上时,系统可按照单节点系统操作;而当多个从机位于总线上时,则系统按照多节点系统操作。 为了较为全面地介绍单总线系统,将系统分为三个部分讨论:硬件结构、命令序列和信号方式信号类型和时序。 二、硬件结构 顾名思义,单总线只有一根数据线。设备(主机或从机)通过一个漏极开路或三态端口,连接至该数据线,这样允许设备在不发送数据时释放数据总线,以便总线被其它设备所使用。单总线端口为漏极开路其内部等效电路如图1 所示。 单总线要求外接一个约5k 的上拉电阻;这样,单总线的闲置状态为高电平。不管什么原因,如果传输过程需要暂时挂起,且要求传输过程还能够继续的话,则总线必须处于空闲状态。位传输之间的恢复时间没有限制,只要总线在恢复期间处于空闲状态(高电平)。如果总线保持低电平超过480us,总线上的所有器件将复位。另外在寄生方式供电时,为了保证单总线器件在某些工作状态下(如温度转换期间EEPROM写入等)具有足够的电源电流,必须在总线上提供强上拉(如图1所示的MOSFET )。 三、命令序列 典型的单总线命令序列如下: 第一步:初始化 第二步:ROM命令(跟随需要交换的数据) 第三步:功能命令(跟随需要交换的数据) 每次访问单总线器件,必须严格遵守这个命令序列,如果出现序列混乱,则单总线器件不会响应主机。但是,这个准则对于搜索ROM命令和报警搜索命令例外,在执行两者中任何一条命令之后,主机不能执行其后的功能命令,必须返回至第一步。 3 .1 初始化 基于单总线上的所有传输过程都是以初始化开始的,初始化过程由主机发出的复位脉冲和从机响应的应答脉冲组成。应答脉冲使主机知道,总线上有从机设备,且准备就绪。复位和应答脉冲的时间详见单总线信号部分。 3.2 ROM命令 在主机检测到应答脉冲后,就可以发出ROM 命令。这些命令与各个从机设备的唯一64位ROM代码相关,允许主机在单总线上连接多个从机设备时,指定操作某个从机设备。这些命令还允许主机能够检测到总线上有多少个从机设备以及其设备类型,或者有没有设备处于报警状态。从机设备可能支持5 种ROM命令(实际情况与具体型号有关),每种命令长度为8 位。主机在发出功能命令之前,必须送出合适的ROM命令。ROM命令的操作流程如图2 所示。下面将简要地介绍各个ROM命令的功能,以及使用在何种情况下。DS18B20 以单总线协议工作
单总线协议详解
单总线传输协议b2s (附全部verilog源码)
单总线协议
1,wire,协议
单总线协议
单总线协议-以DS18B20举例