當前位置:編程學習大全網 - 源碼下載 - 485通信協議怎麽規定

485通信協議怎麽規定

把通訊做成命令,應答的幀形式,最好是幀長度固定。

舉個例子,

主機發送給從機的數據

幀頭 命令 參數1 參數2 參數3 參數4 校驗和 幀尾

從機回復的數據

回復幀頭 應答命令 結果1 結果2 結果3 結果4 校驗和 回復幀尾

在從機接收到幀頭和命令後,並不進行處理,而是暫存起來,知道接收到幀尾,並接校驗通過後,才真正執行。

假如從收到幀頭起,壹定的時間內,還沒有收到完整的幀,或者幀校驗失敗,那麽從機用特殊的格式回復。

當然,超時時間也可以不從幀頭算,從上壹個字節算也可以。

這樣的幀結構就能保證通訊的正確性,壹般來講,幀越長,通訊效率越高,但是占用暫存空間越打,而且出錯的可能越大,出錯後付出的代價也越大,實時性也越差,而且幀長度超過壹定值後,通訊效率也不會再明顯增加。

幀越短,通訊效率越低,但是靈活。

像上面的例子,幀長度是8,通訊效率是62.5%。如果將幀長度改為16,通訊效率變為81.25%

下面是源代碼:

直接拷貝就能夠編譯通過了。當然要把寄存器改了。只有幾行需要改的哈:

#include "tot.h"

#define GOOD_PARSE 0

#define BADID_PARSE 1

#define BADLEN_PARSE 2

short parsed;

char *pbuf;

void tsip_input_proc(TSIPPKT *rpt,unsigned char inbyte);

void rpt_packet(TSIPPKT *rpt,int *obuf);

void tsip_input_proc(TSIPPKT *rpt,unsigned char inbyte)

{

switch(rpt->status)

{

case TSIP_PARSED_DLE_1:

switch(inbyte)

{

case 0:

case ETX: // illegal data

rpt->len=0;

rpt->status=TSIP_PARSED_EMPTY;

break;

case DLE: // try normal message start again

rpt->len=0;

rpt->status=TSIP_PARSED_DLE_1;

break;

default: // legal ID ;start message

rpt->len=0;

rpt->status=TSIP_PARSED_DATA;

rpt->codes=inbyte;

break;

}

break;

case TSIP_PARSED_DATA:

switch(inbyte)

{

case DLE: // expect DLE or ETX next

rpt->status=TSIP_PARSED_DLE_2;

break;

default: // normal data byte

rpt->buf[rpt->len]=inbyte;

rpt->len++;

break;

}

break;

case TSIP_PARSED_DLE_2:

switch(inbyte)

{

case DLE: // normal data byte

rpt->buf[rpt->len]=inbyte;

rpt->len++;

rpt->status=TSIP_PARSED_DATA;

break;

case ETX: // end of message,return TURE here

rpt->status=TSIP_PARSED_FULL;

break;

default: // error:treat as TSIP_PARSED_DLE_1,start new report packet

rpt->codes=inbyte;

rpt->len=0;

rpt->status=TSIP_PARSED_DATA;

break;

}

break;

case TSIP_PARSED_FULL:

case TSIP_PARSED_EMPTY:

default:

switch(inbyte)

{

case DLE: // normal message start

rpt->len=0;

rpt->status=TSIP_PARSED_DLE_1;

break;

default: // error:ignore inbyte

rpt->len=0;

rpt->status=TSIP_PARSED_EMPTY;

break;

}

break;

}

if(rpt->len>MAX_RPTBUF) // error:start new report packet

{

rpt->status=TSIP_PARSED_EMPTY;

rpt->len=0;

}

}

//串口字符交換*******************************************************************/

int bGetShort(char *bp)

{

int outval;

char *optr;

optr=(char *)&outval;

*optr=*bp<<8 & 0xFF00;

*optr=*(++bp) | *optr;

return outval;

}

//串口報文

int rpt_0x14(TSIPPKT *rpt,int output[1])

{

char *buf;

buf=rpt->buf;

if(rpt->len!=2)return 0;

output[0]=bGetShort(&buf[0]);

return 1;

}

void rpt_packet(TSIPPKT *rpt,int *obuf)

{

parsed=GOOD_PARSE;

switch(rpt->codes)

{

case 20:

rpt_0x14(rpt,obuf);

break;

default:

parsed=BADID_PARSE;

break;

}

}

//發送

void send_cmd(TSIPPKT *cmd, void sendb(char))

{

char *cbuf, *cbufend;

sendb (DLE);

sendb (cmd->codes);

cbufend = cmd->buf + cmd->len;

for (cbuf = cmd->buf; cbuf < cbufend; cbuf++) {

if (*cbuf == DLE) sendb (DLE);

sendb (*cbuf);

}

sendb (DLE);

sendb (ETX);

}

void sendb(char outbyte)

{

//ScibRegs.SCITXBUF=outbyte;

}

//字符交換

void bPutShort(unsigned int *in, char *out)

{

char *inptr;

inptr=(char *)in;

*out= (*inptr>>8) & 0x00FF;

*(++out) = *inptr & 0x00FF;

}

//命令

void cmd_0x0(TSIPPKT *cmd,SCICALOUT *out)

{

bPutShort(&(out->ve),&(cmd->buf[0]));

cmd->len = 2;

cmd->codes =37;

}

//串口使用中斷方式接收,發送不采用中斷

int input[MAX_RPTBUF];

void SCIRXD_ISR(void)

{

tsip_input_proc(&rpt,ScibRegs.SCIRXBUF.bit.RXDT);// analyse

if (rpt.status == TSIP_PARSED_FULL) // receive complete

{

rpt_packet(&rpt,input); // output reports

rpt.status=TSIP_PARSED_EMPTY; // prepare for next

}

ScibRegs.SCIFFRX.bit.RXFFOVRCLR=1; // Clear Overflow flag

ScibRegs.SCIFFRX.bit.RXFFINTCLR=1; // Clear Interrupt flag

PieCtrlRegs.PIEACK.all|= PIEACK_GROUP9; // Issue PIE ack

}

//發送調用方式

// cmd_100x0(&cmd);

// send_cmd(&cmd,&sendb);

//發送調用方式

// cmd_100x0(&cmd);

// send_cmd(&cmd,&sendb);

上面的就是源代碼。。記住把寄存器改了哦。無論是單片機還是上位機都可以用這個哈。

  • 上一篇:推薦壹本java編程思想書
  • 下一篇:視頻編碼器VJEncoder2
  • copyright 2024編程學習大全網