三菱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 上传.届时欢迎大家参与讨论.尤其是在校的学生朋友... 嗯!
一定. good job! 努力学习中!!! 如果是232的接口的话,很好监听的!有这个Serial Port Monitor软件可以监听分析的。
我比较感兴趣的是像这些大厂家他们是如何处理文件下载和上传的。呵呵。 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) 【5楼】 oldtom
监听是个好办法.
不过,我手头一台PLC都没有.呵呵.
【6楼】 billleu
This is a good turn in the near future to look forward to.Thank you. To : yy888 许意义
Last time you got one copy from the bbs,so you shold know where is. 历时三天.没搞定!
在这里向大家表示歉意.
问题不是出在方法上.而是我是半路出家,研究PLC.
在对通信协议数据分析理解上稍有吃力.
我会尽快完成DEMO版本的软件.上传至BBS. //仿三菱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
}
} 用的是STM32T片子,在Keil下开发的 【7楼】 wisebaby 明君
我这里有PLC,需要的话我可以借一个给你。 louwenyan
oste
多谢两位帮助.我已经摸索出很多.相信自己可以搞定.
再次表示感谢. 【15楼】 wisebaby 明君
祝早日成功!./emotion/em174.gif 已有成型版本发布
详情参见 [■ 仿三菱 FX1N PLC 下载通讯协议 C Code示范程序 V1.0.1版本 正式发布 ] 一贴
地址如下:
http://www.ourdev.cn/bbs/bbs_content_all.jsp?bbs_sn=3579264
页:
[1]