发 帖  
[文章]

一步一步学习ModBus

2018-9-2 23:05:01  4307 CAN 上位机
0
MR陈 2018-9-2 23:10:31
回复

举报

MR陈 2018-9-7 00:22:17
回复

举报

MR陈 2018-9-10 00:51:59
2回复

举报

  • 陈淼 2018-10-24 15:19

    你好,能看下你modbus功能码03通过串口助手的从机调试代码嘛,谢谢

  • MR陈 回复 陈淼: 2018-12-13 09:42

    /*功能码3函数*/
    void  Modbus_Fun3()
    {
            u16        F3_Addr;
            u8        F3_Num;  //主机要读取的字节数量
            u8  F3_NumByte;   // 从机要回复的自己数量,串口回复数量应该在256-1-2=253之间
            u8         i = 0,j;
            u8         F3_Return_Num;//正常应答从机返回的总字节数       
            u16 F3_Crc_Value;
            F3_Addr = modbus.rcbuf[2]*256 + modbus.rcbuf[3]*1;  //起始地址
            if(F3_Addr>=0x00 && F3_Addr<=0xFF)  //判断地址是否处于协议要求的地址范围内(功能码3地址应该处于0x0000 至 0xFFFF之间)
            {
                    F3_Num         = modbus.rcbuf[4]*256 + modbus.rcbuf[5]*1;  //读取数量
                    if(F3_Num >= 0 &&        F3_Num <= 0x7D )  //读取寄存器数量
                    {
                            //开始填写需要回复的数据到发送缓冲区
                            modbus.Sendbuf[i++]=modbus.myadd;//第一填充本从机地址
                            modbus.Sendbuf[i++]=0x03;//第二、填充运行的功能码
                            F3_NumByte = (F3_Num*2)%256;                //有效数据数=寄存器数量*2
                            modbus.Sendbuf[i++]=F3_NumByte;//第三、填充字节数,
                            for(j = 0;j < F3_Num;j ++)  //填充主机需要的数据
                            {
                                    modbus.Sendbuf[i++] = F3_RegValue[F3_Addr + j] /256;
                                    modbus.Sendbuf[i++] = F3_RegValue[F3_Addr + j] %256;
                            }
                            F3_Crc_Value = crc16( modbus.Sendbuf, i );  //计算返回数据的CRC
                            //注意本来crc16( uchar *puchMsg, uint usDataLen )已经把低位放在前面了
                            modbus.Sendbuf[i++] = F3_Crc_Value / 256;//填充CRC校验低位,
                            modbus.Sendbuf[i++] = F3_Crc_Value % 256;//填充CRC校验高位
                            for(F3_Return_Num = 0;F3_Return_Num < i;F3_Return_Num ++)//从机发送数据
                            {
                                    USART_SendData(USART1,modbus.Sendbuf[F3_Return_Num]);
                                    while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) ==RESET);
                            }       
                    }
                    else  //如果要求读取的寄存器数量不在规定数量之内
                    {
                            u8 F3_unusual_NumReg,i;
                            u16 F3_Unusual_Return_CRC;
                            modbus.Sendbuf[i++] = modbus.myadd;//第一填充本从机地址
                            modbus.Sendbuf[i++] = (modbus.rcbuf[1] | 0x80);//第二、填充运行的功能码+0x80 异常码
                            modbus.Sendbuf[i++] = 0x03;  //填充异常代码
                            F3_Unusual_Return_CRC = crc16( modbus.Sendbuf, i );
                            modbus.Sendbuf[i++] = F3_Unusual_Return_CRC / 256;//填充CRC校验低位,
                            modbus.Sendbuf = F3_Unusual_Return_CRC % 256;//填充CRC校验高位
                            for(F3_unusual_NumReg = 0;F3_unusual_NumReg <= i;F3_unusual_NumReg ++)
                            {
                                    USART_SendData(USART1,modbus.Sendbuf[F3_unusual_NumReg]);  //地址
                                    while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) ==RESET);
                            }
                    }
            }
            else  //如果地址范围不在规定地址区间内
            {
                    u8 F3_unusual_Addr,i;
                    u16 F3_Unusual_Addr_CRC;
                    modbus.Sendbuf[i++] = modbus.myadd;//第一填充本从机地址
                    modbus.Sendbuf[i++] = (modbus.rcbuf[1] | 0x80);//第二、填充运行的功能码+0x80 异常码
                    modbus.Sendbuf[i++] = 0x02;  //填充异常代码
                    F3_Unusual_Addr_CRC = crc16( modbus.Sendbuf, i );
                    modbus.Sendbuf[i++] = F3_Unusual_Addr_CRC / 256;//填充CRC校验低位,
                    modbus.Sendbuf = F3_Unusual_Addr_CRC % 256;//填充CRC校验高位
                    for(F3_unusual_Addr = 0;F3_unusual_Addr <= i;F3_unusual_Addr ++)
                    {
                            USART_SendData(USART1,modbus.Sendbuf[F3_Unusual_Addr_CRC]);  //地址
                            while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) ==RESET);
                    }                                                                                       
            }
           
    }

一个小工 2018-12-7 17:05:39
1回复

举报

评论

您需要登录后才可以回帖 登录/注册

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
快速回复 返回顶部 返回列表
关注微信公众号

电子发烧友网

电子发烧友论坛

社区合作
刘勇
联系电话:15994832713
邮箱地址:liuyong@huaqiu.com
社区管理
elecfans短短
微信:elecfans_666
邮箱:users@huaqiu.com
关闭

站长推荐 上一条 /6 下一条

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