感謝大大不斷解答小弟的疑惑,
想再請教關於 CRC 校驗的部分,
從數位電表的說明文件上看來,是必須要有CRC 校驗的,
依我目前修改的範例似乎是沒有CRC 這部分,
那這樣應該會無法完成通訊吧?!
我有找到一個庫,範例本身就帶了CRC 校驗的部分,
https://github.com/GDV0/ArduiModbus
- #include <Modbus_RTU.h>
- // Defines 1 Client and 1 Server devices
- Modbus_RTU myServer = Modbus_RTU(0);
- Modbus_RTU myClient = Modbus_RTU(0);
- // Defines a message and data buffers
- Modbus_Frame myFrame;
- Modbus_Data myData;
- unsigned short CRC16;
- t_baud Baudrate;
- unsigned long MsgTimeout;
- int i;
- void setup()
- {
- // Force type for each device
- myServer.SetType(MDB_SERVER);
- myClient.SetType(MDB_CLIENT);
-
- // Preset Server address
- myServer.Server_SetAddress(5);
- // Initialize serial line
- myClient.GetBaudrate(&Baudrate);
- Serial.begin(Baudrate);
-
- // Get the inter-frame time (equivalent to 3,5 char)
- myClient.GetFrameTimeout(&MsgTimeout);
-
- Serial.println("");
- Serial.println("Test Modbus_RTU library");
- Serial.println("=======================");
-
- // Modbus test type
- Serial.println("");
- Serial.println(" Test Function code 03: Read Holding Registers");
- Serial.println(" ---------------------------------------------");
- }
- void loop()
- {
- Serial.println("");
- Serial.println(" --> Read 5 registers from address 10");
- Serial.println(" Result should be 0x1111, 0x2222, 0x3333, 0x4444, 0x5555");
- // Build Client request
- Serial.println("");
- Serial.println(" Request sent by the Client");
- myClient.Client_ReadHoldingRegisters(5, 10, 5, &myFrame);
- DisplayFrame(&myFrame);
-
- // Build Server response
- if (myServer.Server_Update(&myFrame))
- {
- Serial.println(" --> OK Response available");
- Serial.println("");
- Serial.println(" Packet sent by the Server");
- DisplayFrame(&myFrame);
-
- // extract Data received by the Client
- myClient.Client_Update(&myFrame, &myData);
- Serial.println("");
- Serial.println(" Data");
- DisplayData(&myData);
- }
- else
- Serial.println(" --> No response available");
-
- while(1)
- {
- }
- }
- // Function to display a complete frame (Debug mode)
- void DisplayFrame(Modbus_Frame* msg)
- {
- int i;
-
- Serial.print(" Frame size ");
- Serial.print(msg->length, DEC);
- Serial.print(" -> ");
- if (msg->length > 0)
- {
- for (i = 0; i < msg->length; i++)
- {
- Serial.print((unsigned char)(msg->data[i])>>4, HEX);
- Serial.print((unsigned char)(msg->data[i])&0x0F, HEX);
- Serial.print(" ");
- }
- Serial.println();
- }
- }
- // Function to display Data received
- void DisplayData(Modbus_Data* Data)
- {
- int i;
-
- Serial.print(" ==> Number of data received = ");
- Serial.println(Data->length, DEC);
- if (Data->length > 0)
- {
- Serial.print(" Data type = ");
- switch (Data->type)
- {
- case MDB_BIT:
- Serial.println("BIT");
- Serial.print(" Data = ");
- for (i = 0; i < Data->length; i++)
- {
- Serial.print(Data->data[i] & 1, DEC);
- Serial.print((Data->data[i] & 2)>>1, DEC);
- Serial.print((Data->data[i] & 4)>>2, DEC);
- Serial.print((Data->data[i] & 8)>>3, DEC);
- Serial.print((Data->data[i] & 18)>>4, DEC);
- Serial.print((Data->data[i] & 32)>>5, DEC);
- Serial.print((Data->data[i] & 64)>>6, DEC);
- Serial.print((Data->data[i] & 128)>>7, DEC);
- }
- break;
- case MDB_BYTE:
- Serial.println("BYTE");
- Serial.print(" Data = ");
- for (i = 0; i < Data->length; i++)
- {
- Serial.print("0x");
- Serial.print((unsigned char)(Data->data[i])>>4, HEX);
- Serial.print((unsigned char)(Data->data[i])&0x0F, HEX);
- Serial.print(" ");
- }
- break;
- case MDB_WORD:
- Serial.println("WORD");
- Serial.print(" Data = ");
- for (i = 0; i < Data->length; i++)
- {
- Serial.print("0x");
- Serial.print((unsigned char)(Data->data[i*2])>>4, HEX);
- Serial.print((unsigned char)(Data->data[i*2])&0x0F, HEX);
- Serial.print((unsigned char)(Data->data[i*2+1])>>4, HEX);
- Serial.print((unsigned char)(Data->data[i*2+1])&0x0F, HEX);
- Serial.print(" ");
- }
- break;
- default:
- Serial.println("Unknown");
- break;
- }
- Serial.println();
- }
- }
- void DisplayDataOnly(Modbus_Data* Data)
- {
- int i;
- if (Data->length > 0)
- {
- for (i = 0; i < Data->length; i++)
- {
- if (Data->type == MDB_BIT)
- {
- Serial.print(Data->data[i] & 1, DEC);
- Serial.print((Data->data[i] & 2)>>1, DEC);
- Serial.print((Data->data[i] & 4)>>2, DEC);
- Serial.print((Data->data[i] & 8)>>3, DEC);
- Serial.print((Data->data[i] & 18)>>4, DEC);
- Serial.print((Data->data[i] & 32)>>5, DEC);
- Serial.print((Data->data[i] & 64)>>6, DEC);
- Serial.print((Data->data[i] & 128)>>7, DEC);
- }
- if (Data->type == MDB_BYTE)
- {
- Serial.print("0x");
- Serial.print((unsigned char)(Data->data[i])>>4, HEX);
- Serial.print((unsigned char)(Data->data[i])&0x0F, HEX);
- Serial.print(" ");
- }
- if (Data->type == MDB_WORD)
- {
- Serial.print("0x");
- Serial.print((unsigned char)(Data->data[i*2])>>4, HEX);
- Serial.print((unsigned char)(Data->data[i*2])&0x0F, HEX);
- Serial.print((unsigned char)(Data->data[i*2+1])>>4, HEX);
- Serial.print((unsigned char)(Data->data[i*2+1])&0x0F, HEX);
- Serial.print(" ");
- }
- }
- Serial.println();
- }
- }
- /******************************************************************************
- * Callback functions
- * Allow the user to define all device objects
- ******************************************************************************/
- /******************************************************************************
- * t_status Modbus_CB_GetRegister (unsigned short Addr, int* Value)
- * Callback function to read register value
- * Parameters:
- * - Addr: Address of the register from 0x0000 to 0xFFFF
- * - Value: pointer to a variable which will contain the register value
- * Return value:
- * - OK if register address exists
- * - NOK if register address doesn't exist
- ******************************************************************************/
- t_status Modbus_CB_GetRegister(unsigned short Addr, int* Value)
- {
- t_status Status = OK;
-
- // Value = f(Addr) To be defined by application
- switch(Addr)
- {
- case 10:
- *Value = 0x1111;
- break;
- case 11:
- *Value = 0x2222;
- break;
- case 12:
- *Value = 0x3333;
- break;
- case 13:
- *Value = 0x4444;
- break;
- case 14:
- *Value = 0x5555;
- break;
- default:
- Status = NOK;
- }
- return (Status);
- }
复制代码
這個範例看起來像是一個模擬通訊的功能,
因為我就算沒接上 RS485模組,他也能運行,
自己當自己是Master 同時也是 Slave,是這樣嗎?!
這個就自帶了CRC 校驗~
研究了一會,還是搞不太懂該如何將他實際運用...
從// Build Server response 之後的就看不懂了~
|