用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字
云代码 - c代码库

数据帧接收

2016-06-28 作者: stopshooting举报

[c]代码库

/**********************************************************************************************************
建立头文件"transport.h"
**********************************************************************************************************/
#ifndef __TRANSPORT_H
#define __TRANSPORT_H
 
#include "stm8_macro.h"
 
/*********************************************************
 接收数据帧:
 1.结构  : 2字节帧头 + 1字节长度信息 + 数据 + 1字节校验码
  
 2.移植  : 1).IC层,数据的接收中断与发送函数。
           2).CRC_Calculation(u8* ),校验码计算
            
 3.OUTPUT: 1).调用DataFrame_Receive()将接收到的原始数据经过处理、CRC校验,
              将得到的有效数据帧存放于RcvFrameCache.Cache[]中,数据
              不包含帧头。
           2).接收数据超时:调用DataFrame_Receive()接收一帧数据的过程中,
              超过(TIME_OUT)次扫描未接收到数据则输出超时Cmd_TimeOut。
           3).调用getDataFrame(u8* buffer)从RcvFrameCache.Cache[]中获取数据帧
*********************************************************/
 
//////////////////////// 参数配置 ////////////////////////
 
// 长度信息计算方法:
// 0: 长度 = 长度信息本身字节数 + 数据 + 校验码
// 1: 长度 = 长度信息本身字节数 + 数据
// 2: 长度 = 数据 + 校验码
// 3: 长度 = 数据
#define LENGTH_METHOD              (0L)
 
#define FRAME_HEAD1                (0XFFul)//帧头1
#define FRAME_HEAD2                (0xF0ul)//帧头2
 
#define FRAME_LENGTH_MIN           (5ul)   //一帧数据的最小长度
#define FRAME_LENGTH_MAX           (20ul)  //一帧数据的最大长度
 
#define ROW_DATA_SIZE              (100ul) // 接收到的原始数据缓存大小
#define FRAME_CACHE_SIZE           (200ul) // 接收到的帧数据缓存大小
 
#define TIMEOUT_MECHANISMS_ENABLE  1       //超时处理机制  0:失能  1:使能
 
#if TIMEOUT_MECHANISMS_ENABLE != 0
    #define TIME_OUT               (500ul) //接收一帧数据超时的时间阈值,
                                           //单位:调用Command_Receive()函数的周期
#endif
 
//////////////////////////////////////////////////////////
 
typedef enum {
  Cmd_NoCmd = 0, //未收到完整数据包
  Cmd_OK,        //接收成功
  Cmd_TimeOut,   //接收超时
  Cmd_LEN_Wrong, //接收到的数据包错误(长度不在范围内)
  Cmd_CRC_Wrong  //CRC校验错误
} _frameRes_;
 
 
void Uart_Init(u32 baudrate);
void UartSendData(u8 *ptr, u8 len);
u8   UartSendStr(u8 *str);
 
u8 CRC_Calculation(u8* pbuf);
_frameRes_ DataFrame_Receive(void);
_frameRes_ getDataFrame(u8 *buffer);
u8 framePakage(u8 *buffer, const u8 cmdDataLen, ...);
 
#endif /*__TRANSPORT_H*/
 
 
/**********************************************************************************************************
建立源文件"transport.c"
***********************************************************************************************************/
 
#include "transport.h"
#include "stdarg.h"
#include "stm8s.h"
 
 
 
//从接收到的数据帧中获取 总长度 = 长度 + 数据 + 校验码
//len : 长度信息
#if   LENGTH_METHOD == 0
    #define GET_TOTAL_LENGTH(len)  (len)
#elif LENGTH_METHOD == 1
    #define GET_TOTAL_LENGTH(len)  (len+1)
#elif LENGTH_METHOD == 2
    #define GET_TOTAL_LENGTH(len)  (len+1)
#elif LENGTH_METHOD == 3
    #define GET_TOTAL_LENGTH(len)  (len+2)
#else
    #error "wrong define LENGTH_METHOD !"
#endif
 
 
typedef enum{
  FINDING_HEAD1 = 0,
  FINDING_HEAD2,
  NEED_LENGTH,
  GETTING_DATA,
  GETTING_CHECKSUM
} RcvStatus_TypeDef;
 
volatile struct{
  u8 Reg[ROW_DATA_SIZE];     //串口接收到的原始数据缓存
  u8 countTail;              //串口接收计数
} RcvRawData;                //接收到的原始数据
 
struct {
  u8  Cache[FRAME_CACHE_SIZE]; //接收有效指令缓存器,不包含帧头
  u8  countTail;               //
} RcvFrameCache;               //接收到的帧数据
 
//#define DEBUG
#ifdef DEBUG
struct {
  u16 correctNum;
  u8  errNum;
  u8  errbuf[256];
} FrameNum;
#endif
 
static void RowDataInput(u8 byte);
 
////////////////////////////////////////////////////////////
 
//----------------------------------------------------------------
 
/******** IC层 ********/
 
/*
 @Function : UART初始化
             8bit数据位,1位停止位,无校验位,允许接收和发送
 @Input    : 波特率
 @Output   : None
 **/
  
void Uart_Init(u32 baudrate)
{
    UART2_Cmd(DISABLE);
 
    UART2_DeInit();  //恢复默认值
     
    UART2_Init(baudrate,
               UART2_WORDLENGTH_8D,            // 8bit数据位
               UART2_STOPBITS_1,               // 1bit停止位
               UART2_PARITY_NO,                // 无校验位
               UART2_SYNCMODE_CLOCK_DISABLE,   // 禁用同步模式
               UART2_MODE_TXRX_ENABLE);        // 发送、接收使能
 
    UART2_ITConfig(UART2_IT_RXNE_OR, ENABLE);  // 开接收中断
     
    UART2_Cmd(ENABLE);                         // 使能UART2
}
 
/*
 @Function : 发送数据
 @Input     : ptr   数据首地址
             len   要发送的长度
 @Output   : None
 **/
void UartSendData(u8 *ptr, u8 len)
{
    while(len--)
    {
        while(UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET);
        UART2_SendData8(*ptr++);
    }
}
 
/*
 @Function : 发送数据
 @Input     : ptr   数据首地址
 @Output   : 发送的字节长度
 **/
u8 UartSendStr(u8 *str)
{
    u8 i;
 
    for(i=0; *str != 0x00; i++)
    {
        while(UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET);
        UART2_SendData8(*str++);
    }
    return i;
}
 
/*
 @Function : UART2中断服务函数
 @Input     : None
 @Output   : None
 **/
@far @interrupt void UART2_IRQHandler(void)
{
    u8 byte;
     
    if(UART2_GetFlagStatus(UART2_FLAG_RXNE) != RESET)
    {
        UART2_ClearFlag(UART2_FLAG_RXNE);
         
        byte = UART2_ReceiveData8();
         
        RowDataInput(byte);
    }
}
 
//----------------------------------------------------------------
 
/******** 传输层 ********/
 
/*
 @Function : CRC计算
 @Input     : ptr  数据帧首地址,不包含帧头(首地址内容为长度)
 @Output   : CRC校验码
 **/
u8 CRC_Calculation(u8* pbuf)
{
    u8 len, check_code;
     
    len = pbuf[0];
    check_code = (u8)(len ^ pbuf[1] ^ pbuf[len-3] ^ pbuf[len-2]);
     
    return check_code;
}
 
/*
 @Function : 数据帧CRC校验
 @Input     : ptr  数据帧首地址
 @Output   : 0  校验失败
             1  校验成功
 **/
static u8 CRC_Check(u8 *pbuf)
{
    u8 len, check_code;
     
    len = pbuf[0];
    check_code = CRC_Calculation(pbuf);
 
    if(check_code == pbuf[len-1])
    {
        return 1;
    }
    return 0;
}
 
/*
 @Function : 数据复制
 @Input     : ptrdes
             ptrsrc
             len    复制的字节长度
 @Output   : 目的地址
 **/
static void* mymemcpy(void* pdes, void* psrc, unsigned int len)
{
    char* ptrdes = (char*)pdes;
    char* ptrsrc = (char*)psrc;
 
    if(pdes == 0 || psrc == 0)
        return pdes;
    if(ptrdes>ptrsrc?(ptrdes-ptrsrc<len):(ptrsrc-ptrdes<len))//有重叠
    {
        return pdes;
    }
    while(len--)
    {
        *ptrdes++ = *ptrsrc++;
    }
    return pdes;
}
 
/*
 @Function : 封装成帧
 @Attention: STVD 环境下: va_list 在调用va_arg()后地址至少+2,
             故输入的可变形参必须为 2字节变量
 @Input     : buffer     封装后的数据存入地址
             cmdDataLen 数据长度(不包含:包头,长度,校验码)
             ...        数据(必须为16位变量) (不包含:包头,长度,校验码)
 @Output   : 1 输入数据有误
              0 成功
 **/
u8 framePakage(u8 *buffer, const u8 cmdDataLen, ...)
{
    unsigned char i;
    unsigned char frame[FRAME_LENGTH_MAX];
    va_list ap;
     
    va_start(ap, cmdDataLen);
 
    if(cmdDataLen < FRAME_LENGTH_MIN - 1)
    {
        return 1;//输入数据错误
    }
    frame[0] = FRAME_HEAD1;
    frame[1] = FRAME_HEAD2;
 
    //长度
#if   LENGTH_METHOD == 0
    frame[2] = (unsigned char)(cmdDataLen + 2);
#elif LENGTH_METHOD == 1 || LENGTH_METHOD == 2
    frame[2] = (unsigned char)(cmdDataLen + 1);
#elif LENGTH_METHOD == 3
    frame[2] = (unsigned char)cmdDataLen;
#endif
    //数据
    for(i=0; i<cmdDataLen; i++)
    {
        frame[i+3] = (unsigned char)va_arg(ap, unsigned int);
        i = i;
    }
    va_end(ap);
     
    frame[i+3] = CRC_Calculation(frame+2);
    mymemcpy(buffer, frame, FRAME_LENGTH_MAX);
    return 0;
}
 
/*
 @Function : 输入接收到的原始数据
 @Input    : byte   接收到的1字节原始数据
 @Output   : None
 **/
static void RowDataInput(u8 byte)
{
    if(++RcvRawData.countTail >= ROW_DATA_SIZE)
    {
        RcvRawData.countTail = 0;
    }
    RcvRawData.Reg[RcvRawData.countTail] = byte;
}
 
/*
 @Function : 接收数据帧(用于扫描接收数据)
             接收到的数据存储于RcvFrameCache.Cache中
 @Input    : None
 @Output   : 接收状态
 **/
_frameRes_ DataFrame_Receive(void)
{
    static u8 buffer[FRAME_LENGTH_MAX];
    static RcvStatus_TypeDef RcvStatus;
    static u8 rec_countHead;
    static u8 cmd_offset;
    static u8 total_len;
#ifdef TIMEOUT_MECHANISMS_ENABLE
    static u16 timeout;
#endif
    u8 byte;
    _frameRes_ res = Cmd_NoCmd;
 
    if(rec_countHead != RcvRawData.countTail)//有接收到数据
    {
        if(++rec_countHead >= ROW_DATA_SIZE)
        {
            rec_countHead = 0;
        }
         
        switch(RcvStatus)
        {
            case FINDING_HEAD1 :
                byte = RcvRawData.Reg[rec_countHead];
                if(byte == (u8)(FRAME_HEAD1))
                {
                    RcvStatus = FINDING_HEAD2;
                    #ifdef TIMEOUT_MECHANISMS_ENABLE
                    timeout = 0x8000;
                    #endif
                }
                break;
            case FINDING_HEAD2 :
                byte = RcvRawData.Reg[rec_countHead];
                if(byte == (u8)(FRAME_HEAD2))
                {
                    RcvStatus = NEED_LENGTH;
                }
                else
                {
                    RcvStatus = FINDING_HEAD1;
                }
                break;
            case NEED_LENGTH :
                byte = RcvRawData.Reg[rec_countHead];
                if(byte<FRAME_LENGTH_MIN || byte>FRAME_LENGTH_MAX)
                {
                    RcvStatus = FINDING_HEAD1;
                    res = Cmd_CRC_Wrong;
                    break;
                }
                cmd_offset = 0;
                buffer[cmd_offset++] = byte;
                RcvStatus = GETTING_DATA;
                break;
            case GETTING_DATA :
                byte = RcvRawData.Reg[rec_countHead];
                buffer[cmd_offset++] = byte;
                total_len = GET_TOTAL_LENGTH(buffer[0]);
                if(cmd_offset == total_len - 1)
                {
                    RcvStatus = GETTING_CHECKSUM;
                }
                break;
            case GETTING_CHECKSUM :
                byte = RcvRawData.Reg[rec_countHead];
                buffer[cmd_offset] = byte;
                RcvStatus = FINDING_HEAD1;
                timeout = 0;
                if(CRC_Check(buffer))//CRC校验
                {
                    if(RcvFrameCache.countTail + total_len - 1 >= FRAME_CACHE_SIZE)
                    {
                        mymemcpy(&RcvFrameCache.Cache[RcvFrameCache.countTail],
                                  buffer,
                                  (int)(FRAME_CACHE_SIZE - RcvFrameCache.countTail));
                        mymemcpy(&RcvFrameCache.Cache[0],
                                  buffer + (FRAME_CACHE_SIZE - RcvFrameCache.countTail),
                                  (int)(RcvFrameCache.countTail + total_len - FRAME_CACHE_SIZE));
                        RcvFrameCache.countTail = (u8)(RcvFrameCache.countTail + total_len - FRAME_CACHE_SIZE);
                    }
                    else
                    {
                        mymemcpy(&RcvFrameCache.Cache[RcvFrameCache.countTail],
                                  buffer,
                                  total_len);
                        RcvFrameCache.countTail += total_len;
                    }
                    res = Cmd_OK;
                }
                else
                {
                    res = Cmd_CRC_Wrong;
                }
                break;
        }
    }
    #if TIMEOUT_MECHANISMS_ENABLE != 0
    else//没有接收到数据
    {
        //超时计时
        if(timeout & 0x8000)
        {
            if((++timeout & ~0x8000) >= TIME_OUT)
            {
                timeout = 0;
                RcvStatus = FINDING_HEAD1;
                res = Cmd_TimeOut;
            }
        }
    }
    #endif
    #ifdef DEBUG
    if(res == Cmd_OK)
        FrameNum.correctNum++;
    else if(res != Cmd_NoCmd)
    {
        static u8 Framecount = 0;
        FrameNum.errNum++;
        FrameNum.errbuf[Framecount++] = res;
    }
    #endif
    return res;
}
 
/*
 @Function : 获取数据帧(获取缓存中未处理的数据帧)
             接收到的数据存储于RcvFrameCache.Cache中,
 @Input    : buffer
 @Output   : 接收状态
 **/
_frameRes_ getDataFrame(u8 *buffer)
{
    #ifdef DEBUG
    u8 i;
    u8 framebuf[FRAME_LENGTH_MAX];
    #endif
    vu8 total_len;
    static u8  countHead;
    _frameRes_ fr = Cmd_NoCmd;;
    if(countHead != RcvFrameCache.countTail)
    {
        total_len = RcvFrameCache.Cache[countHead];
        total_len = GET_TOTAL_LENGTH(total_len);
        if(countHead + total_len - 1 >= FRAME_CACHE_SIZE)
        {
            mymemcpy(buffer,
                     &RcvFrameCache.Cache[countHead],
                     (int)(FRAME_CACHE_SIZE - countHead));
            mymemcpy(buffer + (FRAME_CACHE_SIZE - countHead),
                     &RcvFrameCache.Cache[0],
                     (int)(countHead + total_len - FRAME_CACHE_SIZE));
            countHead = (u8)(countHead + total_len - FRAME_CACHE_SIZE);
        }
        else
        {
            mymemcpy(buffer,
                     &RcvFrameCache.Cache[countHead],
                     total_len);
            countHead += total_len;
        }
        fr = Cmd_OK;
         
    #ifdef DEBUG
        for(i=0; i<FRAME_LENGTH_MAX; i++)
        {
            framebuf[i] = 0x00;
        }
        mymemcpy(framebuf,
                 buffer,
                 FRAME_LENGTH_MAX);
    #endif
    }
    return fr;
}


网友评论    (发表评论)


发表评论:

评论须知:

  • 1、评论每次加2分,每天上限为30;
  • 2、请文明用语,共同创建干净的技术交流环境;
  • 3、若被发现提交非法信息,评论将会被删除,并且给予扣分处理,严重者给予封号处理;
  • 4、请勿发布广告信息或其他无关评论,否则将会删除评论并扣分,严重者给予封号处理。


扫码下载

加载中,请稍后...

输入口令后可复制整站源码

加载中,请稍后...