Net Micro Framework研究—串口操作

分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

               

.Net Micro Framework研究串口操作

试验平台:Digi MF开发板

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

public   bool  EchoByte()

        {

            SerialPort serial;

             bool  exceptionRaised  =   false ;

             bool  testResult  =   true ;

             string  message  =   " This is an echo test.  Enter the character to echo, or ESC to exit. " ;

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

             byte [] buffer  =   new   byte [ 1 ];

             try

            {

                serial  =   new  SerialPort( new  SerialPort.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 ;

             return  testResult;

        }

 

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

(图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代码

 

using  System;
using  Microsoft.SPOT;
using  System.Threading;
using  Microsoft.SPOT.Hardware;

namespace  MFModbus
{
     public   class  ModbusRtu
    {
         private  Thread m_worker;
         private   bool  m_RunFlag;

         private   byte  bytRtuDataFlag = 0 ;
         private   byte  bytRtuDataIdx;
         private   byte [] bytRtuData  =   new   byte [ 8 ];

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

        SerialPort serial  =   null ;

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

         public  ModbusRtu( byte  mModbusAddr)
        {
            ModbusAddr = mModbusAddr;
             for  ( int  i  =   0 ; i  <   5 ; i ++ )
            {
                input[i]  =   new  InputPort(pin[i],  false , Port.ResistorMode.PullUp);
            }
        }

         ~ ModbusRtu()
        {
            Stop();
        }

         // CRC16校验
         private  UInt16 GetCheckCode( byte [] buf,  int  nEnd)
        {
            UInt16 crc  =  (UInt16) 0xffff ;
             int  i, 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 ;
                }
            }
             return  crc;
        }

         // 启动Modbus服务
         public   void  Run()
        {
             try
            {
                 // 仅有波特率选项,竟然没有奇偶校验控制
                serial  =   new  SerialPort( new  SerialPort.Configuration(Serial.COM1, BaudRate.Baud9600,  false ));
                Debug.Print( " Open Serial OK " );
                m_worker  =   new  Thread( new  ThreadStart( this .ModbusThreadProc));
                m_RunFlag  =   true ;
                m_worker.Start();
            }
             catch
            {
                Debug.Print( " Serial Error " );
            }           
        }

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

         // Modbus Slave服务
         private   void  ModbusThreadProc()
        {
            Debug.Print( " Start Modbus Slave " );
             byte [] bytData = new   byte [ 1 ];
             while  (m_RunFlag)
            {
                serial.Read(bytData,  0 , bytData.Length, Timeout.Infinite);
                RtuSlave(bytData[ 0 ]);
            }
        }
         // 串口数据处理
         private   void  RtuSlave( byte  bytData)
        {
             // 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 )
                {
                     // 信息处理
                    UInt16 intCRC16  =  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  =   new   byte [ 255 ];
                         byte  bytErrorFlag  =   0 ;
                         byte  bytErrorNo  =   1 ;

                         // Debug.Print("CRC OK");
                         // 读数据
                         if  (bytRtuData[ 1 ]  ==   3 )
                        {
                            UInt16 lngDataAddr  =  bytRtuData[ 2 ];
                            lngDataAddr  =  (UInt16)((lngDataAddr  <<   8 )  +  bytRtuData[ 3 ]);   // 地址
                            UInt16 lngDataNum  =  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  ( int  i  =   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校验高位                  

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

                                 // Debug.Print("SendData OK " + 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 ;
        }

         // 串口号
         public   static   class  Serial
        {
             public   const  SerialPort.Serial COM1  =  (SerialPort.Serial) 0 ;
             public   const  SerialPort.Serial COM2  =  (SerialPort.Serial) 1 ;
        }

         // 串口波特率
         public   static   class  BaudRate
        {
             public   const  SerialPort.BaudRate Baud4800  =  (SerialPort.BaudRate) 4800 ;
             public   const  SerialPort.BaudRate Baud9600  =  (SerialPort.BaudRate) 9600 ;
             public   const  SerialPort.BaudRate Baud19200  =  (SerialPort.BaudRate) 19200 ;
             public   const  SerialPort.BaudRate Baud38400  =  (SerialPort.BaudRate) 38400 ;
             public   const  SerialPort.BaudRate Baud57600  =  (SerialPort.BaudRate) 57600 ;
             public   const  SerialPort.BaudRate Baud115200  =  (SerialPort.BaudRate) 115200 ;
             public   const  SerialPort.BaudRate Baud230400  =  (SerialPort.BaudRate) 230400 ;
        }
    }
}

 

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

 

 (图MF10280002.JPG) 

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

 

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

 

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

 

           

分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值