modbus-C语言实现

modbus结构

地址位+功能码+数据+校验(crc16)

下面为代码进行判断地址 功能码和校验位是否正确,并打印错误信息

void RS485_Service(void)
{u16 recCRC;if(RS485_FrameFlag==1){printf("here1\r\n");if(RS485_RX_BUFF[0]==RS485_Addr)//µØÖ·ÕýÈ·{printf("here2\r\n");if((RS485_RX_BUFF[1]==01)||(RS485_RX_BUFF[1]==02)||(RS485_RX_BUFF[1]==03)||(RS485_RX_BUFF[1]==05)||(RS485_RX_BUFF[1]==06)||(RS485_RX_BUFF[1]==15)||(RS485_RX_BUFF[1]==16))//¹¦ÄÜÂëÕýÈ·{printf("here3\r\n");startRegAddr=(((u16)RS485_RX_BUFF[2])<<8)|RS485_RX_BUFF[3];//»ñÈ¡¼Ä´æÆ÷ÆðʼµØÖ·if(startRegAddr<1000)//¼Ä´æÆ÷µØÖ·ÔÚ·¶Î§ÄÚ{printf("here4\r\n");calCRC=CRC_Compute(RS485_RX_BUFF,RS485_RX_CNT-2);//¼ÆËãËù½ÓÊÕÊý¾ÝµÄCRCprintf("calCRC IS %d\r\n",calCRC);recCRC=RS485_RX_BUFF[RS485_RX_CNT-1]|(((u16)RS485_RX_BUFF[RS485_RX_CNT-2])<<8);//½ÓÊÕµ½µÄCRC(µÍ×Ö½ÚÔÚǰ£¬¸ß×Ö½ÚÔÚºó)printf("recCRC IS %d\r\n",recCRC); if(calCRC==recCRC)//CRCУÑéÕýÈ·{//LED1=0;printf("here5\r\n");/switch(RS485_RX_BUFF[1])//¸ù¾Ý²»Í¬µÄ¹¦ÄÜÂë½øÐд¦Àí{case 2://¶ÁÊäÈ뿪¹ØÁ¿{Modbus_02_Solve();break;}case 1://¶ÁÊä³ö¿ª¹ØÁ¿{Modbus_01_Solve();break;}case 5://дµ¥¸öÊä³ö¿ª¹ØÁ¿{Modbus_05_Solve();break;}case 15://д¶à¸öÊä³ö¿ª¹ØÁ¿{Modbus_15_Solve();break;}case 03: //¶Á¶à¸ö¼Ä´æÆ÷{			printf("read 03\r\n ");																													Modbus_03_Solve();break;}case 06: //дµ¥¸ö¼Ä´æÆ÷{Modbus_06_Solve();break;}case 16: //д¶à¸ö¼Ä´æÆ÷{Modbus_16_Solve();break;}}//}else//CRCУÑé´íÎó{RS485_TX_BUFF[0]=RS485_RX_BUFF[0];RS485_TX_BUFF[1]=RS485_RX_BUFF[1]|0x80;RS485_TX_BUFF[2]=0x04; //Òì³£ÂëRS485_SendData(RS485_TX_BUFF,3);}        }else//¼Ä´æÆ÷µØÖ·³¬³ö·¶Î§{RS485_TX_BUFF[0]=RS485_RX_BUFF[0];RS485_TX_BUFF[1]=RS485_RX_BUFF[1]|0x80;RS485_TX_BUFF[2]=0x02; //Òì³£ÂëRS485_SendData(RS485_TX_BUFF,3);}                                                }else//¹¦ÄÜÂë´íÎó{RS485_TX_BUFF[0]=RS485_RX_BUFF[0];RS485_TX_BUFF[1]=RS485_RX_BUFF[1]|0x80;RS485_TX_BUFF[2]=0x01; //Òì³£ÂëRS485_SendData(RS485_TX_BUFF,3);}}RS485_FrameFlag=0;//¸´Î»Ö¡½áÊø±êÖ¾RS485_RX_CNT=0;//½ÓÊÕ¼ÆÊýÆ÷ÇåÁãRS485_TX_EN=0;//¿ªÆô½ÓÊÕģʽ                }                
}

 下面举例子 功能码为2的处理程序

void Modbus_02_Solve(void)
{u16 ByteNum;u16 i;RegNum= (((u16)RS485_RX_BUFF[4])<<8)|RS485_RX_BUFF[5];//»ñÈ¡¼Ä´æÆ÷ÊýÁ¿if((startRegAddr+RegNum)<100)//¼Ä´æÆ÷µØÖ·+ÊýÁ¿ÔÚ·¶Î§ÄÚ{RS485_TX_BUFF[0]=RS485_RX_BUFF[0];RS485_TX_BUFF[1]=RS485_RX_BUFF[1];ByteNum=RegNum/8;//×Ö½ÚÊýif(RegNum%8) ByteNum+=1;//Èç¹ûλÊý»¹ÓÐÓàÊý£¬Ôò×Ö½ÚÊý+1RS485_TX_BUFF[2]=ByteNum;//·µ»ØÒª¶ÁÈ¡µÄ×Ö½ÚÊýfor(i=0;i>=1;//µÍλÏÈ·¢ËÍRS485_TX_BUFF[3+i/8]|=((*Modbus_InputIO[startRegAddr+i])<<7)&0x80;if(i==RegNum-1)//·¢Ë͵½×îºóÒ»¸öλÁË{if(RegNum%8) RS485_TX_BUFF[3+i/8]>>=8-(RegNum%8);//Èç¹û×îºóÒ»¸ö×Ö½Ú»¹ÓÐÓàÊý£¬ÔòÊ£ÓàMSBÌî³ä0}}calCRC=CRC_Compute(RS485_TX_BUFF,ByteNum+3);RS485_TX_BUFF[ByteNum+3]=(calCRC>>8)&0xFF;RS485_TX_BUFF[ByteNum+4]=(calCRC)&0xFF;RS485_SendData(RS485_TX_BUFF,ByteNum+5);}else//¼Ä´æÆ÷µØÖ·+ÊýÁ¿³¬³ö·¶Î§{RS485_TX_BUFF[0]=RS485_RX_BUFF[0];RS485_TX_BUFF[1]=RS485_RX_BUFF[1]|0x80;RS485_TX_BUFF[2]=0x02; //Òì³£ÂëRS485_SendData(RS485_TX_BUFF,3);}
}

 但是在调试的时候一直有问题,校验不正确。后来发现是发送时 xcom勾选了发送新行。发送时多发了\r\n 一定要仔细!

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部