[应用相关] STM32 上移植 FreeModbus RTU

[复制链接]
2461|39
sj8zw8 发表于 2020-2-27 20:21 | 显示全部楼层
代码直接复制,这个是复制粘贴过来就有的功能吗?
sj8zw8 发表于 2020-2-27 20:21 | 显示全部楼层
我发不出来那种可以直接复制的,发出来格式就变了。
sj8zw8 发表于 2020-2-27 20:21 | 显示全部楼层
 楼主| stm32jy 发表于 2020-2-28 13:00 | 显示全部楼层
定时器中断服务函数 void TIM2_IRQHandler(void)
  1. void TIM2_IRQHandler(void)
  2. {
  3. if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
  4. {
  5. TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  6. prvvTIMERExpiredISR();
  7. }
  8. }


 楼主| stm32jy 发表于 2020-2-28 13:01 | 显示全部楼层

高级工具里面有个 <>工具 ,放这里就行了
 楼主| stm32jy 发表于 2020-2-28 13:02 | 显示全部楼层
打开 port.h 文件,这个文件可以从\demo\BARE 文件夹下拷贝过来的
281415e589ec6b42d2.png


 楼主| stm32jy 发表于 2020-2-28 13:02 | 显示全部楼层
这是\demo\BARE 文件夹下原 port.h 文件的内容
799855e589ee7bbd94.png
 楼主| stm32jy 发表于 2020-2-28 13:03 | 显示全部楼层
在 port.h 文 件 补 充 完 成 以 下 两 个 函 数 ENTER_CRITICAL_SECTION( ) 和
EXIT_CRITICAL_SECTION( ),这两个函数跟中断有关,开或者关中断。
367155e589f25e6608.png
 楼主| stm32jy 发表于 2020-2-28 13:04 | 显示全部楼层
以下是工程项目文件夹下修改后的 port.h 文件内容
250545e589f513e45b.png
 楼主| stm32jy 发表于 2020-2-28 13:04 | 显示全部楼层
分别完善以下 4 个回调函数
4.3.1、操作输入寄存器 eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer,
USHORT usAddress, USHORT usNRegs )
4.3.2、操作保持寄存器 eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer,
USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
4.3.3、操作线圈 eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT
usAddress, USHORT usNCoils, eMBRegisterMode eMode )4.3.4、操作离散寄存器 eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer,
USHORT usAddress, USHORT usNDiscrete )
 楼主| stm32jy 发表于 2020-2-28 13:06 | 显示全部楼层
第一次编译报错,删除porttimer.c 中定时器使能和失能函数前的inline 字样。
173695e589fc24fcab.png
 楼主| stm32jy 发表于 2020-2-28 13:06 | 显示全部楼层
再次编译,出现关于assert的错误
42515e589fdf61538.png
 楼主| stm32jy 发表于 2020-2-28 13:07 | 显示全部楼层
在主函数下面添加以下代码,即可解决以上问题,编译无误后开始添加测试代码来测试移植的FreeModbus是否成功。
  1. #ifdef  USE_FULL_ASSERT
  2. /**
  3.   * [url=home.php?mod=space&uid=247401]@brief[/url]  Reports the name of the source file and the source line number
  4.   *         where the assert_param error has occurred.
  5.   * @param  file: pointer to the source file name
  6.   * @param  line: assert_param error line source number
  7.   * @retval None
  8.   */  
  9. void assert_failed(uint8_t* file, uint32_t line)  
  10. {  
  11.   /* User can add his own implementation to report the file name and line number,
  12.      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */  
  13.    
  14.   /* Infinite loop */  
  15.   while (1)  
  16.   {  
  17.   }  
  18. }
  19. #else
  20. void __aeabi_assert(const char * x1, const char * x2, int x3)
  21. {
  22. }


 楼主| stm32jy 发表于 2020-2-28 13:07 | 显示全部楼层
若想使用FreeModbus,先对FreeModbus进行初始化,需要调用eMBInit函数和eMBEnable函数,eMBInit函数函数是设置硬件的,有五个参数,分别是01.Modbus的模式:这里可以选择RTUASCIITCP02.设备的地址:这里可以直接写死,也可以通过拨码开关来设置;03.Modbus选择的串口号,这里默认是串口204.波特率,默认写11520005.校验位,默认不效验。然后在主循环中调用eMBPoll函数不断查询。主函数具体如下:
  1. int main(void)
  2. {       
  3.         delay_init();            //延时函数初始化                   
  4. //初始化 RTU模式 从机地址为1 USART2 9600 无效验
  5. eMBInit(MB_RTU, 0x01, 0x02, 9600, MB_PAR_NONE);
  6. //启动FreeModbus
  7. eMBEnable();
  8.         while(1)
  9.         {               
  10.          //FreeMODBUS不断查询
  11.     eMBPoll();
  12.         }
  13. }



 楼主| stm32jy 发表于 2020-2-28 13:08 | 显示全部楼层
添加测试代码部分,实现寄存器的读写操作,这里添加了一组寄存器的数据,和对其读写操作的函数
  1. //Modbus 进程函数
  2. void Modbus_app()
  3. {
  4.   ( void ) eMBPoll( );
  5. }


 楼主| stm32jy 发表于 2020-2-28 13:09 | 显示全部楼层
添加输入寄存器、保持寄存器、线圈的起始地址和定义的内容,具体如下
  1. /* ----------------------- Defines ------------------------------------------*/
  2. //保持寄存器起始地址
  3. #define REG_HOLDING_START 0x0001
  4. //保持寄存器数量
  5. #define REG_HOLDING_NREGS 8
  6. //保持寄存器内容
  7. uint16_t usRegHoldingBuf[REG_HOLDING_NREGS] = {0x147b,0x3f8e,0x147b,0x400e,0x1eb8,0x4055,0x147b,0x408e};

  8. //输入寄存器起始地址
  9. #define REG_INPUT_START 0x0001
  10. //输入寄存器数量
  11. #define REG_INPUT_NREGS 8
  12. //输入寄存器内容
  13. uint16_t usRegInputBuf[REG_INPUT_NREGS] = {0x1111,0x2222,0x3333,0x4444,0x5555,0x6666,0x7777,0x8888};

  14. //线圈寄存器起始地址
  15. #define REG_COILS_START 0x0001
  16. //线圈寄存器数量
  17. #define REG_COILS_SIZE 16
  18. //线圈寄存器内容
  19. uint8_t ucRegCoilsBuf[REG_COILS_SIZE/8] = {0x00,0xFF};


 楼主| stm32jy 发表于 2020-2-28 13:09 | 显示全部楼层
添加输入寄存器、保持寄存器、线圈的处理函数,具体如下:
  1. // 保持寄存器的读写函数 支持的命令为读 0x03 和写0x06 可读可写  
  2. eMBErrorCode
  3. eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,eMBRegisterMode eMode )
  4. {
  5.   //错误状态
  6.   eMBErrorCode eStatus = MB_ENOERR;
  7.   //偏移量
  8.   int16_t iRegIndex;
  9.   
  10.         //判断寄存器是不是在范围内
  11.   if( ( (int16_t)usAddress >= REG_HOLDING_START )&& ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
  12.   {
  13.     //计算偏移量
  14.     iRegIndex = ( int16_t )( usAddress - REG_HOLDING_START);
  15.     switch ( eMode )
  16.    {
  17.      //读处理函数
  18.       case MB_REG_READ:
  19.                                         while( usNRegs > 0 )
  20.                                         {
  21.                                                 *pucRegBuffer++ = ( uint8_t )( usRegHoldingBuf[iRegIndex] >> 8 );
  22.                                                 *pucRegBuffer++ = ( uint8_t )( usRegHoldingBuf[iRegIndex] & 0xFF );
  23.                                                 iRegIndex++;
  24.                                                 usNRegs--;
  25.                                         }
  26.                         break;

  27.     //写处理函数
  28.      case MB_REG_WRITE:
  29.                                         while( usNRegs > 0 )
  30.                                         {
  31.                                                 usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
  32.                                                 usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
  33.                                                 iRegIndex++;
  34.                                                 usNRegs--;
  35.                                         }
  36.                  break;
  37.   }
  38. }
  39. else
  40. {
  41. //返回错误状态
  42. eStatus = MB_ENOREG;
  43. }

  44. return eStatus;
  45. }

  46. //读输入寄存器函数 支持的命令为读 0x04
  47. eMBErrorCode
  48. eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
  49. {
  50.     eMBErrorCode    eStatus = MB_ENOERR;
  51.     int             iRegIndex;

  52.     if( ( usAddress >= REG_INPUT_START )
  53.         && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
  54.     {
  55.         iRegIndex = ( int )( usAddress - REG_INPUT_START );
  56.         while( usNRegs > 0 )
  57.         {
  58.             *pucRegBuffer++ =
  59.                 ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
  60.             *pucRegBuffer++ =
  61.                 ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
  62.             iRegIndex++;
  63.             usNRegs--;
  64.         }
  65.     }
  66.     else
  67.     {
  68.         eStatus = MB_ENOREG;
  69.     }

  70.     return eStatus;
  71. }

  72. //线圈处理函数 可读可写 支持的命令为读 0x01 0x05
  73. eMBErrorCode
  74. eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
  75.                eMBRegisterMode eMode )
  76. {
  77.     //错误状态
  78.     eMBErrorCode eStatus = MB_ENOERR;
  79.     //寄存器个数
  80.     int16_t iNCoils = ( int16_t )usNCoils;
  81.     //寄存器偏移量
  82.     int16_t usBitOffset;

  83.    //判断寄存器是不是在范围内
  84.    if( ( (int16_t)usAddress >= REG_COILS_START ) &&( usAddress + usNCoils <= REG_COILS_START + REG_COILS_SIZE ) )
  85.    {
  86.      //计算寄存器偏移量
  87.      usBitOffset = ( int16_t )( usAddress - REG_COILS_START );
  88.      switch ( eMode )
  89.      {
  90.                                 //读操作
  91.                                 case MB_REG_READ:
  92.                                                 while( iNCoils > 0 )
  93.                                                 {
  94.                                                         *pucRegBuffer++ = xMBUtilGetBits( ucRegCoilsBuf, usBitOffset,
  95.                                                         ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ) );
  96.                                                         iNCoils -= 8;
  97.                                                         usBitOffset += 8;
  98.                                                 }
  99.                           break;

  100.                                 //写操作
  101.                                 case MB_REG_WRITE:
  102.                                                 while( iNCoils > 0 )
  103.                                                 {
  104.                                                         xMBUtilSetBits( ucRegCoilsBuf, usBitOffset,
  105.                                                         ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ),
  106.                                                         *pucRegBuffer++ );
  107.                                                         iNCoils -= 8;
  108.                                                 }
  109.                                 break;
  110.     }
  111.   }
  112.         else
  113.         {
  114.            eStatus = MB_ENOREG;
  115.         }
  116.         return eStatus;
  117.                
  118. return MB_ENOREG;
  119. }


 楼主| stm32jy 发表于 2020-2-28 13:10 | 显示全部楼层
本次成功的在STM32平台上移植了FreeModbus ,可以通过ModbusPoll工具进行测试 859515e58a0ce68f67.png
molo 发表于 2020-9-4 16:52 | 显示全部楼层
不错,能上传个源码工程下载吗?
星空520 发表于 2021-2-23 09:56 | 显示全部楼层
stm32jy 发表于 2020-2-28 13:10
本次成功的在STM32平台上移植了FreeModbus ,可以通过ModbusPoll工具进行测试

你这个测试软件能共享一下吗?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部