[C] 数据帧接收 →→→→→进入此内容的聊天室

来自 , 2020-02-19, 写在 C, 查看 136 次.
URL http://www.code666.cn/view/cbf8710b
  1. /**********************************************************************************************************
  2. 建立头文件"transport.h"
  3. **********************************************************************************************************/
  4. #ifndef __TRANSPORT_H
  5. #define __TRANSPORT_H
  6.  
  7. #include "stm8_macro.h"
  8.  
  9. /*********************************************************
  10.  接收数据帧:
  11.  1.结构  : 2字节帧头 + 1字节长度信息 + 数据 + 1字节校验码
  12.  
  13.  2.移植  : 1).IC层,数据的接收中断与发送函数。
  14.            2).CRC_Calculation(u8* ),校验码计算
  15.            
  16.  3.OUTPUT: 1).调用DataFrame_Receive()将接收到的原始数据经过处理、CRC校验,
  17.               将得到的有效数据帧存放于RcvFrameCache.Cache[]中,数据
  18.               不包含帧头。
  19.            2).接收数据超时:调用DataFrame_Receive()接收一帧数据的过程中,
  20.               超过(TIME_OUT)次扫描未接收到数据则输出超时Cmd_TimeOut。
  21.            3).调用getDataFrame(u8* buffer)从RcvFrameCache.Cache[]中获取数据帧
  22. *********************************************************/
  23.  
  24. //////////////////////// 参数配置 ////////////////////////
  25.  
  26. // 长度信息计算方法:
  27. // 0: 长度 = 长度信息本身字节数 + 数据 + 校验码
  28. // 1: 长度 = 长度信息本身字节数 + 数据
  29. // 2: 长度 = 数据 + 校验码
  30. // 3: 长度 = 数据
  31. #define LENGTH_METHOD              (0L)
  32.  
  33. #define FRAME_HEAD1                (0XFFul)//帧头1
  34. #define FRAME_HEAD2                (0xF0ul)//帧头2
  35.  
  36. #define FRAME_LENGTH_MIN           (5ul)   //一帧数据的最小长度
  37. #define FRAME_LENGTH_MAX           (20ul)  //一帧数据的最大长度
  38.  
  39. #define ROW_DATA_SIZE              (100ul) // 接收到的原始数据缓存大小
  40. #define FRAME_CACHE_SIZE           (200ul) // 接收到的帧数据缓存大小
  41.  
  42. #define TIMEOUT_MECHANISMS_ENABLE  1       //超时处理机制  0:失能  1:使能
  43.  
  44. #if TIMEOUT_MECHANISMS_ENABLE != 0
  45.         #define TIME_OUT               (500ul) //接收一帧数据超时的时间阈值,
  46.                                                                            //单位:调用Command_Receive()函数的周期
  47. #endif
  48.  
  49. //////////////////////////////////////////////////////////
  50.  
  51. typedef enum {
  52.   Cmd_NoCmd = 0, //未收到完整数据包
  53.   Cmd_OK,        //接收成功
  54.   Cmd_TimeOut,   //接收超时
  55.   Cmd_LEN_Wrong, //接收到的数据包错误(长度不在范围内)
  56.   Cmd_CRC_Wrong  //CRC校验错误
  57. } _frameRes_;
  58.  
  59.  
  60. void Uart_Init(u32 baudrate);
  61. void UartSendData(u8 *ptr, u8 len);
  62. u8   UartSendStr(u8 *str);
  63.  
  64. u8 CRC_Calculation(u8* pbuf);
  65. _frameRes_ DataFrame_Receive(void);
  66. _frameRes_ getDataFrame(u8 *buffer);
  67. u8 framePakage(u8 *buffer, const u8 cmdDataLen, ...);
  68.  
  69. #endif /*__TRANSPORT_H*/
  70.  
  71.  
  72. /**********************************************************************************************************
  73. 建立源文件"transport.c"
  74. ***********************************************************************************************************/
  75.  
  76. #include "transport.h"
  77. #include "stdarg.h"
  78. #include "stm8s.h"
  79.  
  80.  
  81.  
  82. //从接收到的数据帧中获取 总长度 = 长度 + 数据 + 校验码
  83. //len : 长度信息
  84. #if   LENGTH_METHOD == 0
  85.         #define GET_TOTAL_LENGTH(len)  (len)
  86. #elif LENGTH_METHOD == 1
  87.         #define GET_TOTAL_LENGTH(len)  (len+1)
  88. #elif LENGTH_METHOD == 2
  89.         #define GET_TOTAL_LENGTH(len)  (len+1)
  90. #elif LENGTH_METHOD == 3
  91.         #define GET_TOTAL_LENGTH(len)  (len+2)
  92. #else
  93.         #error "wrong define LENGTH_METHOD !"
  94. #endif
  95.  
  96.  
  97. typedef enum{
  98.   FINDING_HEAD1 = 0,
  99.   FINDING_HEAD2,
  100.   NEED_LENGTH,
  101.   GETTING_DATA,
  102.   GETTING_CHECKSUM
  103. } RcvStatus_TypeDef;
  104.  
  105. volatile struct{
  106.   u8 Reg[ROW_DATA_SIZE];     //串口接收到的原始数据缓存
  107.   u8 countTail;              //串口接收计数
  108. } RcvRawData;                //接收到的原始数据
  109.  
  110. struct {
  111.   u8  Cache[FRAME_CACHE_SIZE]; //接收有效指令缓存器,不包含帧头
  112.   u8  countTail;               //
  113. } RcvFrameCache;               //接收到的帧数据
  114.  
  115. //#define DEBUG
  116. #ifdef DEBUG
  117. struct {
  118.   u16 correctNum;
  119.   u8  errNum;
  120.   u8  errbuf[256];
  121. } FrameNum;
  122. #endif
  123.  
  124. static void RowDataInput(u8 byte);
  125.  
  126. ////////////////////////////////////////////////////////////
  127.  
  128. //----------------------------------------------------------------
  129.  
  130. /******** IC层 ********/
  131.  
  132. /*
  133.  @Function : UART初始化
  134.              8bit数据位,1位停止位,无校验位,允许接收和发送
  135.  @Input    : 波特率
  136.  @Output   : None
  137.  **/
  138.  
  139. void Uart_Init(u32 baudrate)
  140. {
  141.         UART2_Cmd(DISABLE);
  142.  
  143.         UART2_DeInit();  //恢复默认值
  144.        
  145.     UART2_Init(baudrate,
  146.                UART2_WORDLENGTH_8D,            // 8bit数据位
  147.                UART2_STOPBITS_1,               // 1bit停止位
  148.                UART2_PARITY_NO,                // 无校验位
  149.                UART2_SYNCMODE_CLOCK_DISABLE,   // 禁用同步模式
  150.                UART2_MODE_TXRX_ENABLE);        // 发送、接收使能
  151.  
  152.         UART2_ITConfig(UART2_IT_RXNE_OR, ENABLE);  // 开接收中断
  153.        
  154.         UART2_Cmd(ENABLE);                         // 使能UART2
  155. }
  156.  
  157. /*
  158.  @Function : 发送数据
  159.  @Input     : ptr   数据首地址
  160.              len   要发送的长度
  161.  @Output   : None
  162.  **/
  163. void UartSendData(u8 *ptr, u8 len)
  164. {
  165.     while(len--)
  166.     {
  167.                 while(UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET);
  168.                 UART2_SendData8(*ptr++);
  169.     }
  170. }
  171.  
  172. /*
  173.  @Function : 发送数据
  174.  @Input     : ptr   数据首地址
  175.  @Output   : 发送的字节长度
  176.  **/
  177. u8 UartSendStr(u8 *str)
  178. {
  179.         u8 i;
  180.  
  181.         for(i=0; *str != 0x00; i++)
  182.         {
  183.                 while(UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET);
  184.                 UART2_SendData8(*str++);
  185.         }
  186.         return i;
  187. }
  188.  
  189. /*
  190.  @Function : UART2中断服务函数
  191.  @Input     : None
  192.  @Output   : None
  193.  **/
  194. @far @interrupt void UART2_IRQHandler(void)
  195. {
  196.         u8 byte;
  197.        
  198.         if(UART2_GetFlagStatus(UART2_FLAG_RXNE) != RESET)
  199.         {
  200.                 UART2_ClearFlag(UART2_FLAG_RXNE);
  201.                
  202.                 byte = UART2_ReceiveData8();
  203.                
  204.                 RowDataInput(byte);
  205.         }
  206. }
  207.  
  208. //----------------------------------------------------------------
  209.  
  210. /******** 传输层 ********/
  211.  
  212. /*
  213.  @Function : CRC计算
  214.  @Input     : ptr  数据帧首地址,不包含帧头(首地址内容为长度)
  215.  @Output   : CRC校验码
  216.  **/
  217. u8 CRC_Calculation(u8* pbuf)
  218. {
  219.         u8 len, check_code;
  220.        
  221.         len = pbuf[0];
  222.         check_code = (u8)(len ^ pbuf[1] ^ pbuf[len-3] ^ pbuf[len-2]);
  223.        
  224.         return check_code;
  225. }
  226.  
  227. /*
  228.  @Function : 数据帧CRC校验
  229.  @Input     : ptr  数据帧首地址
  230.  @Output   : 0  校验失败
  231.              1  校验成功
  232.  **/
  233. static u8 CRC_Check(u8 *pbuf)
  234. {
  235.         u8 len, check_code;
  236.        
  237.         len = pbuf[0];
  238.         check_code = CRC_Calculation(pbuf);
  239.  
  240.         if(check_code == pbuf[len-1])
  241.         {
  242.                 return 1;
  243.         }
  244.         return 0;
  245. }
  246.  
  247. /*
  248.  @Function : 数据复制
  249.  @Input     : ptrdes
  250.              ptrsrc
  251.              len    复制的字节长度
  252.  @Output   : 目的地址
  253.  **/
  254. static void* mymemcpy(void* pdes, void* psrc, unsigned int len)
  255. {
  256.         char* ptrdes = (char*)pdes;
  257.         char* ptrsrc = (char*)psrc;
  258.  
  259.         if(pdes == 0 || psrc == 0)
  260.                 return pdes;
  261.         if(ptrdes>ptrsrc?(ptrdes-ptrsrc<len):(ptrsrc-ptrdes<len))//有重叠
  262.         {
  263.                 return pdes;
  264.         }
  265.     while(len--)
  266.     {
  267.         *ptrdes++ = *ptrsrc++;
  268.     }
  269.         return pdes;
  270. }
  271.  
  272. /*
  273.  @Function : 封装成帧
  274.  @Attention: STVD 环境下: va_list 在调用va_arg()后地址至少+2,
  275.              故输入的可变形参必须为 2字节变量
  276.  @Input     : buffer     封装后的数据存入地址
  277.              cmdDataLen 数据长度(不包含:包头,长度,校验码)
  278.              ...        数据(必须为16位变量) (不包含:包头,长度,校验码)
  279.  @Output   : 1 输入数据有误
  280.                           0 成功
  281.  **/
  282. u8 framePakage(u8 *buffer, const u8 cmdDataLen, ...)
  283. {
  284.         unsigned char i;
  285.         unsigned char frame[FRAME_LENGTH_MAX];
  286.         va_list ap;
  287.        
  288.         va_start(ap, cmdDataLen);
  289.  
  290.         if(cmdDataLen < FRAME_LENGTH_MIN - 1)
  291.         {
  292.                 return 1;//输入数据错误
  293.         }
  294.         frame[0] = FRAME_HEAD1;
  295.         frame[1] = FRAME_HEAD2;
  296.  
  297.         //长度
  298. #if   LENGTH_METHOD == 0
  299.         frame[2] = (unsigned char)(cmdDataLen + 2);
  300. #elif LENGTH_METHOD == 1 || LENGTH_METHOD == 2
  301.         frame[2] = (unsigned char)(cmdDataLen + 1);
  302. #elif LENGTH_METHOD == 3
  303.         frame[2] = (unsigned char)cmdDataLen;
  304. #endif
  305.         //数据
  306.         for(i=0; i<cmdDataLen; i++)
  307.         {
  308.                 frame[i+3] = (unsigned char)va_arg(ap, unsigned int);
  309.                 i = i;
  310.         }
  311.         va_end(ap);
  312.        
  313.         frame[i+3] = CRC_Calculation(frame+2);
  314.         mymemcpy(buffer, frame, FRAME_LENGTH_MAX);
  315.         return 0;
  316. }
  317.  
  318. /*
  319.  @Function : 输入接收到的原始数据
  320.  @Input    : byte   接收到的1字节原始数据
  321.  @Output   : None
  322.  **/
  323. static void RowDataInput(u8 byte)
  324. {
  325.         if(++RcvRawData.countTail >= ROW_DATA_SIZE)
  326.         {
  327.                 RcvRawData.countTail = 0;
  328.         }
  329.         RcvRawData.Reg[RcvRawData.countTail] = byte;
  330. }
  331.  
  332. /*
  333.  @Function : 接收数据帧(用于扫描接收数据)
  334.              接收到的数据存储于RcvFrameCache.Cache中
  335.  @Input    : None
  336.  @Output   : 接收状态
  337.  **/
  338. _frameRes_ DataFrame_Receive(void)
  339. {
  340.         static u8 buffer[FRAME_LENGTH_MAX];
  341.         static RcvStatus_TypeDef RcvStatus;
  342.     static u8 rec_countHead;
  343.     static u8 cmd_offset;
  344.         static u8 total_len;
  345. #ifdef TIMEOUT_MECHANISMS_ENABLE
  346.     static u16 timeout;
  347. #endif
  348.     u8 byte;
  349.         _frameRes_ res = Cmd_NoCmd;
  350.  
  351.     if(rec_countHead != RcvRawData.countTail)//有接收到数据
  352.     {
  353.                 if(++rec_countHead >= ROW_DATA_SIZE)
  354.                 {
  355.                         rec_countHead = 0;
  356.                 }
  357.                
  358.         switch(RcvStatus)
  359.         {
  360.             case FINDING_HEAD1 :
  361.                                 byte = RcvRawData.Reg[rec_countHead];
  362.                 if(byte == (u8)(FRAME_HEAD1))
  363.                 {
  364.                     RcvStatus = FINDING_HEAD2;
  365.                                         #ifdef TIMEOUT_MECHANISMS_ENABLE
  366.                                         timeout = 0x8000;
  367.                                         #endif
  368.                 }
  369.                 break;
  370.             case FINDING_HEAD2 :
  371.                                 byte = RcvRawData.Reg[rec_countHead];
  372.                 if(byte == (u8)(FRAME_HEAD2))
  373.                 {
  374.                     RcvStatus = NEED_LENGTH;
  375.                 }
  376.                 else
  377.                 {
  378.                     RcvStatus = FINDING_HEAD1;
  379.                 }
  380.                 break;
  381.             case NEED_LENGTH :
  382.                                 byte = RcvRawData.Reg[rec_countHead];
  383.                 if(byte<FRAME_LENGTH_MIN || byte>FRAME_LENGTH_MAX)
  384.                 {
  385.                     RcvStatus = FINDING_HEAD1;
  386.                     res = Cmd_CRC_Wrong;
  387.                     break;
  388.                 }
  389.                 cmd_offset = 0;
  390.                                 buffer[cmd_offset++] = byte;
  391.                 RcvStatus = GETTING_DATA;
  392.                 break;
  393.             case GETTING_DATA :
  394.                                 byte = RcvRawData.Reg[rec_countHead];
  395.                                 buffer[cmd_offset++] = byte;
  396.                                 total_len = GET_TOTAL_LENGTH(buffer[0]);
  397.                                 if(cmd_offset == total_len - 1)
  398.                                 {
  399.                                         RcvStatus = GETTING_CHECKSUM;
  400.                                 }
  401.                 break;
  402.                         case GETTING_CHECKSUM :
  403.                                 byte = RcvRawData.Reg[rec_countHead];
  404.                                 buffer[cmd_offset] = byte;
  405.                                 RcvStatus = FINDING_HEAD1;
  406.                                 timeout = 0;
  407.                                 if(CRC_Check(buffer))//CRC校验
  408.                                 {
  409.                                         if(RcvFrameCache.countTail + total_len - 1 >= FRAME_CACHE_SIZE)
  410.                                         {
  411.                                                 mymemcpy(&RcvFrameCache.Cache[RcvFrameCache.countTail],
  412.                                                                   buffer,
  413.                                                                   (int)(FRAME_CACHE_SIZE - RcvFrameCache.countTail));
  414.                                                 mymemcpy(&RcvFrameCache.Cache[0],
  415.                                                                   buffer + (FRAME_CACHE_SIZE - RcvFrameCache.countTail),
  416.                                                                   (int)(RcvFrameCache.countTail + total_len - FRAME_CACHE_SIZE));
  417.                                                 RcvFrameCache.countTail = (u8)(RcvFrameCache.countTail + total_len - FRAME_CACHE_SIZE);
  418.                                         }
  419.                                         else
  420.                                         {
  421.                                                 mymemcpy(&RcvFrameCache.Cache[RcvFrameCache.countTail],
  422.                                                                   buffer,
  423.                                                                   total_len);
  424.                                                 RcvFrameCache.countTail += total_len;
  425.                                         }
  426.                                         res = Cmd_OK;
  427.                                 }
  428.                                 else
  429.                                 {
  430.                                         res = Cmd_CRC_Wrong;
  431.                                 }
  432.                                 break;
  433.         }
  434.     }
  435.         #if TIMEOUT_MECHANISMS_ENABLE != 0
  436.     else//没有接收到数据
  437.     {
  438.                 //超时计时
  439.                 if(timeout & 0x8000)
  440.                 {
  441.                         if((++timeout & ~0x8000) >= TIME_OUT)
  442.                         {
  443.                                 timeout = 0;
  444.                                 RcvStatus = FINDING_HEAD1;
  445.                                 res = Cmd_TimeOut;
  446.                         }
  447.                 }
  448.     }
  449.         #endif
  450.         #ifdef DEBUG
  451.         if(res == Cmd_OK)
  452.                 FrameNum.correctNum++;
  453.         else if(res != Cmd_NoCmd)
  454.         {
  455.                 static u8 Framecount = 0;
  456.                 FrameNum.errNum++;
  457.                 FrameNum.errbuf[Framecount++] = res;
  458.         }
  459.         #endif
  460.     return res;
  461. }
  462.  
  463. /*
  464.  @Function : 获取数据帧(获取缓存中未处理的数据帧)
  465.              接收到的数据存储于RcvFrameCache.Cache中,
  466.  @Input    : buffer
  467.  @Output   : 接收状态
  468.  **/
  469. _frameRes_ getDataFrame(u8 *buffer)
  470. {
  471.         #ifdef DEBUG
  472.         u8 i;
  473.         u8 framebuf[FRAME_LENGTH_MAX];
  474.         #endif
  475.         vu8 total_len;
  476.         static u8  countHead;
  477.         _frameRes_ fr = Cmd_NoCmd;;
  478.     if(countHead != RcvFrameCache.countTail)
  479.     {
  480.                 total_len = RcvFrameCache.Cache[countHead];
  481.                 total_len = GET_TOTAL_LENGTH(total_len);
  482.                 if(countHead + total_len - 1 >= FRAME_CACHE_SIZE)
  483.                 {
  484.                         mymemcpy(buffer,
  485.                                          &RcvFrameCache.Cache[countHead],
  486.                                          (int)(FRAME_CACHE_SIZE - countHead));
  487.                         mymemcpy(buffer + (FRAME_CACHE_SIZE - countHead),
  488.                                          &RcvFrameCache.Cache[0],
  489.                                          (int)(countHead + total_len - FRAME_CACHE_SIZE));
  490.                         countHead = (u8)(countHead + total_len - FRAME_CACHE_SIZE);
  491.                 }
  492.                 else
  493.                 {
  494.                         mymemcpy(buffer,
  495.                                          &RcvFrameCache.Cache[countHead],
  496.                                          total_len);
  497.                         countHead += total_len;
  498.                 }
  499.                 fr = Cmd_OK;
  500.                
  501.         #ifdef DEBUG
  502.                 for(i=0; i<FRAME_LENGTH_MAX; i++)
  503.                 {
  504.                         framebuf[i] = 0x00;
  505.                 }
  506.                 mymemcpy(framebuf,
  507.                              buffer,
  508.                              FRAME_LENGTH_MAX);
  509.         #endif
  510.     }
  511.         return fr;
  512. }
  513.  
  514.  
  515.  

回复 "数据帧接收"

这儿你可以回复上面这条便签

captcha