搜索
bottom↓
回复: 17

三菱FX1N PLC通讯协议验证

[复制链接]

出0入0汤圆

发表于 2009-5-26 19:10:44 | 显示全部楼层 |阅读模式
三菱FX1N PLC通讯协议验证

MCU:ATmega32
FOSC:11.0592MHZ

通讯类型:RS232C

波特率:9600
数据位:7
校验位:EVEN (ECC偶校验)
停止位:1

====================================================
PC:
05

PLC:
06
=====================================================
PC:
02 30 30 45 30 32 30 32 03 36 43

PLC:
02 36 32 36 36 03 44 37
====================================================
PC:
05

PLC:
06
=====================================================
PC:
02 45 30 30 30 31 43 30 30 31 03 44 44

PLC:
02 30 41 03 37 34
====================================================
PC:
05

PLC:
06
=====================================================
PC:
02 30 30 45 30 32 30 32 03 36 43

PLC:
02 36 32 36 36 03 44 37
====================================================
PC:
05

PLC:
06
=====================================================
PC:
02 45 30 31 38 30 30 30 32 45 03 45 38

PLC:
02 30 38 30 30 43 35 44 43 30 30 30 30 30 30 30 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 32 30 03 44 36
====================================================
PC:
02 45 30 31 38 30 32 45 32 45 03 46 46

PLC:
02 32 30 32 30 46 34 30 39 46 46 30 42 46 34 30 31 45 37 30 33 36 34 30 45 43 37 30 45 44 43 30 45 46 46 30 45 39 30 30 31 46 45 30 33 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 03 45 35
====================================================
PC:
05

PLC:
06
=====================================================
PC:
02 45 30 30 30 45 30 36 30 32 03 45 35

PLC:
02 31 30 30 30 03 43 34
====================================================
PC:
05

......

验证结束.PLC不做应答.

PC 三菱 SWOPC-WIN-C 上位机软件 发送 2次 05(请求发送信号)后.做出超时响应.


以下为ATmega32的硬件程序参考.

验证程序工程文件ourdev_448071.rar(文件大小:61K) (原文件名:FX1NPLCCom.rar)

程序说明:
1.硬件采用RS232C通讯.注意将"请求发送RTS和允许发送CTS短接";PLCRXD--PCTXD;PLCTXD--PCRXD;PLCGND--PCGND.
2.ATmega32采用FIFO 发送. TimeOut 超时接收.
3.整个流程加入指示灯,每个操作步骤都将伴随指示灯的指示操作.并且程序内部设有全局变量 EnterCounter 方便查看操作步骤.

注意:
1.PC 三菱 SWOPC-WIN-C 上位机软件 和 PLC 必须采用规定的RS232C设置!

Good Luck.


====================================================

我本来也是一个PLC门外汉.一点不懂.
从4月底到现在每天坚持学习PLC的点点滴滴.不断摸索.至今已经算是入了门了.
今后将继续深入学习PLC,希望能自己能在开源项目上多做贡献!只为那些想学习的人.引引路.过了"入门"的槛后面的路,就会好了.在这里有个不情之请,希望那些在校的学生多多参与.积极参与.提高自身技术技能水平.在当今这个时代....以下省略上万字...     好好学吧!

这几天进行整个PLC下载通信协议调试,待编写通过后,会第一时间将PLC Com DEMO 上传.届时欢迎大家参与讨论.尤其是在校的学生朋友...

出0入0汤圆

 楼主| 发表于 2009-5-26 19:58:35 | 显示全部楼层
嗯!

一定.

出0入0汤圆

发表于 2009-5-26 20:09:54 | 显示全部楼层
good job!

出0入0汤圆

发表于 2009-5-26 20:14:05 | 显示全部楼层
努力学习中!!!

出0入0汤圆

发表于 2009-5-27 08:47:58 | 显示全部楼层
如果是232的接口的话,很好监听的!有这个Serial Port Monitor软件可以监听分析的。


我比较感兴趣的是像这些大厂家他们是如何处理文件下载和上传的。呵呵。

出0入0汤圆

发表于 2009-5-27 09:07:54 | 显示全部楼层
To : oldtom.

For FX There didn't open the document,but i have one copy for commucation protocol from the oem vender for mitsubish.
but for A-serial and Q-serial the Mitsubish had opened the full document,last time i had upload to the bbs.

点击此处下载 ourdev_448520.pdf(文件大小:5.63M) (原文件名:FX-232AW RE422 TO RS232C INTERFACE UNIT.pdf)

for the Q -serial ,i had upload one time.so you just need read other you can find it,

点击此处下载 ourdev_448533.pdf(文件大小:5.63M) (原文件名:FXPROTCOL.pdf)

出0入0汤圆

 楼主| 发表于 2009-5-27 09:50:37 | 显示全部楼层
【5楼】 oldtom

监听是个好办法.

不过,我手头一台PLC都没有.呵呵.

【6楼】 billleu

This is a good turn in the near future to look forward to.Thank you.

出0入0汤圆

发表于 2009-5-27 12:14:13 | 显示全部楼层
To : yy888 许意义

Last time you got one copy from the bbs,so you shold know where is.

出0入0汤圆

 楼主| 发表于 2009-5-30 21:42:14 | 显示全部楼层
历时三天.没搞定!

在这里向大家表示歉意.

问题不是出在方法上.而是我是半路出家,研究PLC.

在对通信协议数据分析理解上稍有吃力.

我会尽快完成DEMO版本的软件.上传至BBS.

出0入0汤圆

发表于 2009-5-30 22:00:57 | 显示全部楼层
//仿三菱PLC与触摸屏的通讯程序 现在还只能用D和M,其他单元应该很好扩展
//希望对大家做通讯有帮助!由于水平有限,有错误的地方请大家帮忙纠正一下.
#include <stm32f10x_lib.h>                        // STM32F10x Library Definitions
//#include <stdio.h>
#include "STM32_Init.h"                           // STM32 Initialization
   

uint8 comrx[256]; // UART0数据接收缓冲区
uint8 comtx[256]; // UATT0数据发送缓冲区
//uint8 rcv_new;          // 接收新数据标志

uint16 v_variable[256]; //触摸屏通讯控制的D字节单元
uint8 bit_data[64];     //触摸屏通讯控制的B位单元
uint8 rxcount=2;//接收计数器
uint8 secount=1;//发送计数器
uint8 rxend;//和校验
uint8 rxflish=0,endbit=0;//
uint8 txreg;//发送位数计数器

void clrbit(void);
void setbit(void);
void writebyte(void);
int read16bit(uchar *reip);
void readbyte(void);
void readbit(void);
uchar sumsdd(uchar su1);
uchar charjiema(uchar *chip);
uchar charaiss(uchar cam);
void coding(void);
void senderr(void);
void  SendByte(uint8 data);
void SendString(uchar *sendip);
void SendStringx(uint8 const *data);
void timex(int tims);


/****************************************************************************
* 名称:addchack()
* 功能:和校验。
* 入口参数:
           comrx                  接收数据缓冲区(全局变量)
           adcount                和校验数据的个数
* 出口参数:无
****************************************************************************/
uchar addchack(uchar adcount)//和校验
{
  uchar sadd,si;
  sadd=0;
  for(si=0x00;si<adcount-1;si++)
     {
          sadd+=comrx[si];
          }
  si=charjiema(&comrx[adcount-1]);//转换ASIIC的和值为十六进制
  if(sadd==si)
    {return(1);}
  else
    {return(0);}
}

/****************************************************************************
* 名称:senderr()
* 功能:发送错误信号。
* 入口参数:无        
* 出口参数:无
****************************************************************************/


void senderr(void)//发送错误
{
   SendByte(0x15);
}

/****************************************************************************
* 名称:coding()
* 功能:接收解码。
* 入口参数:
           comrx                  接收数据缓冲区(全局变量)
           rxflish                开始解码标志 (全局变量)
           rxcount                接收数据的个数(全局变量)
* 出口参数:无
****************************************************************************/

void coding(void)//接收解码
{
if(rxflish)//开始解码
{
  rxflish=0;
  if(addchack(rxcount-1)==0x01)//接收和校验正确
    {
    switch (comrx[0] )
      {
         case 0x30://读处理
              if(comrx[1]==0x30)
                    {
                         readbit();//读位
                         }
                   else
                    {
                         readbyte();//读字节
                         }
              break;
         case 0x31://写处理
              writebyte();//写字节
              break;
         case 0x37://置位
              setbit();
              break;
         case 0x38://清位
              clrbit();
              break;
          }
         }
  else
    {
         senderr();//发送错误
         }
}
}

/****************************************************************************
* 名称:charaiss()
* 功能:ASIIC码转十六进制
* 入口参数:
           cam                    要转换数据   
* 出口参数:
           cam                    转换后的数据
****************************************************************************/
uchar charaiss(uchar cam)//ASIIC码转十六进制
{
if(cam<0x40)
    {
         cam=cam-0x30;
         }
else
    {
         cam=cam-0x37;
         }
return(cam);
}

/****************************************************************************
* 名称:charjiema()
* 功能:解码二位ASIIC为一位十六进制。
* 入口参数:
           chip                    要转换数据的指针   
* 出口参数:
           ch_a                    转换后的数据
****************************************************************************/
uchar charjiema(uchar *chip)//解码二位ASIIC为一位十六进制
{
  uchar ch_a=0,ch_b=0;
  ch_a=charaiss(*chip);
  ch_a=ch_a<<4;
  chip++;
  ch_b=charaiss(*chip);
  ch_a=ch_a|ch_b;
  return(ch_a);
}

/****************************************************************************
* 名称:sumsdd()
* 功能:求和校验值。
* 入口参数:
           comrx                  接收数据缓冲区(全局变量)
           su1                    要求和数据的个数
* 出口参数:
           su1                    要发送数据的个数
****************************************************************************/
uchar sumsdd(uchar su1)//求和校验值
{
uchar si,ssd;
  ssd=0;
for(si=1;si<=su1;si++)//求和
   {
     ssd+=comtx[si];
    }
si=ssd>>4;
if(si>0x09)//转成ASIIC码
   {si=si+0x37;}
else
   {si=si+0x30;}
su1++;
comtx[su1]=si;
si=ssd&0x0f;
if(si>0x09)
   {si=si+0x37;}
else
   {si=si+0x30;}
su1++;
comtx[su1]=si;
return(su1+1);

}

/****************************************************************************
* 名称:readbit()
* 功能:读位操作。
* 入口参数:
           comrx                  接收数据缓冲区(全局变量)
           bit_data               B位单元(全局变量)
* 出口参数:无
****************************************************************************/
void readbit(void)//读位
{
uchar ri,rem,rec,rema;
uchar address,bytenum;
address=charjiema(&comrx[3]);//解析出开始地址
bytenum=charjiema(&comrx[5]);//解析出字节数量
comtx[0]=0x02;
rec=1;

for(ri=0;ri<bytenum;ri++)
    {                           //
         rem=bit_data[address];//读一个字节的位
         rema=(rem&0xf0)>>4;
         if(rema>0x09)//转换成ASIIC码
           {
            comtx[rec]=rema+0x37;
            }
         else
           {
            comtx[rec]=rema+0x30;
            }
         rec++;
         rema=rem&0x0f;
     if(rema>0x09)//
           {
            comtx[rec]=rema+0x37;
            }
         else
           {
            comtx[rec]=rema+0x30;
            }
         rec++;         
     address++;
         }
comtx[rec]=0x03;//写结束字
secount=sumsdd(rec);//求和
SendString(&comtx[0]);


}

/****************************************************************************
* 名称:readbyte()
* 功能:读字节操作。
* 入口参数:
           comrx                    接收数据缓冲区(全局变量)
           v_variable               D字节单元(全局变量)
* 出口参数:无
****************************************************************************/
void readbyte(void)  
{
uchar ri,rec,rema,rem;
int remx ;
uchar address,bytenum;
address=charjiema(&comrx[3]);//解析出开始地址
address=address/2;
bytenum=charjiema(&comrx[5]);//解析出字节数量
bytenum=bytenum/2;
comtx[0]=0x02;
rec=1;
for(ri=0;ri<bytenum;ri++)
    {                         //把十六位的二进制转成ASIIC码
         remx=v_variable[address];
        // rem=(uchar)(remx>>8);
         rem=(uchar)(remx&0x00ff);
         rema=(rem&0xf0)>>4;
         if(rema>0x09)
           {
            comtx[rec]=rema+0x37;
            }
         else
           {
            comtx[rec]=rema+0x30;
            }
         rec++;
     rema=rem&0x0f;
     if(rema>0x09)
           {
            comtx[rec]=rema+0x37;
            }
         else
           {
            comtx[rec]=rema+0x30;
            }
         rec++;
        // rem=(uchar)(remx&0x00ff);
         rem=(uchar)(remx>>8);
     rema=(rem&0xf0)>>4;
         if(rema>0x09)
           {
            comtx[rec]=rema+0x37;
            }
         else
           {
            comtx[rec]=rema+0x30;
            }
         rec++;
     rema=rem&0x0f;
     if(rema>0x09)
           {
            comtx[rec]=rema+0x37;
            }
         else
           {
            comtx[rec]=rema+0x30;
            }
         rec++;
         address++;
         }
comtx[rec]=0x03;
secount=sumsdd(rec);//和校验
SendString(&comtx[0]);
}

/****************************************************************************
* 名称:read16bit()
* 功能:读4位ASIIC码转换成16位INT型
* 入口参数:
           reip                    需要转换数据指针
           
* 出口参数:
           rea                     转换后的数据
****************************************************************************/
int read16bit(uchar *reip)//读4位ASIIC码转换成16位INT型
{
  int reb,rea;
  uchar re_c;
  re_c=charjiema(reip);
  reb=(int)(re_c);
  reip++;
  reip++;
  re_c=charjiema(reip);
  rea=(int)(re_c);
  rea=rea<<8;
  reb=reb&0x00ff;
  rea=rea|reb;
  return(rea);
}

/****************************************************************************
* 名称:writebyte()
* 功能:写字节操作。
* 入口参数:
           comrx                    接收数据缓冲区(全局变量)
           v_variable               D字节单元(全局变量)
* 出口参数:无
****************************************************************************/
void writebyte(void)
{
uchar ri;
uchar address,bytenum;
address=charjiema(&comrx[3]);    //解析出开始地址
address=address/2;
bytenum=charjiema(&comrx[5]);    //解析出字节数量
bytenum=bytenum/2;  
for(ri=0;ri<bytenum;ri++)        //写字节
    {
          v_variable[address]=read16bit(&comrx[7+ri*4]);
          address++;
         }
SendByte(0x06);                 //返回正确
}

/****************************************************************************
* 名称:setbit()
* 功能:位设置1。
* 入口参数:
           comrx                  接收数据缓冲区(全局变量)
           bit_data               B位单元(全局变量)
* 出口参数:无
****************************************************************************/
void setbit(void)//位设置1
{
uchar address;
uchar aby,abi;
uchar abm;
address=charjiema(&comrx[1]);    //解析出开始地址
aby=address/8;
abi=address%8;
abm=0x01<<abi;                    //置1
bit_data[aby]=bit_data[aby]|abm;
SendByte(0x06);                   //返回正确
}


/****************************************************************************
* 名称:clrbit()
* 功能:位清零。
* 入口参数:
           comrx                  接收数据缓冲区(全局变量)
           bit_data               B位单元(全局变量)
* 出口参数:无
****************************************************************************/
void clrbit(void)//位清零
{
uchar address;
uchar aby,abi;
uchar abm;
address=charjiema(&comrx[1]);     //解析出开始地址
aby=address/8;
abi=address%8;
abm=0x01<<abi;
abm=~abm;                         //清零
bit_data[aby]=bit_data[aby]&abm;
SendByte(0x06);                   //返回正确
}


/****************************************************************************
* 名称:SendString()
* 功能:向串口发送字符串。
* 入口参数:
           sendip                要发送的数据指针
           secount               要发送数据的个数(全局变量)
* 出口参数:无
****************************************************************************/  
void timex(int tims)
{
  char tim;
  for(;tims>0;tims--)
    {
         tim=100;
     for(;tim>0;tim--);
         }
  }
  
/****************************************************************************
* 名称:SendString()
* 功能:向串口发送字符串。
* 入口参数:
           sendip                要发送的数据指针
           secount               要发送数据的个数(全局变量)
* 出口参数:无
****************************************************************************/  
void SendString(uchar *sendip)
{
for(;secount>0;secount--)
    {
      SendByte(*sendip);
      sendip++;
     }
}

/****************************************************************************
* 名称:SendByte()
* 功能:向串口发送字节数据。
* 入口参数:data                要发送的数据
* 出口参数:无
****************************************************************************/
/**
void  SendByte(uint8 data)
{
   U0THR = data;                                // 发送数据
   while( (U0LSR&0x20)==0 );
}
**/
void SendByte(uint8 ch)  
{
  while (!(USART1->SR & USART_FLAG_TXE));
  USART1->DR = (ch & 0x1FF);
  
}

/****************************************************************************
* 名称:SendString()
* 功能:向串口发送字符串。
* 入口参数:data                要发送的数据指针
* 出口参数:无
****************************************************************************/
void SendStringx(uint8 const *data)
{
  while(1)
  {
    if(*data=='\0')break;    //判断是否到了字符尾
    SendByte(*data++);       //发送字符
   }
}

/*----------------------------------------------------------------------------
  USART1_IRQHandler
  Handles USART1 global interrupt request.
*----------------------------------------------------------------------------*/
void USART1_IRQHandler (void) {
  volatile unsigned int IIR;
  uint16  i;
  //struct buf_st *p;

    IIR = USART1->SR;
    if (IIR & USART_FLAG_RXNE)                   //接收中断
        {                  // read interrupt
      USART1->SR &= ~USART_FLAG_RXNE;                  // clear interrupt
          i=(USART1->DR & 0x1FF);            //读接收数据
  
    switch(i)
               {
                    case 0x02://开始字
                             rxcount=0;
                             break;
                        case 0x03://结束字
                             comrx[rxcount]=i;
                                 rxcount++;
                                 rxend=0;
                                 endbit=1;
                             break;
                        case 0x06://接收正确
                             break;
                        case 0x15://接受错误
                             break;
                        default:
                             comrx[rxcount]=i;
                                 rxcount++;
                                 if(endbit)//接收到结束字
                                   {
                                    rxend++;
                                        if(rxend==0x02)//接收完一条数
                                           {
                                            rxflish=1;//置接受完标志
                         endbit=0;//清接收到结束字标志2006-12-6 8:55
                                            }
                                    }
                                 break;
                    }
      }
   

   
   
   
  


    if (IIR & USART_FLAG_TXE)                   //发送中断
         {
      USART1->SR &= ~USART_FLAG_TXE;                  // clear interrupt
          
    }
}

出0入0汤圆

发表于 2009-5-30 22:03:02 | 显示全部楼层
用的是STM32T片子,在Keil下开发的

出0入0汤圆

发表于 2009-5-30 22:23:35 | 显示全部楼层
【7楼】 wisebaby 明君

我这里有PLC,需要的话我可以借一个给你。

出0入0汤圆

 楼主| 发表于 2009-5-31 11:20:36 | 显示全部楼层
louwenyan
oste

多谢两位帮助.我已经摸索出很多.相信自己可以搞定.

再次表示感谢.

出0入0汤圆

发表于 2009-6-7 16:40:29 | 显示全部楼层
【15楼】 wisebaby 明君
祝早日成功!

出0入0汤圆

 楼主| 发表于 2009-9-24 14:17:45 | 显示全部楼层
已有成型版本发布
详情参见 [■ 仿三菱 FX1N PLC 下载通讯协议 C Code示范程序 V1.0.1版本 正式发布 ] 一贴

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

本版积分规则

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

GMT+8, 2024-4-20 08:56

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

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