線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1913
推到 Plurk!
推到 Facebook!

關於ModBus的問題

缺席
臥雲初行雁
一般會員


發表:2
回覆:8
積分:2
註冊:2002-06-17

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-04-15 12:31:39 IP:61.218.xxx.xxx 未訂閱
各位前輩好,小弟試著用Modbus protocol由pc 控制PLC,但怎麼試都不對,望請各位前輩能指點。下面附我的source code,謝謝。 OS:windows XP sp2 Compiler: VC++ interface: RS-232     
 
#include "stdafx.h"
#include 
#include 
#include 
#include     using namespace std;    //User define functions
unsigned short CRC16(char *puchMsg,unsigned short usDataLen);    //User define structures    int _tmain(int argc, _TCHAR* argv[])
{            HANDLE hComm;
        DCB dcb = {0};
        unsigned long lrc,BS;
        unsigned short Command_string[10] = {0x01, 0x01, 0x00, 0x13, 0x00, 0x25};            hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, NULL, 0);
    if (hComm == INVALID_HANDLE_VALUE)
    {   // error opening port; abort
        MessageBox(0, "開啟通訊埠錯誤", "Comm Error", MB_OK);
        return 0;
    }            
    GetCommState(hComm, &dcb);
        dcb.BaudRate = CBR_9600;
        dcb.Parity   = NOPARITY;
        dcb.ByteSize = 8;
        dcb.StopBits = ONESTOPBIT;        if(!SetCommState(hComm, &dcb))
    {
        MessageBox(0, "通訊埠設定錯誤", "Set Error", MB_OK);
        CloseHandle(hComm);
        return 0;
    }        
    
    
        if(hComm == 0)
                return 0;
        
        unsigned short len;
        
        for(len = 0;len < 1024;len  )
        {
                if(Command_string[len] != '!')
                        continue;
                else
                        break;
        
        }                    
        unsigned short CRC_Check = CRC16((char *)Command_string, len); //get 2bytes CRC code            cout << hex << CRC_Check << endl;
        cout << "The CRC_Check size is:" << sizeof(CRC_Check) << endl;
        Command_string[len] = 0xFF & CRC_Check;
        Command_string[len 1] = (CRC_Check >> 2) & 0xFF;
        Command_string[len 2] = '\0';            cout << hex << Command_string << endl;
        
        for(BS = 0;BS < 1024;BS  )
        {
                if(Command_string[BS] != '!')
                        continue;
                else
                        break;        
        }            WriteFile(hComm, Command_string, BS, &lrc, NULL);            //-------------讀取回應的值----------------------------------------------------------------------
        char inbuff[10];
        DWORD nBytesRead, dwEvent, dwError;
        COMSTAT cs;            //--------------取得狀態-------------------------
        GetCommState(hComm, &dcb); 
        ClearCommError(hComm, &dwError, &cs);            //check data is big than our buffer
        if(cs.cbInQue > sizeof(inbuff))
        {
                PurgeComm(hComm, PURGE_RXCLEAR);
                return 0;
        }
        ReadFile(hComm, inbuff, cs.cbInQue, &nBytesRead, NULL); //recive data from com port
        inbuff[cs.cbInQue] = '\0';
        
        cout << inbuff << endl;
                    system("PAUSE");
        CloseHandle(hComm);
        return 0;
}        //CRC16 Generation Function
unsigned short CRC16(char *puchMsg,unsigned short usDataLen)
{
         /* unsigned char *puchMsg : message to calculate CRC upon */
         /* unsigned short usDataLen : quantity of bytes in message */            unsigned char uchCRCHi = 0xFF ; /* high byte of CRC initialized */
        unsigned char uchCRCLo = 0xFF ; /* low byte of CRC initialized */
        unsigned uIndex ; /* will index into CRC lookup table */
        while (usDataLen--) /* pass through message buffer */
        {
                uIndex = uchCRCHi ^ *puchMsg   ; /* calculate the CRC */
                uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
                uchCRCLo = auchCRCLo[uIndex] ;
        }
        return (uchCRCHi << 8 | uchCRCLo) ;
}
身在風雲心無塵 古今聖賢誰為鄰 一笑橫江挂書劍 九重天外臥龍深
------
身在風雲心無塵
古今聖賢誰為鄰
一笑橫江挂書劍
九重天外臥龍深
liangnet
中階會員


發表:19
回覆:148
積分:83
註冊:2004-01-03

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-04-16 09:56:39 IP:211.20.xxx.xxx 未訂閱
你說的不對是怎樣情形??? 無回應??還是PLC回應錯誤訊息??    你的程式碼中的Command_string有問題…
        unsigned short Command_string[10] = {0x01, 0x01, 0x00, 0x13, 0x00, 0x25};            for(len = 0;len < 1024;len  )
        {
                if(Command_string[len] != '!')
                        continue;
                else
                        break;
        
        }    Command_string 陣列只有10個元素…但你這個for-loop卻用到1024,這樣超出範圍會有問題吧?                
發表人 - liangnet 於 2005/04/16 10:00:35
臥雲初行雁
一般會員


發表:2
回覆:8
積分:2
註冊:2002-06-17

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-04-18 13:38:43 IP:61.218.xxx.xxx 未訂閱
關於上次問的這個問題呢,小弟已經找到問題並解決了,程式本身並沒問題,buffer開到1024也沒有問題,因為有for loop去計算我所要的長度,問題是在於error check的部份,本來是看www.Modbus.org上面的reference guide(PI–MBUS–300 Rev. J)第113頁的格式並照著去做的,但怎麼傳data都不會回傳訊息。最後經人提示是CRC的Hi byte and Lo byte對調過來就可以了。 本來手冊上的格式 Addr|Func|Data Count|Data|Data|Data|CRC Lo|CRC Hi 改成 Addr|Func|Data Count|Data|Data|Data|CRC Hi|CRC Lo p.s使用的PLC是永宏FBs-40MA 另外我會測試其它的PLC看是否有類似的問題出現 身在風雲心無塵 古今聖賢誰為鄰 一笑橫江挂書劍 九重天外臥龍深
------
身在風雲心無塵
古今聖賢誰為鄰
一笑橫江挂書劍
九重天外臥龍深
系統時間:2024-05-04 8:19:34
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!