मैं एक सीरियल डिवाइस खोलने और उसमें से डेटा भेजने/प्राप्त करने के लिए सी का उपयोग कर रहा हूं। प्राप्त करना बिना किसी समस्या के काम करता है, लेकिन मेरे द्वारा भेजा गया कोई भी डेटा डिवाइस तक नहीं पहुंचता है। मैं इस तरह डिवाइस खोलता हूं:

int open_tty() {
    int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_CLOEXEC);  

    struct termios config;
    cfsetispeed(&config, B38400);
    cfsetospeed(&config, B38400);
    config.c_cflag &= ~PARENB;                                                                                                                                          
    config.c_cflag &= ~CSTOPB;                                                                                                                                          
    config.c_cflag &= ~CSIZE;                                                                                                                                           
    config.c_cflag |= CS8;                                                                                                                                              

    tcsetattr(fd, TCSANOW, &config);                                                         

    return fd;
}

...
write(fd, data, length)
...

स्ट्रेस के अनुसार, सब कुछ ठीक काम करता है:

openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_CLOEXEC) = 3
ioctl(3, TCGETS, {B38400 -opost isig icanon echo ...}) = 0
ioctl(3, SNDCTL_TMR_START or TCSETS, {B38400 -opost isig icanon echo ...}) = 0
ioctl(3, TCGETS, {B38400 -opost isig icanon echo ...}) = 0
write(3, "some data.......", 16) = 16

हालांकि, डिवाइस को कोई डेटा प्राप्त नहीं होता है (इसे एक एसीके पैकेट भेजना चाहिए)। अगर मैं अजगर में वही काम करता हूं, तो सब कुछ ठीक काम करता है:

s=serial.Serial('/dev/ttyUSB0', baudrate=9600*4)
s.write('some data.......')

स्ट्रेस:

openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NONBLOCK|O_CLOEXEC) = 3
ioctl(3, TCGETS, {B38400 -opost isig icanon echo ...}) = 0
ioctl(3, TCGETS, {B38400 -opost isig icanon echo ...}) = 0
ioctl(3, TCGETS, {B38400 -opost isig icanon echo ...}) = 0
ioctl(3, SNDCTL_TMR_START or TCSETS, {B38400 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCGETS, {B38400 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TIOCMBIS, [TIOCM_DTR])         = 0
ioctl(3, TIOCMBIS, [TIOCM_RTS])         = 0
ioctl(3, TCFLSH, TCIFLUSH)              = 0
write(3, "some data.......", 16) = 16

किसी भी तरह की सहायता का स्वागत किया जाएगा।

संपादित करें: जैसा कि @abarnert ने सुझाव दिया था, मैंने DTR और RTS बिट्स सेट किए और बफर को फ्लश किया:

char rts = TIOCM_RTS;
char dtr = TIOCM_DTR;
ioctl(fd, TIOCMBIS, &dtr);
ioctl(fd, TIOCMBIS, &rts);
tcflush(fd, TCIFLUSH);

इसके कारण निम्नलिखित अतिरिक्त syscalls सीधे write कॉल से पहले भेजे गए:

ioctl(3, TIOCMBIS, [TIOCM_DTR|TIOCM_DSR|0x200]) = 0
ioctl(3, TIOCMBIS, [[TIOCM_RTS|0x30200}) = 0
ioctl(3, TCFLSH, TCIFLUSH)               = 0

हालाँकि, मुझे अभी भी डिवाइस से कोई ACK पैकेट वापस नहीं मिला है।

डिवाइस एक VirtualRobotix GPS uBlox 8 है (http://www.virtualrobotix.it/index.php/en/shop/gps/3dr-gps-ublox-8-542015-11-30-13-35 -34_-विवरण) USB से सीरियल कनवर्टर का उपयोग करके कनेक्ट किया गया है।

0
Lukor 27 अप्रैल 2018, 08:59

1 उत्तर

सबसे बढ़िया उत्तर

हम्म्म्म, मुझे डर है कि आपने termios पैरामीटर सेट करने में सही प्रक्रिया का पालन नहीं किया है। सबसे पहले आपको वास्तविक कॉन्फ़िगर किए गए पैरामीटर प्राप्त करने के लिए tcgetattrs(3) का उपयोग करना चाहिए (और termios संरचना को प्रारंभ करने के लिए, अन्यथा आपके कोड में कचरे के लिए प्रारंभ नहीं किया गया है, जैसा कि आपने इसे एक स्वचालित के रूप में घोषित किया है वेरिएबल), फिर आप जो चाहते हैं उसे बदलते हैं, और अंत में आप वांछित कॉन्फ़िगरेशन सेट करते हैं।

सही प्रक्रिया है:

 struct termios param;
 res = tcgetattrs(fd, &param); /* VERY IMPORTANT: first get the actual parameters */
 if (res < 0) {
      perror("tegetattrs");
      exit(EXIT_FAILURE);
 }
 cfsetispeed(&param, B38400);
 cfsetospeed(&param, B38400);
 param.c_cflag &= ~PARENB;
 /* ... all the needed configuration. */
 /* and finally. */
 res = tcsetattrs(fd, &param);
 if (res < 0) { /* error */
     perror("tcsetattrs");
     exit(EXIT_FAILURE);
 }

(साथ ही, त्रुटियों के लिए वापसी मान res की जांच करना आम बात है)

जैसा कि मैनुअल पेज termios(3) लाइन स्पीड सेट करने के संबंध में कहता है:

लाइन की गति

मान प्राप्त करने और सेट करने के लिए बॉड दर फ़ंक्शन प्रदान किए जाते हैं termios संरचना में इनपुट और आउटपुट बॉड दरों का। NS नए मान तब तक प्रभावी नहीं होते जब तक tcsetattr() सफलतापूर्वक नहीं हो जाता कहा जाता है।

गति को B0 पर सेट करना मॉडेम को "हैंग अप" करने का निर्देश देता है। वास्तविक B38400 से संबंधित बिट दर को setserial(8) से बदला जा सकता है।

इनपुट और आउटपुट बॉड दरें termios संरचना में संग्रहित की जाती हैं।

(उद्धरण मेरा है)

1
Luis Colorado 30 अप्रैल 2018, 17:29