搜索
bottom↓
回复: 48

终于把modbus程序改好了,能和组态王通讯,发上来供大家参考。

  [复制链接]

出0入0汤圆

发表于 2011-11-3 19:26:23 | 显示全部楼层 |阅读模式
/*********Modbus通信协议**********/
#include<pic.h>
#include <stdio.h>
#include<math.h>
#define uchar unsigned char
#define uint  unsigned int
__CONFIG(0x3b31);
/**********全局变量的定义*********/
uint CRC16=0;
uint wdata,wdata2;//数据寄存器
uchar c[32]; // 命令寄存器
uchar counter=0; //帧前时间计数器
uchar counter2=0; //接受字节计数?
uchar cnt=0;     //数据计数器
uchar mymeter=0; //本机标志位
uchar ADDR_H=0x01;//本机地址
bit flag=0;
/************************初始化*********************************/
  void INIT()
  {
   T2CON=0x4d;        //延时10ms,打开T2
   PR2=249;         
   TXSTA=0X04;        //异步,高速波特率
   SPBRG=0x19;         //波特率为9600
   RCSTA=0X90;        //USART打开,连续接收串行数据
   TRISC=0x80;        //第七位接收,第六位发送
   GIE=1;
   PEIE=1;
   TMR2IE=1;
   RCIE=1;
   mymeter=0;        //本机标志位为0
   counter2=0;        //接受字节数为0
   cnt=0;                //数据计数为
   }
//*******帧前延时时间**********
void delay(uint b)   //延时函数,延时时间为bms
{
  uchar i;
   while(b--)
   {
    for(i=0;i<125;i++)   //延时1ms
      {;}
   }
}

//**********CRC校验函数*********
unsigned int cal_crc( unsigned char  *puchMsg, uchar usDataLen)                //需要校验的数据地址和字节数
{
uint crc=0xffff;
uchar i;
while(usDataLen--!=0)
{
  crc=crc^(*puchMsg);
  for(i=0;i<8;i++)
  {                                   
   if((crc&0x0001)==1)
   {
    crc=crc>>1;
    crc^=0xA001;
   }
   else
   {crc=crc>>1;}
  }
  puchMsg++;
}
return(crc);
}
/***********读数据功能函数**********/
void read_dat()
{
uchar r;
delay(10);
c[0]=1;
c[1]=3;
c[2]=6;      
c[3]=wdata/256;
c[4]=wdata%256;
c[5]=wdata2/256;
c[6]=wdata2%256;
c[7]=wdata2/256;
c[8]=wdata2%256;
CRC16=cal_crc(c,9);
c[9]=CRC16%256;
c[10]=CRC16/256;
for(r=0;r<11;r++)
{
        TXREG=c[r];
    TXEN=1;
        while(TXIF==0||TRMT==0);
    TXEN=0;         
    delay(10);
}          
}
/***********写数据功能函数**********/
void write_dat()
{
uchar i;
delay(10);
wdata=c[4]*256+c[5];
for(i=0;i<8;i++)
{
TXREG=c;
TXEN=1;
while(TXIF==0||TRMT==0);
TXEN=0;
delay(10);
}
}
//*********主函数******************
main()
{
uchar i;
INIT();//初始化程序
flag=0;
wdata=0x44;
wdata2=0x55;
while(1)
{
  if(flag==1)
  {
   flag=0;
   CRC16=c[7]*256+c[6];      //crc校验函数//如果校验正确  或不正确而后分析功能
   if(CRC16==cal_crc(c,6))  //
            {   
                            
                          switch(c[1])
                              {
                              case 0x01:
                                            {    ;
                                                        break;}//取得一组逻辑线圈的当前状态(ON/OFF)
                                  case 0x02:
                                            {   ;
                                                        break;}//取得一组开关输入的当前状态(ON/OFF)
                                  case 0x03:
                                            { read_dat() ;
                                                        break;}//在一个或多个保持寄存器中取得当前的二进制值
                              case 0x04:
                                            {    ;
                                                        break;}//在一个或多个输入寄存器中取得当前的二进制值
                                  case 0x05:
                                            {    ;
                                                        break;}//强置一个逻辑线圈的通断状态
                                   case 0x06:
                                            {write_dat() ;
                                                        break;}//把具体二进值装入一个保持寄存器
                              //……?#############
                              default:  break;
                                  }
                     }
            else //错误报告
                    {
                            c[1]=c[1]|0x80;
                          delay(10);
                          CRC16=cal_crc(c,6);
              c[6]=CRC16%256;
              c[7]=CRC16/256;
              for(i=0;i<8;i++)
                {
                       TXREG=c;
                TXEN=1;
                       while(TXIF==0||TRMT==0);
                TXEN=0;         
                delay(10);
                }       
                }
                        cnt=0;
   }
   else
   asm("NOP");
   }  
}
//*******中断函数**********************
void interrupt pic()      
{  
    if(TMR2IE==1&&TMR2IF==1)     //定时10ms,帧前延时
   {
      TMR2IF=0;
      if(counter>=5)
   {
        counter=5;
   }
      else
   {
        counter++;
   }
}
    if(RCIF==1)
  {
    uchar temp;
    TMR2IE=0;  
   if(counter>=5)   //是帧首
  {
    cnt=0;
        temp=RCREG;   //取出地址码
    counter=0;   //帧前时间清零
        counter2=0;  //收到的字节数
     if(temp==ADDR_H)//判断地址码是否正确
      {
        c[0]=ADDR_H;
        mymeter=1;  //如果正确就使标志位置1       
           }
     else     
     {                                                                  
           mymeter=0;                                                   
          }
   }
  else  
   {
     if(mymeter==1)    //若是本机
       {  
         counter2++;
         c[counter2]=RCREG;
                 if(counter2>=7)
         {
               mymeter=0;
               counter2=0;
                   flag=1;
          }          
       }
    }
         if (OERR==1)
      {
         CREN=0;
         CREN=1;
      }
         counter=0;      //帧前时间清零
         TMR2IE=1;
}     
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2011-12-3 16:01:52 | 显示全部楼层
感谢分享,谢谢LZ,膜拜楼主!

出0入0汤圆

发表于 2011-12-3 16:32:36 | 显示全部楼层
谢谢LZ

出0入0汤圆

发表于 2011-12-3 16:57:36 | 显示全部楼层
mk

出0入0汤圆

发表于 2011-12-3 21:26:11 | 显示全部楼层
mark~~~

出0入0汤圆

发表于 2011-12-3 21:44:01 | 显示全部楼层
mark~

出5入42汤圆

发表于 2011-12-4 01:01:57 | 显示全部楼层
Mark.谢谢lz。

出0入0汤圆

发表于 2011-12-4 01:27:41 | 显示全部楼层
崇拜楼主,让我开眼

出0入0汤圆

发表于 2011-12-4 09:46:44 | 显示全部楼层
果断 支持。  PIC 没有用过,不过听说 工业级的还行!

出0入0汤圆

发表于 2011-12-4 10:55:48 | 显示全部楼层

出0入0汤圆

发表于 2011-12-4 11:16:48 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-12-4 11:22:40 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2011-12-5 12:09:23 | 显示全部楼层
用的是pic16f877a,大家要有兴趣可以多多探讨

出0入0汤圆

发表于 2012-2-6 09:47:27 | 显示全部楼层
mark

出75入4汤圆

发表于 2012-2-6 11:11:39 | 显示全部楼层
买了两块pic16f877还一直没动过,想买个仿真下载器试试

出0入0汤圆

发表于 2012-2-7 22:27:47 | 显示全部楼层
写的不是很方便人看 感觉不是标准的MODBUS通信协议

出0入0汤圆

发表于 2012-2-20 21:37:42 | 显示全部楼层
以前写过一个,有空借鉴一下。

出0入0汤圆

发表于 2012-2-20 22:45:55 | 显示全部楼层
利害!有时间要学习一下。

出0入0汤圆

发表于 2012-2-23 13:25:36 | 显示全部楼层
MODBUS

出0入0汤圆

发表于 2012-2-26 00:30:49 | 显示全部楼层
不错,支持

出0入0汤圆

发表于 2012-4-3 09:32:53 | 显示全部楼层
MARK mark mark

出0入0汤圆

发表于 2013-6-24 12:07:06 | 显示全部楼层
MARK.
         

出0入0汤圆

发表于 2013-7-8 09:50:42 | 显示全部楼层
modbus  主机

出0入0汤圆

发表于 2013-7-22 22:38:02 | 显示全部楼层
开源很彻底啊,赞一个!

出0入0汤圆

发表于 2013-7-25 19:47:18 | 显示全部楼层
谢谢啊

出0入0汤圆

发表于 2013-7-25 20:24:32 | 显示全部楼层
组态王,,,,是电脑端的软件 吧?

出0入0汤圆

发表于 2013-7-26 13:08:54 | 显示全部楼层
mark~~~                                      

出0入0汤圆

发表于 2013-8-14 22:42:14 | 显示全部楼层
....mark.....

出200入0汤圆

发表于 2013-8-14 22:48:45 来自手机 | 显示全部楼层
学习………………

出0入0汤圆

发表于 2013-9-11 21:10:59 | 显示全部楼层
学习学习!

出0入0汤圆

发表于 2014-5-22 09:36:25 | 显示全部楼层
mark下!【把modbus程序改好了,能和组态王通讯】

出0入0汤圆

发表于 2014-5-26 10:01:04 | 显示全部楼层
是PIC的程序,MARK一下

出0入0汤圆

发表于 2014-6-5 10:32:55 | 显示全部楼层
MARK,谢谢楼主分享,

出0入0汤圆

发表于 2014-6-7 18:47:59 | 显示全部楼层
本帖最后由 slaoliu 于 2014-6-7 19:35 编辑

mark.   pic  MODBUS从站程序,组态王读modbus?

出0入0汤圆

发表于 2014-6-11 15:31:17 | 显示全部楼层
条理性差,写的很乱

出0入0汤圆

发表于 2014-9-26 20:48:33 来自手机 | 显示全部楼层
谢谢分享,楼主辛苦了。

出0入0汤圆

发表于 2014-9-26 21:10:45 | 显示全部楼层
标记一下以后留用

出0入0汤圆

发表于 2014-10-3 16:50:05 | 显示全部楼层
校验不通过

出0入0汤圆

发表于 2014-10-3 18:29:25 | 显示全部楼层
谢谢楼主,PIC16F877A已经是很老的芯片了,推荐用PIC16F887,性价高.

出0入0汤圆

发表于 2014-10-6 09:15:04 | 显示全部楼层
不错,谢谢

出0入0汤圆

发表于 2014-10-6 22:49:50 | 显示全部楼层
Modbus协议还是挺好用的,简单,支持的设备多。

出0入0汤圆

发表于 2014-10-15 21:58:42 | 显示全部楼层
还是HMI的界面更容易被接受和使用

出0入0汤圆

发表于 2014-10-15 22:05:20 | 显示全部楼层
lz在搞笑吧。
主要看你指令解释部分,结果全空着呢,你这modbus协议不能用啊。
闪瞎了我的狗眼

出0入0汤圆

发表于 2014-10-16 14:49:32 | 显示全部楼层
谢谢分享,楼主辛苦了

出0入0汤圆

发表于 2014-12-5 22:59:13 | 显示全部楼层
麻烦把组态王程序发下吧

出0入0汤圆

发表于 2014-12-5 23:10:39 | 显示全部楼层
踩一下,很好

出0入0汤圆

发表于 2014-12-6 21:44:43 | 显示全部楼层
谢谢分享,膜拜

出0入0汤圆

发表于 2014-12-10 18:04:53 | 显示全部楼层
程序值得借鉴。有时间移植到我的DSPIC电路上试试。

出0入0汤圆

发表于 2017-9-7 10:07:15 | 显示全部楼层
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 17:25

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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