当前位置:   article > 正文

crc校验modbus,实现linux,c++的modbus通信,并控制电机

crc校验modbus,实现linux,c++的modbus通信,并控制电机
  1. #include <cstdint>
  2. #include <thread>
  3. #include <unistd.h>
  4. #include <arpa/inet.h>
  5. #include <sys/socket.h>
  6. #include <pthread.h>
  7. #include <iostream>
  8. #include <cstring>
  9. #include <netinet/in.h>
  10. #include <limits>
  11. #include <linux/can.h>
  12. #include <net/if.h>
  13. #include <linux/sockios.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <fstream>
  18. #include <sstream>
  19. #include <linux/can/raw.h>
  20. #include <sys/ioctl.h>
  21. #include <sys/types.h>
  22. #include <fcntl.h>
  23. // CRC校验函数(这里使用简单的CRC16校验)
  24. uint16_t crc16(const uint8_t* data, size_t length) {
  25. static const uint16_t polynomial = 0xA001;
  26. uint16_t crc = 0xFFFF;
  27. for (size_t pos = 0; pos < length; ++pos) {
  28. crc ^= (uint16_t)data[pos];
  29. for (uint8_t i = 8; i != 0; --i) {
  30. if (crc & 0x0001) {
  31. crc = (crc >> 1) ^ polynomial;
  32. }
  33. else {
  34. crc >>= 1;
  35. }
  36. }
  37. }
  38. std::printf("%02X ", crc);
  39. return crc;
  40. }
  41. void sendCanFrame(int canSock, int ifaceNum, uint32_t canID, uint8_t* data, size_t size)
  42. {
  43. struct can_frame frame;
  44. frame.can_id = canID;
  45. frame.can_dlc = size;
  46. memcpy(frame.data, data, size);
  47. struct sockaddr_can addr;
  48. memset(&addr, 0, sizeof(addr));
  49. addr.can_family = AF_CAN;
  50. addr.can_ifindex = ifaceNum;
  51. ssize_t nbytes = write(canSock, &frame, sizeof(frame));
  52. if (nbytes < 0) {
  53. perror("Failed to write CAN frame");
  54. }
  55. }
  56. // 假设的setmotor函数定义
  57. bool setmotor(uint32_t id, uint32_t speed) {
  58. int canSock0 = socket(PF_CAN, SOCK_RAW, CAN_RAW);
  59. if (canSock0 < 0) {
  60. perror("Failed to open CAN socket");
  61. return 1;
  62. }
  63. struct ifreq ifr0;
  64. strcpy(ifr0.ifr_name, "can0");
  65. if (ioctl(canSock0, SIOCGIFINDEX, &ifr0) < 0) {
  66. perror("Failed to get7 CAN interface index");
  67. return 1;
  68. }
  69. // 将CAN0接口绑定到套接字
  70. struct sockaddr_can addr0;
  71. memset(&addr0, 0, sizeof(addr0));
  72. addr0.can_family = AF_CAN;
  73. addr0.can_ifindex = ifr0.ifr_ifindex;
  74. if (bind(canSock0, (struct sockaddr*)&addr0, sizeof(addr0)) < 0) {
  75. perror("Failed to bind CAN socket");
  76. return 1;
  77. }
  78. uint8_t data1[2] = { 0x1,static_cast<uint8_t>(id) };
  79. sendCanFrame(canSock0, ifr0.ifr_ifindex, 0x0, data1, sizeof(data1));
  80. uint8_t data2[8] = { 0x2F, 0x60, 0x60, 0x00, 0x03, 0x00, 0x00, 0x00 };
  81. sendCanFrame(canSock0, ifr0.ifr_ifindex, (0x600 + id), data2, sizeof(data2));
  82. uint8_t data3[8] = { 0x23, 0xFF, 0x60, 0X00, static_cast<uint8_t>(speed & 0xff), static_cast<uint8_t>((speed >> 8) & 0xff), 0x00, 0x00 };
  83. sendCanFrame(canSock0, ifr0.ifr_ifindex, (0x600 + id), data3, sizeof(data3));
  84. uint8_t data4[8] = { 0x23, 0x83, 0x60, 0X00, 0x88, 0x13, 0x00, 0x00 };
  85. sendCanFrame(canSock0, ifr0.ifr_ifindex, (0x600 + id), data4, sizeof(data4));
  86. uint8_t data5[8] = { 0x23, 0x84, 0x60, 0X00, 0x88, 0x13, 0x00, 0x00 };
  87. sendCanFrame(canSock0, ifr0.ifr_ifindex, (0x600 + id), data5, sizeof(data5));
  88. uint8_t data6[8] = { 0x2B, 0x40, 0x60, 0X00, 0x06, 0x00, 0x00, 0x00 };
  89. sendCanFrame(canSock0, ifr0.ifr_ifindex, (0x600 + id), data6, sizeof(data6));
  90. uint8_t data7[8] = { 0x2B, 0x40, 0x60, 0X00, 0x07, 0x00, 0x00, 0x00 };
  91. sendCanFrame(canSock0, ifr0.ifr_ifindex, (0x600 + id), data7, sizeof(data7));
  92. uint8_t data8[8] = { 0x2B, 0x40, 0x60, 0X00, 0x0F, 0x00, 0x00, 0x00 };
  93. sendCanFrame(canSock0, ifr0.ifr_ifindex, (0x600 + id), data8, sizeof(data8));
  94. sleep(1);
  95. if (speed <= 200 && speed > 24000) {
  96. uint8_t data7[8] = { 0x2B, 0x40, 0x60, 0X00, 0x07, 0x00, 0x00, 0x00 };
  97. sendCanFrame(canSock0, ifr0.ifr_ifindex, (0x600 + id), data7, sizeof(data7));
  98. }
  99. else if (id == 1)
  100. {
  101. if (speed <= 200 && speed > 1500)
  102. {
  103. uint8_t data7[8] = { 0x2B, 0x40, 0x60, 0X00, 0x07, 0x00, 0x00, 0x00 };
  104. sendCanFrame(canSock0, ifr0.ifr_ifindex, (0x600 + id), data7, sizeof(data7));
  105. }
  106. }
  107. return true;
  108. }
  109. const char* SERVER_IP = "192.168.1.104";
  110. const int SERVER_PORT = 8009;
  111. const int BUFFER_SIZE = 1024;
  112. // 客户端连接结构
  113. struct ClientConnection {
  114. int socket_fd;
  115. struct sockaddr_in client_addr;
  116. socklen_t client_addr_size;
  117. };
  118. // 接收数据的线程函数
  119. void* receive_thread(void* arg) {
  120. ClientConnection* conn = static_cast<ClientConnection*>(arg);
  121. uint8_t buffer[BUFFER_SIZE];
  122. ssize_t bytes_read;
  123. while (true) {
  124. bytes_read = recv(conn->socket_fd, buffer, BUFFER_SIZE, 0);
  125. if (bytes_read <= 0) {
  126. std::cerr << "Client disconnected" << std::endl;
  127. break;
  128. }
  129. // 确保接收到足够的数据
  130. if (bytes_read < 8) {
  131. std::cerr << "Invalid data length received from client" << std::endl;
  132. continue;
  133. }
  134. uint16_t received_crc = (buffer[7] << 8) | buffer[6];
  135. uint16_t calculated_crc = crc16(buffer, 6);
  136. std::printf("%02X\n ", received_crc);
  137. std::printf("%02X \n", calculated_crc);
  138. if (calculated_crc == received_crc)
  139. {
  140. // 提取最后两个字节并转换为10进制
  141. uint16_t speed = buffer[5] | (buffer[4] << 8);
  142. // 检查第二个字节的值
  143. if (buffer[1] == 0x06 && buffer[3] == 0xF3 && buffer[2] == 03) {
  144. if (setmotor(4, speed)) { // 假设电机ID为0,根据实际需要修改
  145. std::string response = "id :4 MOTOR_SET_SUCCESS Speed: " + std::to_string(speed);
  146. send(conn->socket_fd, response.c_str(), response.length() + 1, 0);
  147. }
  148. else {
  149. send(conn->socket_fd, "MOTOR_SET_FAILURE", 17, 0);
  150. }
  151. }
  152. else {
  153. // 只返回speed值
  154. std::string response = "motor :4 Speed: " + std::to_string(speed);
  155. send(conn->socket_fd, response.c_str(), response.length() + 1, 0);
  156. }
  157. }
  158. }
  159. close(conn->socket_fd);
  160. delete conn;
  161. return nullptr;
  162. }
  163. // 接受客户端连接的线程函数
  164. void* accept_thread(void* arg) {
  165. int server_fd = *(static_cast<int*>(arg));
  166. struct sockaddr_in client_addr;
  167. socklen_t client_addr_size = sizeof(client_addr);
  168. while (true) {
  169. int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_addr_size);
  170. if (client_fd == -1) {
  171. std::cerr << "Error accepting connection" << std::endl;
  172. continue;
  173. }
  174. std::cout << "Client connected" << std::endl;
  175. // 创建ClientConnection对象并传递给接收线程
  176. ClientConnection* conn = new ClientConnection{ client_fd, client_addr, client_addr_size };
  177. pthread_t receive_thread_id;
  178. if (pthread_create(&receive_thread_id, nullptr, receive_thread, conn)) {
  179. std::cerr << "Error creating receive thread" << std::endl;
  180. close(client_fd);
  181. delete conn;
  182. }
  183. else {
  184. // 分离线程,以便在结束时自动回收资源
  185. pthread_detach(receive_thread_id);
  186. }
  187. }
  188. return nullptr;
  189. }
  190. int main() {
  191. int server_fd;
  192. struct sockaddr_in server_addr;
  193. // 创建套接字
  194. server_fd = socket(AF_INET, SOCK_STREAM, 0);
  195. if (server_fd == -1) {
  196. std::cerr << "Error creating socket" << std::endl;
  197. return 1;
  198. }
  199. // 设置服务器地址
  200. memset(&server_addr, 0, sizeof(server_addr));
  201. server_addr.sin_family = AF_INET;
  202. server_addr.sin_port = htons(SERVER_PORT);
  203. server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
  204. // 绑定套接字到地址
  205. if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
  206. std::cerr << "Error binding socket" << std::endl;
  207. close(server_fd);
  208. return 1;
  209. }
  210. // 监听连接
  211. if (listen(server_fd, 5) == -1) {
  212. std::cerr << "Error listening on socket" << std::endl;
  213. close(server_fd);
  214. return 1;
  215. }
  216. std::cout << "Server listening on " << SERVER_IP << ":" << SERVER_PORT << std::endl;
  217. // 创建接受连接的线程
  218. pthread_t accept_thread_id;
  219. if (pthread_create(&accept_thread_id, nullptr, accept_thread, &server_fd)) {
  220. std::cerr << "Error creating accept thread" << std::endl;
  221. close(server_fd);
  222. return 1;
  223. }
  224. // 分离线程,以便在结束时自动回收资源
  225. pthread_detach(accept_thread_id);
  226. // 主线程可以继续执行其他任务,或者等待直到服务器被强制关闭
  227. // 这里我们简单地让主线程休眠,防止它立即退出
  228. while (true) {
  229. sleep(1);
  230. }
  231. return 0;
  232. }

协议已经验证过正确。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/294157
推荐阅读
相关标签
  

闽ICP备14008679号