rs485编程java_串行编程RS485
我的任務是通過RS485 2線系統實現ModBus協議 . (實際上它是三根線,A / B和GND) . 雖然ModBus不是重點,但是之前的步驟......界面上的簡單I / O.
我正在使用FTDI USB-RS485轉換器將Linux主機(不可互換)連接到Windows主機(可與其他Linux主機互換,但我想避免這種情況)
編碼應該是19200,8,n,1 . 但它似乎不起作用 .
我沒有準確的代碼,但在Linux上我這樣做:
int fd = open("/dev/ttyS3", O_RDWR | O_CTTY);
if(fd == -1) return "Error while opening the port";
接下來,我配置端口 .
struct termios tty;
tcgetattr(fd, &tty);
cfsetispeed(&tty, B19200);
cfsetospeed(&tty, B19200);
tty.c_cflag = CS8; //Empties the cflags and sets the character width.
tty.c_cflag |= (CLOCAL | CREAD); //Sets 'recommended' options.
tty.c_lflag = 0;
tty.c_iflag = 0;
tty.c_oflag = 0;
tcgetattr(fd, TCSANOW, &tty);
奇偶校驗和流量控制目前尚未規劃,因為最終結果將連接到低級別的電路板,我需要自己處理信號 . 此外,沒有任何電線可以實現“不受約束的通信” . (畢竟我不希望XON / XOFF字符限制我可以傳輸的字節范圍)
所有這些功能都能正常運行并設置數據 .
在Windows上,我打開這樣的串口:
DCB SP;
HANDLE hSerial = CreateFile("COM6", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if(hSerial == INVALID_HANDLE_VALUE) return "Error while opening the port";
GetCommState(hSerial, &SP);
奇偶校驗被禁用,以及流量控制 . 字節大小設置為8 .
編輯:因為已經被問到,這是我的Windows上的波特率代碼(來自內存)SP.DCBlength = sizeof(SP); SP.BaudRate = 19200; SP.Parity = NOPARITY; SP.StopBits = ONESTOPBIT; SetCommState(hSerial,&SP);
同樣,所有這些功能都運行得很完美 .
現在,對于讓我頭疼的測試用例 .
在Linux主機上,我創建了一個256字節大小的字節緩沖區 . 該緩沖區填充0-255的字符值...然后通過寫入發送 . 與此同時,另一方正在等待“ReadFile”數據到達 .
使用此配置,對于“其他Linux主機”以及Windows主機,256字節到達...但是它不是0-255的數字,而是00 06等 .
當我在設置我真正想要的選項之前將termios結構的所有成員設置為0時,我可以讓Linux主機工作 . 我猜,這是因為控制字符...但是如果我這樣做,Windows主機要么只接收256個字節中的4個 .
正如我所說,不幸的是我沒有方便的代碼 . 如果有人知道我能從哪個方面解決這個問題,我將非常感激 . 一旦我再次訪問它,我將發布更多代碼 .
我是如何實現讀取操作的:
DWORD nBytes = 0;
char Buffer[256], *ptr = Buffer;
int Rem = 256;
while(Rem) {
ReadFile(hSerial, ptr, Rem, &nBytes, 0);
Rem -= nBytes;
ptr += nBytes;
}
//Evaluate Buffer
需要注意的是,我確實設置了超時,但不記得確切的值 .
編輯:因為我現在可以再次訪問我的工作地點,這是實際(當前)代碼 .
const char *InitCOM(const char *TTY) {
struct termios tty;
hSerial = open(TTY, O_RDWR | O_NOCTTY | O_NDELAY);
if(hSerial == -1) return "Opening of the port failed";
fcntl(hSerial, F_SETFL, 0);
if(tcgetattr(hSerial, &tty) != 0) return "Getting the parameters failed.";
if(cfsetispeed(&tty, B19200) != 0 || cfsetospeed(&tty, B19200) != 0) return "Setting the baud rate failed.";
//CFlags
//Note: I am full aware, that there's an '=', and that it makes the '&=' obsolete, but they're in there for the sake of completeness.
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; //8-bit characters
tty.c_cflag |= (CLOCAL | CREAD);und erlaubt 'Lesen'.
tty.c_cflag &= ~(PARENB | PARODD);
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
//Input Flags
tty.c_iflag &= ~IGNBRK;
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
//Local Flags
tty.c_lflag = 0;
//Output Flags
tty.c_oflag = 0;
//Control-Characters
tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 5;
if(tcsetattr(hSerial, TCSAFLUSH, &tty) != 0) return "Setting the new parameters failed";
return NULL;
}
至于實際的發送/接收代碼:
int main(int argc, char* argv[]) {
#if defined FOR_PC
const char *err = InitCOM("/dev/ttyUSB0");
#else
const char *err = InitCOM("/dev/ttyS3");
#endif
if(err) printf("Error while initalizing: %s ErrNum: %d\n", err, errno);
else {
/*unsigned char C[256]; //Original code with the array
int nBytes;
#ifdef FOR_PC
int Rem = 256, ReqCount = 0;
unsigned char *ptr = C;
while(Rem > 0) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(hSerial, &fds);
select(hSerial+1, &fds, NULL, NULL, NULL);
nBytes = read(hSerial, ptr, Rem);
if(nBytes > 0) {
Rem -= nBytes;
ptr += nBytes;
++ReqCount;
}
}
printf("Number of received Bytes: %d in %d sends.\n\n", 256 - Rem, ReqCount);
for(int i = 0; i < 256; ++i) {
printf("%02X ", C[i]);
if((i%32) == 31) printf("\n");
}
#else
for(int i = 0; i < 256; ++i) C[i] = i;
nBytes = write(hSerial, C, 256);
printf("\nWritten Bytes: %d\n", nBytes);
#endif*/
//Single-Byte Code
unsigned char C = 0x55;
#ifdef FOR_PC
while(true) { //Keeps listening
fd_set fds;
FD_ZERO(&fds);
FD_SET(hSerial, &fds);
select(hSerial+1, &fds, NULL, NULL, NULL);
read(hSerial, &C, 1);
printf("Received value 0x%02X\n", C);
}
#else
write(hSerial, &C, 1); //Sends one byte
#endif
close(hSerial);
}
return 0;
}
至于示波器:我已經通過發送測試了兩個方向 . 他們的工作非常令人欽佩 .
0x55的信號是50微秒長度的常數上/下(應該如此,所以設置波特率也沒問題) .
那么我的'接收'代碼中有什么東西我做錯了嗎? '選擇'錯了嗎?
總結
以上是生活随笔為你收集整理的rs485编程java_串行编程RS485的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java中常用的定位方式有哪些_java
- 下一篇: java soap 头_如何将java头