CANoe9.0用CAPL控制数控电源

2019-07-13 22:12发布

1.前言 本文提供一种基于CAPL控制数控电源的方法,其实现原理是CAPL中调用RS232,发送SCPI指令与数控电源通信。 理论上,本文适用于串口通信的数控电源或其他串口设备。 2.开发环境 2.1硬件环境 数控电源KORAD KA3005P,CANcaseXL 2.2软件环境 CANoe 9.0,串口调试助手 3.参考资料 KA系列标准通信协议_百度文库  https://wenku.baidu.com/view/6adf09f1294ac850ad02de80d4d8d15abe230039.html CANoe DEMO:File-Sample Configurations-IO HIL-RS232,这里是个使用RS232的DEMO 4.测试SCPI指令 将数控电源连上PC,注意,虽然是USB接口,但是数控电源内部虚拟了串口,可以在设备管理器中发现。 用串口助手打开电源的串口,设置波特率为9600(这里测试任何一个波特率都可以,不知为什么)。 然后以ASCII的方式发送指令。 这里测试的目的主要是为了验证通信。 具体的指令可以根据文档描述测试一下,这里就不细说了。 5.建立CANoe工程 创建个合适的工程,建立CAPL NODE,DBC,以及PANEL 6.编辑CAPL代码 以下代码参考了Demo /*@!Encoding:936*/ includes { } variables { // GLOBAL const int kBUFFER_SIZE = 1000; const int kINFO = 1; const int kWARN = 2; const int kERROR = 3; const int kHANDSHAKE_DISABLED = 0; const int kHANDSHAKE_RTSCTS = 33; // define for dp serial port com9 const dword port = 9; const dword baudrate = 9600; const dword dataBits = 8; const dword stopBits = 1; const dword parity = 0;//0:none 1:even 0:odd // data is copied from callback buffer to gReceiverBuffer (collects data) byte gReceiverCallbackBuffer[kBUFFER_SIZE]; byte gReceivedBuffer[kBUFFER_SIZE]; dword gReceivedIndex= 0; // state variable byte gSending = 0; byte gGetValueSt = 0; byte gSetValueSt = 0; msTimer t100ms; msTimer t20ms; } on preStart { InitSerialPort(); } on start { setTimer(t100ms,100); } //RS232 Init InitSerialPort() { // close serial port (port may have changed, former port shall not remain open) if(Rs232Close(port)!=1) writeLineEx(0,kERROR,"An error occurred during closing of the serial port %d.", port); // set state (close aborts all open requests) gSending = 0; // open the serial port (comes up with Windows defaults) if(Rs232Open(port)==1) writeLineEx(0,kINFO, "Serial port %d successfully opened.", port); else writeLineEx(0,kERROR,"An error occurred during opening of the serial port %d.", port); // configure the serial port // - just take the panel content if(Rs232Configure(port,baudrate,dataBits,stopBits,parity)==1) writeLineEx(0,kINFO, "Serial port %d successfully initialized.", port); else writeLineEx(0,kERROR,"An error occurred during initialization of the serial port %d.", port); // port, handshake, xonLim, xoffLim, xonChar, xoffChar, writeTimeout // without last timeout parameter: use default timeout // for transmission of small amounts of data one may not need to use handshake ! // e.g. 33 for RTS/CTS as second parameter for large volumes of data, 0 for small volumes if(Rs232SetHandshake(port, kHANDSHAKE_DISABLED, 0, 0, 0, 0)) writeLineEx(0,kINFO, "Handshake parameters for serial port %d successfully configured.", port); else writeLineEx(0,kERROR,"An error occurred during the serial port %d configuration of handshake parameters.", port); // set buffer for reception (otherwise callback would not work) if(Rs232Receive(port, gReceiverCallbackBuffer, kBUFFER_SIZE)) writeLineEx(0,kINFO, "Receiver buffer for serial port %d successfully set.", port); else writeLineEx(0,kERROR,"An error occurred during setting the receiver buffer for serial port %d.", port); } //RS232 Call back RS232OnReceive( dword port, byte buffer[], dword number ) { dword i; for(i=0;i=5) { DP_DataRecevied(gReceivedBuffer,gReceivedIndex); gReceivedIndex=0; } } } //RS232 Call back RS232OnSend( dword port, byte buffer[], dword number ) { // set state gSending = 0; //writeLineEx(0,kINFO,"Transmission of %d bytes from port %d completed !", number, port); } //RS232 Call back RS232OnError( dword port, dword errorFlags ) { // set state gSending = 0; writeLineEx(0,kERROR,"Error handler called with error code %d !", errorFlags); if ( errorFlags & 1 ) writeLineEx(0,1,"%d informs of send error",errorFlags); if ( errorFlags & 2 ) writeLineEx(0,1,"%d informs of receive error",errorFlags); if ( errorFlags & 4 ) writeLineEx(0,1,"%d informs of frame error",errorFlags); if ( errorFlags & 8 ) writeLineEx(0,1,"%d informs of parity error",errorFlags); if ( errorFlags & 16 ) writeLineEx(0,1,"%d informs of overrun error",errorFlags); if ( errorFlags & 32 ) writeLineEx(0,1,"%d informs of receiver overrun error",errorFlags); if ( errorFlags & 64 ) writeLineEx(0,1,"%d informs of break state",errorFlags); if ( errorFlags & 128 ) writeLineEx(0,1,"%d informs of send timeout error",errorFlags); } CopyBuffer( byte destBuffer[], dword destOffset, byte srcBuffer[], dword srcNumber ) { dword i; for (i=0; i3000) writeLineEx(0,kERROR,"Voltage too high! "); else { buf[i++]=(byte)(vol/1000)+0x30; vol%=1000; buf[i++]=(byte)(vol/100)+0x30; vol%=100; buf[i++]='.'; buf[i++]=(byte)(vol/10)+0x30; buf[i++]=(byte)(vol%10)+0x30; DP_Send(buf, i); } } DP_SetCurrent(float data) { char str[7]="ISET1:"; char buf[100]; word vol=0; byte i; for(i=0; i<6; i++) { buf[i]=str[i]; } vol = (word)(data*1000); if(vol>5000) writeLineEx(0,kERROR,"Current too high! "); else { buf[i++]=(byte)(vol/1000)+0x30; vol%=1000; buf[i++]='.'; buf[i++]=(byte)(vol/100)+0x30; vol%=100; buf[i++]=(byte)(vol/10)+0x30; buf[i++]=(byte)(vol%10)+0x30; DP_Send(buf, i); } } DP_DataRecevied(byte buffer[], dword len) { switch(gGetValueSt) { case 0: putValue(Env_GetVoltage,AtoF(buffer,len)); gGetValueSt=1; break; case 1: putValue(Env_GetCurrent,AtoF(buffer,len)); gGetValueSt=0; break; default: break; } } float AtoF(byte buffer[], dword len) { double getData; dword i; byte flag; dword per; getData = 0;//static per=1;//static flag=0;//static for(i=0; i   7.测试 8.总结 (1)CANoe十分强大,可以干很多事情,本文中的方法也只是众多控制数控电源方式中的一种,本人未开发过基于CANoe的自动化测试设备,也并不清楚并不清楚商业上是如何实现的。 (2)DEMO很有参考价值,不会的可以找DEMO参考 (3)他节点可以通过调用dbc中定义的环境变量,来获取或者设置电源的电压电流 (4)win10微软拼音在360浏览器编辑此贴,打字会抽风