Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 

391 řádky
9.2 KiB

  1. #include "stm32f4xx.h"
  2. #include "hardware.h"
  3. #include "ucos_ii.h"
  4. #include "os.h"
  5. #include "app_cfg.h"
  6. #include "sys_cfg.h"
  7. #include "string.h"
  8. #include "modbus.h"
  9. extern OS_EVENT* ModbusReceived; /*接收到modbus请求报文*/
  10. /*0x270F+1=K10000*/
  11. uint8_t ModbusCoil[1250]; /*10000/8=1250*/
  12. uint16_t ModbusReg[10000];
  13. void AddCrc16(uint8_t *data, uint16_t length);
  14. int8_t ChcekCrc16(uint16_t recCrc16, uint8_t *data, uint16_t length);
  15. uint8_t ModbusReadCoil(uint16_t addres, uint16_t num);
  16. uint8_t ModbusWriteCoil(uint16_t addres, uint16_t num, uint8_t *data);
  17. uint8_t ModbusReadReg(uint16_t addres, uint16_t num);
  18. uint8_t ModbusWriteReg(uint16_t addres, uint16_t num, uint8_t *data);
  19. /*USART接收空闲中断*/
  20. void USART1_IRQHandler(void)
  21. {
  22. OSIntEnter(); /*进入中断*/
  23. uint32_t temp;
  24. uint16_t rxLenRemain;
  25. if(USART_GetITStatus(USART1, USART_IT_IDLE) == SET)
  26. {
  27. /*在计算数据长度之前先关闭DMA接收通道,防止计算过程中DMA继续转运数据*/
  28. DMA_Cmd(DMA2_Stream2, DISABLE);
  29. /*清除IDLE中断标志位*/
  30. temp = USART1->SR;
  31. temp = USART1->DR;
  32. (void)temp;
  33. /*清除传输已经完成TCIF2、传输已经完成一半HTIF2标志位*/
  34. DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_TCIF2 | DMA_FLAG_HTIF2);
  35. /*计算数据长度*/
  36. rxLenRemain = DMA_GetCurrDataCounter(DMA2_Stream2);
  37. ModbusRxLen = MODBUS_RX_BUF_SIZE - rxLenRemain;
  38. if(ModbusRxLen != 0)
  39. {
  40. OSSemPost(ModbusReceived);
  41. }
  42. /*重新指定接收地址*/
  43. DMA_MemoryTargetConfig(DMA2_Stream2, (uint32_t)ModbusRxBuf, DMA_Memory_0);
  44. /*重启DMA*/
  45. DMA_SetCurrDataCounter(DMA2_Stream2, MODBUS_RX_BUF_SIZE);
  46. DMA_Cmd(DMA2_Stream2, ENABLE);
  47. }
  48. OSIntExit(); /*退出中断*/
  49. }
  50. /*modbus响应帧发送*/
  51. void ModbusSend(uint8_t *txBuf, uint16_t len)
  52. {
  53. /*先关闭DMA发送通道*/
  54. DMA_Cmd(DMA2_Stream7, DISABLE);
  55. /*等待DMA关闭*/
  56. while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE);
  57. /*清除传输已经完成TCIF7、传输已经完成一半HTIF7、FIFO错误FEIF7标志位*/
  58. DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_FEIF7 | DMA_FLAG_HTIF7 | DMA_FLAG_TCIF7);
  59. /*配置发送地址和长度*/
  60. DMA_MemoryTargetConfig(DMA2_Stream7, (uint32_t)txBuf, DMA_Memory_0);
  61. DMA_SetCurrDataCounter(DMA2_Stream7, len);
  62. /*启动 DMA 发送*/
  63. DMA_Cmd(DMA2_Stream7, ENABLE);
  64. }
  65. /*modbus协议帧解析任务*/
  66. void AppTaskModbusParse (void *p_arg)
  67. {
  68. INT8U err;
  69. MODBUS_FRAME frame;
  70. uint16_t rxLen;
  71. uint8_t rxBuf[256];
  72. while(1)
  73. {
  74. OSSemPend(ModbusReceived, 0, &err);
  75. rxLen = ModbusRxLen;
  76. memcpy(rxBuf, ModbusRxBuf, rxLen);
  77. frame.crc = ((uint16_t)(rxBuf[rxLen - 1])) | ((uint16_t)rxBuf[rxLen - 2] << 8);
  78. if(ChcekCrc16(frame.crc, rxBuf, rxLen) != 0)
  79. {
  80. /****************************crc错误处理******************************/
  81. }
  82. frame.slaveAddres = rxBuf[0];
  83. if(frame.slaveAddres != SLAVE_ADDRES)
  84. {
  85. /*****************************从机地址错误处理************************/
  86. }
  87. frame.func = rxBuf[1];
  88. frame.opeAddres = ((uint16_t)rxBuf[2] << 8) | ((uint16_t)rxBuf[3]);
  89. frame.opeNum = ((uint16_t)rxBuf[4] << 8) | ((uint16_t)rxBuf[5]);
  90. switch(frame.func)
  91. {
  92. case 0x01:/*读线圈*/
  93. ModbusReadCoil(frame.opeAddres, frame.opeNum);
  94. break;
  95. case 0x03:/*读寄存器*/
  96. ModbusReadReg(frame.opeAddres, frame.opeNum);
  97. break;
  98. case 0x0F:/*写多个线圈*/
  99. frame.wNum = rxBuf[6];
  100. memcpy(frame.wData, &rxBuf[7], frame.wNum);
  101. ModbusWriteCoil(frame.opeAddres, frame.opeNum, frame.wData);
  102. break;
  103. case 0x10:/*写多个寄存器*/
  104. frame.wNum = rxBuf[6];
  105. memcpy(frame.wData, &rxBuf[7], frame.wNum);
  106. ModbusWriteReg(frame.opeAddres, frame.opeNum, frame.wData);
  107. break;
  108. default:/*功能码错误*/
  109. break;
  110. }
  111. ModbusSend(ModbusTxBuf, ModbusTxLen);
  112. }
  113. }
  114. uint8_t ModbusReadCoil(uint16_t addres, uint16_t num)
  115. {
  116. uint16_t byteIndI;
  117. uint8_t bitIndI;
  118. uint16_t byteIndO;
  119. uint8_t bitIndO;
  120. uint8_t dataLen;
  121. uint8_t index;
  122. uint8_t readVal;
  123. uint8_t writeVal;
  124. if(addres > 0x270F || (addres + num) > 0x270F)
  125. {
  126. /********************地址超限处理*****************/
  127. }
  128. dataLen = (num + 7) / 8;
  129. memset(&ModbusTxBuf[3], 0, 253);/*清零发送数组*/
  130. for(uint16_t i = 0; i < num; i++)
  131. {
  132. byteIndO = i / 8;
  133. bitIndO = i % 8;
  134. byteIndI = (addres + i) / 8;
  135. bitIndI = (addres + i) % 8;
  136. readVal = ModbusCoil[byteIndI] & ((uint8_t)1 << bitIndI);
  137. if(readVal != 0)
  138. {
  139. index = 3 + byteIndO;
  140. writeVal = (uint8_t)1u << bitIndO;
  141. ModbusTxBuf[index] |= writeVal;
  142. }
  143. }
  144. ModbusTxBuf[0] = SLAVE_ADDRES;
  145. ModbusTxBuf[1] = 0x01;
  146. ModbusTxBuf[2] = dataLen;/*响应帧返回数据字节数*/
  147. AddCrc16(ModbusTxBuf, 3 + dataLen);
  148. ModbusTxLen = 5 + dataLen;
  149. }
  150. uint8_t ModbusWriteCoil(uint16_t addres, uint16_t num, uint8_t *data)
  151. {
  152. uint16_t byteIndI;
  153. uint8_t bitIndI;
  154. uint16_t byteIndO;
  155. uint8_t bitIndO;
  156. uint8_t readVal;
  157. uint8_t writeVal;
  158. if(addres > 0x270F || (addres + num) > 0x270F)
  159. {
  160. /********************地址超限处理*****************/
  161. }
  162. for(uint16_t i = 0; i < num; i++)
  163. {
  164. byteIndI = (addres + i) / 8;
  165. bitIndI = (addres + i) % 8;
  166. byteIndO = i / 8;
  167. bitIndO = i % 8;
  168. readVal = data[byteIndO] | ((uint8_t)1 << bitIndO);
  169. writeVal = (uint8_t)1 << bitIndI;
  170. if(readVal != 0)
  171. {
  172. ModbusCoil[byteIndI] |= writeVal;
  173. }
  174. else
  175. {
  176. ModbusCoil[byteIndI] &= (~writeVal);
  177. }
  178. ModbusTxBuf[0] = SLAVE_ADDRES;
  179. ModbusTxBuf[1] = 0x0F;
  180. /*操作地址*/
  181. ModbusTxBuf[2] = (uint8_t)(addres >> 8);
  182. ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
  183. /*成功写入的数量*/
  184. ModbusTxBuf[4] = (uint8_t)(num >> 8);
  185. ModbusTxBuf[5] = (uint8_t)(num & 0x00FF);
  186. AddCrc16(ModbusTxBuf, 6);
  187. ModbusTxLen = 8;
  188. }
  189. }
  190. uint8_t ModbusReadReg(uint16_t addres, uint16_t num)
  191. {
  192. uint8_t index;
  193. uint8_t readValH;
  194. uint8_t readValL;
  195. uint8_t dataLen;
  196. if(addres > 0x270F || (addres + num) > 0x270F)
  197. {
  198. /********************地址错误处理*****************/
  199. }
  200. dataLen = num * 2;
  201. for(uint16_t i = 0; i < num; i++)
  202. {
  203. index = 3 + (i * 2);
  204. readValH = (uint8_t)(ModbusReg[addres + i] >> 8);
  205. readValL = (uint8_t)(ModbusReg[addres + i] & 0x00FF);
  206. ModbusTxBuf[index] = readValH;
  207. ModbusTxBuf[index + 1] = readValL;
  208. }
  209. ModbusTxBuf[0] = SLAVE_ADDRES;
  210. ModbusTxBuf[1] = 0x03;
  211. ModbusTxBuf[2] = dataLen;
  212. AddCrc16(ModbusTxBuf, 3 + dataLen);
  213. ModbusTxLen = 5 + dataLen;
  214. }
  215. uint8_t ModbusWriteReg(uint16_t addres, uint16_t num, uint8_t *data)
  216. {
  217. uint8_t index;
  218. uint8_t writeValH;
  219. uint8_t writeValL;
  220. uint16_t writeVal;
  221. if(addres > 0x270F || (addres + num) > 0x270F)
  222. {
  223. /********************地址错误处理*****************/
  224. }
  225. for(uint16_t i = 0; i < num; i++)
  226. {
  227. index = i * 2;
  228. writeValH = data[index];
  229. writeValL = data[index + 1];
  230. writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
  231. ModbusReg[addres + i] = writeVal;
  232. }
  233. ModbusTxBuf[0] = SLAVE_ADDRES;
  234. ModbusTxBuf[1] = 0x10;
  235. /*操作地址*/
  236. ModbusTxBuf[2] = (uint8_t)(addres >> 8);
  237. ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
  238. /*成功写入数量*/
  239. ModbusTxBuf[4] = (uint8_t)(num >> 8);
  240. ModbusTxBuf[5] = (uint8_t)(num & 0x00FF);
  241. AddCrc16(ModbusTxBuf, 6);
  242. ModbusTxLen = 8;
  243. }
  244. uint16_t Crc16(const uint8_t *data, uint16_t length);
  245. void AddCrc16(uint8_t *data, uint16_t length)
  246. {
  247. uint16_t crc16 = Crc16(data, length);
  248. /*低前高后*/
  249. data[length] = (uint8_t)(crc16 & 0x00FF);
  250. data[length + 1] = (uint8_t)(crc16 >> 8);
  251. }
  252. /*crc16校验*/
  253. uint16_t Crc16(const uint8_t *data, uint16_t length)
  254. {
  255. uint16_t crc;
  256. uint16_t byteInd;
  257. uint8_t bitInd;
  258. crc = 0xFFFFu;
  259. for (byteInd = 0u; byteInd < length; byteInd++)
  260. {
  261. crc ^= (uint16_t)data[byteInd];
  262. for (bitInd = 0u; bitInd < 8u; bitInd++)
  263. {
  264. if ((crc & 0x0001u) != 0u)
  265. {
  266. crc >>= 1;
  267. crc ^= 0xA001u;
  268. }
  269. else
  270. {
  271. crc >>= 1;
  272. }
  273. }
  274. }
  275. return crc;
  276. }
  277. /*crc16检查*/
  278. int8_t ChcekCrc16(uint16_t recCrc16, uint8_t *data, uint16_t length)
  279. {
  280. uint16_t crc16 = Crc16(data, (length - 2));
  281. if(recCrc16 == crc16)
  282. {
  283. return 0;
  284. }
  285. else
  286. {
  287. return -1;
  288. }
  289. }