搜索
bottom↓
楼主: xukai871105

STM32 移植FreeModbus 详细过程

  [复制链接]

出0入0汤圆

发表于 2013-9-5 04:43:38 | 显示全部楼层
Does anyone ever implement the Modbus protocol through USB instead of UART?

出0入0汤圆

发表于 2013-9-7 15:12:40 | 显示全部楼层
先收藏,谢谢分享

出0入0汤圆

发表于 2013-9-9 14:26:53 | 显示全部楼层
好东西,标记

出0入0汤圆

发表于 2013-9-11 17:36:24 | 显示全部楼层
文档看了一遍又一遍,别人的代码也读了一遍又一遍,还是搞不懂。。。

出0入0汤圆

发表于 2013-9-11 23:11:54 | 显示全部楼层
Mark,太给力了

出0入0汤圆

发表于 2013-9-12 08:51:01 | 显示全部楼层
好帖子,帮顶,学习一下,移植到LPC1788/LPC1850上

出0入0汤圆

发表于 2013-9-12 08:52:41 | 显示全部楼层
不知道从什么开始,每天刷微博,编程每天  膜拜 阿莫里面的  神仙 和 无私的 大大们了····作为一个学僧党,我要奋起直追···

出0入0汤圆

发表于 2013-9-15 22:20:24 | 显示全部楼层
好东西,留个印。。。。。。。。。。。

出0入0汤圆

发表于 2013-9-18 16:34:06 | 显示全部楼层
从头到尾看了一遍,开始移植了

出0入0汤圆

发表于 2013-9-18 17:09:49 | 显示全部楼层
头一次听说FREEMODBUS

出0入0汤圆

发表于 2013-9-18 20:25:30 | 显示全部楼层
好东西   以前用AVR 写过modbus   只实现读写功能    等学会32  要试试   果断收藏了

出0入0汤圆

 楼主| 发表于 2013-9-18 23:28:34 | 显示全部楼层
szmini2006 发表于 2013-9-18 17:09
头一次听说FREEMODBUS

希望对你有帮助!

出0入0汤圆

发表于 2013-9-19 15:20:48 | 显示全部楼层
xukai871105 发表于 2013-9-18 23:28
希望对你有帮助!

好的,正好学习一下,谢谢

出0入0汤圆

发表于 2013-9-19 15:42:35 | 显示全部楼层
请问这个FREEMODBUS和MODBUS有什么区别呢?

出0入0汤圆

 楼主| 发表于 2013-9-19 22:27:35 | 显示全部楼层
凌滨 发表于 2013-9-19 15:42
请问这个FREEMODBUS和MODBUS有什么区别呢?

modbus是协议名称 freemodbus是协议实现的一种方法
好比TCP IP和LwIP

出0入0汤圆

发表于 2013-9-21 18:21:18 | 显示全部楼层
请问楼主,你调试的时候用的是RS232接口还是RS485接口?我用RS232接口调试,能成功,但是CRC错误,time out错误、miss bytes错误,频繁出现...

出0入0汤圆

发表于 2013-9-22 10:42:07 | 显示全部楼层
xukai871105 发表于 2013-9-19 22:27
modbus是协议名称 freemodbus是协议实现的一种方法
好比TCP IP和LwIP

请问你调试时用的是笔记本还是台式机?我用笔记本,USB转串口调试时,频繁出错,用你提供的程序,移植到keil下,也出错...

出0入0汤圆

发表于 2013-9-22 11:14:51 | 显示全部楼层
本帖最后由 Semiconductor 于 2013-9-22 11:20 编辑

楼主的经验分享很详细,感谢!
中秋假期,潜心研读了。
另,在“六、寄存器读写函数”中,强制线圈函数中的写线圈部分,似乎有纰漏,原代码如下:
  1. /**
  2. * @brief 线圈寄存器处理函数,线圈寄存器可读,可读可写
  3. * @param pucRegBuffer 读操作---返回数据指针,写操作--返回数据指针
  4. * usAddress 寄存器起始地址
  5. * usNRegs 寄存器长度
  6. * eMode 操作方式,读或者写
  7. * @retval eStatus 寄存器状态
  8. */
  9. eMBErrorCode
  10. eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
  11. eMBRegisterMode eMode )
  12. {
  13. //错误状态
  14. eMBErrorCode eStatus = MB_ENOERR;
  15. //寄存器个数
  16. int16_t iNCoils = ( int16_t )usNCoils;
  17. //寄存器偏移量
  18. int16_t usBitOffset;

  19. //检查寄存器是否在指定范围内
  20. if( ( (int16_t)usAddress >= REG_COILS_START ) &&
  21. ( usAddress + usNCoils <= REG_COILS_START + REG_COILS_SIZE ) )
  22. {
  23. //计算寄存器偏移量
  24. usBitOffset = ( int16_t )( usAddress - REG_COILS_START );
  25. switch ( eMode )
  26. {
  27. //读操作
  28. case MB_REG_READ:
  29. while( iNCoils > 0 )
  30. {
  31. *pucRegBuffer++ = xMBUtilGetBits( ucRegCoilsBuf, usBitOffset,
  32. ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ) );
  33. iNCoils -= 8;
  34. usBitOffset += 8;
  35. }
  36. break;

  37. //写操作
  38. case MB_REG_WRITE:
  39. while( iNCoils > 0 )
  40. {
  41. xMBUtilSetBits( ucRegCoilsBuf, usBitOffset,
  42. ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ),
  43. *pucRegBuffer++ );
  44. iNCoils -= 8;
  45. }
  46. break;
  47. }

  48. }
  49. else
  50. {
  51. eStatus = MB_ENOREG;
  52. }
  53. return eStatus;
  54. }
复制代码
纰漏部分的修改代码如下:
  1. //写操作
  2. case MB_REG_WRITE:
  3. while( iNCoils > 0 )
  4. {
  5. xMBUtilSetBits( ucRegCoilsBuf, usBitOffset,
  6. ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ),
  7. *pucRegBuffer++ );
  8. iNCoils -= 8;
  9. usBitOffset += 8;  //增添纰漏部分
  10. }
复制代码
如有不对,还望指教。

出0入0汤圆

发表于 2013-9-22 17:07:45 | 显示全部楼层
不错 支持楼主

出0入0汤圆

 楼主| 发表于 2013-9-23 09:17:10 | 显示全部楼层
Semiconductor 发表于 2013-9-22 11:14
楼主的经验分享很详细,感谢!
中秋假期,潜心研读了。
另,在“六、寄存器读写函数”中,强制线圈函数中的 ...

非常感谢,我也发现问题了,一直没有找出来!

出0入0汤圆

发表于 2013-9-23 23:55:40 | 显示全部楼层
再提出一个问题,劳烦楼主

在用06号(写单个保持寄存器)、16号(写多个保持寄存器)、23号(读/写多个保持寄存器)功能时,程序体现不一致,具体为:
06号、16号功能可正常写40001保持寄存器,但23号功能在读/写40001、40002寄存器时,实际程序中读/写的寄存器为40002、40003,即后移了一个寄存器地址。

出0入0汤圆

发表于 2013-9-24 00:29:40 | 显示全部楼层
本帖最后由 Semiconductor 于 2013-9-24 09:15 编辑

找到原因,如下
原【modbus】文件夹下的【functions】文件夹下的【mbfuncholding.c】文件中 的【eMBFuncReadWriteMultipleHoldingRegister】 函数为
  1. eMBException
  2. eMBFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
  3. {
  4.     USHORT          usRegReadAddress;
  5.     USHORT          usRegReadCount;
  6.     USHORT          usRegWriteAddress;
  7.     USHORT          usRegWriteCount;
  8.     UCHAR           ucRegWriteByteCount;
  9.     UCHAR          *pucFrameCur;

  10.     eMBException    eStatus = MB_EX_NONE;
  11.     eMBErrorCode    eRegStatus;

  12.     if( *usLen >= ( MB_PDU_FUNC_READWRITE_SIZE_MIN + MB_PDU_SIZE_MIN ) )
  13.     {
  14.         usRegReadAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF] << 8U );
  15.         usRegReadAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF + 1] );
  16.         usRegReadAddress++;

  17.         usRegReadCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF] << 8U );
  18.         usRegReadCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF + 1] );

  19.         usRegWriteAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF] << 8U );
  20.         usRegWriteAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF + 1] );
  21.         usRegWriteAddress++;

  22.         usRegWriteCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF] << 8U );
  23.         usRegWriteCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF + 1] );

  24.         ucRegWriteByteCount = pucFrame[MB_PDU_FUNC_READWRITE_BYTECNT_OFF];

  25.         if( ( usRegReadCount >= 1 ) && ( usRegReadCount <= 0x7D ) &&
  26.             ( usRegWriteCount >= 1 ) && ( usRegWriteCount <= 0x79 ) &&
  27.             ( ( 2 * usRegWriteCount ) == ucRegWriteByteCount ) )
  28.         {
  29.             /* Make callback to update the register values. */
  30.             eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF],
  31.                                           usRegWriteAddress, usRegWriteCount, MB_REG_WRITE );

  32.             if( eRegStatus == MB_ENOERR )
  33.             {
  34.                 /* Set the current PDU data pointer to the beginning. */
  35.                 pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
  36.                 *usLen = MB_PDU_FUNC_OFF;

  37.                 /* First byte contains the function code. */
  38.                 *pucFrameCur++ = MB_FUNC_READWRITE_MULTIPLE_REGISTERS;
  39.                 *usLen += 1;

  40.                 /* Second byte in the response contain the number of bytes. */
  41.                 *pucFrameCur++ = ( UCHAR ) ( usRegReadCount * 2 );
  42.                 *usLen += 1;

  43.                 /* Make the read callback. */
  44.                 eRegStatus =
  45.                     eMBRegHoldingCB( pucFrameCur, usRegReadAddress, usRegReadCount, MB_REG_READ );
  46.                 if( eRegStatus == MB_ENOERR )
  47.                 {
  48.                     *usLen += 2 * usRegReadCount;
  49.                 }
  50.             }
  51.             if( eRegStatus != MB_ENOERR )
  52.             {
  53.                 eStatus = prveMBError2Exception( eRegStatus );
  54.             }
  55.         }
  56.         else
  57.         {
  58.             eStatus = MB_EX_ILLEGAL_DATA_VALUE;
  59.         }
  60.     }
  61.     return eStatus;
  62. }
复制代码
修改为:
  1. eMBException
  2. eMBFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
  3. {
  4.     USHORT          usRegReadAddress;
  5.     USHORT          usRegReadCount;
  6.     USHORT          usRegWriteAddress;
  7.     USHORT          usRegWriteCount;
  8.     UCHAR           ucRegWriteByteCount;
  9.     UCHAR          *pucFrameCur;

  10.     eMBException    eStatus = MB_EX_NONE;
  11.     eMBErrorCode    eRegStatus;

  12.     if( *usLen >= ( MB_PDU_FUNC_READWRITE_SIZE_MIN + MB_PDU_SIZE_MIN ) )
  13.     {
  14.         usRegReadAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF] << 8U );
  15.         usRegReadAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF + 1] );
  16.         //修改
  17.        //usRegReadAddress++;

  18.         usRegReadCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF] << 8U );
  19.         usRegReadCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF + 1] );

  20.         usRegWriteAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF] << 8U );
  21.         usRegWriteAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF + 1] );
  22.         //修改
  23.       //usRegWriteAddress++;

  24.         usRegWriteCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF] << 8U );
  25.         usRegWriteCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF + 1] );

  26.         ucRegWriteByteCount = pucFrame[MB_PDU_FUNC_READWRITE_BYTECNT_OFF];

  27.         if( ( usRegReadCount >= 1 ) && ( usRegReadCount <= 0x7D ) &&
  28.             ( usRegWriteCount >= 1 ) && ( usRegWriteCount <= 0x79 ) &&
  29.             ( ( 2 * usRegWriteCount ) == ucRegWriteByteCount ) )
  30.         {
  31.             /* Make callback to update the register values. */
  32.             eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF],
  33.                                           usRegWriteAddress, usRegWriteCount, MB_REG_WRITE );

  34.             if( eRegStatus == MB_ENOERR )
  35.             {
  36.                 /* Set the current PDU data pointer to the beginning. */
  37.                 pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
  38.                 *usLen = MB_PDU_FUNC_OFF;

  39.                 /* First byte contains the function code. */
  40.                 *pucFrameCur++ = MB_FUNC_READWRITE_MULTIPLE_REGISTERS;
  41.                 *usLen += 1;

  42.                 /* Second byte in the response contain the number of bytes. */
  43.                 *pucFrameCur++ = ( UCHAR ) ( usRegReadCount * 2 );
  44.                 *usLen += 1;

  45.                 /* Make the read callback. */
  46.                 eRegStatus =
  47.                     eMBRegHoldingCB( pucFrameCur, usRegReadAddress, usRegReadCount, MB_REG_READ );
  48.                 if( eRegStatus == MB_ENOERR )
  49.                 {
  50.                     *usLen += 2 * usRegReadCount;
  51.                 }
  52.             }
  53.             if( eRegStatus != MB_ENOERR )
  54.             {
  55.                 eStatus = prveMBError2Exception( eRegStatus );
  56.             }
  57.         }
  58.         else
  59.         {
  60.             eStatus = MB_EX_ILLEGAL_DATA_VALUE;
  61.         }
  62.     }
  63.     return eStatus;
  64. }
复制代码
即将usRegReadAddress++;usRegReadAddress++;屏蔽即可

出0入0汤圆

发表于 2013-9-25 16:36:24 | 显示全部楼层
10楼的问题是不是485门控信号的延时,建议用示波器看下

出0入0汤圆

发表于 2013-9-26 10:08:14 | 显示全部楼层
Semiconductor 发表于 2013-9-24 00:29
找到原因,如下
原【modbus】文件夹下的【functions】文件夹下的【mbfuncholding.c】文件中 的【eMBFuncRea ...

你好,能请教一下freemodbus吗?你的qq是多少?

出0入0汤圆

发表于 2013-9-26 11:02:24 | 显示全部楼层
我也回过头来研究研究。自己写的虽然凑合也能用。但还是要学学规范的东西。

出0入0汤圆

发表于 2013-9-26 11:08:36 | 显示全部楼层
太酷了!!

出0入0汤圆

发表于 2013-9-26 11:08:57 | 显示全部楼层
好详尽的资料

出0入0汤圆

发表于 2013-9-26 11:09:18 | 显示全部楼层
顶礼膜拜

出0入0汤圆

发表于 2013-9-26 11:09:39 | 显示全部楼层
很虔诚地学习

出0入0汤圆

发表于 2013-9-27 14:47:05 | 显示全部楼层
要做主机,认真学习

出0入0汤圆

发表于 2013-9-27 15:13:48 | 显示全部楼层
mark

出0入0汤圆

发表于 2013-10-2 15:53:56 | 显示全部楼层
经过两个星期的学习,终于搞明白了,在stm32f103vct6上移植freemodbus(程序实测stm32f103rbt6下也能用)。遇到一些问题,在后期的辅助视频里一一详细地给出了说明,非常给力!可能会遇到一些问题:illegal address(因为quantity和你的程序设置有关),time out(可能是你的串口驱动或者485于驱动问题导致的),no connection(串口线TR是否接反,ab是否接反)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入16汤圆

发表于 2013-10-2 16:12:56 来自手机 | 显示全部楼层
收藏一下!准备移植

出0入0汤圆

发表于 2013-10-2 16:45:16 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2013-10-2 21:37:01 | 显示全部楼层
我的硬件是STM32F103C8T6,我的RS485硬件用我自己的程序发送与接收没有问题,但把楼主的程序用上去没反应(用的是UTRA1,在楼主程序中把RS485控制端都做了修改),用MODBUS调试软件下发但STM32无反应,不知哪出了问题?
谢谢

出0入0汤圆

 楼主| 发表于 2013-10-3 10:05:04 | 显示全部楼层
linlingpeng 发表于 2013-10-2 15:53
经过两个星期的学习,终于搞明白了,在stm32f103vct6上移植freemodbus(程序实测stm32f103rbt6下也能用)。遇 ...

总结的很有道理,我也受用了!

出0入0汤圆

发表于 2013-10-3 17:49:55 | 显示全部楼层
感谢分享,很好。

出0入0汤圆

发表于 2013-10-4 00:32:51 | 显示全部楼层
等待 modbus tcp发布!

出0入0汤圆

 楼主| 发表于 2013-10-4 14:21:53 | 显示全部楼层
min2004 发表于 2013-10-4 00:32
等待 modbus tcp发布!

最近堕落了,一直看电影,北京出差5天受打击了,正在恢复中!

出0入0汤圆

发表于 2013-10-5 01:12:27 | 显示全部楼层
xukai871105 发表于 2013-10-4 14:21
最近堕落了,一直看电影,北京出差5天受打击了,正在恢复中!

要不断跟楼主学习,楼主受啥打击了? 楼主高手啊!

出0入0汤圆

发表于 2013-10-5 09:55:40 | 显示全部楼层
楼主,你好,可否加个好友,最近也在搞一个STM32与欧姆龙触摸屏通信的项目,遇到一些问题,有些问题请教

出0入0汤圆

发表于 2013-10-13 10:45:40 | 显示全部楼层
Semiconductor 发表于 2013-9-24 00:29
找到原因,如下
原【modbus】文件夹下的【functions】文件夹下的【mbfuncholding.c】文件中 的【eMBFuncRea ...

请问:我注释掉了怎么还是不行

出0入0汤圆

发表于 2013-10-13 10:52:35 来自手机 | 显示全部楼层
cchwhk 发表于 2013-10-13 10:45:40

请问:我注释掉了怎么还是不行

你目前的现象是什么?

出0入0汤圆

发表于 2013-10-13 12:44:15 | 显示全部楼层
学习学习

出0入0汤圆

发表于 2013-10-13 16:19:01 | 显示全部楼层
xukai871105 发表于 2012-8-12 20:00
五 定时器相关部分代码编写
        定时器的作用前面已经说明了,在这里就罗列一下相关的移植代码。定时器 ...

好东西啊.

出0入0汤圆

发表于 2013-10-13 18:49:06 | 显示全部楼层
Semiconductor 发表于 2013-10-13 10:52
你目前的现象是什么?

我找到问题啦,先谢谢哈,那两句注释掉后,eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )这个函数中的*PRT++ = __REV16(usRegHoldingBuf[iRegIndex++]); 和*pucRegBuffer++ = ( unsigned char )( usRegHoldingBuf[iRegIndex] >> 8 );
                                                                                *pucRegBuffer++ = ( unsigned char )( usRegHoldingBuf[iRegIndex] & 0xFF );
                                                 iRegIndex++;这三句只能要一种,现在改了,已经没问题了。

出0入0汤圆

发表于 2013-10-19 22:06:50 | 显示全部楼层
hao  。学习了

出0入0汤圆

发表于 2013-10-19 22:52:13 | 显示全部楼层
不错,正在学习MODBUS协议,准备用STM8进行开发

出0入0汤圆

发表于 2013-10-20 22:52:38 | 显示全部楼层
很不错!这几天也在研究使用MODBUS协议和MCGS显示屏之间的通讯,使用STM32F107,学习一下!

出0入0汤圆

发表于 2013-10-21 15:22:19 | 显示全部楼层
太喜欢楼主的精神,做一件事就把它搞懂,搞透彻,而不是一知半解

出0入0汤圆

 楼主| 发表于 2013-10-22 08:57:16 | 显示全部楼层
liuchuanxhu 发表于 2013-10-21 15:22
太喜欢楼主的精神,做一件事就把它搞懂,搞透彻,而不是一知半解

你看看 我在论坛里还发布了 nmealib和uIP的资料

出0入0汤圆

发表于 2013-10-22 09:02:30 | 显示全部楼层
顶一下.............

出0入0汤圆

发表于 2013-10-24 15:16:13 | 显示全部楼层
好象我顶过了么,这么好的东西再顶一下

出0入0汤圆

发表于 2013-10-30 15:01:19 | 显示全部楼层
用得上。MARK。

出0入0汤圆

发表于 2013-10-30 17:09:24 | 显示全部楼层
写得很详细,谢谢了

出0入0汤圆

发表于 2013-11-4 21:38:31 | 显示全部楼层
看了楼主的心得笔记 移植了一下初次接触的freemodbus 到STM32上 用的是RS232 但是貌似有点儿问题

配置好modbus poll 开始工作后 接收到的是 IIIegal Data Adress  用虚拟串口抓出来的数据显示是
modbus poll 发送的是:01 03 00 00 00 08 44 0C
STM32反馈的是数据是:01 83 02 C0 F1

我知道83是读保持寄存器错误,02是发送的是非法数据地址?这个怎么分析或者什么原因造成的呢?怎么就非法数据地址了呢?

出0入0汤圆

发表于 2013-11-4 21:51:55 | 显示全部楼层
mark,

出0入0汤圆

 楼主| 发表于 2013-11-5 13:31:14 | 显示全部楼层
byrin219 发表于 2013-11-4 21:38
看了楼主的心得笔记 移植了一下初次接触的freemodbus 到STM32上 用的是RS232 但是貌似有点儿问题

配置好mo ...

请修改 modbus poll的读取个数为8

出0入0汤圆

发表于 2013-11-5 14:59:00 | 显示全部楼层
不错,好东西,,

出0入0汤圆

发表于 2013-11-5 23:08:06 | 显示全部楼层

出0入0汤圆

发表于 2013-11-6 16:46:55 | 显示全部楼层
楼主 写的不错,那个串口中断 中的 Overrun 有没有必要处理一下。你看

出0入0汤圆

发表于 2013-11-7 15:39:58 | 显示全部楼层
本帖最后由 semonpic 于 2013-11-8 11:12 编辑

我讲串口中断优化了下,楼主你看
void USART2_IRQHandler(void)
{
  
  if(((USART2->CR1&0x20)!=0)&&((USART2->SR&0xA0)!=0))//接收中断处理
  {
                         
                prvvUARTRxISR();
    //USART_ClearITPendingBit(USART2, USART_IT_RXNE);   
                USART2->SR &=(0x00000020);
  }
  

  if(((USART2->CR1&0x40)!=0)&&((USART2->SR&0x40)!=0))//发送完成中断处理
  {
                prvvUARTTxReadyISR();
   // USART_ClearITPendingBit(USART2, USART_IT_TC);
                USART2->SR&=(0x00000040);
  }


出0入0汤圆

 楼主| 发表于 2013-11-7 16:10:15 | 显示全部楼层
semonpic 发表于 2013-11-7 15:39
我讲串口中断优化了下,楼主你看
void USART2_IRQHandler(void)
{

看来您是不喜欢使用 libraray的啊!!!

出0入0汤圆

发表于 2013-11-7 16:25:09 | 显示全部楼层
牛人如此多。

出0入0汤圆

发表于 2013-11-10 20:35:52 | 显示全部楼层
正在学习中,顶起!

出0入0汤圆

发表于 2013-11-10 20:55:42 | 显示全部楼层
非常感谢您的资料,谢谢

出0入0汤圆

发表于 2013-11-13 18:16:53 | 显示全部楼层
mark,好东西

出0入0汤圆

发表于 2013-11-15 16:56:49 | 显示全部楼层
表示第一次看到ModBus的库,以前都是自己写主机从机程序,跑起来还蛮顺的,支持一下

出0入0汤圆

发表于 2013-11-15 17:56:41 | 显示全部楼层
学习了                    

出0入0汤圆

发表于 2013-11-21 21:30:44 | 显示全部楼层
谢谢分享啊,正在学习。

出0入0汤圆

发表于 2013-11-22 13:12:17 | 显示全部楼层
楼主有没有 modbus 主站的STM32 程序

出0入0汤圆

发表于 2013-11-22 17:32:35 | 显示全部楼层
xukai871105 发表于 2012-8-18 22:23
多谢啊,混了那么久还没有一个帖子穿上裤子!
感觉穿上裤子的难度和写SCI论文难度差不多啊!

楼兄,我也按你的工程移植了,但用上位机软件和STM32通信时,他上位机老是提示超时,但单步进入程序里,已经是收到了正确的数据,比如读保持REG等,这是什么情况呢,不过不是modbus poll上位机

出0入0汤圆

发表于 2013-11-24 13:48:10 | 显示全部楼层
支持!!!!!!!!!!!!!!

出0入0汤圆

发表于 2013-11-25 15:43:38 | 显示全部楼层
楼主,我的STM32在串口驱动vMBPortSerialEnable 函数中使能RS485控制线,但发送的时侯老是丢了一个字节,导至上位机接收不正常,你的会出现丢数据么

出0入0汤圆

发表于 2013-11-25 16:18:30 | 显示全部楼层
hejiang177 发表于 2013-11-25 15:43
楼主,我的STM32在串口驱动vMBPortSerialEnable 函数中使能RS485控制线,但发送的时侯老是丢了一个字节,导 ...

找到问题了,因为IO控制速度很快,也就是说CPU置位了低,使RS485为接收,但这时USART还没发完,所以要在vMBPortSerialEnable函数中增加一句        while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);就OK了(_TRUE==xRxEnable)
{
                while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
                RS485_RECVIE;
                USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
        }
        else{
                RS485_SNED;
                USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);       

        }

        if(_TRUE==xTxEnable){
                //RS485_SNED;
                USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
        }else{
            //RS485_RECVIE;
            USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
        }

出0入0汤圆

发表于 2013-11-26 09:30:57 | 显示全部楼层
LZ强啊,谢谢您的分享,我不是很懂,看了你的这个帖子,决定静下心来想搞一下看看~

出0入0汤圆

发表于 2013-11-26 10:08:34 | 显示全部楼层
byrin219 发表于 2013-11-4 21:38
看了楼主的心得笔记 移植了一下初次接触的freemodbus 到STM32上 用的是RS232 但是貌似有点儿问题

配置好mo ...

兄弟,其实我也有这个疑问因为在这个函数中usAddress 变量在上一个调用这个函数时,自加了一,所 以这里usAddress==1,而 REG_HOLDING_NREGS 数量8, usNRegs 数量也是8的话,则usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS 不成立,1+8=9 大于了 REG_HOLDING_START + REG_HOLDING_NREGS

所以返回地址非法错误了,也就是搞不明白DEMO程序为什么不从,BUFFER【0】开始读或写,而要从BUFFER[1]去读写了,不知是哪里没 解正确

出0入0汤圆

发表于 2013-12-16 23:53:28 | 显示全部楼层
谢谢楼主,Mark一下,回单位慢慢看~o(∩_∩)o 哈哈

出0入0汤圆

发表于 2013-12-17 08:19:42 | 显示全部楼层
牛!!!!!!!

出0入0汤圆

发表于 2013-12-17 09:58:24 | 显示全部楼层
xukai871105 发表于 2012-8-12 20:00
五 定时器相关部分代码编写
        定时器的作用前面已经说明了,在这里就罗列一下相关的移植代码。定时器 ...

好东西。谢谢楼主。

出0入0汤圆

发表于 2013-12-17 10:41:59 | 显示全部楼层
果断收藏了

出0入0汤圆

发表于 2013-12-18 21:44:50 | 显示全部楼层
哈哈,按照楼主的教程移植成功了,必须要顶一个,如果楼主能再出一个NModbus的C#教程就更好了~o(∩_∩)o 哈哈

出0入0汤圆

 楼主| 发表于 2013-12-18 22:08:07 | 显示全部楼层
chxaitz 发表于 2013-12-18 21:44
哈哈,按照楼主的教程移植成功了,必须要顶一个,如果楼主能再出一个NModbus的C#教程就更好了~o(∩_∩)o 哈 ...

呵呵 MODBUS TCP和NMODBUS都是我欠下的文字债啊!

出0入0汤圆

发表于 2013-12-18 23:24:19 | 显示全部楼层
hejiang177 发表于 2013-11-26 10:08
兄弟,其实我也有这个疑问因为在这个函数中usAddress 变量在上一个调用这个函数时,自加了一,所 以这里u ...

原先我是把所有的usAddress++给去掉的,后来感觉不应该改变源码,就把所有的 REG_XX_START 都定义为0x01而不是0x00,这样就那个iRegIndex就又能从0开始了~o(∩_∩)o 哈哈

出0入0汤圆

发表于 2013-12-19 09:34:55 | 显示全部楼层
MARK,以后再来研究,感谢,

出0入0汤圆

发表于 2013-12-19 14:06:40 | 显示全部楼层
值得拥有

出0入0汤圆

发表于 2013-12-20 16:03:47 | 显示全部楼层
xukai871105 发表于 2013-12-18 22:08
呵呵 MODBUS TCP和NMODBUS都是我欠下的文字债啊!


在430的移植中遇到的问题,能帮忙指导下么 ?

它官方的demo是基于GCC 的,我加到IAR工程中usOldSR = _DINT( );这里报错

Error[Pe513]: a value of type "void" cannot be assigned to an entity of type "USHORT"



所在的函数如下:
  1. void EnterCriticalSection( void )
  2. {
  3.     USHORT usOldSR;
  4.     if( ucCriticalNesting == 0 )
  5.     {
  6.         usOldSR = _DINT( );
  7.         ucGIEWasEnabled = usOldSR & GIE ? TRUE : FALSE;
  8.     }
  9.     ucCriticalNesting++;
  10. }
复制代码


而这个函数被这样宏定义:
#define ENTER_CRITICAL_SECTION( )   EnterCriticalSection( )

这里ENTER_CRITICAL_SECTION( ) 是关总中断么?
这里要如何修改?
谢谢。。

出0入0汤圆

发表于 2013-12-21 11:30:34 | 显示全部楼层
学习了。谢谢

出0入0汤圆

发表于 2013-12-21 11:39:29 | 显示全部楼层
最近我也在看modbus

出0入0汤圆

 楼主| 发表于 2013-12-21 20:52:12 | 显示全部楼层
motoedy 发表于 2013-12-20 16:03
在430的移植中遇到的问题,能帮忙指导下么 ?

它官方的demo是基于GCC 的,我加到IAR工程中usOldSR = _DI ...

ENTER_CRITICAL_SECTION( ) 的确是关中断的意思

如果我没有记错的话,_EINT是开总中断,_DINT为关总中断

如果这部分存在问题,可以把上面的宏写成空,先绕过去再说不会影响你的移植体验,可以回过头来弄弄!

出0入0汤圆

发表于 2013-12-21 23:08:49 | 显示全部楼层
谢谢楼主,学习一下啊!

出0入0汤圆

发表于 2013-12-21 23:26:25 | 显示全部楼层
嗯,先留意一下,以后留着用

出0入0汤圆

发表于 2013-12-23 13:30:27 | 显示全部楼层
xukai871105 发表于 2013-12-21 20:52
ENTER_CRITICAL_SECTION( ) 的确是关中断的意思

如果我没有记错的话,_EINT是开总中断,_DINT为关总中断 ...

这里的开中断和关中断的两个宏定义,用在Freemodbus里面是做临界代码用的吧?
Freemodbus里面对中断打断要求很严格么?还是作者的编程习惯?
临界代码这个一般是用在OS里面的吧,这里裸奔的话需要么?

出0入0汤圆

发表于 2013-12-24 11:24:38 | 显示全部楼层
Flyback 发表于 2012-9-13 21:44
STM32用的还不是很顺,现在代码改成和你上传的一样的方式,使用发送完成中断TC

但是只能响应一次 ,通信 ...

请问您解决了这个问题吗  我现在也纠结于这个难题好几天了 232可行  一改成485立刻不行了

出0入0汤圆

发表于 2013-12-24 16:54:44 | 显示全部楼层
xukai871105 发表于 2013-12-21 20:52
ENTER_CRITICAL_SECTION( ) 的确是关中断的意思

如果我没有记错的话,_EINT是开总中断,_DINT为关总中断 ...

又遇到问题了,Freemodbus必须独占一个定时器么?
vMBPortTimersEnable( );
vMBPortTimersDisable(  );

这两个函数都是直接开或关了某一个定时器啊,
假如我只有两个定时器,而这两个定时器都有其他用途,那岂不是Freemodbus这里就没法用了?

出0入0汤圆

 楼主| 发表于 2013-12-25 09:21:30 | 显示全部楼层
motoedy 发表于 2013-12-24 16:54
又遇到问题了,Freemodbus必须独占一个定时器么?
vMBPortTimersEnable( );
vMBPortTimersDisable(  );

别着急,你尝试一下其他方式的软件定时器

出0入0汤圆

发表于 2013-12-25 09:50:10 | 显示全部楼层
谢谢  楼主。

出0入0汤圆

发表于 2013-12-25 09:56:05 | 显示全部楼层
谢谢  楼主。

出0入0汤圆

发表于 2013-12-25 10:10:19 | 显示全部楼层
xukai871105 发表于 2013-12-25 09:21
别着急,你尝试一下其他方式的软件定时器

他这里用定时器只是为了产生多少个50us么?

出0入0汤圆

发表于 2013-12-26 09:23:11 | 显示全部楼层
xukai871105 发表于 2013-12-25 09:21
别着急,你尝试一下其他方式的软件定时器

你们在实际应用中,
eMBPoll();
这个查询函数都是放在主函数的while循环里面么?
那你们主程序就不干别的事么?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 21:56

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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