关于C#编写modbus通讯协议的求助

关于C#编写modbus通讯协议的求助,第1张

C#的行吗可以的话我再给你大概的代码

拿读数据做例子,其他的功能重要改掉03功能码就行

先组成命令的byte数组

byte[] Dp = new byte[8];

byte[] DpC = new byte[6];

Dp[0] = 0x01;//这是表的地址,假定是01

Dp[1] = 0x03;//这是功能码,03是读寄存器数据

Dp[2] = 0x00;

Dp[3] = 0x03;//表的相应寄存器地址

Dp[4] = 0x00;

Dp[5] = 0x0C;//表的相应寄存器参数,根据功能码和表的不同,这几个编码有变化

for (int i = 0; i < 6; i++)

{

DpC[i] = Dp[i];

}

uint ValCRC;

ValCRC = CRC(DpC);//CRC为自己写的CRC-16校验码的函数,具体的实现这里不给要的话可以发给你

Dp[6] = (byte)(ValCRC % 256);

Dp[7] = (byte)(ValCRC / 256);

然后把这个数组发给串口,编程语言不同发送方式不同

还在程序可以设置波特率,校验什么的,编程语言不同设置方式也不同

然后接受数据,也是一个byte数组

然后自己解析数组,把需要的转化成10进制或者你需要的格式 望采纳

<p>这是我自己用单片机写过的ModBus通信程序,你可以参照一下。其实比较简单,就是按步骤一步步的来就行了。</p>

<p></p>

这个是MODBUS控制电磁阀的一个程序。其中还有AD采集的部分。对CRC校验用查表的方法。至于怎样把校验的结果拆分成高低位字节,再发送,看程序吧。

#include"reg51h"

#include"intrinsh"

#define uchar unsigned char

#define uint unsigned int

#define Pressure P0

////////////////

/////////////////////

uchar addr;

uchar  Pressure_updata;

uchar  Pressure_lowdata;

/////////////////

sbit    Dcf_open=P1^0;//电磁阀开启

sbit    Dcf_close=P1^1;//电磁阀关闭

bit   dr;

bit   Dcf_state=1 ;

bit   Halfsecond=0;

bit   Onesecond=0;

//////////////////////////////

sbit   Mydress_set=P2^5 ;

sbit    P_uplimite =P2^6 ;

sbit   P_lowlimite=P2^7;

sbit   Stor=P3^2;

sbit    myint=P3^3;

sbit   ADC_wr     =P3^6;

sbit   ADC_rd     =P3^7;

sbit   xuantong   =P1^7;

sbit   addrset=P1^2;

sbit   upset=P1^3;

sbit   lowset=P1^4;

/////////////////////////

uchar code   Myreturnstateopen[3] ={0x01,0x01,0x00};

uchar code   Myreturnstateclose[3]={0x01,0x01,0x01};

uchar code   Myreturnopen[3] ={0x01,0x01,0x10};

uchar code   Myreturnclose[3]={0x01,0x01,0x20};

uchar receive_count=0;

uchar mysend[6],aq[8];

uchar Adc_value;

unsigned  long   Mycount=0;

uchar jishi=0;  //定时一秒计数

uint crc=0,myaw=0;

uint crc16(unsigned char puchMsg, unsigned int usDataLen);

bit  yifasong=0;

void Beginsend( uchar Me );

bit check_modbus() ;

void Open_dcf() ;

void Close_dcf();

void timer0() ;

void uart_init(void) ;

void delay(uint z) ;

void Read_adc();

void  Tosend();

/////////

/延时/

void delay(uint z)

{

  uchar y;

while(z--)

for(y=113;y>0;y--);

}

/串口初始化/

void uart_init(void)   interrupt 4    using 1

{

if(RI)

           {  

                  aq[receive_count]=SBUF;

    RI=0;

receive_count++;

if(0==receive_count%8)

{

yifasong=0;

receive_count=0;

};

                       

                    RI=0;

              }

}

/定时器0初始化/

void timer0()  interrupt 1    using 1

{

 TH0=0x4b;

TL0=0x63;

jishi++;

if (0==jishi%10) {

 Halfsecond=1;

aq[0]=0;aq[1]=0;aq[2]=0;aq[3]=0;aq[4]=0;aq[5]=0;aq[6]=0;aq[7]=0;receive_count=0;

}

   

}  

void Read_adc()

{  

  ADC_rd=1;

   ADC_wr=1;

   _nop_();

    _nop_();

   _nop_();

   _nop_();

   myint=1;

   P0=0xff;        

ADC_wr=0;

    _nop_();

   _nop_();

   _nop_();

   _nop_();

       ADC_wr=1;                        

while( myint==1);    

      ADC_rd=0;                    

     _nop_();

     _nop_();

     _nop_();

    _nop_();

    _nop_();

   

    Adc_value=P0;                   //读出的数据赋与addate

    ADC_rd=1;

}

void Open_dcf()

{

 Dcf_open=0;    delay(1200); Dcf_open=1;  Dcf_state=1;

}

void Close_dcf()

{

 Dcf_close=0;   delay(1200);Dcf_close=1; Dcf_state=0;

}

void Read_Pressure()  

{  

   Read_adc()  ;

if (Dcf_state)

   {

     if((Adc_value<Pressure_lowdata)|| (Adc_value>Pressure_updata))

         {

              delay(1200);

                    if((Adc_value<Pressure_lowdata)|| (Adc_value>Pressure_updata)) {   Close_dcf(); }

           }

      else

          {                 ; }

    }

 

else

  {

    if((Adc_value>Pressure_lowdata)&&(Adc_value<Pressure_updata))

       {        delay(1200);

                    if((Adc_value>Pressure_lowdata)&&(Adc_value<Pressure_updata))   {  Open_dcf(); }

  }

  else        ;

   }

}

void initialize()

{

TMOD=0x20;

SCON=0x50;//串口通讯方式1

TH1=0xfd;//波特率9600

TL1=0xfd;

TH0=0x4b;

TL0=0x63;

TI=0;//发送中断标志位清零

RI=0;//接收中断标志位清零

Mydress_set=1;P_lowlimite=1; P_uplimite=1; xuantong=1;

Mydress_set=0;delay(20);addrset=1;delay(20);addr=P0;

delay(20);

addrset=0;Mydress_set=1;delay(200);P0=0xff;

P_lowlimite=0;delay(20);lowset=1;delay(20);Pressure_lowdata=P0;

delay(20);

lowset=0;P_lowlimite=1;P0=0xff;            

 P_uplimite=0; delay(20);upset=1;Pressure_updata=P0;delay(20);upset=0;P_uplimite=1;P0=0xff;

 xuantong=0;

}

void main(void)

{

IE=0x92;

   TR0=1;TR1=1;

        // WDTRST=0x1E;

           // WDTRST=0xE1;//初始化看门狗

   

       initialize();

 

       Stor=0;

for(;;)  { // WDTRST=0x1E;

            //WDTRST=0xE1;//喂狗指令

 if (Halfsecond==1)  {

                    Halfsecond=0;

                     Read_Pressure();

      }

      //够一秒开始转换

if(receive_count==0&&(yifasong==0))

              {   Stor=0;  

  dr= check_modbus();

                       if (dr&&addr==aq[0])

                         {                     if(aq[1]==0x05)

                                                   

                                                            switch ( aq[3])

                                                              {

                                           case  0x00     :    

                                                               

                 if(!Dcf_state)      Open_dcf();

              Beginsend(0) ;           break;

                                                             case  0x01     :                                                                

                                                             

                                                            if(Dcf_state)      Close_dcf();

                                                     

                                                          Beginsend(1);          

                                                               break;

                             

                                                                 default  :             ;

                                          }

             

                                    else if(aq[1]==0x01)

                                                   

                      {

                 if(Dcf_state)

{   Beginsend(2);

                                                                           }

                        else  

                 

                                                                      {   Beginsend(3);  

                                                                            }

                          }

                                  else;

                }

                     else

            ;

               }

       }    

}

void Beginsend(uchar Me )

{

uchar i;

ES=0; Stor=1;

TI=0;

mysend[0]=addr;

switch(Me)

{

case 0:

       { for(i=1;i<4;i++)

              {

 

              mysend[i] =  Myreturnopen[i-1];

               }

i=0;

}break;

case 1:

{for(i=1;i<4;i++)

              {

 

              mysend[i] =   Myreturnclose[i-1];

               } i=0;}break;

case 2:

     {   for(i=1;i<4;i++)

              {

 

              mysend[i] = Myreturnstateopen[i-1];

               } i=0;}break;

case 3:

{for(i=1;i<4;i++)

              {

 

               mysend[i] =  Myreturnstateclose[i-1];

}i=0;}break;

default : ;}

myaw=crc16(mysend,4);

mysend[4] =myaw&0x00ff;

mysend[5] =(myaw>>8)&0x00ff;

for(i=0;i<6;i++)

      {

   

    SBUF=mysend[i];

   

while(TI!=1);

TI=0;

       }

Stor=0;

ES=1;

yifasong=1;

}

bit check_modbus()

{

uchar m,n   ;

 

crc=crc16(aq,6);

 m=crc;n=crc>>8&0x00ff;

if(aq[6]==m&&aq[7]==n)

return    1 ;

else

return    0;

}

uint crc16(uchar puchMsg, uint usDataLen)

{

uchar uchCRCHi = 0xFF ; // 高CRC字节初始化

uchar uchCRCLo = 0xFF ; // 低CRC 字节初始化

unsigned long uIndex ; // CRC循环中的索引

while (usDataLen--) // 传输消息缓冲区

{

uIndex = uchCRCHi ^ puchMsg++ ; // 计算CRC

uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;

uchCRCLo = auchCRCLo[uIndex] ;

}

return (uchCRCHi  | uchCRCLo<<8);

}

/CRC校验/

// CRC 高位字节值表

modbus程序应包含通讯模块,modbus读写指令生成模块,人机交互等主要组成部分。通过人机交互,设定前端设备id,以及通讯参数,寄存器地址等,通过modbus指令生成模块生成指令,并将指令通过通讯模块送出,并接收返回数据 ,数据解析后通过人机交互窗口显示。

无需关心数据是否接收完毕,只要有数据发过来,都收到自己的缓冲区当中。

在应用层,打开一个任务以定期扫描缓冲区中的新数据。 如果有新数据,确定其是否为必需的协议帧。 通过帧头帧尾标识符还有校验等判断接收帧的正确性,如果正确再处理,不正确丢弃。

Modbus没有固定的帧头标记,长度也没有固定。 判断时,首先查找具有正确地址的字符,然后找出后续功能代码是否正确。 根据功能代码,确定后续数据有多长并进行校验。 如果验证正确,则说明帧是正确的。

扩展资料:

举例说明如下:

从站地址03,从0开始读取10个寄存器,则接收到的帧为03 03 00 00 00 0a xx xx,查找从站地址03的字节,找到后,以下功能码为03,符合功能码范围。

该功能码的数据包括固定为8个字节的校验和,然后在其后没有8个字节时,表示其已被没收,然后在关闭后进行判断。 如果正确,则可以在应用层中正确处理该帧。

以上就是关于关于C#编写modbus通讯协议的求助全部的内容,包括:关于C#编写modbus通讯协议的求助、单片机串口modbus协议通信程序,或者讲一下详细过程怎么写也行!谢谢了!、单片机modbus下位机程序怎么编写等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zz/10640783.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-10
下一篇2023-05-10

发表评论

登录后才能评论

评论列表(0条)

    保存