BM85调试.docx
《BM85调试.docx》由会员分享,可在线阅读,更多相关《BM85调试.docx(27页珍藏版)》请在冰豆网上搜索。
BM85调试
可编程BM85调试报告
一、SA85卡的安装
计算机通过SA85卡(需ISA插槽)接入MBPLUS网。
推荐使用如下设定:
memoryaddress=CE800(内存地址)
hardwareinterruptNONE(硬件中断)
设定如下图:
图1
|-----------------------------------------------------------|
|LED|
||
|NA8|
|.|
|.|
|.|
|NA1|
||
|..IR7SM8d|
|..IR67u|
|..IR56d|
|..IR45u|
|..IR34u|-+
|..IR23u|+-+
|--2d||
|1d||
||+-+
+----------------------|-+
||
||||||||||||||||||||
IR2-7:
最低短接,即选择无中断。
SM1-8:
内存地址选择CE800.'d'=down;'u'=up
NA1-8:
地址开关。
朝左为1,朝右为零。
12345678
Address1000000--
2100000--
3010000--
4110000--
..........
63011111--
64111111--
SA85卡的驱动程序有16位和32位两种。
此次调试在NTWorkstation4.0上进行。
由于下载软件bm85load.exe需要16位驱动程序(在DOS下格式为:
bm85load/s5c/re000/p4.4bm85.exe)。
所以需安装SA85卡的16位驱动程序。
步骤如下:
1、安装驱动程序
2、拷贝autoexec.nt和config.nt到Winnt/System32目录下,重新启动计算机即可加载Mbp16.sys等软件。
运行mbpstat.exe,可检测到SA85卡,即16位驱动程序已生效。
另外,安装32位的NT驱动程序后,即可在控制面板/设备上检测
到WinConXMBXDriver,即32位的驱动程序已生效。
二、BM85软件的设计和调试
硬件配置:
BM85简介:
可编程BM85背板带有两个MB+通信端口和4个RS232(九针)串口。
根据如下两图,分别设定BM85的MBPlus地址和BM85运行模式。
图2
图3
使用两个BM85进行通信连接。
其中一个BM85(称为A)的一个MB+通信口与上面MB+网络进行通信,一个串行通信口与Modem连接;另一个BM85(称为B)的一个串行通信口与Modem连接,一个串行通信口与下面带有Modbus端口的PLC或变频器等设备相连。
设备连接示意图如下:
图4
软件设计要求:
程序在BorlandC++4.5下编译、建立、连接。
安装BorlandC++4.5,拷贝bm85lib.lib到LIB文件夹,改名为bidsl.lib,删除原bidsl.lib。
打开DEMO程序,在此环境下编写程序。
由于串口通信协议采用Modbus,程序只支持读(0x3)和写(0x10)功能。
根据Modbus协议,Master读功能的帧格式为:
SlaveAdd.+0x3+StartAdd.+NumofRegisterstobeRead+CRC16
(1Byte)(1Byte)(2Byte)(2Byte)(2Byte)
Slave的Response帧格式为:
SlaveAdd.+0x3+ByteCount+Data+CRC16
(1Byte)(1Byte)(1Byte)(2Byte)
Master写功能的帧格式为:
SlaveAdd.+0x10+StartAdd.+NumofRegisterstobeWrited+
(1Byte)(1Byte)(2Byte)(2Byte)
ByteCount+Data+CRC16
(1Byte)(2Byte)
Slave的Response帧格式为:
SlaveAdd.+0x10+StartAdd.+NumofRegisterstobeWrited+CRC16
(1Byte)(1Byte)(2Byte)(2Byte)(2Byte)
数据传输时,DataRegister高位先行,CRC16则为低位先行。
对于BM85来说,MBPlus通信协议的帧格式大致与modbus相似,主要区别在于寻址方式不同,并且BM85滤去了CRC16校验码(在HDLC中)。
MBPlus采用五个字节命名地址的方式。
例如:
在当前MB+网络上的设备五,寻址方式为:
50000
在另一MB+网络上的设备五,通过7号网桥连接,其寻址方式为:
75000
通过BM85或主机适配卡寻址,应指定特定的SLAVEPATH,因此
在当前MB+网络上的设备五的路径1,寻址方式为:
51000
在另一MB+网络上的设备五的路径4,通过7号网桥连接,其寻址方式为:
75400
Master程序设计如下:
首先在BM85内分配一块内存区,作为读、写的存储区域。
采用多任务形式,即调用Bm85lib.lib中函数
voidtask_create(intid,//idnumberpassedtotask
void(*task_entry)(unsigned),//taskproceduretoexecute
unsignedstacksize)//typically1024
任务一:
与Modbus设备进行通信,读、写串口。
先对串口进行初始化,调用函数
voiduart_set_baud(unsignedport,//0to3
unsignedbaud,//10,20,30...to57600
charparity,//'N','O','E'
unsignedbits,//5to8
unsignedstop);//1or2
voidtrans(intmsg_len,unsignedchar*msg)
intreceive(unsignedchar*msg)有信息返回值>0
由于此时BM85作为Master,它先读取Modbus设备数据,并把这些
数据写入BM85分配出内存区中读数据区域(供MODBUSPLUS设备使
用);接着把分配出内存区中写数据区域数据发送到Modbus设备。
注意事项:
由于数据的请求、接收需要一些延时,程序中调用了函数
Task_delay(unsignedd)进行必要的延时,同时亦可对读写
的时间进行适当的控制。
任务二:
与MBPlus设备进行通信。
在”bm85.h”中包含有与MODBUSPLUS网络设备通信所需的接口子函数。
在与MODBUSPLUS网络设备通信之前,必须先调用函数:
intmbplus_reset(void)
而且每秒必须调用函数:
intmbplus_do_config_stat(void),才能保持MODBUSPLUS
接口激活,否则MODBUSPLUS系统认为BM85应用程序已崩溃,如
发生此情况,则在调用intmbplus_do_config_stat(void)前仍需调用
intmbplus_reset(void)函数。
MODBUSPLUS系统支持32个独立的通道,可利用函数
intmbplus_select(unsigned*s)一次同时检测所有通道状态。
各通
道状态如下:
s[0]bit0=1ifDATAMASTERPATH1ready
s[0]12
…78
s[1]bit0=1ifDATASLAVEPATH1ready
s[2]PROGRAMMASTERPATH1ready
s[3]PROGRAMSLAVEPATH1ready
由于本程序对MODBUSPLUS设备做MASTER,不必使用此函数。
调用函数:
intmbplus_check_ready(unsignedcharmpath)
通道号为1-841-4881-88C1-C8,其中:
mpath=1-8forDM1-DM8,41-48(hex)forDS1-DS8,
81-88(hex)forPM1-PM8,C1-C8forPS1-PS8
若通道未准备好返回=0
出错返回<0
信息在等待返回>0
MODBUSPLUS消息处理顺序:
MASTER在MASTER的一空闲通道上用mbplus_send_request()发送
请求;
MASTER用mbplus_select()等待响应;
SLAVE用mbplus_select()检测哪个通道有MASTER请求;
SLAVE用mbplus_recv_request()读取MASTER请求;
SALVE用mbplus_send_reply()发送响应;
MASTER用mbplus_select()确认是否有响应消息;
MASTER用mbplus_recv_reply()读取SLAVE响应消息;
以下为各函数原形:
intmbplus_send_request(unsignedcharmpath,//通道号//1-8data,0x81-88program
unsignedchar*route,//5字节寻址路径
unsignedchar*msg,//256字符
unsignedmsg_len);//字符长度
intmbplus_recv_reply(unsignedcharmpath,
//通道号1-881-88
unsignedchar*msg);//256字符
intmbplus_recv_request(unsignedcharmpath,
//通道号41-48c1-c8
unsignedchar*msg);//256字符
intmbplus_send_reply(unsignedchar*msg,
//256字符
由于此时BM85作为Master,它先读取BM85分配出内存区中读数据区域,并把这些数据通过MBPLUS接口发送到MBPLUS网上设备;接着通过MBPLUS接口读取MBPLUS网上设备的数据,并把这些数据写入BM85分配出的内存区的写数据区域(供Modbus设备使用)。
Slave程序设计如下:
首先在BM85内分配一块内存区,作为读、写数据的存储区域。
亦采用多任务形式,即调用Bm85lib.lib中函数
voidtask_create(unsignedtask_id)。
任务一:
作为Master与Modbus设备进行通信,读、写串口。
此任务与Master程序的任务一完全相同。
任务二:
作为Slave与Modbus设备(在该调试中即为BM85串口)进行通
信。
其目的是定时检测串口中是否有ModbusMaster设备发送请求指令,若有读指令,则把BM85分配得到的相应读区域数据返回响应;若有写指令,则把欲写入的数据写入BM85分配得到的相应写区域,并返回对应的响应,否则,Master会产生超时事件。
Master和Slave程序如下:
MASTER程序:
#include
#include
#include
#include
#include"bm85.h"//libraryfunctionprototypes
#include
staticunsignedcharauchCRCHi[]={
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,
0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,
0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,
0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,
0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,
0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,
0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,
0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,
0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,
0x40
};
staticcharauchCRCLo[]={
0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4,
0x04,0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09,
0x08,0xC8,0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,0x1E,0xDE,0xDF,0x1F,0xDD,
0x1D,0x1C,0xDC,0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,
0x11,0xD1,0xD0,0x10,0xF0,0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,0x36,0xF6,0xF7,
0x37,0xF5,0x35,0x34,0xF4,0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,
0x3B,0xFB,0x39,0xF9,0xF8,0x38,0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA,0xEE,
0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,
0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,0xA0,0x60,0x61,0xA1,0x63,0xA3,0xA2,
0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4,0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,
0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68,0x78,0xB8,0xB9,0x79,0xBB,
0x7B,0x7A,0xBA,0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,0xB4,0x74,0x75,0xB5,
0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,0x50,0x90,0x91,
0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,0x9C,0x5C,
0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98,0x88,
0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,
0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,
0x40
};
voidCRC16(unsignedchar*puchMsg,unsignedshortusDataLen)
{
unsignedcharuchCRCHi=0xFF;
unsignedcharuchCRCLo=0xFF;
unsigneduIndex;
while(usDataLen--)
{
uIndex=uchCRCHi=uchCRCHi^*puchMsg++;
uchCRCHi=uchCRCLo^auchCRCHi[uIndex];
uchCRCLo=auchCRCLo[uIndex];
}
*puchMsg=uchCRCHi;
*(puchMsg+1)=uchCRCLo;
//return(uchCRCHi<<8|uchCRCLo);
}
intcheck_crc16(unsignedchar*puchMsg,unsignedshortusDataLen){
CRC16(puchMsg,usDataLen);
if(puchMsg[usDataLen]==0&&puchMsg[usDataLen+1]==0)return1;
else
return0;
}
voidtrans(intmsg_len,unsignedchar*msg)
{
inti;
for(i=0;iuart_putchar(0,msg[i]);
}
intreceive(unsignedchar*msg)
{
inti=0;
intresponse,msg_len;
while(0<=(response=uart_getchar(0)))
{
if(response<255)
{
msg[i]=response&(0xff);
i++;
}
}
if((i>=4)&&(check_crc16(msg,i)==1))
msg_len=i;
else
msg_len=0;
returnmsg_len;
}
classreg4x
{
unsignedtotal_regs;
unsigned*reg;
public:
reg4x(unsignedregs);
intread4x(unsignedref,unsignedno,unsigned*buf);
intwrite4x(unsignedref,unsignedno,unsigned*response);
};
reg4x:
:
reg4x(unsignedregs)
{
reg=(unsigned*)calloc(2,regs);
if(reg)total_regs=regs;
elsetotal_regs=0;
}
intreg4x:
:
read4x(unsignedref,u