proteus元件制作步骤及方法.docx
一、Proteus VSM仿真模型简介在使用Proteus仿真单片机系统的过程中,经常找不到所需的元件,这就需要自己编写。 Proteus VSM的一个主要特色是使用基于DLL组件模型的可扩展性。这些模型分为两类:电 气模型(Electrical Model)和绘图模型(Graphical Model)。电气模型实现元件的电气 特性,按规定的时序接收数据和输出数据;绘图模型实现仿真时与用户的交互,例如LCD 的显示。一个元件可以只实现电气模型,也可以都实现电气和绘图模型。Proteus为VSM模型提供了一些C+抽象类接口,用户创建元件时需要在DLL中实现相 应的抽象类。VSM模型和Proteus系统通信的原理如下图:绘图模型接口抽象类:ICOMPONENT-ISIS内部一个活动组件对象,为VSM模型提供在原理图上绘图和用户交互 的服务。IACTIVEMODEL-用户实现的VSM绘图模型要继承此类,并实现相应的绘图和键盘鼠标事件 处理。电气模型接口抽象类:IINSTANCE一个PROSPICE仿真原始模型,为VSM模型提供访问属性、模拟节点和数据引 脚的服务,还允许模型通过仿真日志发出警告和错误信息。ISPICECKT (模拟)一一SPICE拥有的模拟元件,提供的服务:访问、创建和删除节点,在 稀疏矩阵上分配空间,同时还允许模型在给定时刻强制仿真时刻点的发生和挂起仿真。ISPICEMODEL (模拟)一一用户实现的VSM模拟元件要继承此类,并实现相应的载入数据, 在完成的时间点处理数据等。IDSIMCKT (数字)一一DSIM拥有的数字元件,提供的服务:访问数字系统的变量,创建回 调函数和挂起仿真。IDSIMMODEL (数字)一一用户实现的VSM数字元件要继承此类,并实现相应的引脚状态变化 的判断和回调事件的处理。IDSIMPIN (数字)一一数字组件的引脚,提供检测引脚状态和创建输出事务事件的服务。IDBUSPIN (数字)一一数字组件的数据或地址总线,提供检测总线状态和创建总线输出事务 事件的服务。IMIXEDMODEL (混合)一一同时继承了 ISPICEMODEL和IDSIMMODEL,元件既有模拟特性, 又有数字特性。为了让Proteus访问用户模型中的成员函数,必须创建用户模型的一个实例。这不 能通过类的接口来实现,只能通过从DLL中导出几个C函数来实现,在用户模型中必须实现 这些C函数,达到构造和析构用户模型实例的效果。(1) 构造和析构绘图模型实例:IACTIVEMODEL *createactivemodel (CHAR *device, ILICENCESERVER *ils)VOID deleteactivemodel (IACTIVEMODEL *model)(2) 构造和析构模拟电气模型实例:ISPICEMODEL *createspicemodel (CHAR *device, ILICENCESERVER *ils)VOID deletespicemodel (ISPICEMODEL *model)(3) 构造和析构数字电气模型实例:IDSIMMODEL *createdsimmodel (CHAR *device, ILICENCESERVER *ils)VOID deletedsimmodel (IDSIMMODEL *model)(4) 构造和析构混合电气模型实例:IMIXEDMODEL *createmixedmodel (CHAR *device, ILICENCESERVER *ils)VOID deletemixedmodel (IDSIMMODEL *model)二、Proteus VSM仿真模型开发流程1. 绘制元件图形、引脚和相关符号。2. 制作元件,设置元件属性。3. 用C+编写元件,实现电气和绘图模型,编译生成DLL。4. 搭建电路仿真测试。三、VSM模型开发实例下面以TG19264A点阵式液晶显示元件的开发为实例详细讲解开发过程。1. 打开Proteus,选择菜单 查看>>Snap 10 th,选择左边绘图工具栏的2D graphics box, 绘制如图所示的三个图形。2. 选择2D graphics line,给出两条直线,设置width为36th,颜色为灰色。选择2D graphics circle,给四个角绘制安装孔。选择Markers for component origin,给三个图形分别绘 图符号原点(图中红色部分)。3. 选择Device pin,顺时针旋转90度,放置20个引脚,如图所示。GND、VCC、V0、Vee、 LED+的电气类型选择PP-Power Pin, D/I、R/W、E、CS1、RET、CS2、CS3的电气类型选择 IP-Input, D0D7 的电气类型选择 IO- Bidirectionalo4. 右键拖出选择框选择第一个符号,选择菜单库制作符号,命名为LCD19264A_C,确定。 同理,第二和第三个分别命名为LCD19264A_1和LCD19264A_0。当用户调用drawsymbol (-1),将绘制 LCD19264A_C,调用 drawsymbol (1),将绘制 LCD19264A_1,调用 drawsymbol (0),将绘制 LCD19264A_0。5. 右键拖出选择框选择符号LCD19264A_C,选择菜单库制作元件,Device Properties 设置如图,Device PropertiesGeneral Properties:External Module:of States:Bitwise States?LCD 1926,Device Name:Reference Prefix: L Active Component Properties:-Enter properties for component dnirridtion. Please refer to the Proteus VSM SDK for more information.Symbol Name Ster LCD19264ALink to DLL?Help<BackNext点击Next。跳过封装设置,点击Next。组件属性设置如图,点击Next。选择数据手册(可选),点击Next。选择器件库,点击OK。6. 打开VC,新建工程,选择Win32 Dynamic-Link Library,给工程命名,建立空的DLL 工程。从Proteus安装目录的INCLUDE文件夹中将VSM.HPP复制到当前工程目录,新建文件 LCD19264A.H 和 LCD19264A.CPP,编写如下代码。CODE:*个*个* 文件:LCD19264A.H*说明:不支持以下特性* (1)不支持显示开关控制* (2)不支持设置显示起始行* i nclude "vsm.hpp”/LCD常量#define LCD_BLK_NUM 3 /lcd block number#define LCD_BLK_LEN 64 /lcd block length#define LCD_LINE_NUM 8 /lcd line number#define LCD_LENGTH (LCD_BLK_LEN*LCD_BLK_NUM) /led length#define LCD_WIDTH 64 /led width#define BLANK_WIDTH 50 /the width of blank#define SYM_LINEWIDTH 28 /the width of symbol line/LCD命令掩码#define CMD_MASK 0xe0/LCD命令#define DISP_ONOFF 0x00 开关背光#define SET_STARTLINE 0xe0 /设置起始行#define SET_XADDRESS 0x80 /设置 X 地址#define SET_YADDRESS 0x40 /设置 Y 地址延时常量#define DELAY_1s 1000000000000#define DELAY_1ms 1000000000#define DELAY_1us 1000000#define DELAY_1ns 1000#define DELAY_1ps 1/*LCD元件既有数字电气特性,也有绘图特性,所以要继承IACTIVEMODEL和IDSIMMODEL*/class LCD19264A : publie IACTIVEMODEL,publie IDSIMMODELpublie:/*电气模型成员函数*/数字电路总是返回TRUEINT isdigital (CHAR *pinname);/当创建模型实例时被调用,做初始化工作VOID setup (IINSTANCE *inst, IDSIMCKT *dsim);/仿真运行模式控制,交互仿真中每帧开始时被调用VOID runetrl (RUNMODES mode);/交互仿真时用户改变按键等的状态时被调用VOID aetuate (REALTIME time, ACTIVESTATE newstate);交互仿真时每帧结束时被调用,通过传递ACTIVEDATA数据与绘图模型通信,从而调用 animate()进行绘图BOOL indieate (REALTIME time, ACTIVEDATA *data);当引脚状态变化时被调用,主要用来处理数据输入和输出VOID simulate (ABSTIME time, DSIMMODES mode);/可通过seteallbaek()设置在给定时间调用的回调函数VOID eallbaek (ABSTIME time, EVENTID eventid);/* 绘图模型成员函数 */当创建模型实例时被调用,做初始化工作 VOID initialize (ICOMPONENT *ept);/被PROSPICE调用,返回模拟电气模型ISPICEMODEL *getspicemodel (CHAR *device);/被PROSPICE调用,返回数字电气模型IDSIMMODEL *getdsimmodel (CHAR *device);/当原理图需要重绘时被调用VOID plot (ACTIVESTATE state);/当相应的电气模型产生活动事件时被调用,常用来更新图形VOID animate (INT element, ACTIVEDATA *newstate);用来处理键盘和鼠标事件BOOL actuate (WORD key, INT x, INT y, DWORD flags);private:IINSTANCE *instance; /PROSPICE 仿真原始模型IDSIMCKT *ckt; /DSIM 的数字元件ICOMPONENT *component; /ISIS 内部一个活动组件对象引脚定义IDSIMPIN *di; /D/IIDSIMPIN *rw; /R/WIDSIMPIN *en; /EIDSIMPIN *cs1; /CS1IDSIMPIN *cs2; /CS2IDSIMPIN *cs3; /CS3IDSIMPIN *d8; /D0D7IBUSPIN *databus; /D0.7/LCD参数BYTE x_addr; /X 地址(见手册)BYTE y_addr; /Y 地址(见手册)BYTE status; /状态(见手册)BYTE cur_blk; 当前块号(总共分3块,见手册)BYTE DDRAMLCD_BLK_NUMLCD_BLK_LEN*LCD_WIDTH/8; /LCD 显示 RAMBOOL new_flag; /新数据到达标志/显示参数BOX lcdarea; /LCD 显示区域float pix_width, pix_height; /每象素对应矩形的宽和高 ;CODE:* 文件:LCD19264A.CPP*说明:不支持以下特性* (1)不支持显示开关控制* (2)不支持设置显示起始行"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""/*#i nclude#i nclude "LCD19264A.h"/电气模型的实现构造数字电气模型实例extern "C" IDSIMMODEL _declspec(dllexport) * createdsimmodel (CHAR *device, ILICENCESERVER *ils)授权认证ils->authorize(0x88888888, 0x69); /版本为 6.9return new LCD19264A; /创建模型实例析构数字电气模型实例extern "C" VOID _declspec(dllexport) deletedsimmodel (IDSIMMODEL *model)delete (LCD19264A *)model; /删除模型实例数字电路总是返回TRUEINT LCD19264A:isdigital (CHAR *pinname)return 1;/当创建模型实例时被调用,做初始化工作VOID LCD19264A:setup (IINSTANCE *inst, IDSIMCKT *dsim)instance = inst; /PROSPICE 仿真原始模型ckt = dsim; /DSIM的数字元件获取引脚di = instance->getdsimpin("D/I,d/i”, true);di->setstate(FLT); /FLOATrw = instance->getdsimpin("R/W,r/w”, true);rw->setstate(FLT);en = instance->getdsimpin("E,e”, true);en->setstate(FLT);cs1 = instance->getdsimpin("CS1,cs1”, true);cs1->setstate(FLT);cs2 = instance->getdsimpin("CS2,cs2”, true);cs2->setstate(FLT);cs3 = instance->getdsimpin("CS3,cs3”, true);cs3->setstate(FLT);d0 = instance->getdsimpin("D0,d0”, true);d0->setstate(FLT);d1 = instance->getdsimpin("D1,d1”, true);d1->setstate(FLT);d2 = instance->getdsimpin("D2,d2”, true);d2->setstate(FLT);d3 = instance->getdsimpin("D3,d3”, true);d3->setstate(FLT);d4 = instance->getdsimpin("D4,d4”, true);d4->setstate(FLT);d5 = instance->getdsimpin("D5,d5”, true);d5->setstate(FLT);d6 = instance->getdsimpin("D6,d6”, true);d6->setstate(FLT);d7 = instance->getdsimpin("D7,d7”, true);d7->setstate(FLT);为方便操作,将D0D7映射为8位总线databus = instance->getbuspin("LCD_DBUS”, d, 8);databus->settiming(100,100,100); /设置时间延迟databus->setstates(SHI,SLO,FLT); /设置总线逻辑为1,0,三态时的驱动状态/lcd modelx_addr = 0; /X地址(见手册)y_addr = 0; /Y地址(见手册)status = 0; /状态(见手册)new_flag = TRUE; /新数据到达标志 /仿真运行模式控制,交互仿真中每帧开始时被调用VOID LCD19264A:runctrl (RUNMODES mode) 交互仿真时用户改变按键等的状态时被调用VOID LCD19264A:actuate (REALTIME time, ACTIVESTATE newstate) 交互仿真时每帧结束时被调用,通过传递ACTIVEDATA数据与绘图模型通信,从而调用 animate()进行绘图BOOL LCD19264A:indicate (REALTIME time, ACTIVEDATA *data) if(new_flag) /有新数据到达data->type = ADT_REAL; /call back animate() to refresh lcd data->realval = (float)time*DSIMTICK;return TRUE; 当引脚状态变化时被调用,主要用来处理数据输入和输出VOID LCD19264A:simulate (ABSTIME time, DSIMMODES mode) BYTE data;if(en->isnegedge() /E 的下降沿到达if(rw->istate()=SLO)|(rw->istate()=WLO) /R/W 为低表示写读块选择if(cs1->istate()=SLO)|(cs1->istate()=WLO) cur_blk = 0;else if(cs2->istate()=SLO)|(cs2->istate()=WLO) cur_blk = 1;else if(cs3->istate()=SLO)|(cs3->istate()=WLO) cur_blk = 2;elsereturn; /not select blockdata = (BYTE)databus->getbusvalue(); /读数据if(di->istate()=SHI)|(di->istate()=WHI) /D/I 为高表示数据DDRAMcur_blkx_addr*LCD_BLK_LEN+y_addr = data; /写入数据 new_flag = TRUE; /新数据到达标志y_addr = (y_addr+1)%LCD_BLK_LEN); /y 地址自动加 1 if(y_addr=0)x_addr = (x_addr+1)%LCD_LINE_NUM); /自动换行else /D/I为低表示命令switch(data&CMD_MASK)case DISP_ONOFF: /开关背光 break;case SET_STARTLINE: /设置起始行 break;case SET_XADDRESS: /设置 X 地址x_addr = (data&0x07); /bit2bit0 break;case SET_YADDRESS: /设置 Y 地址y_addr = (data&0x3f); /bit5bit0break;default:break;else /E的下降沿到达,R/W为高表示读结束databus->drivetristate(time); /驱动总线为三态 else if(en->isposedge() /E 的上升沿到达&& (rw->istate()=SHI)|(rw->istate()=WHI) /R/W 为高表示读 if(di->istate()=SHI)|(di->istate()=WHI) /D/I 为高表示数据读块选择if(cs1->istate()=SLO)|(cs1->istate()=WLO) cur_blk = 0;else if(cs2->istate()=SLO)|(cs2->istate()=WLO) cur_blk = 1;else if(cs3->istate()=SLO)|(cs3->istate()=WLO) cur_blk = 2;elsereturn; /not select blockdata = DDRAMcur_blkx_addr*LCD_BLK_LEN+y_addr;databus->drivebusvalue(time, data); /输出数据y_addr = (y_addr+1)%LCD_BLK_LEN); /y 地址自动加 1 if(y_addr=0)x_addr = (x_addr+1)%LCD_LINE_NUM); /自动换行else /D/I为低表示命令databus->drivebusvalue(time, status); 输出状态/可通过setcallback()设置在给定时间调用的回调函数 VOID LCD19264A:callback (ABSTIME time, EVENTID eventid) /绘图模型的实现/ Exported constructor for active component models.extern "C" IACTIVEMODEL _declspec(dllexport) * createactivemodel (CHAR *device, ILICENCESERVER *ils) ils->authorize (0x88888888,0x69); /6.9 return new LCD19264A;/ Exported destructor for active component models.extern "C" VOID _declspec(dllexport) deleteactivemodel (IACTIVEMODEL *model) delete (LCD19264A *)model;/当创建模型实例时被调用,做初始化工作VOID LCD19264A:initialize (ICOMPONENT *cpt) /获取ICOMPONENT接口和初始化 component = cpt;component->setpenwidth(0);component->setpencolour(BLACK);component->setbrushcolour(BLACK);/获取显示区域component->getsymbolarea(0,&lcdarea);/计算每象素对应矩形的宽和高pix_width =(float)(lcdarea.x2-lcdarea.x1-BLANK_WIDTH*2-SYM_LINEWIDTH*2)/LCD_LENGTH; pix_height =(float)(lcdarea.y2-lcdarea.y1-BLANK_WIDTH*2-SYM_LINEWIDTH*2)/LCD_WIDTH; /被PROSPICE调用,返回模拟电气模型ISPICEMODEL *LCD19264A:getspicemodel (CHAR *) return NULL;/被PROSPICE调用,返回数字电气模型IDSIMMODEL *LCD19264A:getdsimmodel (CHAR *) return this;/当原理图需要重绘时被调用VOID LCD19264A:plot (ACTIVESTATE state) /绘制LCD19264A_C元件基本图形 component->drawsymbol(-1);刷新LCD数据显示new_flag = TRUE;animate (0, NULL);/当相应的电气模型产生活动事件时被调用,常用来更新图形VOID LCD19264A:animate (INT element, ACTIVEDATA *data) BOX pix;BYTE dat,block,line,byte_off,bit_off;if(new_flag) 当有新数据到达new_flag = FALSE;component->begincache (ledarea); /打开缓冲component->drawsymbol(1); /显示 LCD19264_1 符号/显示各点数据for(block=0; blockfor(line=0; linefor(byte_off=0; byte_offdat = DDRAMblockline*LCD_BLK_LEN+byte_off; /get byte datafor(bit_off=0; bit_off<8; bit_off+)if(dat&(1< pix.xl =(int)(BLANK_WIDTH+(block*LCD_BLK_LEN+byte_off)*pix_width+0.5);pix.y1 = -(int)(BLANK_WIDTH+(line*8+bit_off)*pix_height+0.5);pix.x2 = pix.x1 + (int)(pix_width+0.5);pix.y2 = pix.y1 - (int)(pix_height+0.5);component->drawbox(pix); /绘制 1 个象素点component->endcache(); 结束缓冲,显示数据用来处理键盘和鼠标事件BOOL LCD19264A:actuate (WORD key, INT x, INT y, DWORD flags)return FALSE;7.搭建电路如下电路,新建Keil C工程,编写代码测试元件。如下图:DEFAULT INPUT OUTPUT BIDIR PnWFRP3.D/RXD P3 1/TXD P3.2/iNTD P3.3/iNlTP3.4/TO P3.5ZT1 P3.6AjiiR| > | l> | II | | ANIMATING: 00:00:15.65 (CPU load 22%)xwa 查看(妙编辑(£) ®(O ia(B «i+(n) B»(Q iS5tft(3 调试<6)模板系统3 WWtl) _丽有ei临蔺*£肩如七i w吕岛押B 0 Sl:D-型国!©!>>.& 留/口 lalcoABl* CD厂-茂臾1隰(腐束)有限公司 ABCDEFGHUKLMNOPQRTJVWX YZabcdefghi jklimopqrstuv wxyzOl23456789!©#$%”材()DO00DIQ1D2Q2D3Q3D404D505DOQ0D707OE LE