共2条
1/1 1 跳转至页
问
请教一下各位,通讯问题 我有四台设备要通讯 都是485口的,四台设备并在一起,其他三台可以通上,只有单片机的通不上?????? (单片机) 单通可以和西门子的PLC通上, 但和令两台设备通不上,西门子的PLC单通可以和令两台设备就能通上,这是为什么??????????那为大虾帮帮我十分感谢。
答 1: 最大的可能是波特率不准的原因也可能是程序流程问题。 答 2: 通讯问题 答 3: 通讯问题都是9600的,如果程序流程有问题,单片机为什么可以和西门子的PLC通上?????? 答 4: 不同产品的误差容限不同波特率是一方面,其它如485数据建立时间等等,不同设计的容限都不同,除硬指标如波特率、电压等外,其它的不配合都可用软件解决或因软件造成,如果是这方面的问题,不是“流程”是什么? 答 5: 楼上的哥哥帮帮小弟吧
chunyang你好:
/* MODBUS通讯规约中CRC校验码地计算 */
#include "AT89X51.H"
#include "INTRINS.H"
#define uchar unsigned char
uchar in_command=0;
uchar sbuf_count=0;
char getsbuf[8];/*接受字符缓冲区*/
char return_xy[17]={0x01,0x01,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
char *pint3;
char outcount=0;
char m=17;/*返回数据字节数*/
void XyToCrc(char mm,char *pint);
void Init_SerialComm(void);
void Init_CpuIO(void);
void DelayX1ms(uchar count);
void outchar(char i);
void get_digital(void);
void main(void)
{
char *pint1;
char charx,chary;
Init_SerialComm(); /*初始化串口*/
Init_CpuIO(); /*初始化IO口*/
for(;;)
{
get_digital(); /*采集数字量*/
pint1=return_xy;
return_xy[1]=0x01;
return_xy[2]=0x0c;
XyToCrc(m-2,pint1); /*计算返回数据的校验码*/
charx=return_xy[0];
chary=return_xy[1];
charx=return_xy[2];
chary=return_xy[3];
charx=return_xy[4];
chary=return_xy[5];
charx=return_xy[6];
chary=return_xy[7];
charx=return_xy[8];
chary=return_xy[9];
charx=return_xy[10];
chary=return_xy[11];
charx=return_xy[12];
chary=return_xy[13];
chary=return_xy[14];
charx=return_xy[15];
chary=return_xy[16];
if (outcount>=m)
{TI=0;RI=0;outcount=0;}
if(in_command==1)
{
in_command=0;
pint3=return_xy;
outcount=0;
XyToCrc(m-2,pint1); /*计算返回数据的校验码*/
TI=1; /*数据返回*/
}
}
}
void Init_SerialComm(void) /*初始化串口*/
{
SCON=0x50; /*SCON: serail mode 1, 8-bit UART, enable receive*/
TMOD=0x20; /*TMOD: timer 1, mode 2, 8-bit reload*/
TH1=0xfd; /*baud rate 9600b/s TH1=0xfd; */
/*TL1=0xfd;*/
PCON=0x00; /* SMOD=0*/
IE=0x90; /*IE.7=EA=1;IE.4=ES=1,IE.3=ET1=0, IE.2=EX1=0,IE.1=ET0=0,IE.0=EX0=0,Enable global interrupt and serial interrupt*/
TR1=1; /*start timer 1*/
}
void Init_CpuIO(void) /*初始化IO口*/
{
P1=0xff;/*关闭采集口*/
P2=0xff;/*关闭采集口*/
/*p3_0=RXD,p3_1=TXD,p3_2=/INT0,p3_3=/INT1 P3口的第二定义在IE中设置起用*/
/*p3_4=T0,p3_5=T1,p3_6=/WR,p3_7=/RD */
}
void DelayX1ms(uchar count) /*延时1ms*/
{
uchar k;
while(count!=0)
{count--;
for(k=0;k<72;k++)
{}
}
}
/*串口接收中断处理函数*/
void Serial(void) interrupt 4
{
char *pint2;
char i,crcl=0,crch=0;
if(RI)
{
RI=0;/* sbuf_count getsbuf[3] */
getsbuf[sbuf_count++]=SBUF;
switch(sbuf_count) /*接收一个数据就判断一次是否是发给自己的命令*/
{
case 0x01:
if(getsbuf[0]!=return_xy[0])
sbuf_count=0x00;
break;
case 0x02:
if(getsbuf[1]!=0x01)
sbuf_count=0x00;
break;
case 0x03:
if(getsbuf[2]!=0x00)
sbuf_count=0x00;
break;
case 0x04:
if(getsbuf[3]!=0x00)
sbuf_count=0x00;
break;
case 0x05:
if(getsbuf[4]!=0x00)
sbuf_count=0x00;
break;
case 0x06:
if(getsbuf[5]!=0x60)
sbuf_count=0x00;
break;
case 0x07:
break;
case 0x08:
crcl=getsbuf[6];
crch=getsbuf[7];
pint2=getsbuf;
XyToCrc(6,pint2); /*计算接受数据地校验码 */
if(crcl==getsbuf[6] && crch==getsbuf[7]) /*接受地校验码和计算的校验码相同 */
{
in_command=1; /*产生有效命令 */
}
else
{
in_command=0;
}
for(i=0;i<8;i++)
{
getsbuf[i]=0x00; /*清接受缓冲区 */
}
crcl=0x00;crch=0x00;sbuf_count=0;
break;
default:
break;
}
}
if(TI)
{
TI=0;
if(outcount<m)
{
SBUF=*pint3;
pint3++;
outcount++;
}
}
}
void XyToCrc(char mm,char *pint)
{
char i,j,k,crcl;
int xyl,crc;
crc=0xffff; /*先将CRC寄存器全部置高*/
for(i=0;i<mm;i++) /*mm个数据计算CRC*/
{
crcl=crc; /*与CRC异或*/
crcl^=*pint;
xyl=crcl;
xyl&=0x00ff;
crc&=0xff00;
crc|=xyl;
for(j=0;j<=7;j++) /*计算八次*/
{
k=crc&0x0001;
crc>>=1;
crc&=0x7fff;
if(k==1) /*标志位*/
{
crc^=0xa001;
}
}
pint++; /*取下一个CHAR数据*/
}
/*下面将CRC结果低八位在前高八位在后传入发送缓冲区*/
xyl=crc;
xyl>>=8;
xyl&=0x00ff;
*pint=crc;
pint++;
*pint=xyl;
}
void outchar(char i) /*数据返回*/
{
char c;
for( c=0;c<i;c++)
{
SBUF=return_xy[c];
}
}
void get_digital(void) /*采集数字量*/
{
char i,num=0x01,x,y;
for(i=0;i<8;i++) /*采集前八组数字量*/
{
P2=0XFF;P1=~num;
do /*去抖动*/
{
DelayX1ms(10);
x=~P0;
DelayX1ms(20);
y=~P0;
}while(x!=y);
return_xy[i+3]=x;
num<<=1;
}
for(i=0,num=0x01;i<4;i++) /*采集后4组数字量*/
{
P1=0XFF;P2=~num;
do
{
DelayX1ms(10);
x=~P0;
DelayX1ms(20);
y=~P0;
}while(x!=y);
return_xy[i+11]=x;
num<<=1;
}
P2=0xEF;/*采集本系统所设置的地址*/
do
{
DelayX1ms(10);
x=~P0;
DelayX1ms(20);
y=~P0;
}while(x!=y);
return_xy[0]=x;
}
答 6: 楼上的哥哥帮帮小弟吧.这是控制开关触电程序,小弟对这一点都不懂,能帮帮我吗?帮我改改可以吗?不胜感谢. 答 7: 抱歉,我可没有时间帮你看程序! 而且你可能来本坛的时间未久,如此寻求“帮助”的方式是本坛一向不提倡的。方法和方向性的指点俺老汉向来不吝,但如此直接给结果的还从未有过。过去、现在和未来,均此。
答 1: 最大的可能是波特率不准的原因也可能是程序流程问题。 答 2: 通讯问题 答 3: 通讯问题都是9600的,如果程序流程有问题,单片机为什么可以和西门子的PLC通上?????? 答 4: 不同产品的误差容限不同波特率是一方面,其它如485数据建立时间等等,不同设计的容限都不同,除硬指标如波特率、电压等外,其它的不配合都可用软件解决或因软件造成,如果是这方面的问题,不是“流程”是什么? 答 5: 楼上的哥哥帮帮小弟吧
chunyang你好:
/* MODBUS通讯规约中CRC校验码地计算 */
#include "AT89X51.H"
#include "INTRINS.H"
#define uchar unsigned char
uchar in_command=0;
uchar sbuf_count=0;
char getsbuf[8];/*接受字符缓冲区*/
char return_xy[17]={0x01,0x01,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
char *pint3;
char outcount=0;
char m=17;/*返回数据字节数*/
void XyToCrc(char mm,char *pint);
void Init_SerialComm(void);
void Init_CpuIO(void);
void DelayX1ms(uchar count);
void outchar(char i);
void get_digital(void);
void main(void)
{
char *pint1;
char charx,chary;
Init_SerialComm(); /*初始化串口*/
Init_CpuIO(); /*初始化IO口*/
for(;;)
{
get_digital(); /*采集数字量*/
pint1=return_xy;
return_xy[1]=0x01;
return_xy[2]=0x0c;
XyToCrc(m-2,pint1); /*计算返回数据的校验码*/
charx=return_xy[0];
chary=return_xy[1];
charx=return_xy[2];
chary=return_xy[3];
charx=return_xy[4];
chary=return_xy[5];
charx=return_xy[6];
chary=return_xy[7];
charx=return_xy[8];
chary=return_xy[9];
charx=return_xy[10];
chary=return_xy[11];
charx=return_xy[12];
chary=return_xy[13];
chary=return_xy[14];
charx=return_xy[15];
chary=return_xy[16];
if (outcount>=m)
{TI=0;RI=0;outcount=0;}
if(in_command==1)
{
in_command=0;
pint3=return_xy;
outcount=0;
XyToCrc(m-2,pint1); /*计算返回数据的校验码*/
TI=1; /*数据返回*/
}
}
}
void Init_SerialComm(void) /*初始化串口*/
{
SCON=0x50; /*SCON: serail mode 1, 8-bit UART, enable receive*/
TMOD=0x20; /*TMOD: timer 1, mode 2, 8-bit reload*/
TH1=0xfd; /*baud rate 9600b/s TH1=0xfd; */
/*TL1=0xfd;*/
PCON=0x00; /* SMOD=0*/
IE=0x90; /*IE.7=EA=1;IE.4=ES=1,IE.3=ET1=0, IE.2=EX1=0,IE.1=ET0=0,IE.0=EX0=0,Enable global interrupt and serial interrupt*/
TR1=1; /*start timer 1*/
}
void Init_CpuIO(void) /*初始化IO口*/
{
P1=0xff;/*关闭采集口*/
P2=0xff;/*关闭采集口*/
/*p3_0=RXD,p3_1=TXD,p3_2=/INT0,p3_3=/INT1 P3口的第二定义在IE中设置起用*/
/*p3_4=T0,p3_5=T1,p3_6=/WR,p3_7=/RD */
}
void DelayX1ms(uchar count) /*延时1ms*/
{
uchar k;
while(count!=0)
{count--;
for(k=0;k<72;k++)
{}
}
}
/*串口接收中断处理函数*/
void Serial(void) interrupt 4
{
char *pint2;
char i,crcl=0,crch=0;
if(RI)
{
RI=0;/* sbuf_count getsbuf[3] */
getsbuf[sbuf_count++]=SBUF;
switch(sbuf_count) /*接收一个数据就判断一次是否是发给自己的命令*/
{
case 0x01:
if(getsbuf[0]!=return_xy[0])
sbuf_count=0x00;
break;
case 0x02:
if(getsbuf[1]!=0x01)
sbuf_count=0x00;
break;
case 0x03:
if(getsbuf[2]!=0x00)
sbuf_count=0x00;
break;
case 0x04:
if(getsbuf[3]!=0x00)
sbuf_count=0x00;
break;
case 0x05:
if(getsbuf[4]!=0x00)
sbuf_count=0x00;
break;
case 0x06:
if(getsbuf[5]!=0x60)
sbuf_count=0x00;
break;
case 0x07:
break;
case 0x08:
crcl=getsbuf[6];
crch=getsbuf[7];
pint2=getsbuf;
XyToCrc(6,pint2); /*计算接受数据地校验码 */
if(crcl==getsbuf[6] && crch==getsbuf[7]) /*接受地校验码和计算的校验码相同 */
{
in_command=1; /*产生有效命令 */
}
else
{
in_command=0;
}
for(i=0;i<8;i++)
{
getsbuf[i]=0x00; /*清接受缓冲区 */
}
crcl=0x00;crch=0x00;sbuf_count=0;
break;
default:
break;
}
}
if(TI)
{
TI=0;
if(outcount<m)
{
SBUF=*pint3;
pint3++;
outcount++;
}
}
}
void XyToCrc(char mm,char *pint)
{
char i,j,k,crcl;
int xyl,crc;
crc=0xffff; /*先将CRC寄存器全部置高*/
for(i=0;i<mm;i++) /*mm个数据计算CRC*/
{
crcl=crc; /*与CRC异或*/
crcl^=*pint;
xyl=crcl;
xyl&=0x00ff;
crc&=0xff00;
crc|=xyl;
for(j=0;j<=7;j++) /*计算八次*/
{
k=crc&0x0001;
crc>>=1;
crc&=0x7fff;
if(k==1) /*标志位*/
{
crc^=0xa001;
}
}
pint++; /*取下一个CHAR数据*/
}
/*下面将CRC结果低八位在前高八位在后传入发送缓冲区*/
xyl=crc;
xyl>>=8;
xyl&=0x00ff;
*pint=crc;
pint++;
*pint=xyl;
}
void outchar(char i) /*数据返回*/
{
char c;
for( c=0;c<i;c++)
{
SBUF=return_xy[c];
}
}
void get_digital(void) /*采集数字量*/
{
char i,num=0x01,x,y;
for(i=0;i<8;i++) /*采集前八组数字量*/
{
P2=0XFF;P1=~num;
do /*去抖动*/
{
DelayX1ms(10);
x=~P0;
DelayX1ms(20);
y=~P0;
}while(x!=y);
return_xy[i+3]=x;
num<<=1;
}
for(i=0,num=0x01;i<4;i++) /*采集后4组数字量*/
{
P1=0XFF;P2=~num;
do
{
DelayX1ms(10);
x=~P0;
DelayX1ms(20);
y=~P0;
}while(x!=y);
return_xy[i+11]=x;
num<<=1;
}
P2=0xEF;/*采集本系统所设置的地址*/
do
{
DelayX1ms(10);
x=~P0;
DelayX1ms(20);
y=~P0;
}while(x!=y);
return_xy[0]=x;
}
答 6: 楼上的哥哥帮帮小弟吧.这是控制开关触电程序,小弟对这一点都不懂,能帮帮我吗?帮我改改可以吗?不胜感谢. 答 7: 抱歉,我可没有时间帮你看程序! 而且你可能来本坛的时间未久,如此寻求“帮助”的方式是本坛一向不提倡的。方法和方向性的指点俺老汉向来不吝,但如此直接给结果的还从未有过。过去、现在和未来,均此。
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
与电子爱好者谈读图四被打赏50分 | |
与电子爱好者谈读图二被打赏50分 | |
【FRDM-MCXN947评测】Core1适配运行FreeRtos被打赏50分 | |
【FRDM-MCXN947评测】双核调试被打赏50分 | |
【CPKCORRA8D1B评测】---移植CoreMark被打赏50分 | |
【CPKCORRA8D1B评测】---打开硬件定时器被打赏50分 | |
【FRDM-MCXA156评测】4、CAN loopback模式测试被打赏50分 | |
【CPKcorRA8D1评测】--搭建初始环境被打赏50分 | |
【FRDM-MCXA156评测】3、使用FlexIO模拟UART被打赏50分 | |
【FRDM-MCXA156评测】2、rt-thread MCXA156 BSP制作被打赏50分 |