支持多点通信协议的定义

2019-07-20 15:09发布

本帖最后由 mftang2016 于 2017-4-16 09:51 编辑

本文介绍一种通信协议的实现原理和方法,其可支持单点、多点通信。可用于串口、usb、网口、485等多种通信介质。下面介绍其实现方法和原理:

360截图20170416093844410.jpg
固件实现:
1. 数据解析文件
[mw_shl_code=c,true]/*******************************************************************************
** File name:         ZCS_Parser.c
** Created by:         Mingfei Tang               
** Created date: 2016/2/18               
** Version:         V1.00                        
** Descriptions: for zcs protocol parsered
** Details:      
**------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Descriptions:
**
*******************************************************************************/
#include "includes.h"

void ZCS_ParserReset(ZCS* pst_zcs )
{
    pst_zcs->StateStep = _ZCS_HEAD_H;
    pst_zcs->DataLen = 0;
    pst_zcs->HostPckLength = 0;
    pst_zcs->PackeParseLen.LenIndex = 0;
    pst_zcs->ParseLength    = 512;
   
    memset( pst_zcs->DataBuf, 0, sizeof(pst_zcs->DataBuf));
    memset( pst_zcs->RecvDataBuf, 0, sizeof(pst_zcs->RecvDataBuf));
    memset( pst_zcs->HostSendBuf, 0, sizeof(pst_zcs->HostSendBuf));
   
    pst_zcs->PackeParseLen.PF_UID  = 6;
}

/* Header H -0 */
static void ZCS_Check_HEADH( ZCS* pst_zcs )
{
    INT8U u8_input = pst_zcs->InByte;
   
    if( u8_input == HEAD )
    {
        pst_zcs->Head = u8_input;
        pst_zcs->Head <<= 8;
        pst_zcs->Head &= 0xFF00;
        pst_zcs->StateStep = _ZCS_HEAD_L;
    }
    else
    {
        ZCS_ParserReset( pst_zcs );
    }
}

/* Header L -1 */
static void ZCS_Check_HEADL( ZCS* pst_zcs )
{
    INT8U u8_input = pst_zcs->InByte;
   
    if( u8_input == HEAD )
    {
        pst_zcs->Head += u8_input;
        pst_zcs->StateStep = _ZCS_FNUM_H;
    }
    else
    {
        ZCS_ParserReset( pst_zcs );
    }
}

/* FNUM H -2 */
static void ZCS_Check_FNUMH( ZCS* pst_zcs )
{
    INT8U u8_input = pst_zcs->InByte;

    pst_zcs->FNUM = u8_input;
    pst_zcs->FNUM <<= 8;
    pst_zcs->FNUM &= 0xFF00;
    pst_zcs->StateStep = _ZCS_FNUM_L;
}

/* FNUM L -3 */
static void ZCS_Check_FNUML( ZCS* pst_zcs )
{
    INT8U u8_input = pst_zcs->InByte;

    pst_zcs->FNUM += u8_input;
    pst_zcs->StateStep = _ZCS_UID;
    pst_zcs->PackeParseLen.LenIndex = 0;
}

/* UID -4 */
static void ZCS_Check_UID( ZCS* pst_zcs )
{
    INT8U inByte = pst_zcs->InByte;  
   
    pst_zcs->UID[pst_zcs->PackeParseLen.LenIndex++] = inByte;
    if( pst_zcs->PackeParseLen.LenIndex == pst_zcs->PackeParseLen.PF_UID)
    {
        pst_zcs->PackeParseLen.LenIndex = 0;        
        pst_zcs->StateStep = _ZCS_CMD_H;  
    }
}

/* CMD H -5 */
static void ZCS_Check_CMDH( ZCS* pst_zcs )
{
    INT8U u8_input = pst_zcs->InByte;

    pst_zcs->CMD = u8_input;
    pst_zcs->CMD <<= 8;
    pst_zcs->CMD &= 0xFF00;
    pst_zcs->StateStep = _ZCS_CMD_L;
}

/* CMD L -6 */
static void ZCS_Check_CMDL( ZCS* pst_zcs )
{
    INT8U u8_input = pst_zcs->InByte;

    pst_zcs->CMD += u8_input;
    pst_zcs->StateStep = _ZCS_DLEN_H;
}

/* data length H -7 */
static void ZCS_Check_datalengthH( ZCS* pst_zcs )
{
    INT8U u8_input = pst_zcs->InByte;

    pst_zcs->DataLen = u8_input;
    pst_zcs->DataLen <<= 8;
    pst_zcs->DataLen &= 0xFF00;
    pst_zcs->StateStep = _ZCS_DLEN_L;
}

/* data length L -8 */
static void ZCS_Check_datalengthHL( ZCS* pst_zcs )
{
    INT8U u8_input = pst_zcs->InByte;

    pst_zcs->DataLen += u8_input;
    pst_zcs->PackeParseLen.LenIndex = 0;

    if( pst_zcs->DataLen >= pst_zcs->MaxParseLength)
    {
           ZCS_ParserReset( pst_zcs );
    }
    else if( !pst_zcs->DataLen ){
           pst_zcs->StateStep = _ZCS_CRC16_H;
    }
    else{
           pst_zcs->StateStep = _ZCS_DATA;
    }
}

/* data packet -9 */
static void ZCS_Check_DataPck( ZCS* pst_zcs )
{
    INT8U inByte = pst_zcs->InByte;  

    pst_zcs->DataBuf[pst_zcs->PackeParseLen.LenIndex++] = inByte;
    if( pst_zcs->PackeParseLen.LenIndex == pst_zcs->DataLen)
    {
        pst_zcs->PackeParseLen.LenIndex = 0;
        pst_zcs->StateStep = _ZCS_CRC16_H;
    }
}

/* calculate CRC16 */
static void ZCS_Check_calculateCRC( ZCS* pst_zcs )
{
    INT16U crc16Cal;
    INT8U i;

    pst_zcs->PackeParseLen.LenIndex = 0;
    /* header */
    pst_zcs->RecvDataBuf[pst_zcs->PackeParseLen.LenIndex++] = (pst_zcs->Head >>8) & 0xff;
    pst_zcs->RecvDataBuf[pst_zcs->PackeParseLen.LenIndex++] = pst_zcs->Head & 0xff;

     /* FNUM */
    pst_zcs->RecvDataBuf[pst_zcs->PackeParseLen.LenIndex++] = (pst_zcs->FNUM >>8) & 0xff;
    pst_zcs->RecvDataBuf[pst_zcs->PackeParseLen.LenIndex++] = pst_zcs->FNUM & 0xff;

     /* UID */
    for(  i = 0; i < pst_zcs->PackeParseLen.PF_UID; i++ )
    {
      pst_zcs->RecvDataBuf[pst_zcs->PackeParseLen.LenIndex++] = pst_zcs->UID;
    }  

    /* CMD */
    pst_zcs->RecvDataBuf[pst_zcs->PackeParseLen.LenIndex++] = (pst_zcs->CMD >>8) & 0xff;
    pst_zcs->RecvDataBuf[pst_zcs->PackeParseLen.LenIndex++] = pst_zcs->CMD & 0xff;

    /* data length */
    pst_zcs->RecvDataBuf[pst_zcs->PackeParseLen.LenIndex++] = (pst_zcs->DataLen >>8) & 0xff;
    pst_zcs->RecvDataBuf[pst_zcs->PackeParseLen.LenIndex++] = pst_zcs->DataLen & 0xff;

     /* data */
    for(  i = 0; i < pst_zcs->DataLen; i++ )
    {
        pst_zcs->RecvDataBuf[pst_zcs->PackeParseLen.LenIndex++] = pst_zcs->DataBuf;
    }

    /* calculate CRC16 */
    crc16Cal =   UTL_ChkCrc16(  pst_zcs->RecvDataBuf, pst_zcs->PackeParseLen.LenIndex);

    if( crc16Cal == pst_zcs->CRC16 )
    {
        pst_zcs->RecvDataBuf[pst_zcs->PackeParseLen.LenIndex++] = (crc16Cal >>8) & 0xff;
        pst_zcs->RecvDataBuf[pst_zcs->PackeParseLen.LenIndex++] =  crc16Cal & 0xff;
        pst_zcs->PacketFlags_bit.PF_ACTION = 1;
        pst_zcs->PackeParseLen.LenIndex = 0;
    }
    else
    {
        ZCS_ParserReset( pst_zcs );
    }
}

/* CRC16 H -10 */
static void ZCS_Check_CRC16H( ZCS* pst_zcs )
{
    INT8U u8_input = pst_zcs->InByte;

    pst_zcs->CRC16 = u8_input;
    pst_zcs->CRC16 <<= 8;
    pst_zcs->CRC16 &= 0xFF00;
    pst_zcs->StateStep = _ZCS_CRC16_L;
}

/* CRC16 L -11 */
static void ZCS_Check_CRC16L( ZCS* pst_zcs )
{
    INT8U u8_input = pst_zcs->InByte;

    pst_zcs->CRC16 |= u8_input;
    ZCS_Check_calculateCRC( pst_zcs );
}

/* must match with ZCS_STATE total number */
static void (* const ZCS_Check[])(ZCS*) = {
    ZCS_Check_HEADH,
    ZCS_Check_HEADL,
    ZCS_Check_FNUMH,
    ZCS_Check_FNUML,
    ZCS_Check_UID,
    ZCS_Check_CMDH,
    ZCS_Check_CMDL,
    ZCS_Check_datalengthH,
    ZCS_Check_datalengthHL,
    ZCS_Check_DataPck,
    ZCS_Check_CRC16H,
    ZCS_Check_CRC16L,
};

void ZCS_Parser( ZCS* pst_zcs, INT8U u8_input )
{
    pst_zcs->InByte = u8_input;
    ZCS_Check[pst_zcs->StateStep]( pst_zcs );              
}


// 数据包模式解析
INT8U ZCS_CommHandlerAction(  ZCS *pst_zcs, INT8U *pbuff)
{
    INT16U cmd;
    INT8U UID[6];
    INT16U packetlenth;

    memset( UID, 0xff, 6);
    packetlenth = 0;
   
    //Step - 1  header
    if(pbuff[COLLECT_PROTOCOL_HEADER1_OFFSET]!=FRAME_HEADER0
    || pbuff[COLLECT_PROTOCOL_HEADER2_OFFSET]!=FRAME_HEADER1)
    {
          return FALSE;
    }
    else{
          pst_zcs->Head = FRAME_HEADER0<<8|FRAME_HEADER1;
          packetlenth += 2;
    }

    //Step - 2 FUMN
    pst_zcs->FNUM = pbuff[COLLECT_PROTOCOL_FUMN_OFFSET]<<8|pbuff[COLLECT_PROTOCOL_FUMN_OFFSET+1];
    packetlenth += 2;

    //Step - 3 UID
    memcpy( pst_zcs->UID, pbuff+COLLECT_PROTOCOL_UID_OFFSET, 6);
    packetlenth += 6;

    //step - 4 cmd
    cmd = MAKE_WORD(pbuff[COLLECT_PROTOCOL_CMD_OFFSET],pbuff[COLLECT_PROTOCOL_CMD_OFFSET+1]);        

    pst_zcs->CMD = cmd&0xff;
    pst_zcs->PacketFlags_bit.PF_ACTION = 1;
    packetlenth += 2;

    //step - 5 date length
    pst_zcs->DataLen = pbuff[COLLECT_PROTOCOL_DATA_LENGTH_OFFSET]<<8|pbuff[COLLECT_PROTOCOL_DATA_LENGTH_OFFSET+1];
    packetlenth += 2;

    //step - 6 copy data
    if( pst_zcs->DataLen )
    {
          memcpy( pst_zcs->DataBuf, pbuff+COLLECT_PROTOCOL_DATA_OFFSET, pst_zcs->DataLen);
          packetlenth += pst_zcs->DataLen;
    }
   
    //step - 7 calculte crc
    if(CheckCRC(pbuff,packetlenth+2) == RC_ERR)
    {
          return FALSE ;
    }        

    //Action
    if( pst_zcs->PacketFlags_bit.PF_ACTION )
    {
          ZCS_SlaveExecuter( pst_zcs );
          pst_zcs->PacketFlags_bit.PF_ACTION = 0;
          return TRUE;
    }

    return FALSE;
}

/* EOF*/[/mw_shl_code]

2. 执行协议文件
[mw_shl_code=c,true]/*******************************************************************************
** File name:         ZCS_Excuter.c
** Created by:         Mingfei Tang               
** Created date: 2016/2/18               
** Version:         V1.00                        
** Descriptions: for zcs protocol parsered
** Details:      
**------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Descriptions:
**
*******************************************************************************/
#include "includes.h"

static INT8U ZCS_Builder( ZCS *pst_zcs )
{
    INT16U         i;
    INT16U         cal_Crc;
   
    i = 0;
    /* packet head -1 */
    pst_zcs->HostSendBuf[i++] = HEAD;
    pst_zcs->HostSendBuf[i++] = HEAD;
   
    /* FNUM */
    pst_zcs->HostSendBuf[i++] = (pst_zcs->FNUM >>8) & 0xff;
    pst_zcs->HostSendBuf[i++] = pst_zcs->FNUM & 0xff;
   
    /* UID */
    for(INT8U  j = 0; j < pst_zcs->PackeParseLen.PF_UID; j++)
    {
        pst_zcs->HostSendBuf[i++] = pst_zcs->UID[j];
    }
   
    /* CMD */
    pst_zcs->HostSendBuf[i++] = (pst_zcs->CMD >>8) & 0xff;
    pst_zcs->HostSendBuf[i++] = pst_zcs->CMD & 0xff;
   
    /* data length */
    pst_zcs->HostSendBuf[i++] = (pst_zcs->DataLen >>8) & 0xff;
    pst_zcs->HostSendBuf[i++] = pst_zcs->DataLen & 0xff;
   
    /* data packet */
    for(INT16U  j = 0; j < pst_zcs->DataLen; j++)
    {
        pst_zcs->HostSendBuf[i++] = pst_zcs->DataBuf[j];
    }   

    /* crc 16*/
    cal_Crc = UTL_ChkCrc16( pst_zcs->HostSendBuf, i );
   
    pst_zcs->HostSendBuf[i++] = (cal_Crc >> 8) & 0XFF;
    pst_zcs->HostSendBuf[i++] = cal_Crc & 0XFF ;   
   
    pst_zcs->HostPckLength = i;
    if( pst_zcs->pf_SendPut != NULL )
    {
        pst_zcs->pf_SendPut( pst_zcs->HostSendBuf, pst_zcs->HostPckLength);
        return( 1 );
    }   
   
    return 0;   
}

/* return 1: support, 0: not support */
static INT8U ZCS_SearchCmd( ZCS *pst_zcs, PFNCT_ZCS* func )
{
    INT16U i;
    ZCS_CmdNode* tptr;
   
    /* Search command set */
    tptr = (ZCS_CmdNode *)pst_zcs->CmdTable;
    for( i=0; i<pst_zcs->CmdTotal; i++ )
    {
        if( pst_zcs->CMD == (tptr+i)->command )
        {
                *func = (PFNCT_ZCS)(tptr+i)->pf_FuncPtr;
                return( 1 );
        }
    }
   
    return( 0 );        
}

/* return 1: support, 0: not support */
INT8U ZCS_ActionExecuter( ZCS* zcs )
{
    PFNCT_ZCS fptr = NULL;

    if( ZCS_SearchCmd(zcs, &fptr ) == 0 )
    {
            goto exit;
    }
   
    if( fptr != NULL )
    {
            fptr( zcs );
    }
   
    return( 1 );
   
exit:
    return( 0 );
}

/*******************************************************************************
            Host action
********************************************************************************/
INT8U ZCS_HostSendPacket( ZCS *pst_zcs )
{
    if( !ZCS_Builder( pst_zcs ) == 1 )
    {
        return 0;
    }
   
    return 1;
}

/*******************************************************************************
            slave action
********************************************************************************/
INT8U ZCS_SlaveExecuter( ZCS *pst_zcs )
{
    if(ZCS_ActionExecuter( pst_zcs ))
    {
        //Refrsh command
        pst_zcs->CMD |= ZCS_SUCESS;
    }
    else
    {
        pst_zcs->CMD |= ZCS_ERROR;
    }
   
    /* Slave action */
    if( !ZCS_Builder( pst_zcs ) == 1 )
    {
        return 0;
    }
   
    return 1;
}

/* EOF */[/mw_shl_code]
3. 头文件定义
[mw_shl_code=c,true]#ifndef __ZCS_H
#define __ZCS_H

#define ZCS_SUCESS                      0X8000
#define ZCS_ERROR                       0X4000

#define HEAD                            0xfb
#define MAX_RETRY                        3


typedef enum
{
    ERR_OK = 0x0000,
    ERR_OUT_OF_MEMORY=0x0001,
    ERR_PARAM=0x0002,
    ERR_SAMPLING=0x0003,
    ERR_UNSUPORT_SAMPLE_RATE=0x0004,
    ERR_END = 0x0005,
    ERR_SENSOR_ALREADY_EXIST=0x0100,
    ERR_SENSOR_NOT_EXIST=0x0101,
    ERR_GPRSINFOR=0x0103,
    ERR_LOG=0x0104,
    ERR_SENSOR=0x0202,
    ERR_SENSORNORSP = 0x7fffff41,
}Comm_error_code;


typedef enum {
  HOST_RECV=1,
  SLAVE_RECV,
  HOST_SEND,
} ZCS_ROLE;

typedef enum {
    _ZCS_HEAD_H = 0,
    _ZCS_HEAD_L,
    _ZCS_FNUM_H,
    _ZCS_FNUM_L,
    _ZCS_UID,
    _ZCS_CMD_H,
    _ZCS_CMD_L,
    _ZCS_DLEN_H,
    _ZCS_DLEN_L,
    _ZCS_DATA,
    _ZCS_CRC16_H,
    _ZCS_CRC16_L,
} ZCS_STATE;

typedef struct {
    INT8U PF_REPEAT        :1;
    INT8U PF_REPEATED        :1;
    INT8U                  :1;
    INT8U                 :1;
    INT8U PF_BROADCAST        :1;
    INT8U PF_ACTION     :1;
    INT8U PF_SPECIAL    :1;
    INT8U PF_INIT       :1;
}ZCS_PacketFlag;

typedef struct {
    INT8U                 :1;
    INT8U                 :1;
    INT8U               :1;
    INT8U                 :1;
    INT8U CS_ERR_BUSY   :1;
    INT8U CS_ERR_DATA   :1;
    INT8U CS_ERR_CMD    :1;
    INT8U               :1;
} ZCS_CommStatus;

typedef struct {
    INT8U PF_HEAD;
    INT8U PF_FNUM;
    INT8U PF_UID;
    INT8U PF_CMD;
    INT8U PF_DLEN;
    INT8U PF_DATAPACLEN;
    INT8U PF_CRC16;
    INT8U LenIndex;
}ZCS_PackeParseLEN;


typedef struct _ZCS {
    /* ZCS internal use only */
    ZCS_PackeParseLEN PackeParseLen;
    ZCS_STATE         StateStep;
    INT8U          Role;
    INT8U          InByte;
    INT8U       RtnCode;
    INT8U          VerPac;
    INT16U         SlaveAddr;
    INT16U         HostAddr;   
    /* data packet */
    INT16U      Head;
    INT16U         FNUM;
    INT16U      CRC16;
    INT16U      CMD;
    INT16U         DataLen;
    INT8U         *DataBuf;
    INT8U         *RecvDataBuf;
    INT8U         UID[6];
    /* Host structure */
    INT8U                 *HostSendBuf;
    INT16U                 HostPckLength;   
    /* Use accessible */
    union {
      INT8U             PacketFlags;
      ZCS_PacketFlag         PacketFlags_bit;
    };
    union {
      INT8U                    CommStatus;
      ZCS_CommStatus         CommStatus_bit;
    };
    void                (*pf_SendPut)(INT8U*, INT16U);
    INT16U                 ParseLength;
    INT16U              MaxParseLength;
    void*                  CmdTable;
    INT16U                 CmdTotal;
} ZCS;

typedef void (*PFNCT_ZCS)(ZCS *);

typedef struct {
        INT16U                 command;
        PFNCT_ZCS         pf_FuncPtr;
        PFNCT_ZCS         pf_PostFuncPtr;
} ZCS_CmdNode;


#endif /* __ZCS_H  */[/mw_shl_code]

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。