wisebaby 发表于 2009-5-26 19:10:44

三菱FX1N PLC通讯协议验证

三菱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 上传.届时欢迎大家参与讨论.尤其是在校的学生朋友...

wisebaby 发表于 2009-5-26 19:58:35

嗯!

一定.

foshan_lcy 发表于 2009-5-26 20:09:54

good job!

huimin1985 发表于 2009-5-26 20:14:05

努力学习中!!!

oldtom 发表于 2009-5-27 08:47:58

如果是232的接口的话,很好监听的!有这个Serial Port Monitor软件可以监听分析的。


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

billleu 发表于 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)

wisebaby 发表于 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.

billleu 发表于 2009-5-27 12:14:13

To : yy888 许意义

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

wisebaby 发表于 2009-5-30 21:42:14

历时三天.没搞定!

在这里向大家表示歉意.

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

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

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

louwenyan 发表于 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; // UART0数据接收缓冲区
uint8 comtx; // UATT0数据发送缓冲区
//uint8 rcv_new;          // 接收新数据标志

uint16 v_variable; //触摸屏通讯控制的D字节单元
uint8 bit_data;   //触摸屏通讯控制的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);
voidSendByte(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=charjiema(&comrx);//转换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 )
      {
       case 0x30://读处理
              if(comrx==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=ssd>>4;
if(si>0x09)//转成ASIIC码
   {si=si+0x37;}
else
   {si=si+0x30;}
su1++;
comtx=si;
si=ssd&0x0f;
if(si>0x09)
   {si=si+0x37;}
else
   {si=si+0x30;}
su1++;
comtx=si;
return(su1+1);

}

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

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


}

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

/****************************************************************************
* 名称: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);    //解析出开始地址
address=address/2;
bytenum=charjiema(&comrx);    //解析出字节数量
bytenum=bytenum/2;
for(ri=0;ri<bytenum;ri++)      //写字节
    {
          v_variable=read16bit(&comrx);
          address++;
       }
SendByte(0x06);               //返回正确
}

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


/****************************************************************************
* 名称:clrbit()
* 功能:位清零。
* 入口参数:
         comrx                  接收数据缓冲区(全局变量)
         bit_data               B位单元(全局变量)
* 出口参数:无
****************************************************************************/
void clrbit(void)//位清零
{
uchar address;
uchar aby,abi;
uchar abm;
address=charjiema(&comrx);   //解析出开始地址
aby=address/8;
abi=address%8;
abm=0x01<<abi;
abm=~abm;                         //清零
bit_data=bit_data&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                要发送的数据
* 出口参数:无
****************************************************************************/
/**
voidSendByte(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;
uint16i;
//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=i;
                               rxcount++;
                               rxend=0;
                               endbit=1;
                             break;
                        case 0x06://接收正确
                             break;
                        case 0x15://接受错误
                             break;
                        default:
                             comrx=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
          
    }
}

louwenyan 发表于 2009-5-30 22:03:02

用的是STM32T片子,在Keil下开发的

oste 发表于 2009-5-30 22:23:35

【7楼】 wisebaby 明君

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

wisebaby 发表于 2009-5-31 11:20:36

louwenyan
oste

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

再次表示感谢.

oste 发表于 2009-6-7 16:40:29

【15楼】 wisebaby 明君
祝早日成功!./emotion/em174.gif

wisebaby 发表于 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
页: [1]
查看完整版本: 三菱FX1N PLC通讯协议验证