`
lovecontry
  • 浏览: 1036383 次
文章分类
社区版块
存档分类
最新评论

.Net Micro Framework研究—串口操作

 
阅读更多

.Net Micro Framework研究串口操作

试验平台:Digi MF开发板

Digi提供的示例中包含了串口的示例程序,主要代码如下:

publicboolEchoByte()

{

SerialPortserial;

boolexceptionRaised=false;

booltestResult=true;

stringmessage=" Thisisanechotest.Enterthecharactertoecho,orESCtoexit. ";

byte[]encodedMessage=c_encoding.GetBytes(message);

byte[]buffer=newbyte[1];

try

{

serial
=newSerialPort(newSerialPort.Configuration(Cpu.Serial.COM1,Cpu.BaudRate.Baud115200,false));



serial.Write(encodedMessage,
0,message.Length);



while(buffer[0]!=0x1b)

{

serial.Read(buffer,
0,buffer.Length,Timeout.Infinite);

serial.Write(buffer,
0,buffer.Length);

}



serial.Dispose();

}

catch

{

exceptionRaised
=true;

}

if(exceptionRaised==true)

testResult
=false;

returntestResult;

}

部署运行后,你可以用超级终端进行测试,测试图如下:

(图MF10280001.JPG

注意:如果串口程序非正常退出,有可能导致开发板无法发送数据(接收倒是正常),重启开发板即可。

用测试程序还是体现不出.Net Micro Framework的优势,我决定用MF实现Modbus Rtu Slave服务端(支持Modbus Rtu 3号命令),并且地址为0的数据存放了GPIO入的信息,这样在上位机就很方面的检测IO信号了。

用了大约15分钟,就把我以前用C++开发的Modbus Rtu Slave程序移植到MF平台上来的,我想如果用单片来开发,虽然也有可能借用以前的代码,但很方便的把IO信号也非常快捷的集成进来,恐怕不容易。

值得一提的是VS2005 的调试功能非常强大,很容易添加断点及监控当前变量的值,同时用debug.print()命令也非常好使,这样调试程序绝对比调试单片舒服。

下面贴出我写的Modbus RtuSlave代码

usingSystem;
usingMicrosoft.SPOT;
usingSystem.Threading;
usingMicrosoft.SPOT.Hardware;

namespaceMFModbus
{
publicclassModbusRtu
{
privateThreadm_worker;
privateboolm_RunFlag;

privatebytebytRtuDataFlag=0;
privatebytebytRtuDataIdx;
privatebyte[]bytRtuData=newbyte[8];

//设备地址,默认为1
privatebyteModbusAddr=1;
//数据区(注意,Modbus读写是以字(双字节)为单位的)
privatebyte[]DataBuff=newbyte[128];

SerialPortserial
=null;

InputPort[]input
=newInputPort[5];
Cpu.Pin[]pin
=newCpu.Pin[5]{(Cpu.Pin)0,(Cpu.Pin)1,(Cpu.Pin)2,(Cpu.Pin)5,(Cpu.Pin)6};

publicModbusRtu(bytemModbusAddr)
{
ModbusAddr
=mModbusAddr;
for(inti=0;i<5;i++)
{
input[i]
=newInputPort(pin[i],false,Port.ResistorMode.PullUp);
}
}

~ModbusRtu()
{
Stop();
}

//CRC16校验
privateUInt16GetCheckCode(byte[]buf,intnEnd)
{
UInt16crc
=(UInt16)0xffff;
inti,j;
for(i=0;i<nEnd;i++)
{
crc
^=(UInt16)buf[i];
for(j=0;j<8;j++)
{
if((crc&1)!=0)
{
crc
>>=1;
crc
^=0xA001;
}
else
crc
>>=1;
}
}
returncrc;
}

//启动Modbus服务
publicvoidRun()
{
try
{
//仅有波特率选项,竟然没有奇偶校验控制
serial=newSerialPort(newSerialPort.Configuration(Serial.COM1,BaudRate.Baud9600,false));
Debug.Print(
"OpenSerialOK");
m_worker
=newThread(newThreadStart(this.ModbusThreadProc));
m_RunFlag
=true;
m_worker.Start();
}
catch
{
Debug.Print(
"SerialError");
}
}

//停止Modbus服务
publicvoidStop()
{
m_RunFlag
=false;
if(serial!=null)
serial.Dispose();
}

//ModbusSlave服务
privatevoidModbusThreadProc()
{
Debug.Print(
"StartModbusSlave");
byte[]bytData=newbyte[1];
while(m_RunFlag)
{
serial.Read(bytData,
0,bytData.Length,Timeout.Infinite);
RtuSlave(bytData[
0]);
}
}
//串口数据处理
privatevoidRtuSlave(bytebytData)
{
//Debug.Print(bytRtuDataIdx.ToString()+"-"+bytData.ToString());
if(bytRtuDataFlag==0)
{
//如果数据为首地址
if(bytData==ModbusAddr)
{
bytRtuDataFlag
=1;
bytRtuDataIdx
=0;
bytRtuData[bytRtuDataIdx
++]=bytData;
}
}
else
{
bytRtuData[bytRtuDataIdx
++]=bytData;
if(bytRtuDataIdx>=8)
{
//信息处理
UInt16intCRC16=GetCheckCode(bytRtuData,8-2);

//Debug.Print("CRC:"+bytRtuData[8-2].ToString()+""+((byte)(intCRC16&0xFF)).ToString()+"|"+bytRtuData[8-1].ToString()+""+((byte)((intCRC16>>8)&0xff)).ToString());
//CRC16校验检验
if(bytRtuData[8-2]==(intCRC16&0xFF)&&bytRtuData[8-1]==((intCRC16>>8)&0xff))
{
byte[]bytSendData=newbyte[255];
bytebytErrorFlag=0;
bytebytErrorNo=1;

//Debug.Print("CRCOK");
//读数据
if(bytRtuData[1]==3)
{
UInt16lngDataAddr
=bytRtuData[2];
lngDataAddr
=(UInt16)((lngDataAddr<<8)+bytRtuData[3]);//地址
UInt16lngDataNum=bytRtuData[4];
lngDataNum
=(UInt16)((lngDataNum<<8)+bytRtuData[5]);//数量

if(lngDataAddr*2+lngDataNum*2>1024||lngDataNum>120)
{
bytErrorNo
=2;
bytErrorFlag
=0;
}
else
{
bytSendData[
0]=bytRtuData[0];
bytSendData[
1]=bytRtuData[1];
bytSendData[
2]=(byte)(lngDataNum*2);

//读GPIO信号
DataBuff[0]=0;
DataBuff[
1]=(byte)((input[0].Read()?1:0)|(input[1].Read()?2:0)|(input[2].Read()?4:0)|(input[3].Read()?8:0)|(input[4].Read()?16:0));

for(inti=0;i<bytSendData[2];i++)
{
bytSendData[
3+i]=DataBuff[lngDataAddr*2+i];
}
intCRC16
=GetCheckCode(bytSendData,3+lngDataNum*2);
bytSendData[
3+lngDataNum*2]=(byte)(intCRC16&0xFF);//CRC校验低位
bytSendData[4+lngDataNum*2]=(byte)((intCRC16>>8)&0xff);//CRC校验高位

//发送数据
intintRet=serial.Write(bytSendData,0,5+lngDataNum*2);

//Debug.Print("SendDataOK"+intRet.ToString());
bytErrorFlag=1;
}
}

if(bytErrorFlag==0)
{
//协议不支持
bytSendData[0]=bytRtuData[0];
bytSendData[
1]=(byte)(bytRtuData[1]|0x80);
bytSendData[
2]=bytErrorNo;

intCRC16
=GetCheckCode(bytSendData,3);
bytSendData[
3]=(byte)(intCRC16&0xFF);//CRC校验低位
bytSendData[4]=(byte)((intCRC16>>8)&0xff);//CRC校验高位

//发送数据
serial.Write(bytSendData,0,5);
}
}
bytRtuDataFlag
=0;
}
}
return;
}

//串口号
publicstaticclassSerial
{
publicconstSerialPort.SerialCOM1=(SerialPort.Serial)0;
publicconstSerialPort.SerialCOM2=(SerialPort.Serial)1;
}

//串口波特率
publicstaticclassBaudRate
{
publicconstSerialPort.BaudRateBaud4800=(SerialPort.BaudRate)4800;
publicconstSerialPort.BaudRateBaud9600=(SerialPort.BaudRate)9600;
publicconstSerialPort.BaudRateBaud19200=(SerialPort.BaudRate)19200;
publicconstSerialPort.BaudRateBaud38400=(SerialPort.BaudRate)38400;
publicconstSerialPort.BaudRateBaud57600=(SerialPort.BaudRate)57600;
publicconstSerialPort.BaudRateBaud115200=(SerialPort.BaudRate)115200;
publicconstSerialPort.BaudRateBaud230400=(SerialPort.BaudRate)230400;
}
}
}

程序部署运行后,直接用标准的Modbus Rtu客户端程序测试即可,我用的是我以前编写的Modbus Rtu Client程序,测试如下:

(图MF10280002.JPG)

这时候,你直接操作SW2的拨码,该数字就会发生变化(前提SW1的拨码都拨到右边)。

缺点:很奇怪的是串口的参数仅能配置波特率,奇偶校验,数据位却无法配置。

总的印象:用MF开发嵌入式系统还是非常有前景的,至少使产品的开发周期大大缩短,并且代码升级维护方便。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics