Arduino mega 2560与Uno基于Modbus协议的通信实现

基于Modbus协议的板间通信

大家好! 如果觉得我写的还行,记得关注本人博客并点赞呦,第一次写博客,还请各位多多包涵,本篇文章主要为大家展示了Arduino mega 2560与Uno板子基于Modbus协议双向通信的实现过程。

内容如下

  1. Arduino mega 2560主板
  2. Arduino uno 从板
  3. CRC校验算法
  4. 总结

1 .Arduino mega 2560 主板

我们将Arduino mega 2560作为主板,用它向从板Uno发送经过Modbus协议打包后的消息帧,我们在此使用RTU消息帧模式,将要发送的消息帧定义成五位数组的模式,包括8bit主板地址码,8bit功能码,8bit数据位及16bit的CRC校验码,利用CRC校验保证传输消息的正确性,消息帧中的功能码则对应与从板的不同功能,在收到功能码后从板执行对应功能 。

Arduino mega 2560 主板主要代码

主板上消息帧发送部分的代码如下:

void SendFrameA()  //帧发送函数
 {
    
   int bufferSize=3;  
   int h;
   crc=calculateCRC(&buffer[0],bufferSize);  //crc计算 并把结果装到buffer数组中
   buffer[bufferSize]=crc&0x00ff;  //低字节先加入
   bufferSize++;
   buffer[bufferSize]=crc>>8;  //高字节后加入
   bufferSize++;

   Send(&buffer[0],bufferSize); //调用发送函数 

   Serial.print("Send buffer:0x");  //串口显示
   for(h=0;h<5;h++)
     {
       Serial.print(buffer[h],HEX);
       delay(10);
     }
     Serial.println(" ");
 }
 
 void Send(uint8_t* data,uint8_t arraySize) //发送函数 按位发送
 {
  for(int i=0;i<arraySize;i++)
  {
    Serial2.write(*(data+i));      
  }
 }

2. Arduino uno 从板

Arduino uno作为我们的从板部分,用它接我们的外设部分,即配套的功能扩展板,在这部分我们依据Modbus协议定义了接收部分的函数,在该板收到主板所发送的消息帧后提取其中的功能码,并依据接收到的消息算出新的CRC,并将其与主板发送来的CRC进行比较,如果两者相同,就代表传输无误,便执行功能码对应的功能,如果两者不同,则返回错误信息,从而使主板重发消息,功能在执行完毕后也向主板发送返回信息,并使主板根据其返回信息 显示通信完成与否。

Arduino uno 从板主要代码

从板上消息帧接收部分的代码如下:

int8_t Receive()  //接收函数
{
  int recSize;
  unsigned int recrc;
  
  if(Serial2.available()==0)
  {
    return 0;
  }
  delay(15);
  recSize=0;
  while(Serial2.available() > 0)
  {
    recBuffer[recSize] = Serial2.read();
    recSize++;
  }
  recrc=((recBuffer[recSize - 1]<<8)|recBuffer[recSize - 2]);
  
   if(calculateCRC(&recBuffer[0],recSize - 2)==recrc) //CRC帧检测
   {
     int k;
     Serial.print("Receive buffer:0x");
     for(k=0;k<5;k++)
     {
       Serial.print(recBuffer[k],HEX);
       delay(10);
     }
     Serial.println(" ");
     switch(recBuffer[1])  //根据接受的消息中的功能码 选择执行相应功能
     {
       case 0x10: RUNLED();break;
       case 0x20: Temp();break;
       case 0x30: RGB();break;
       case 0x40: MUSIC();break;    
     }   
     recSize = 0;
     return 0;
   }
}

3. CRC校验算法

在此次通信实现过程中,我们的CRC校验采用了查表法实现,具体实现过程需要先定义CRC 高位字节值表和CRC 低位字节值表,然后调用事先写好的校验算法函数查表获得消息对应的CRC高低位值,具体内容如下。

1.CRC 高位字节值表

// CRC 高位字节值表
const byte chCRCHTalbe[] =
{
  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
};

2.CRC 低位字节值表

// CRC 低位字节值表
const byte chCRCLTalbe[] =
{
  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
};

3.CRC 校验函数模块

//CRC校验算法
 unsigned short calculateCRC(byte* pchMsg, unsigned short DataLen)
{
  byte chCRCHi = 0xFF; // 高CRC字节初始化
  byte chCRCLo = 0xFF; // 低CRC字节初始化
  unsigned short Index;         // CRC循环中的索引
  while (DataLen--)
  {
    // 计算CRC
    Index = chCRCLo ^ *pchMsg++ ;
    chCRCLo = chCRCHi ^ chCRCHTalbe[Index];
    chCRCHi = chCRCLTalbe[Index] ;
  }
  return ((chCRCHi << 8) | chCRCLo) ;//CRC校验算法
}

4. 总结

本次基于Modbus通信协议的通信过程,我们使用到了Arduino mega 2560,Arduino Uno,多功能扩展板Easy MIX V1以及LCM12864液晶显示屏,最终实现了基于Modbus协议的四种数据功能的传输,双向通信过程中,主从板所调用的帧发送和接收函数基本一致。在此过程中LCM12864的显示功能使用到了U8glib库文件,在Uno板与计算机通信的同时又与mega板通信,由于其硬串口的不足,需要我们自己进行软串口的定义,在主板程序中还涉及屏幕上二级菜单的设计,具体完整代码及所需库文件就不在此处进行详细展示,如各位需要,欢迎随时私信联系,期待和大家的共同探讨与学习。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值