最新日志

发表于:2008-7-16 23:47:59
标签:无标签

1

盖茨语录:受益终生的10句良言

  生活是不公平的,要去适应它。

  Life is not fair, get used to it. 

  世界并不会在意你的自尊。这世界指望你在自我感觉良好之前先要有所成就。

  The world won\\\"t care about your self-esteem. The world will expect you to accomplish something before you feel good about yourself. 

  刚毕业的你不会一年挣4万美元,在你将此职位和汽车都挣到手以前,你不会成为一个公司的副总裁,并拥有一部装有电话的汽车。

You will not make 40 thousand dollars a year right out of high school. You won\\\"t be a vice president with a car phone, until you earn both.

  你认为你的教师严厉,等你在老板手下干活时再这样想,老板可不像教师那样有任期限制的。

  If you think your teacher is tough, wait till you get a boss. He doesn\\\"t have tenure. 

  如果你陷入困境,那不是你父母的过错,所以不要抱怨错误,要从中汲取教训。 

  If you mess up, it\\\"s not your parents\\\" fault, so don\\\"t whine about our mistakes, learn from them.

  在你出生之前,你的父母并非像他们现在这样乏味。他们变成今天这个样子,是因为这些年来一直在为你付帐单,给你洗衣服,听你大谈如何的酷。所以在对父母喋喋不休之前,还是先去打扫一下你自己的屋子吧。

  Before you were born, your parents weren\\\"t as boring as they are now. They got that way from paying your bills, cleaning your clothes and listening to you talk about how cool you are. So before you save the rain forest from the parasites of your parents\\\" generation, try \\\"delousing\\\" the closet in your own room.

  你的学校也许已经不再分优等生和劣等生,但生活却仍在做出类似区分。某些学校已经废除不及格分,只要你想找到正确答案,学校会给你无数次机会。这和现实生活中的任何事情没有一点相似之处。

  Your school may have done away with winners and losers, but life has not. In some schools they have abolished failing grades; they\\\"ll give you as many times as you want to get the right answer. This doesn\\\"t bear the slightest resemblance to anything in real life. 

  生活不分学期,你并没有暑假可以休息,也没有几位雇主乐于帮助你发现自我。自己找时间做吧。

  Life is not divided into semesters. You don\\\"t get summers off and very few employers are interested in helping you find yourself. Do that on your own time. 

  电视不是真实的生活。现实生活中,人们实际上得离开咖啡屋去干自己的工作。

  Television is NOT real life. In real life people actually have to leave the coffee shop and go to jobs.

  善待乏味的人。有可能到头来你的顶头上司就是一个乏味的人。

  Be nice to nerds. Chances are you\\\"ll end up working for one. 

点击此处查看原文 >>

系统分类: 生活点滴   |    用户分类:    |    来源: 转贴

评论(0) | 阅读(106)
发表于:2008-7-8 23:08:45
标签:无标签

0

拟I2C通信协议C程序

/*********************************************************************************
****Micocontroller:   AT89C51 at 12MHz      ** * * * **        *       ********     **      
************Device:   24aa512, 2            **        **       * *      **     **     **
*Programming Model:   Virtual I2C           ** * *    **      *    *      ***   ********    
************Author:   ***                   **        **     * *** *      *** **     **
**************Date:   2006.11.08            **        ** * *        *******   **     **   
*********************************************************************************/
#include<string.h>
           #include<at89x51.h>
           #include<intrins.h>
           #define DELAY_TIME 60 /*经实验,不要小于50!否则可能造成时序混乱*/
           #define TRUE 1
           #define FALSE 0
     #define FLASH_PAGE   7 /*存储器页面大小*/
           sbit SCL="P1"^7;/*假设由P1.7和P1.6控制*/
           sbit SDA="P1"^6;
       /********** Function Definition 函数定义 ************/
           void DELAY(unsigned int t) /*延时函数*/
           {
               while(t!=0)
                   t--;
           }
           void I2C_Start(void)
           {
               /*启动I2C总线的函数,当SCL为高电平时使SDA产生一个负跳变*/
               SDA="1";
               SCL="1";
               DELAY(DELAY_TIME);
               SDA="0";
               DELAY(DELAY_TIME);
               SCL="0";
               DELAY(DELAY_TIME);
           }
           void I2C_Stop(void)
           {
               /*终止I2C总线,当SCL为高电平时使SDA产生一个正跳变*/
               SDA="0";
               SCL="1";
               DELAY(DELAY_TIME);
               SDA="1";
               DELAY(DELAY_TIME);
               SCL="0";
               DELAY(DELAY_TIME);
           }
           void SEND_0(void)    /* SEND ACK */
           {
               /*发送0,在SCL为高电平时使SDA信号为低*/
               SDA="0";
               SCL="1";
               DELAY(DELAY_TIME);
               SCL="0";
               DELAY(DELAY_TIME);
           }
           void SEND_1(void)
           {
               /*发送1,在SCL为高电平时使SDA信号为高*/
               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;
           }
           void WriteI2CByte(char b)reentrant
           {
               /*向I2C总线写一个字节*/
               char i;
               for(i=0;i<8;i++)
                   if((b<<i)&0x80)
                       SEND_1();
                   else
                       SEND_0();
           }
      
           char ReadI2CByte(void)reentrant
           {
               /*从I2C总线读一个字节*/
               char b="0",i;
               for(i=0;i<8;i++)
               {
                   SDA="1";     /*释放总线*/
                   SCL="1";     /*接受数据*/
                   DELAY(10);
                   F0=SDA;    /*psw for user flag*/
                   DELAY(10);
                   SCL="0";
                   if(F0==1)
                       {
                           b="b"<<1;
                           b="b|0x01";
                       }
                   else
                       b="b"<<1;
               }
               return b;
           }

       /**********以下为读写24aa512的函数**********/
       void Write_One_Byte(char id, char addrh,char addrl, char thedata)
       {
                 bit acktemp="1";
                 /*write a byte to mem*/
                 I2C_Start();
                 WriteI2CByte(id);
                 acktemp="Check"_Acknowledge();
                 WriteI2CByte(addrh);/*address high byte*/
                 acktemp="Check"_Acknowledge();
                 WriteI2CByte(addrl);/*address low   byte*/
                 acktemp="Check"_Acknowledge();
                 WriteI2CByte(thedata);/*thedata*/
                 acktemp="Check"_Acknowledge();
                 I2C_Stop();
       }
       void Write_A_Page( char id, char *buffer,char addrh,char addrl) /*page data number is different*/
       {
                 bit acktemp="1";
                 bit wrtmp;
                 int i;
                 /*write a page to at24c02*/
                 I2C_Start();
                 WriteI2CByte(id);
                 acktemp="Check"_Acknowledge();
                 WriteI2CByte(addrh);/*address high byte*/
                 acktemp="Check"_Acknowledge();
                 WriteI2CByte(addrl);/*address low   byte*/
                 acktemp="Check"_Acknowledge();
                 for(i=0;i<FLASH_PAGE;i++)
                 {
                   WriteI2CByte(buffer[i]);
                   if(!Check_Acknowledge())
                       {
                           I2C_Stop();
                       }
                  }

                 I2C_Stop();
      

       }
       char Read_One_Byte(char id ,char addrh,char addrl)
       {          bit acktemp="1";
                 char mydata;
                  /*read a byte from mem*/
                 I2C_Start();
                 WriteI2CByte(id);
                 acktemp="Check"_Acknowledge();
                 WriteI2CByte(addrh);/*address high byte*/
                 acktemp="Check"_Acknowledge();
                 WriteI2CByte(addrl);/*address low   byte*/
                 acktemp="Check"_Acknowledge();
                 I2C_Start();
                 WriteI2CByte(id+1);
                 acktemp="Check"_Acknowledge();

                 mydata="ReadI2CByte"();
                 acktemp="Check"_Acknowledge();
                 return mydata;
                 I2C_Stop();
       }
       void Read_N_Bytes(char id ,char *buffer,char n,char addrh,char addrl)
       {
                 bit acktemp="1";
                 int i="0";
                  /*read 8 bytes from mem*/
                 I2C_Start();
                 WriteI2CByte(id);
                 acktemp="Check"_Acknowledge();
                 WriteI2CByte(addrh);/*address high byte*/
                 acktemp="Check"_Acknowledge();
                 WriteI2CByte(addrl);/*address low   byte*/
                 acktemp="Check"_Acknowledge();
                 I2C_Start();
                 WriteI2CByte(id+1);
                 acktemp="Check"_Acknowledge();
      

                 for(i=0;i<n;i++)
                 {
                       buffer[i]=ReadI2CByte();
                       if(i!=n-1)
                           SEND_0();     /*发送应答*/
                       else
                           SEND_1();     /*发送非应答*/
                 }
          I2C_Stop();
       }

       void main()
       {
                 int i;
                 char mybyte;
                 char myarray[8];
                 char myarray2[8];
                 char rdarray1[16];
                 char rdarray2[16];
               
                 for(i=0;i<8;i++)
                 {
                       myarray[i]=i;
                       myarray2[i]=i*16;    
        rdarray1[i]=0;     /*clr*/
        rdarray1[i+8]=0;   /*clr*/
         rdarray2[i]=0;     /*clr*/
        rdarray2[i+8]=0;   /*clr*/
                 }
                 Write_One_Byte(0xa0,0x00,0x20,0x28);
                 Write_A_Page( 0xa0, myarray,0x00,0x10);
                 Write_A_Page(0xa0, myarray2,0x00,0x18);
                 mybyte="Read"_One_Byte(0xa0,0x00,0x20);
                 Read_N_Bytes(0xa0,rdarray1,6,0x00,0x10);

                // Write_A_Page(0xa2, myarray, 0x00,0x10);   /*the second 24aa512*/
                // Write_A_Page(0xa2, myarray2,0x00,0x18);
                  Read_N_Bytes(0xa2,rdarray2,10,0x00,0x17);

     while (1)
     {
              for (i=0;i<6;i++)
           {
              P2=rdarray1[i];
        DELAY(1000);
           }
                      
         for (i=0;i<10;i++)
           {
              P3=rdarray2[i];
      
        DELAY(1000);
           }

     }      

     }

点击此处查看原文 >>

系统分类: 通信网络   |    用户分类: 无分类    |    来源: 转贴

评论(0) | 阅读(231)
发表于:2008-7-6 1:15:26
标签:无标签

0

MODBUS-RTU通讯协议简介

什么是MODBUS

MODBUS MODICON公司最先倡导的一种软的通讯规约,经过大多数公司
 
的实际应用,逐渐被认可,成为一种标准的通讯规约,只要按照这种规约进行
数据通讯或传输,不同的系统就可以通讯。目前,在RS232/RS485通讯过程中,
更是广泛采用这种规约。
    
常用的MODBUS 通讯规约有两种,一种是MODBUS ASCII,一种是MODBUS RTU
 
一般来说,通讯数据量少而且主要是文本的通讯则采用MODBUS ASCII规约,通讯数据数据量大而且是二进制数值时,多采用MODBUS RTU规约。
  
在实际的应用过程中,为了解决某一个特殊问题,人们喜欢自己修改MODBUS规约来满足自己的需要(事实上,人们经常使用自己定义的规约来通讯,这样能解决问题,但不太规范)。更为普通的用法是,少量修改规约,但将规约格式附在软件说明书一起,或直接放在帮助中,这样就方便了用户的通讯。


MODBUS-RTU通讯协议简介
在本章主要讲述如何利用软件通过通讯口来操控该系列仪表。本章内容的掌握需要您具有MODBUS协议的知识储备并且通读了本册其它章节所有内容,对本产品功能和应用概念有较全面了解。
本章内容包括:MODBUS协议简述,通讯应用格式详解,本机的应用细节及参量地址表。
 
1.1          MODBUS协议简述
ACRXXXE系列仪表使用的是MODBUS-RTU通讯协议,MODBUS协议详细定义了校验码、数据序列等,这些都是特定数据交换的必要内容。MODBUS协议在一根通讯线上使用主从应答式连接(半双工),这意味着在一根单独的通讯线上信号沿着相反的两个方向传输。首先,主计算机的信号寻址到一台唯一的终端设备(从机),然后,终端设备发出的应答信号以相反的方向传输给主机。
MODBUS协议只允许在主机(PC,PLC等)和终端设备之间通讯,而不允许独立的终端设备之间的数据交换,这样各终端设备不会在它们初始化时占据通讯线路,而仅限于响应到达本机的查询信号。
 
1.2          查询—回应周期
 
1.2.1           查询
查询消息中的功能代码告之被选中的从设备要执行何种功能。数据段包含了从设备要执行功能的任何附加信息。例如功能代码03是要求从设备读保持寄存器并返回它们的内容。数据段必须包含要告之从设备的信息:从何寄存器开始读及要读的寄存器数量。错误检测域为从设备提供了一种验证消息内容是否正确的方法。
1.2.2           回应
如果从设备产生一正常的回应,在回应消息中的功能代码是在查询消息中的功能代码的回应。数据段包括了从设备收集的数据:如寄存器值或状态。如果有错误发生,功能代码将被修改以用于指出回应消息是错误的,同时数据段包含了描述此错误信息的代码。错误检测域允许主设备确认消息内容是否可用。
 
1.3          传输方式
传输方式是指一个数据帧内一系列独立的数据结构以及用于传输数据的有限规则,下面定义了与MODBUS 协议– RTU方式相兼容的传输方式。
每个字节的位
·   1个起始位
·   8个数据位,最小的有效位先发送
·   无奇偶校验位
·   1个停止位
错误检测(Error checking)CRC(循环冗余校验)
 
1.4          协议
当数据帧到达终端设备时,它通过一个简单的“端口”进入被寻址到的设备,该设备去掉数据帧的“信封”(数据头),读取数据,如果没有错误,就执行数据所请求的任务,然后,它将自己生成的数据加入到取得的“信封”中,把数据帧返回给发送者。返回的响应数据中包含了以下内容:终端从机地址(Address)、被执行了的命令(Function)执行命令生成的被请求数据(Data)和一个校验码(Check)。发生任何错误都不会有成功的响应,或者返回一个错误指示帧。
 
1.4.1           数据帧格式
 
Address
Function
Data
Check
8-Bits
8-Bits
N x 8-Bits
16-Bits
 
 
1.4.2           地址(Address)域
地址域在帧的开始部分,由一个字节(8位二进制码)组成,十进制为0~255,在我们的系统中只使用1~247,其它地址保留。这些位标明了用户指定的终端设备的地址,该设备将接收来自与之相连的主机数据。每个终端设备的地址必须是唯一的,仅仅被寻址到的终端会响应包含了该地址的查询。当终端发送回一个响应,响应中的从机地址数据便告诉了主机哪台终端正与之进行通信。
 
1.4.3           功能(Function)域
功能域代码告诉了被寻址到的终端执行何种功能。下表列出了该系列仪表用到的功能码,以及它们的意义和功能。

代码
意义
行为
03
读数据寄存器
获得一个或多个寄存器的当前二进制值
16
预置多寄存器
设定二进制值到一系列多寄存器中(不对ACRXXXE开放)

 
1.4.4           数据(Data)域
数据域包含了终端执行特定功能所需要的数据或者终端响应查询时采集到的数据。这些数据的内容可能是数值、参考地址或者设置值。例如:功能域码告诉终端读取一个寄存器,数据域则需要指明从哪个寄存器开始及读取多少个数据,内嵌的地址和数据依照类型和从机之间的不同内容而有所不同。
 
1.4.5           错误校验(Check)域
该域允许主机和终端检查传输过程中的错误。有时,由于电噪声和其它干扰,一组数据在从一个设备传输到另一个设备时在线路上可能会发生一些改变,出错校验能够保证主机或者终端不去响应那些传输过程中发生了改变的数据,这就提高了系统的安全性和效率,错误校验使用了16位循环冗余的方法(CRC16)。
 
1.5          错误检测的方法
错误校验(CRC)域占用两个字节,包含了一个16位的二进制值。CRC值由传输设备计算出来,然后附加到数据帧上,接收设备在接收数据时重新计算CRC值,然后与接收到的CRC域中的值进行比较,如果这两个值不相等,就发生了错误。
CRC运算时,首先将一个16位的寄存器预置为全1,然后连续把数据帧中的每个字节中的8位与该寄存器的当前值进行运算,仅仅每个字节的8个数据位参与生成CRC,起始位和终止位以及可能使用的奇偶位都不影响CRC。在生成CRC时,每个字节的8位与寄存器中的内容进行异或,然后将结果向低位移位,高位则用“0”补充,最低位(LSB)移出并检测,如果是1,该寄存器就与一个预设的固定值(0A001H)进行一次异或运算,如果最低位为0,不作任何处理。
上述处理重复进行,直到执行完了8次移位操作,当最后一位(第8位)移完以后,下一个8位字节与寄存器的当前值进行异或运算,同样进行上述的另一个8次移位异或操作,当数据帧中的所有字节都作了处理,生成的最终值就是CRC值。
生成一个CRC的流程为:
1            预置一个16位寄存器为0FFFFH(全1),称之为CRC寄存器。
2            把数据帧中的第一个字节的8位与CRC寄存器中的低字节进行异或运算,结果存回CRC寄存器。
3            将CRC寄存器向右移一位,最高位填以0,最低位移出并检测。
4            如果最低位为0:重复第三步(下一次移位);如果最低位为1:将CRC寄存器与一个预设的固定值(0A001H)进行异或运算。
5            重复第三步和第四步直到8次移位。这样处理完了一个完整的八位。
6            重复第2步到第5步来处理下一个八位,直到所有的字节处理结束。
7       最终CRC寄存器的值就是CRC的值。
此外还有一种利用预设的表格计算CRC的方法,它的主要特点是计算速度快,但是表格需要较大的存储空间,该方法此处不再赘述,请参阅相关资料。
 
1.6          通讯应用格式祥解
本节所举实例将尽可能的使用如图所示的格式,(数字为16进制)。

Addr
Fun
Data start  reg hi
Data start  reg lo
Data #of regs hi
Data #of regs lo
CRC16 lo
CRC16hi
01H
03H
00H
00H
00H
03H
05H
CBH

Addr:从机地址
Fun:功能码
Data start reg hi:数据起始地址 寄存器高字节
Data start reg lo:数据起始地址 寄存器低字节
Data #of reg hi:数据读取个数 寄存器高字节
Data #of reg lo:数据读取个数 寄存器低字节
CRC16 Hi: 循环冗余校验 高字节
CRC16 Lo: 循环冗余校验 低字节
 
1.6.1           读数据(功能码03)
l         查询数据帧
此功能允许用户获得设备采集与记录的数据及系统参数。主机一次请求的数据个数没有限制,但不能超出定义的地址范围。
下面的例子是从01号从机读3个采集到的基本数据(数据帧中每个地址占用2个字节)UA、UB、UC,其中UA的地址为0025H, UB的地址为0026H, UC的地址为0027H。

Addr
 Fun
Data start
Addr hi
Datastart
Addr lo
Data#of
regs hi
Data #of
regs lo
CRC16 lo
CRC16 hi
01H
03H
00H
25H
00H
03H
14H
00H

l         响应数据帧
响应包含从机地址、功能码、数据的数量和CRC错误校验。
下面的例子是读取UA、UB、UC (UA=082CH,UB=082AH,UC=082CH的响应。

Addr
Fun
Byte count
Data1 hi
Data1 lo
Data2 hi
Data2 lo
Data3 hi
Data3 lo
CRC16 lo
CRC16 hi
01H
03H
06H
08H
2CH
08H
2AH
08H
2CH
94H
4EH

l         错误指示码
如果主机请求的地址不存在则返回错误指示码:FFH。
 
1.6.2           预置多寄存器(功能码16,不对ACRXXXE开放
l         查询数据帧
         功能码16允许用户改变多个寄存器的内容,该仪表中系统参数、开关量输出状态等可用此功能号写入。主机一次最多可以写入16(32字节)数据。
 下面的例子是预置ACR220EKACR320EFKACR420EK地址都为1时同时输出开关量Do1Do2
ACR220EK

Addr
Fun
Data Start reg hi
Data start reg lo
Data #of regs hi
Data #of regs lo
Bytecount
Value hi
Value lo
CRC lo
CRC hi
01H
10H
00H
22H
00H
01H
02 H
30H
00H
B4H
D2H

ACR420EK

Addr
Fun
Data Start reg hi
Data start reg lo
Data #of regs hi
Data #of regs lo
Bytecount
Value hi
Value lo
CRC lo
CRC hi
01H
10H
00H
22H
00H
01H
02 H
C0H
00H
F0H
D2H

ACR320EFK