OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8099|回复: 23

Modbus主机如何采集Modbus从机所测得的数据

[复制链接]

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
发表于 2016-7-19 12:03:09 | 显示全部楼层 |阅读模式
15金钱
我现在是 Modbus从机可以准确的采集SHT10的温湿度,MQ-2气体,和光照指标 上位机用 Modbus Poll显示。
现在想 用另一个单片机  采集到从机的这些环境指标 发送至串口助手 怎么办?

最佳答案

查看完整内容[请看2#楼]

我做完从机,采集完环境的数据,可以用Modbus Poll作为主机来显示从机的数是多少。所以我就不用关心主机是怎么工作的,是吧。 现在不用Modbus Poll做主机了,用另外一个单片机做主机,主机怎么才能收到从机采集的数呢? 有没有Modbus主从能通上信的小例程。谢谢。
越努力,越优秀;越独立,越自由
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-19 16:59:09 | 显示全部楼层
我就服这样自己都没弄过,或者甚至自己都不明白的人就在这给别人解决问题的人,真是了不起啊!!你们是提供给别人自己想象中的答案来实现自我价值,是么,这样就显着自己很会一样,是么
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-19 12:03:10 | 显示全部楼层
  我做完从机,采集完环境的数据,可以用Modbus Poll作为主机来显示从机的数是多少。所以我就不用关心主机是怎么工作的,是吧。 现在不用Modbus Poll做主机了,用另外一个单片机做主机,主机怎么才能收到从机采集的数呢? 有没有Modbus主从能通上信的小例程。谢谢。
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-19 13:32:04 | 显示全部楼层
yklstudent 发表于 2016-7-19 13:19
你要做的就是做个MODBUS协议主机,周期读取MODBUS协议从机的内容;

是啊,可是主机的Modbus协议怎么读取呢。 这是我从机部分 Modbus内容:
[mw_shl_code=c,true]/*******************************串口发送函数 ********************************/
void Begin_send(void)
{
        DE_OUT;      //处于发送
        uartsends(sendBuf,sendCount);
        DE_IN;              //发送完后将485置于接收状态
  receCount = 0;   //清接收地址偏移寄存器
}


//fuction:01 读单个或多个线圈状态
void readCoils(void)
{
uint addr;
uint tempAddr;
uint byteCount;
uint  bitCount;
uint crcData;
uint  position;
uint  i,k;
uint tempData;
uchar  exit = 0;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr;
bitCount = (receBuf[4]<<8) + receBuf[5]; //读取的位个数
byteCount = bitCount / 8;    //字节个数
if(bitCount%8 != 0)
  byteCount++;      
  for(k=0;k<byteCount;k++)//字节位置
  {
    position = k + 3;
    sendBuf[position] = 0;
    for(i=0;i<8;i++)
    {
      getCoilVal(tempAddr,&tempData);
      sendBuf[position] |= tempData << i;
      tempAddr++;
      if(tempAddr >= addr+bitCount)//读完
      {
        exit = 1;
        break;
      }
    }
    if(exit == 1)
    break;
  }
  sendBuf[0] = LocalAddr;
  sendBuf[1] = 0x01;
  sendBuf[2] = byteCount;
  byteCount += 3;
  crcData = crc16(sendBuf,byteCount);
  sendBuf[byteCount] = crcData & 0xff;
  byteCount++;
  sendBuf[byteCount] = crcData >> 8;
  sendCount = byteCount + 1;
  Begin_send();   
}

//fuction:02 读取线圈输入(只读寄存器)状态
void readInPutCoils(void)
{
uint addr;
uint tempAddr;
uint byteCount;
uint  bitCount;
uint crcData;
uint  position;
uint  i,k;
uint tempData;
uchar  exit = 0;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr +10000;        //只读线圈寄存器偏移地址10000
bitCount = (receBuf[4]<<8) + receBuf[5]; //读取的位个数
byteCount = bitCount / 8;    //字节个数
if(bitCount%8 != 0)
  byteCount++;      
  for(k=0;k<byteCount;k++)//字节位置
  {
    position = k + 3;
    sendBuf[position] = 0;
    for(i=0;i<8;i++)
    {
      getCoilVal(tempAddr,&tempData);
      sendBuf[position] |= tempData << i;
      tempAddr++;
      if(tempAddr >= addr+10000+bitCount)//读完
      {
        exit = 1;
        break;
      }
    }
    if(exit == 1)
    break;
  }
  sendBuf[0] = LocalAddr;
  sendBuf[1] = 0x02;
  sendBuf[2] = byteCount;
  byteCount += 3;
  crcData = crc16(sendBuf,byteCount);
  sendBuf[byteCount] = crcData & 0xff;
  byteCount++;
    sendBuf[byteCount] = crcData >> 8;
  sendCount = byteCount + 1;
  Begin_send();   
}

/********function code : 03,读取多个寄存器值 ********/

void readRegisters(void)
{
        uint addr;
        uint tempAddr;
        uint crcData;
        uint readCount;
        uint byteCount;
        uint i;
        uint tempData = 0;
        addr = (receBuf[2]<<8) + receBuf[3];
        tempAddr = addr+40000;      //+40000,保持寄存器偏移地址
        readCount = (receBuf[4]<<8) + receBuf[5]; //要读的个数 ,整型
        byteCount = readCount * 2;                  //每个寄存器内容占高,低两个字节
        for(i=0;i<byteCount;i+=2,tempAddr++)
        {
              getRegisterVal(tempAddr,&tempData);   
              sendBuf[i+3] = tempData >> 8;        
              sendBuf[i+4] = tempData & 0xff;  
        }
        sendBuf[0] = LocalAddr;
        sendBuf[1] = 3;  //function code : 03
        sendBuf[2] = byteCount;
        byteCount += 3;             //加上前面的地址,功能码,地址 共3+byteCount个字节
        crcData = crc16(sendBuf,byteCount);
        sendBuf[byteCount] = crcData & 0xff;   // CRC代码低位在前
        byteCount++;
        sendBuf[byteCount] = crcData >> 8 ;           //高位在后
        sendCount = byteCount + 1;                        //例如byteCount=49,则sendBuf[]中实际上有49+1个元素待发
        Begin_send();
}
//fuction 04:读取输入寄存器
void readInPutRegisters(void)
{
        uint addr;
        uint tempAddr;
        uint crcData;
        uint readCount;
        uint byteCount;
        uint i;
        uint tempData = 0;
        addr = (receBuf[2]<<8) + receBuf[3];
        tempAddr = addr+30000;  //+输入寄存器偏移地址:30000
        readCount = (receBuf[4]<<8) + receBuf[5]; //要读的个数 ,整型
        byteCount = readCount * 2;                  //每个寄存器内容占高,低两个字节
        for(i=0;i<byteCount;i+=2,tempAddr++)
        {
              getRegisterVal(tempAddr,&tempData);   
              sendBuf[i+3] = tempData >> 8;        
              sendBuf[i+4] = tempData & 0xff;  
        }
        sendBuf[0] = LocalAddr;
        sendBuf[1] = 4;  //function code : 04
        sendBuf[2] = byteCount;
        byteCount += 3;             //加上前面的地址,功能码,地址 共3+byteCount个字节
        crcData = crc16(sendBuf,byteCount);
        sendBuf[byteCount] = crcData & 0xff;   // CRC代码低位在前
        byteCount++;
        sendBuf[byteCount] = crcData >> 8 ;           //高位在后
        sendCount = byteCount + 1;                        //例如byteCount=49,则sendBuf[]中实际上有49+1个元素待发
        Begin_send();
}
         
//fuction:05 ,强制单个线圈
void forceSingleCoil(void)
{
uint addr;
uint tempAddr;
uint tempData;
uint  onOff;
uchar i;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr;
onOff = (receBuf[4]<<8) + receBuf[5];
if(onOff == 0xff00)
{
  tempData = 1;//设为ON
}
else if(onOff == 0x0000)//设为OFF
{
  tempData = 0;
}
setCoilVal(tempAddr,tempData);
for(i=0;i<receCount;i++)
{
  sendBuf = receBuf;
}
sendCount = receCount;
Begin_send();
}

/****************fuction:06设置单个寄存器ok**********************************************************/

//主机器发送  地址,功能码,寄存器高位,寄存器低位,数据数高位, 数数低位,CRC低位,CRC高位
//例如设置D0 发送,        01      06         00            3F       00                         01                   */
/*********************************************************************************/

void presetSingleRegister(void)
{
uint addr;
uint tempAddr;
uint tempData;
uint crcData;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = (addr+40000);
tempData = (receBuf[4]<<8) + receBuf[5];
setRegisterVal(tempAddr,tempData);  
sendBuf[0] = LocalAddr;
sendBuf[1] = 6;    //function code : 16
sendBuf[2] = addr >> 8;  //寄存器地址高位
sendBuf[3] = addr & 0xff;//寄存器地址低位
sendBuf[4] =receBuf[4];
sendBuf[5] =receBuf[5];
crcData = crc16(sendBuf,6);//生成CRC校验码
sendBuf[6] = crcData & 0xff;  //CRC代码低位在前
sendBuf[7] = crcData >> 8;          //高位在后
sendCount = 8;
Begin_send();
}

/********从机响应主机问询函数,function code : 15,强置多线圈值 *********/
//////////////询问数据包格式:
///////////////////////// receBuf[0] receBuf[1]  receBuf[2]     receBuf[3]   receBuf[4]    receBuf[5]   receBuf[6]  receBuf[7]  receBuf[8] ... receBuf[9]   receBuf[10]
//询问数据格式:receBuf[]={从站地址, 功能码,  起始地址高位,起始地址低位,寄存器数高位,寄存器数低位, 字节计数,  数据高位,  数据低位,... 校验码低位, 校验码高位}
/****************************************************************************/
void forceMultipleCoils(void)
{
uint addr;
uint tempAddr;
uint byteCount;
uint  bitCount;
uint crcData;
uint tempData;
uint  i,k;
uchar  exit = 0;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr;
bitCount = (receBuf[4]<<8) + receBuf[5];
byteCount = bitCount / 8;    //字节个数
if(bitCount%8 != 0)
  byteCount++;     
  for(k=0;k<byteCount;k++)//字节位置
  {
    for(i=0;i<8;i++)
    {
      tempData = (receBuf[k+3] >>i)&0x01;  
      setCoilVal(tempAddr,tempData);
      tempAddr++;
      if(tempAddr >= addr+bitCount)//读完
      {
        exit = 1;
        break;
      }
    }
  
    if(exit == 1)
    break;
  }
sendBuf[0] = LocalAddr;
sendBuf[1] = 15;    //function code : 16
sendBuf[2] = addr >> 8;  //寄存器地址高位
sendBuf[3] = addr & 0xff;//寄存器地址低位
sendBuf[4] = bitCount >> 8;//待设置寄存器数量高位
sendBuf[5] = bitCount & 0xff;//待设置寄存器数量低位
crcData = crc16(sendBuf,6);//生成CRC校验码
sendBuf[6] = crcData & 0xff;  //CRC代码低位在前
sendBuf[7] = crcData >> 8;          //高位在后
sendCount = 8;
Begin_send();
}

/********从机响应主机问询函数,function code : 16,设置多个寄存器值 *********/
//////////////询问数据包格式:
///////////////////////// receBuf[0] receBuf[1]  receBuf[2]     receBuf[3]   receBuf[4]    receBuf[5]   receBuf[6]  receBuf[7]  receBuf[8] ... receBuf[9]   receBuf[10]
//询问数据格式:receBuf[]={从站地址, 功能码,  起始地址高位,起始地址低位,寄存器数高位,寄存器数低位, 字节计数,  数据高位,  数据低位,... 校验码低位, 校验码高位}
/****************************************************************************/
void presetMultipleRegisters(void)
{
uint addr;
uint tempAddr;
uint setCount;
uint crcData;
uint tempData;
uchar i;
addr = (receBuf[2]<<8) + receBuf[3];
tempAddr = addr+40000;
setCount = (receBuf[4]<<8) + receBuf[5];
for(i=0;i<setCount;i++,tempAddr++)
{
  tempData = (receBuf[i*2+7]<<8) + receBuf[i*2+8];//待设置寄存器值
  setRegisterVal(tempAddr,tempData);  
}
sendBuf[0] = LocalAddr;
sendBuf[1] = 16;    //function code : 16
sendBuf[2] = addr >> 8;  //寄存器地址高位
sendBuf[3] = addr & 0xff;//寄存器地址低位
sendBuf[4] = setCount >> 8;//待设置寄存器数量高位
sendBuf[5] = setCount & 0xff;//待设置寄存器数量低位
crcData = crc16(sendBuf,6);//生成CRC校验码
sendBuf[6] = crcData & 0xff;  //CRC代码低位在前
sendBuf[7] = crcData >> 8;          //高位在后
sendCount = 8;
Begin_send();
}


/*************************查询uart接收的数据包内容函数 **************************/
////函数功能:丛机根据串口接收到的数据包receBuf[1]里面的内容,即function code执行相应的命令
/********************************************************************************/
void checkComm0Modbus(void)                   //10ms内必须响应接收数据
{
uint crcData;
uint tempData;
uint temp;
if(receCount > 4)                 //如果接收到数据
{         
  switch(receBuf[1])
  {
case 1:                                                                //读取寄存器(一个或多个)
   {         
      if(receCount >= 8)  //从询问数据包格式可知,receCount应该等于8        ,接收完成一组数据应该关闭接收中断
        {            
          if(receBuf[0]==LocalAddr)   //核对地址
            {         
              crcData = crc16(receBuf,6);                     //核对校验码
              temp=receBuf[7];
              temp=(temp<<8)+receBuf[6];
              if(crcData == temp)
              if(receBuf[1] == 1)
                {
                readCoils();                        //读取线圈输出状态(一个或多个)
                }
                receCount = 0;                                                                           
             }       
          
        }      
          break;
      }
case 2:                                                                //读取寄存器(一个或多个)
   {         
      if(receCount >= 8)  //从询问数据包格式可知,receCount应该等于8        ,接收完成一组数据应该关闭接收中断
        {            
          if(receBuf[0]==LocalAddr)   //核对地址
            {         
              crcData = crc16(receBuf,6);                     //核对校验码
              temp=receBuf[7];
              temp=(temp<<8)+receBuf[6];
              if(crcData == temp)
              if(receBuf[1] == 2)
                {
                readInPutCoils();                        //读取线圈输入状态(一个或多个)
                }
                                                        receCount = 0;                                                                           
             }       
          
        }      
          break;
      }   
   case 3:                                                                //读取寄存器(一个或多个)
   {         
      if(receCount >= 8)  //从询问数据包格式可知,receCount应该等于8        ,接收完成一组数据应该关闭接收中断
        {            
          if(receBuf[0]==LocalAddr)   //核对地址
            {         
              crcData = crc16(receBuf,6);                     //核对校验码
              temp=receBuf[7];
              temp=(temp<<8)+receBuf[6];
              if(crcData == temp)
              if(receBuf[1] == 3)
              {
                readRegisters();                        //读取保持寄存器(一个或多个)
               }
                                                        receCount = 0;                                                                           
            }                  
        }      
        break;
   }
case 4:                                                                //读取寄存器(一个或多个)
   {         
      if(receCount >= 8)  //从询问数据包格式可知,receCount应该等于8        ,接收完成一组数据应该关闭接收中断
      {            
          if(receBuf[0]==LocalAddr)   //核对地址
          {         
            crcData = crc16(receBuf,6);                     //核对校验码
            temp=receBuf[7];
            temp=(temp<<8)+receBuf[6];
            if(crcData == temp)
            if(receBuf[1] == 4)
              {
              readInPutRegisters();                        //读取输入寄存器(一个或多个)
              }
                                                receCount = 0;                                                                           
          }       
          
      }      
          break;
    }
   case 5:                                                                //读取寄存器(一个或多个)
   {         
      if(receCount >= 8)  //从询问数据包格式可知,receCount应该等于8        ,接收完成一组数据应该关闭接收中断
      {            
          if(receBuf[0]==LocalAddr)   //核对地址
          {         
            crcData = crc16(receBuf,6);                     //核对校验码
            temp=receBuf[7];
            temp=(temp<<8)+receBuf[6];
            if(crcData == temp)
            if(receBuf[1] == 5)
              {
              forceSingleCoil();                        //强置单个线圈 状态
              }
                                                receCount = 0;                                                                           
          }       
          
      }      
          break;
    }
case 6: if(receCount >= 8)
           {   
             if(receBuf[0]==LocalAddr)
                  {
                    crcData = crc16(receBuf,6);
                    temp=receBuf[7];
                    temp=(temp<<8)+receBuf[6];
                    if(crcData == temp)
                    if(receBuf[1] == 6)
                      {
                          presetSingleRegister();      //预置单个保持寄存器
                      }
                    receCount = 0;                                                                                                                                         
                 }         
          }
                 break;
case 15://设置多个线圈
      tempData = receBuf[6];
      tempData += 9; //数据个数
      if(receCount >= tempData)
      {
          if(receBuf[0]==LocalAddr )
            {
                crcData = crc16(receBuf,tempData-2);
              if(crcData == (receBuf[tempData-1]<<8)+ receBuf[tempData-2])//更改了??
                {
                  forceMultipleCoils();  
                }
            }
                  receCount = 0;
        }
      break;        
  case 16:                                                //设置多个寄存器
   {
        tempData = (receBuf[4]<<8) + receBuf[5];                 //设置寄存器个数
        tempData = tempData * 2;                                                 //数据个数=        寄存器*2
        tempData += 9;       //从询问数据包格式可知,receCount应该等于9+byteCount
        if(receCount >= tempData)
          {         
            if(receBuf[0]==LocalAddr )        //核对地址
                {         
                  crcData = crc16(receBuf,tempData-2);
                     temp=receBuf[tempData-1];
                  temp=(temp<<8)+receBuf[tempData-2];
                  if(crcData == temp)
                    {  
                    presetMultipleRegisters();  
                    }
                }
              receCount = 0;
            }
        break;
      }   
  default: break;  
  }
}
}

/********************以下为移植的数据修改区**************************************************/
//取线圈状态 返回0表示成功
uint getCoilVal(uint addr,uint *tempData)
{
uint tempAddr;
tempAddr = addr;//只取低8位地址
switch(tempAddr)
{
//  case RWSTATUES0:      *tempData = RWstatus0; break;
  default:  break;     
}
return  0;
}

uint setCoilVal(uint addr,uint tempData)//设定线圈状态 返回0表示成功
{
uint tempAddr;
tempAddr = addr;
switch(tempAddr)
{
//  case RWSTATUES0:   RWstatus0= tempData; break;

  default: break;  
}
return 0;
}
       

/*******************************读取寄存器内容函数 返回0表示成功**************************/
uint getRegisterVal(uint addr,uint *tempData)
{
switch(addr)                                                                 
{
case WEIDU: { *tempData =Temperature ; break; }
case SHIDU: { *tempData =Humidity ; break; }
case CO2: { *tempData =Co2 ; break; }
case RIZHAO: { *tempData =Rizhao ; break; }
default:  break;  
}
return 0;
}


/*******************************设置寄存器内容函数 *返回0表示成功*************************/

uint setRegisterVal(uint addr,uint tempData)
{
switch(addr)
{
case WEIDU: {Temperature=tempData ;break; }
case SHIDU: { Humidity=tempData ;break; }
case CO2: { Co2=tempData ;break; }
case RIZHAO: { Rizhao=tempData  ; break; }
}
return 0;
}[/mw_shl_code]
越努力,越优秀;越独立,越自由
回复

使用道具 举报

0

主题

183

帖子

0

精华

高级会员

Rank: 4

积分
684
金钱
684
注册时间
2016-1-27
在线时间
184 小时
发表于 2016-7-19 14:08:16 | 显示全部楼层
song15032 发表于 2016-7-19 13:32
是啊,可是主机的Modbus协议怎么读取呢。 这是我从机部分 Modbus内容:
[mw_shl_code=c,true]/********* ...

我给你一块钱,你给我一根冰棍,我不给你钱,你就不给我冰棍,这就是协议
回复

使用道具 举报

22

主题

751

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1605
金钱
1605
注册时间
2015-6-10
在线时间
222 小时
发表于 2016-7-19 14:35:33 | 显示全部楼层
你要是只是想发给电脑  可以换一个modbus调试工具  

或者不用modbus协议

你要是想做主机,从机你都会了,主机有什么不会的
回复

使用道具 举报

10

主题

146

帖子

0

精华

高级会员

Rank: 4

积分
764
金钱
764
注册时间
2015-12-19
在线时间
99 小时
发表于 2016-7-19 14:40:07 | 显示全部楼层
MQ-2   这个能线性稳定使用吗?现在读研的课题跟这个有关……   
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-19 14:55:50 | 显示全部楼层
止天 发表于 2016-7-19 14:35
你要是只是想发给电脑  可以换一个modbus调试工具  

或者不用modbus协议

同学,主从机不一样啊。
从机是一直将传感器采集的数发出去,是这样写的:[mw_shl_code=c,true]/*******************************读取寄存器内容函数 返回0表示成功**************************/
uint getRegisterVal(uint addr,uint *tempData)
{
switch(addr)                                                                 
{
case WEIDU: { *tempData =Temperature ; break; }
case SHIDU: { *tempData =Humidity ; break; }
case CO2: { *tempData =Co2 ; break; }
case RIZHAO: { *tempData =Rizhao ; break; }
default:  break;  
}
return 0;
}


/*******************************设置寄存器内容函数 *返回0表示成功*************************/

uint setRegisterVal(uint addr,uint tempData)
{
switch(addr)
{
case WEIDU: {Temperature=tempData ;break; }
case SHIDU: { Humidity=tempData ;break; }
case CO2: { Co2=tempData ;break; }
case RIZHAO: { Rizhao=tempData  ; break; }
}
return 0;
}
[/mw_shl_code]

可是主机要怎么才获取它的数据呢? 有没有简单的例程啊
越努力,越优秀;越独立,越自由
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-19 14:58:49 | 显示全部楼层
njjh1718 发表于 2016-7-19 14:40
MQ-2   这个能线性稳定使用吗?现在读研的课题跟这个有关……

我有关于MQ-2的资料 你看看吧,不知道有没有帮助

MQ-2烟雾气体传感器模块 液化气天然气模块 烟雾模块.rar

2.13 MB, 下载次数: 1491

越努力,越优秀;越独立,越自由
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-19 15:07:54 | 显示全部楼层
不吃鱼的老鼠 发表于 2016-7-19 14:08
我给你一块钱,你给我一根冰棍,我不给你钱,你就不给我冰棍,这就是协议

我懂协议的概念;
我做完从机,采集完环境的数据,可以用Modbus Poll作为主机来显示从机的数是多少。所以我就不用关心主机是怎么工作的,是吧。
现在不用Modbus Poll做主机了,用另外一个单片机做主机,主机怎么才能收到从机采集的数呢? 有没有Modbus主从能通上信的小例程。谢谢。
越努力,越优秀;越独立,越自由
回复

使用道具 举报

0

主题

183

帖子

0

精华

高级会员

Rank: 4

积分
684
金钱
684
注册时间
2016-1-27
在线时间
184 小时
发表于 2016-7-19 16:47:05 | 显示全部楼层
song15032 发表于 2016-7-19 12:03
我做完从机,采集完环境的数据,可以用Modbus Poll作为主机来显示从机的数是多少。所以我就不用关心主机 ...

你把从机搞定了,现在主机不会做?不至于吧
回复

使用道具 举报

0

主题

183

帖子

0

精华

高级会员

Rank: 4

积分
684
金钱
684
注册时间
2016-1-27
在线时间
184 小时
发表于 2016-7-19 16:49:49 | 显示全部楼层
song15032 发表于 2016-7-19 12:03
我做完从机,采集完环境的数据,可以用Modbus Poll作为主机来显示从机的数是多少。所以我就不用关心主机 ...

modbus主从通讯网上有,可以参考
回复

使用道具 举报

22

主题

751

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1605
金钱
1605
注册时间
2015-6-10
在线时间
222 小时
发表于 2016-7-20 08:36:35 | 显示全部楼层
song15032 发表于 2016-7-19 14:55
同学,主从机不一样啊。
从机是一直将传感器采集的数发出去,是这样写的:[mw_shl_code=c,true]/****** ...

你可以把主机要发的东西做成固定码,然后定时发送就行了,就不用写主机程序了。



还有从机是一直将传感器采集的数发出去,

这句话就是不准确的。

modbus你可以看成远程的寄存器,没有说寄存器向cpu主动发东西的

从机不会主动的发数据


回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-20 09:33:14 | 显示全部楼层
止天 发表于 2016-7-20 08:36
你可以把主机要发的东西做成固定码,然后定时发送就行了,就不用写主机程序了。

我没明白主机要发送什么数据啊?
我的从机是采集传感器的,主机就想把从机的数存到主机里,之后我再作别的用。是要将从机采集的数定时发出去么? 还是主机定时采集从机? 我一直弄不明白的是Modbus主机收数据是怎么回事。
越努力,越优秀;越独立,越自由
回复

使用道具 举报

10

主题

146

帖子

0

精华

高级会员

Rank: 4

积分
764
金钱
764
注册时间
2015-12-19
在线时间
99 小时
发表于 2016-7-20 13:07:26 | 显示全部楼层
song15032 发表于 2016-7-19 14:58
我有关于MQ-2的资料 你看看吧,不知道有没有帮助

谢谢你  
回复

使用道具 举报

29

主题

108

帖子

0

精华

高级会员

Rank: 4

积分
613
金钱
613
注册时间
2012-6-15
在线时间
161 小时
发表于 2016-7-20 13:56:17 | 显示全部楼层
song15032 发表于 2016-7-20 09:33
我没明白主机要发送什么数据啊?
我的从机是采集传感器的,主机就想把从机的数存到主机里,之后我再作 ...

如果用的是MODBUS-RTU协议那其实很简单,就是主机请求-》从机应答,从机得有地址还有从机装你采集数据的寄存器地址,既然你都做过从机那应该很好理解,不然你上位机怎么能读到你从机得数据,如果还不理解就百度一下标准协议仔细看看,应用层的协议其实还是很简单的
兴趣使人出色
回复

使用道具 举报

2

主题

23

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
206
金钱
206
注册时间
2016-3-7
在线时间
81 小时
发表于 2016-7-20 14:04:40 | 显示全部楼层
你需要的只是做一个modbus主机程序 参照你做的从机程序
主从实验.jpg
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-20 14:15:23 | 显示全部楼层
qsgang 发表于 2016-7-20 14:04
你需要的只是做一个modbus主机程序 参照你做的从机程序

我可以加你Q么;
我的QQ  517488519
越努力,越优秀;越独立,越自由
回复

使用道具 举报

2

主题

23

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
206
金钱
206
注册时间
2016-3-7
在线时间
81 小时
发表于 2016-7-20 14:23:21 | 显示全部楼层
我可以加你Q么;
我的QQ  517488519

我在从机的基础上做的主机程序(带modbus主从协议 ucosii系统),在战舰V3板上通过实验

ucosii主从 modbus rtu.rar

7.57 MB, 下载次数: 7845

回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-20 16:09:44 | 显示全部楼层
本帖最后由 song15032 于 2016-7-20 16:15 编辑
qsgang 发表于 2016-7-20 14:23
我在从机的基础上做的主机程序(带modbus主从协议 ucosii系统),在战舰V3板上通过实验

很感谢你的分享。思路很清晰,我都能看懂,但是,我觉得和你不是一个方向好像是。
你能看看这是我添加你的从机之后是这样的,可是却通不上信啊:
QQ截图20160720161532.png

LJS_NewEmpty_Project - 从机.rar

2.3 MB, 下载次数: 1519

越努力,越优秀;越独立,越自由
回复

使用道具 举报

2

主题

23

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
206
金钱
206
注册时间
2016-3-7
在线时间
81 小时
发表于 2016-7-21 08:02:29 | 显示全部楼层
很感谢你的分享。思路很清晰,我都能看懂,但是,我觉得和你不是一个方向好像是。
你能看看这是我添加你的从机之后


你到底想搞从机还是主机?被你搞晕了
回复

使用道具 举报

2

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
88
金钱
88
注册时间
2016-8-19
在线时间
13 小时
发表于 2016-8-19 20:03:52 | 显示全部楼层
song15032 发表于 2016-7-20 09:33
我没明白主机要发送什么数据啊?
我的从机是采集传感器的,主机就想把从机的数存到主机里,之后我再作 ...

这个和485通讯是不是一致,主机发送一个数据(0x6),当从机接受到(0x6)开始发送采集到的温度数据?
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-8-23 08:36:50 | 显示全部楼层
18419951276 发表于 2016-8-19 20:03
这个和485通讯是不是一致,主机发送一个数据(0x6),当从机接受到(0x6)开始发送采集到的温度数据?

不知所云。。。
越努力,越优秀;越独立,越自由
回复

使用道具 举报

72

主题

209

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1586
金钱
1586
注册时间
2014-9-11
在线时间
175 小时
发表于 2016-12-19 13:31:55 | 显示全部楼层
学习,谢谢楼主      
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-26 09:08

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表