声振论坛

 找回密码
 我要加入

QQ登录

只需一步,快速开始

查看: 2019|回复: 1

[转帖]解决在SIMULINK中不提供驱动模块的硬件的驱动问题(例程)

[复制链接]
发表于 2006-4-13 16:34 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?我要加入

x
<P>这是一个用C语言S函数在SIMULINK中写硬件驱动的例子,比较有参考意义<BR><BR>#define     S_FUNCTION_LEVEL    2<BR>#undef      S_FUNCTION_NAME<BR>#define     S_FUNCTION_NAME     admultiq3</P>
<P>#include    &lt;stddef.h&gt;<BR>#include    &lt;stdlib.h&gt;</P>
<P>#include    "simstruc.h"</P>
<P>#ifdef      MATLAB_MEX_FILE<BR>#include    "mex.h"<BR>#else<BR>#include    &lt;windows.h&gt;<BR>#include    "io_xpcimport.h"<BR>#endif</P>
<P>/* Input Arguments */</P>
<P>#define NUM_PARAMS             (3)<BR>#define BASE_ADDRESS_ARG       (ssGetSFcnParam(S,0))<BR>#define CHANNEL_ARG            (ssGetSFcnParam(S,1))<BR>#define SAMPLE_TIME_PARAM      (ssGetSFcnParam(S,2))</P>
<P><BR>/* Convert S Function Parameters to Variables of Unsigned Integer Type */</P>
<P>#define BASE                   ((uint_T) mxGetPr(BASE_ADDRESS_ARG)[0])<BR>#define NUM_CHANNEL            ((uint_T) mxGetNumberOfElements(CHANNEL_ARG)[0])<BR>#define SAMPLE_TIME            ((real_T) mxGetPr(SAMPLE_TIME_PARAM)[0])<BR>#define SAMPLE_OFFSET          ((real_T) mxGetPr(SAMPLE_TIME_PARAM)[1])</P>
<P>/* Definition of Quanser Register Adresses for AD conversion */</P>
<P>#define AD_CS           (BASE + 0x04)   /* a write to this address initiates conversion, provided the CONTROL REGISTER has been set up properly */<BR>#define AD_DATA         (BASE + 0x04)   /* a double read from this 8 bit address first yields the high then the low 8 bits of the AD conversion */<BR>#define CONTROL_REG     (BASE + 0x06)   /* the address of the CONTROL REGISTER */<BR>#define STATUS_REG      (BASE + 0x06)   /* the address of the CONTROL REGISTER (or better STATUS REGISTER in case of reading) */</P>
<P>/* Definition of 16 bit CONTROL REGISTER values for the Quanser card */</P>
<P>#define AD_SH           0x200       /* (S/H) = disable sample and hold on the A/D (keep this 1 all the time) */<BR>#define AD_AUTOCAL      0x100       /* (CAL) = enable autocalibartion on the A/D */<BR>#define AD_AUTOZ        0x80        /* (AZ)  = enable auto Zero on the A/D */<BR>#define AD_MUX_EN       0x40        /* (MX)  = enable the 8 channel multiplexer */<BR>#define AD_CLOCK_4M     0x400       /* (CLK) = choose clock frequency of the A/D, (1 = 4MHz, 0 = 2 MHz) */<BR>#define CONTROL_MUST    (AD_SH | AD_CLOCK_4M)  /* bit wise OR, so we keep both S/H and CLK high all the time */</P>
<P>/* Definition of msg string in case we need to report errors */</P>
<P>static char_T msg[256];</P>
<P><BR>/*====================*<BR> * S-function methods *<BR> *====================*/</P>
<P>static void mdlCheckParameters(SimStruct *S)<BR>{<BR>}</P>
<P>static void mdlInitializeSizes(SimStruct *S)<BR>{<BR>    uint_T i;</P>
<P>#ifndef MATLAB_MEX_FILE<BR>#include "io_xpcimport.c"<BR>#endif</P>
<P><BR>    ssSetNumSFcnParams(S, NUM_PARAMS);<BR>    if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) {<BR>        mdlCheckParameters(S);<BR>        if (ssGetErrorStatus(S) != NULL) {<BR>            return;<BR>        }<BR>    } else {<BR>        return; /* Parameter mismatch will be reported by Simulink */<BR>    }</P>
<P>    ssSetNumContStates(S, 0);<BR>    ssSetNumDiscStates(S, 0);</P>

<P>    if (!ssSetNumInputPorts(S, 0)) return;</P>
<P>    if (!ssSetNumOutputPorts(S, mxGetNumberOfElements(CHANNEL_ARG))) return;</P>
<P>    for (i=0;i&lt;mxGetNumberOfElements(CHANNEL_ARG);i++) {<BR>        ssSetOutputPortWidth(S, i, 1);<BR>    }</P>
<P>    ssSetNumSampleTimes(S, 1);</P>
<P>    ssSetNumModes(S, 0);<BR>    ssSetNumNonsampledZCs(S, 0);</P>
<P>    ssSetSFcnParamNotTunable(S,0);<BR>    ssSetSFcnParamNotTunable(S,1);<BR>    ssSetSFcnParamNotTunable(S,2);</P>
<P>    ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE | SS_OPTION_PLACE_ASAP);</P>
<P>}</P>

<P>static void mdlInitializeSampleTimes(SimStruct *S)<BR>{<BR>    ssSetSampleTime(S, 0, SAMPLE_TIME);<BR>    ssSetOffsetTime(S, 0, SAMPLE_OFFSET);<BR>}</P>

<P>#define MDL_START<BR>static void mdlStart(SimStruct *S)<BR>{</P>
<P>#ifndef MATLAB_MEX_FILE</P>
<P><BR>    uint_T i, channel, control_word, w, maxcnt;</P>
<P>    /* Do a calibration */</P>
<P>    rl32eOutpW(CONTROL_REG, (AD_AUTOCAL | CONTROL_MUST));  /* write 1 to CAL, S/H and CLK of CONTROL REGISTER */<BR>    rl32eOutpW(CONTROL_REG, (CONTROL_MUST));               /* write 1 to S/H and CLK of CONTROL REGISTER */</P>
<P>    /* Wait till EOC (End of Conversion = 3rd bit on STATUS REGISTER) goes high */</P>
<P>    w=0;<BR>    maxcnt=0x10000;<BR>    while (((rl32eInpW(STATUS_REG) &amp;0x08) == 0x00 ) &amp;&amp; (w &lt; maxcnt)) w++;<BR>    if (w==0x10000) {           /* if no EOC was detected after all these loops, report an error */<BR>        sprintf(msg,"%s (0x%x): AD calibration failed", "MultiQ3 ASI", BASE);<BR>        ssSetErrorStatus(S,msg);<BR>        return;<BR>    }</P>
<P><BR>#endif</P>
<P>}</P>
<P>static void mdlOutputs(SimStruct *S, int_T tid)<BR>{</P>
<P>#ifndef MATLAB_MEX_FILE</P>
<P>    uint_T i, channel, control_word, hb, lb;<BR>    real_T *y;<BR>    int_T int_data;</P>
<P>    for (i=0;i&lt;mxGetNumberOfElements(CHANNEL_ARG);i++) {<BR>        channel=(uint_T)mxGetPr(CHANNEL_ARG)-1;</P>
<P>        /* enable the multiplexer and select channel */<BR>        /* channel selection is done with shift left 3 operator */<BR>        /* to write the A0 (4th), A1 (5th) and A2 (6th) bits of the CONTROL REGISTER */</P>
<P>        control_word = CONTROL_MUST | AD_MUX_EN | (channel&lt;&lt;3);<BR>        rl32eOutpW(CONTROL_REG, control_word);</P>
<P>        /* wait till EOC (End of Conversion = 3rd bit on STATUS REGISTER) goes high */</P>
<P>        while( ( rl32eInpW(STATUS_REG) &amp;0x08) == 0x00 );</P>
<P>        /* do an actual conversion - any write to the AD_CS register will start the conversion */</P>
<P>        rl32eOutpW(AD_CS, 0);</P>
<P>        /* wait until data ready by observing the EOC_I = 4th bit on the STATUS REGISTER goes high */<BR>        /* in the mean time, select the output in the Simulink model */</P>
<P>        y=ssGetOutputPortSignal(S,i);</P>
<P>        while ((rl32eInpW(STATUS_REG) &amp; 0x10) == 0x00);</P>
<P>        /* Get the data */</P>
<P>        hb = rl32eInpW(AD_DATA)&amp;0xFF; /* the first read is the high byte */<BR>        lb = rl32eInpW(AD_DATA)&amp;0xFF; /* the second read is the low byte */</P>
<P>        /* Reset the CONTROl REGISTER */<BR>        /* this is not really necessary and makes things go faster */</P>
<P>        /* rl32eOutpW(CONTROL_REG, CONTROL_MUST); */</P>
<P>        /* compute the actual value of the measured signal */<BR>        /* using the fixed range of -5/+5 Volts using 12 bits + 1 SGN bit */</P>
<P>        int_data = (hb&lt;&lt;8)|(lb);<BR>        if (hb&amp;0xF0)<BR>            /* the 4 SGN bits on the high bit (hb) are 1, so the signal is negative */<BR>            y[0]=5.0*(int_data-0xF000)/4095.0-5.0;<BR>        else<BR>            /* signal is positive */<BR>            y[0]=5.0*(int_data)/4095.0;</P>
<P>    }</P>
<P>#endif</P>
<P>}</P>
<P>static void mdlTerminate(SimStruct *S)<BR>{<BR>}</P>
<P><BR>#ifdef MATLAB_MEX_FILE  /* Is this file being compiled as a MEX-file? */<BR>#include "simulink.c"   /* Mex glue */<BR>#else<BR>#include "cg_sfun.h"    /* Code generation glue */<BR>#endif</P>
回复
分享到:

使用道具 举报

发表于 2006-5-25 19:31 | 显示全部楼层
不知道楼主还在吗?<BR>想请教下: rl32eInpW  rl32eOutpW 这两个函数如何调用的<BR>一直没弄清楚如何在S函数中完成对板卡的端口的操作,象input能用吗?<BR>这个例子MEX完后 MATLAB找不到rl32eInpW的定义
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

QQ|小黑屋|Archiver|手机版|联系我们|声振论坛

GMT+8, 2024-11-16 14:21 , Processed in 0.053233 second(s), 17 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表