前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[Matlab]Simulink串口接收详解2用S-Function解析数据包

[Matlab]Simulink串口接收详解2用S-Function解析数据包

作者头像
祥知道
发布2020-03-10 15:46:00
2.2K0
发布2020-03-10 15:46:00
举报
文章被收录于专栏:祥的专栏祥的专栏
  1. 文件说明及下载
  • 4.1 文件说明
  • 4.2 文件下载

1.概述

在上一个博文 [Matlab] Simulink 串口接收详解1 中,讲了一下Serial Precive模块的简单用法,但是有时候我们接收的数据是具有复杂定义的数据包。这个时候就需要自己对得到数据进行2次解析。

1.1. S-Function模块设置

在这里我用Matlab中的S-Function写解析函数,如下图中的unPackData模块,是 S-Function 模块。S-Function 函数( unPackData_Q.c )将在后面讲解。

1.2. Data Type Conversion模块设置

还是一次接收一个16字节的uint8数组,实际代表了2个double的数据。之所以加一个数据转换模块,是因为S-Function的输入是double类型的。

如果不经过转换模块,则会报错:

  • Data type mismatch. Input port 1 of ‘recCom_Union/unPackData’ expects a signal of data type ‘double’. However, it is driven by a signal of data type ‘uint8’.
  • Data type mismatch. Output port 1 of ‘recCom_Union/Serial Receive’ is a signal of data type ‘uint8’. However, it is driving a signal of data type ‘double’.

2. 效果

Qt写的发送程序,每隔100ms发送两个double数据,这两个数据按照正弦信号输出:

  • number1 = A1*sin( w1 * time + d1)
  • number2 = A2*sin( w2 * time + d2)

接收效果如下图所示:

3. S-Function源码

3.1. S-Function源码 - unPackData_Q.c

代码语言:javascript
复制
#define S_FUNCTION_NAME  unPackData_Q
#define S_FUNCTION_LEVEL 2


#include "simstruc.h"
#include "DataType.h"//收发数据类型



static void mdlInitializeSizes(SimStruct *S)
{
    /* See sfuntmpl_doc.c for more details on the macros below */

    ssSetNumSFcnParams(S, 0);  /* Number of expected parameters */
    if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
        /* Return if number of expected != number of actual parameters */
        return;
    }

    ssSetNumContStates(S, 0);
    ssSetNumDiscStates(S, 0);

    if (!ssSetNumInputPorts(S, 1)) return;//1个输入口
    ssSetInputPortWidth(S, 0, 16);//16维
    ssSetInputPortRequiredContiguous(S, 0, true); /*direct input signal access*/
    /*
     * Set direct feedthrough flag (1=yes, 0=no).
     * A port has direct feedthrough if the input is used in either
     * the mdlOutputs or mdlGetTimeOfNextVarHit functions.
     * See matlabroot/simulink/src/sfuntmpl_directfeed.txt.
     */
    ssSetInputPortDirectFeedThrough(S, 0, 1);

    if (!ssSetNumOutputPorts(S, 1)) return;//1个输出口
    ssSetOutputPortWidth(S, 0, 2);//宽度为2


    ssSetNumSampleTimes(S, 1);
    ssSetNumRWork(S, 0);
    ssSetNumIWork(S, 0);
    ssSetNumPWork(S, 0);
    ssSetNumModes(S, 0);
    ssSetNumNonsampledZCs(S, 0);

    /* Specify the sim state compliance to be same as a built-in block */
    ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);

    ssSetOptions(S, 0);
}



/* Function: mdlInitializeSampleTimes =========================================
 * Abstract:
 *    This function is used to specify the sample time(s) for your
 *    S-function. You must register the same number of sample times as
 *    specified in ssSetNumSampleTimes.
 */
static void mdlInitializeSampleTimes(SimStruct *S)
{
    ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
    ssSetOffsetTime(S, 0, 0.0);

}



#define MDL_INITIALIZE_CONDITIONS   /* Change to #undef to remove function */
#if defined(MDL_INITIALIZE_CONDITIONS)
  /* Function: mdlInitializeConditions ========================================
   * Abstract:
   *    In this function, you should initialize the continuous and discrete
   *    states for your S-function block.  The initial states are placed
   *    in the state vector, ssGetContStates(S) or ssGetRealDiscStates(S).
   *    You can also perform any other initialization activities that your
   *    S-function may require. Note, this routine will be called at the
   *    start of simulation and if it is present in an enabled subsystem
   *    configured to reset states, it will be call when the enabled subsystem
   *    restarts execution to reset the states.
   */
  static void mdlInitializeConditions(SimStruct *S)
  {
  }
#endif /* MDL_INITIALIZE_CONDITIONS */



#define MDL_START  /* Change to #undef to remove function */
#if defined(MDL_START) 
  /* Function: mdlStart =======================================================
   * Abstract:
   *    This function is called once at start of model execution. If you
   *    have states that should be initialized once, this is the place
   *    to do it.
   */
  static void mdlStart(SimStruct *S)
  {
  }
#endif /*  MDL_START */



/* Function: mdlOutputs =======================================================
 * Abstract:
 *    In this function, you compute the outputs of your S-function
 *    block.
 */
static void mdlOutputs(SimStruct *S, int_T tid)
{//解析核心代码
    int i;
    Un_sendData revData;
    const real_T *u = (const real_T*) ssGetInputPortSignal(S,0);
    real_T       *y = ssGetOutputPortSignal(S,0);

    //Step1.赋值解析[用char的数组buf进行赋值]
    for(i=0;i<16;i++)
    {
        revData.buf[i] = (uint8)(u[i]);
    }

    //Step2.输出[用double数组数据number进行解析]
    y[0] = revData.number[0];
    y[1] = revData.number[1];
}



#define MDL_UPDATE  /* Change to #undef to remove function */
#if defined(MDL_UPDATE)
  /* Function: mdlUpdate ======================================================
   * Abstract:
   *    This function is called once for every major integration time step.
   *    Discrete states are typically updated here, but this function is useful
   *    for performing any tasks that should only take place once per
   *    integration step.
   */
  static void mdlUpdate(SimStruct *S, int_T tid)
  {
  }
#endif /* MDL_UPDATE */



#define MDL_DERIVATIVES  /* Change to #undef to remove function */
#if defined(MDL_DERIVATIVES)
  /* Function: mdlDerivatives =================================================
   * Abstract:
   *    In this function, you compute the S-function block's derivatives.
   *    The derivatives are placed in the derivative vector, ssGetdX(S).
   */
  static void mdlDerivatives(SimStruct *S)
  {
  }
#endif /* MDL_DERIVATIVES */



/* Function: mdlTerminate =====================================================
 * Abstract:
 *    In this function, you should perform any actions that are necessary
 *    at the termination of a simulation.  For example, if memory was
 *    allocated in mdlStart, this is the place to free it.
 */
static void mdlTerminate(SimStruct *S)
{
}


/*======================================================*
 * See sfuntmpl_doc.c for the optional S-function methods *
 *======================================================*/

/*=============================*
 * Required S-function trailer *
 *=============================*/

#ifdef  MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-file? */
#include "simulink.c"      /* MEX-file interface mechanism */
#else
#include "cg_sfun.h"       /* Code generation registration function */
#endif

3.2. 需要的头文件 - DataType.h

代码语言:javascript
复制
#ifndef _Q_DATA_TYPE_H_
#define _Q_DATA_TYPE_H_

//signed
typedef signed char        int8;
typedef short              int16;
typedef int                int32;
typedef long long          int64;
//unsigned
typedef unsigned char      uint8;
typedef unsigned short     uint16;
typedef unsigned int       uint32;
typedef unsigned long long uint64;



typedef union //
{
    char           buf[16];//用于接收
    double         number[2];//用于处理
}Un_sendData;

#endif

4. 文件说明及下载

4.1 文件说明

  • QtSerialSend 文件夹: Qt写的串口发送程序;
  • recCom.mdl:Matlab串口接收程序;
  • recCom_Union.mdl:Matlab串口接收程序,用S-Function进行解析;
  • DataType.h : 定义发送和接收的数据类型,被unPackData_Q.c调用;
  • unPackData_Q.c:用C语言写的S-Function函数,编译后变成unPackData_Q.mexw64,被recCom_Union.mdl调用;
  • unPackData_Q.mexw64:由unPackData_Q.c编译而成,被recCom_Union.mdl调用。

4.2 文件下载

稍后我会上传这些资料到下载区:

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.概述
    • 1.1. S-Function模块设置
      • 1.2. Data Type Conversion模块设置
      • 2. 效果
      • 3. S-Function源码
        • 3.1. S-Function源码 - unPackData_Q.c
          • 3.2. 需要的头文件 - DataType.h
          • 4. 文件说明及下载
            • 4.1 文件说明
              • 4.2 文件下载
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档