Modbus.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #include "includes.h"
  2. unsigned char g_ucModbusRefreshEN = 1;//更新寄存器列表中的数据的使能标志位,1使能,和ModbusRecvProcess配合使用,用于控制收发
  3. unsigned char g_ucModbusRefreshSHUTDOWN = 0;//控制maintask中的更新寄存器列表中的数据的总开关,1关闭,0开启
  4. unsigned short g_ucModbusRefreshTimeOut = 5;//自动读取从机VALUE的等待超时时间,用于收发控制
  5. unsigned short g_ucRegNumCount = 0;//当前正在处理的寄存器地址在列表中的序号。用于控制收发逻辑
  6. SUT_MODBUS_REGPACK sutModbusRegPack = {0};
  7. /**********************************************************************************************************
  8. ModbusRecvProcess()
  9. 处理接收到的MODBUS数据 :slave(u8)|function(u8)|bytecount(u8)|value1H(u8)|value1L(u8)|value2H(u8)|value2L(u8)|......|valueNL(u8)|CRC(u16)
  10. 成功返回1
  11. 失败返回0
  12. num:代表寄存器列表里第几个元素
  13. ************************************************************************************************************/
  14. unsigned char ModbusRecvProcess(unsigned char *pMsg,int len,unsigned short num)
  15. {
  16. unsigned short crc,CRC16;
  17. unsigned char i;
  18. unsigned short value[MODBUS_REG_NUM_MAX];
  19. if(len < 5) return 0;//长度小于5的不是MODBUS数据,就不处理
  20. CRC16=crc16_calc(0xffff,pMsg,len-2);
  21. crc=((unsigned short)pMsg[len-1]&0xff)<<8;
  22. crc+=(unsigned short)pMsg[len-2]&0xff;
  23. if(crc != CRC16) return 0;//CRC校验不对,不处理
  24. if(pMsg[1] == HOLDINGREG){//功能码=0x03,保存进寄存器列表
  25. for(i = 0;i < pMsg[2]/2;i++){
  26. value[i]=((unsigned short)pMsg[i*2+3]&0xff)<<8;
  27. value[i]+=(unsigned short)pMsg[i*2+4]&0xff;
  28. }
  29. sutModbusRegPack.RegList[num].value = value[i-1];
  30. }else if(pMsg[1] == WRITESINGLEREG){//功能码=0x06,说明配置寄存器参数成功
  31. g_ucSetControlAckResult &= 1;
  32. }else{
  33. g_ucSetControlAckResult &= 0;
  34. }
  35. return 1;
  36. }
  37. /**********************************************************************************************************
  38. ModbusCmdReadOneValue()
  39. 发送请求,读MODBUS设备指定一个寄存器地址的参数
  40. num:代表寄存器列表里第几个元素
  41. ************************************************************************************************************/
  42. void ModbusCmdReadOneValue(SUT_MODBUS_REGLIST *pMsg,unsigned short num)
  43. {
  44. unsigned short crc,CRC16;
  45. unsigned char Pack[8],i;
  46. Pack[0] = (pMsg+num)->slave;
  47. Pack[1] = HOLDINGREG;
  48. Pack[2] = (unsigned char)((pMsg+num)->addr >> 8);
  49. Pack[3] = (unsigned char)((pMsg+num)->addr & 0xff);
  50. Pack[4] = 0;
  51. Pack[5] = 1;
  52. CRC16=crc16_calc(0xffff,Pack,6);
  53. Pack[6] = (unsigned char)(CRC16 & 0xff);
  54. Pack[7] = (unsigned char)(CRC16 >> 8);
  55. RS485_DIR_HIGH;
  56. for(i=0;i<8;i++)
  57. {
  58. USART_SendData(USART1,Pack[i]);
  59. while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
  60. }
  61. RS485_DIR_LOW;
  62. }
  63. /**********************************************************************************************************
  64. *更新寄存器列表参数
  65. ************************************************************************************************************/
  66. void ModbusRefreshValue(void)
  67. {
  68. if(g_ucModbusRefreshEN == 1)
  69. {
  70. g_ucModbusRefreshEN = 0;
  71. g_ucModbusRefreshTimeOut = 0;
  72. g_ucRegNumCount++;
  73. if((sutModbusRegPack.RegNum - 1) < g_ucRegNumCount) g_ucRegNumCount = 0;
  74. ModbusCmdReadOneValue(sutModbusRegPack.RegList,g_ucRegNumCount);
  75. }
  76. else
  77. {
  78. if(g_ucModbusRefreshTimeOut > 5)//返回超时,重置g_ucModbusRecv=1
  79. {
  80. g_ucModbusRefreshEN = 1;
  81. g_ucModbusRefreshTimeOut = 0;
  82. }
  83. g_ucModbusRefreshTimeOut++;
  84. }
  85. }
  86. /**********************************************************************************************************
  87. *向MODBUS设备发送配置参数命令
  88. 数据格式 :slave(u8)|function(u8)|AddrH(u8)|AddrL(u8)|valueH(u8)|valueL(u8)|CRC(u16)
  89. ************************************************************************************************************/
  90. void ModbusCmdSetValue(SUT_MODBUS_REGLIST *pMsg)
  91. {
  92. unsigned short crc,CRC16;
  93. unsigned char Pack[8],i;
  94. Pack[0] = pMsg->slave;
  95. Pack[1] = WRITESINGLEREG;
  96. Pack[2] = (unsigned char)(pMsg->addr >> 8);
  97. Pack[3] = (unsigned char)(pMsg->addr & 0xff);
  98. Pack[4] = (unsigned char)(pMsg->value >> 8);
  99. Pack[5] = (unsigned char)(pMsg->value & 0xff);
  100. CRC16=crc16_calc(0xffff,Pack,6);
  101. Pack[6] = (unsigned char)(CRC16 & 0xff);
  102. Pack[7] = (unsigned char)(CRC16 >> 8);
  103. RS485_DIR_HIGH;
  104. for(i=0;i<8;i++)
  105. {
  106. USART_SendData(USART1,Pack[i]);
  107. while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
  108. }
  109. RS485_DIR_LOW;
  110. }