[转帖]解决在SIMULINK中不提供驱动模块的硬件的驱动问题(例程)
<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 <stddef.h><BR>#include <stdlib.h></P>
<P>#include "simstruc.h"</P>
<P>#ifdef MATLAB_MEX_FILE<BR>#include "mex.h"<BR>#else<BR>#include <windows.h><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))<BR>#define NUM_CHANNEL ((uint_T) mxGetNumberOfElements(CHANNEL_ARG))<BR>#define SAMPLE_TIME ((real_T) mxGetPr(SAMPLE_TIME_PARAM))<BR>#define SAMPLE_OFFSET ((real_T) mxGetPr(SAMPLE_TIME_PARAM))</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;</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<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) &0x08) == 0x00 ) && (w < 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<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<<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) &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) & 0x10) == 0x00);</P>
<P> /* Get the data */</P>
<P> hb = rl32eInpW(AD_DATA)&0xFF; /* the first read is the high byte */<BR> lb = rl32eInpW(AD_DATA)&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<<8)|(lb);<BR> if (hb&0xF0)<BR> /* the 4 SGN bits on the high bit (hb) are 1, so the signal is negative */<BR> y=5.0*(int_data-0xF000)/4095.0-5.0;<BR> else<BR> /* signal is positive */<BR> y=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>
不知道楼主还在吗?<BR>想请教下: rl32eInpWrl32eOutpW 这两个函数如何调用的<BR>一直没弄清楚如何在S函数中完成对板卡的端口的操作,象input能用吗?<BR>这个例子MEX完后 MATLAB找不到rl32eInpW的定义
页:
[1]