|
||||||||
|
|
#1
|
|
I have a serial device that is connected to a pc via modem cable (db9f-
db9m straigth-thru). There is a Windows program that reads from and writes to that device. Now I want to replace Windows with Linux, so I have to write the program for myself. I have traced all data in both directions, but when I write the initial string to the device, it does not answer. I found that only 4 lines are being used: RxD (line 2), TxD (line 3), SG (line 5) and CTS (line 8). When the Windows program is started, CTS shows -5,35V against SG, otherwise it shows 0. It seems that this line is used to control flow. I tried to set CTS via ioctl without success. Has somebody an idea, what the underlying protocol might be and how I could control that line in Linux?PS: If this is not the proper newsgroup, could someone point me to the correct one? Paul Paul Pridt |
|
#2
|
|||
|
|||
|
On 2007-04-20, Paul Pridt <(E-Mail Removed)> wrote:
> I have traced all data in both directions, but when I write the > initial string to the device, it does not answer. Evidently you're missing something. Contact the manufacturer of such thing and ask them for the specifications, note that reverse-engineering of software is most of the time illegal. Davide -- Everyone seems so impatient and angry these days. I think it's because so many people use Windows at work -- do you think you'd be Politeness Man after working on Windows 8 hrs. or more? -- Chip Atkinson |
|
#3
|
|||
|
|||
|
On Fri, 20 Apr 2007 14:22:03 +0200, Paul Pridt <(E-Mail Removed)> wrote:
> I have a serial device that is connected to a pc via modem cable (db9f- > db9m straigth-thru). > There is a Windows program that reads from and writes to that device. > Now I want to replace Windows with Linux, so I have to write the > program for myself. > I have traced all data in both directions, but when I write the > initial string to the device, it does not answer. > I found that only 4 lines are being used: RxD (line 2), TxD (line 3), > SG (line 5) and CTS (line 8). > When the Windows program is started, CTS shows -5,35V against SG, > otherwise it shows 0. > It seems that this line is used to control flow. > I tried to set CTS via ioctl without success. > Has somebody an idea, what the underlying protocol might be and how I > could control that line in Linux?PS: If this is not the proper newsgroup, > could someone point me to the correct one? > Paul You've left out a lot of info. You don't tell your level of expertise with serial communications. You don't say which program works on your Windows PC. You don't say what you've tried on the Linux side. You don't say what device you're trying to talk to. It looks like you're only measuring the levels of the lines on one side (the DCE = the PC) of the line. I'd guess that the other side (the DTE) is asserting RTS, but you're not raising CTS in response at the right time so that the DTE doesn't send any data. (There are many other possibilities: you need a null-modem (crossover) cable, not a straight-thru; you need a cable which connects RTS to CTS for each side; you've got one of the following wrong: transmit/receive speed, parity, data bit length, stop bit length; and more.) My suggestion: get ckermit for your Linux distro and try to use it to send/receive. Also buy the book "Using C-Kermit", 2nd ed. It has Appendix II "A Condensed Guide to Serial Communications", a valuable resource. It also has Appendix III "UNIX C-Kermit". -- Dale Dellutri <(E-Mail Removed)> (lose the Q's) |
|
#4
|
|||
|
|||
|
"Paul Pridt" <(E-Mail Removed)> wrote:
>I have a serial device that is connected to a pc via modem cable (db9f- >db9m straigth-thru). > >There is a Windows program that reads from and writes to that device. Are you using the exact same cable for the Linux system that you do for the Windows system? Are you absolutely sure that is indeed a straight through cable? If it is some type of Null Modem, there could be a lot of confusion... >Now I want to replace Windows with Linux, so I have to write the >program for myself. >I have traced all data in both directions, but when I write the >initial string to the device, it does not answer. I'm not sure what you mean by "trace all data in both directions" means. If you have access to an RS-232 data analyzer, that is going to be *very* useful. Tell me how you are tracing data! >I found that only 4 lines are being used: RxD (line 2), TxD (line 3), >SG (line 5) and CTS (line 8). That does *not* match RS-232. In the chart below, the PC serial port is a DTE (for Data Terminal Equipment) and the remote serial device is a DCE (for Data Communications Equipment). PIN DTE FUNCTION NAME DTE DIRECTION 1 Frame Ground FG 2 Transmit Data TxD output 3 Receive Data RxD input 4 Request to Send RTS output 5 Clear to Send CTS input 6 Data Set Ready DSR input 7 Signal Ground SG 8 Carrier Detect DCD input 20 Data Terminal Ready DTR output 22 Ring Indicator RI input The above is virtually guaranteed to be the way your PC's serial port is wired. Your device may or may not be wired exactly the same, or with appropriate wires reversed (TxD and RxD, for example) for proper operation, which would be true of a DCE. If the device is wired as a DTE, then the cable used must be a Null Modem, and if the device is wired as a DCE then the cable must be straight through. >When the Windows program is started, CTS shows -5,35V against SG, >otherwise it shows 0. That cannot be a valid assumption on which pins are which. First, pin 5 is not signal ground on your PC, and is very unlikely to be on your device either. Second, RS-232 lines are either a negative voltage or a positive voltage in respect to ground, and are *never* idle at 0 volts. They have to be more than +3 to be considered positive (not asserted) and more than -3 to be considered negative (asserted). When between those values the signal condition is undefined. Generally on computers the RS232 pins are driven with +/- 12 volt supplies, but technically can be (and must work with) signals as great as +/- 15 volts. Voltage regulation is not required, and actual values might vary even on the same equipment. >It seems that this line is used to control flow. Hardware flow control exists on at least two levels, one as an indication that the device is turned on and ready to work, and the other as an indication that individual characters can or cannot be sent. The exact way that is done can vary (and is usually different than what RS-232 was actually intended to do). Generally the DTR signal is asserted on one side and is connected to DSR on the other. It may also be connected to DCD and CTS, thus indicating that data transmission can begin. Sometimes CTS and RTS are strapped together on each end and connected to DCD on the opposite end. All of those configurations allow more or less ability to determine the ready state of the remote device. Another way is to connect DTR on one end to the opposite DSR and DCD to indicate the device is available. Then CTS and RTS are crossconnected between devices to permit character by character hardware flow control. >I tried to set CTS via ioctl without success. Good trick, given that it is an input not an output, eh! :-) You can monitor CTS, but you cannot set it. RTS is the output, which you can set or clear. But generally speaking, you don't want to do that. If you properly configure your serial port, the device driver can and will control RTS. >Has somebody an idea, what the underlying protocol might be and how I >could control that line in Linux?PS: If this is not the proper newsgroup, >could someone point me to the correct one? Welllll... Post your code for opening and configuring the serial port. Try to cut it down to the simplest, shortest program that you can. Maybe even just snippets with code to open and configure a port; though if you can do it nicely the best would be a short program that compiles and shoud send one command and receive a response from the device. Serial port programming is not really hard as such, but it is extremely confusing. Hence experience counts much more than smarts. Virtually nobody gets it right on their own the first time, and everyone uses good references to keep track of how to do it. First, the Linux HOWTO for serial programming is filled with errors and the program examples are loaded with bugs, so it is an interesting read for the experienced, and a horrible reference for newbies. Avoid it. The number one reference you want is "Serial Programming Guide for POSIX Operating Systems" by Michael Sweet at, http://www.easysw.com/~mike/serial/ There are probably a number of good examples of serial port programming available. One is to get the source code for /minicom/, and see how they did it. A production program is necessarily a bit convoluted, but you can eventually track down how to do almost anything. I have a few simpler examples posted on my web page, which might be useful too. There are multiple examples of how to write a simple terminal program (similar to the examples in the Linux HOWTO for serial programming, except hopefully with fewer gross errors, but unfortunately still with some unexplained "weird stuff"). http://web.newsguy.com/floyd_davidson/code/terminal/ And some generic examples of diddling with ioctl's and serial ports, http://web.newsguy.com/floyd_davidson/code/rs232/ -- Floyd L. Davidson <http://www.apaflo.com/floyd_davidson> Ukpeagvik (Barrow, Alaska) (E-Mail Removed) |
|
#5
|
|||
|
|||
|
Davide Bianchi <(E-Mail Removed)> writes:
>On 2007-04-20, Paul Pridt <(E-Mail Removed)> wrote: >> I have traced all data in both directions, but when I write the >> initial string to the device, it does not answer. >Evidently you're missing something. Contact the manufacturer of such >thing and ask them for the specifications, note that reverse-engineering >of software is most of the time illegal. Reverse engineering is never illegal unless you have signed a contract in which you have bound yourself not to reverse engineer. (Under the MDCA reverse engineering may be illegal in the USA if it is a copy protection scheme that you are reverse engineering). |
|
#6
|
|||
|
|||
|
I use exactly the same cable as with the windows program. It is a
straight-thru cable. I had cut it and reconnected with 2 sniffer ends and used linux/logserial to log all data. As I can see exactly the same data as it is shown in Windows, speed, parity etc seem to be ok. Btw I did started as sniffer with a windows machine and got the same result. A db-9 cable is being used. I can disconnect all lines but 2,3,5,8 and it works in Windows as before. Obviously the device is wired as DCE. I also tried to set RTS on and off via ioctl, no result. When I set hardware flow on, nothing happens, the program appearently waits for response that never comes. Somebody asked about my knowledge level in serial programming: once I wrote a serial device monitor for a specific device in C, so I do have some, problably not very deep knowledge. This device now does provide some measurement values over a rs232 interface. Again, I want to use C. Paul "Floyd L. Davidson" <(E-Mail Removed)> schrieb im Newsbeitrag news:(E-Mail Removed)... > "Paul Pridt" <(E-Mail Removed)> wrote: >>I have a serial device that is connected to a pc via modem cable (db9f- >>db9m straigth-thru). >> >>There is a Windows program that reads from and writes to that device. > > Are you using the exact same cable for the Linux system that you > do for the Windows system? Are you absolutely sure that is > indeed a straight through cable? If it is some type of Null > Modem, there could be a lot of confusion... > >>Now I want to replace Windows with Linux, so I have to write the >>program for myself. >>I have traced all data in both directions, but when I write the >>initial string to the device, it does not answer. > > I'm not sure what you mean by "trace all data in both directions" > means. If you have access to an RS-232 data analyzer, that is > going to be *very* useful. Tell me how you are tracing data! > >>I found that only 4 lines are being used: RxD (line 2), TxD (line 3), >>SG (line 5) and CTS (line 8). > > That does *not* match RS-232. In the chart below, the PC serial > port is a DTE (for Data Terminal Equipment) and the remote > serial device is a DCE (for Data Communications Equipment). > > PIN DTE FUNCTION NAME DTE DIRECTION > 1 Frame Ground FG > 2 Transmit Data TxD output > 3 Receive Data RxD input > 4 Request to Send RTS output > 5 Clear to Send CTS input > 6 Data Set Ready DSR input > 7 Signal Ground SG > 8 Carrier Detect DCD input > > 20 Data Terminal Ready DTR output > 22 Ring Indicator RI input > > The above is virtually guaranteed to be the way your PC's serial > port is wired. Your device may or may not be wired exactly the > same, or with appropriate wires reversed (TxD and RxD, for > example) for proper operation, which would be true of a DCE. If > the device is wired as a DTE, then the cable used must be a Null > Modem, and if the device is wired as a DCE then the cable must > be straight through. > >>When the Windows program is started, CTS shows -5,35V against SG, >>otherwise it shows 0. > > That cannot be a valid assumption on which pins are which. > First, pin 5 is not signal ground on your PC, and is very > unlikely to be on your device either. Second, RS-232 lines are > either a negative voltage or a positive voltage in respect to > ground, and are *never* idle at 0 volts. They have to be more > than +3 to be considered positive (not asserted) and more than > -3 to be considered negative (asserted). When between those > values the signal condition is undefined. > > Generally on computers the RS232 pins are driven with +/- 12 volt > supplies, but technically can be (and must work with) signals as > great as +/- 15 volts. Voltage regulation is not required, and > actual values might vary even on the same equipment. > >>It seems that this line is used to control flow. > > Hardware flow control exists on at least two levels, one as an > indication that the device is turned on and ready to work, and > the other as an indication that individual characters can or > cannot be sent. The exact way that is done can vary (and is > usually different than what RS-232 was actually intended to do). > > Generally the DTR signal is asserted on one side and is > connected to DSR on the other. It may also be connected to > DCD and CTS, thus indicating that data transmission can begin. > Sometimes CTS and RTS are strapped together on each end and > connected to DCD on the opposite end. All of those configurations > allow more or less ability to determine the ready state of the > remote device. > > Another way is to connect DTR on one end to the opposite DSR and > DCD to indicate the device is available. Then CTS and RTS are > crossconnected between devices to permit character by character > hardware flow control. > >>I tried to set CTS via ioctl without success. > > Good trick, given that it is an input not an output, eh! :-) > You can monitor CTS, but you cannot set it. RTS is the output, > which you can set or clear. > > But generally speaking, you don't want to do that. If you > properly configure your serial port, the device driver can and > will control RTS. > >>Has somebody an idea, what the underlying protocol might be and how I >>could control that line in Linux?PS: If this is not the proper newsgroup, >>could someone point me to the correct one? > > Welllll... Post your code for opening and configuring the > serial port. Try to cut it down to the simplest, shortest > program that you can. Maybe even just snippets with code > to open and configure a port; though if you can do it nicely the > best would be a short program that compiles and shoud send > one command and receive a response from the device. > > Serial port programming is not really hard as such, but it is > extremely confusing. Hence experience counts much more than > smarts. Virtually nobody gets it right on their own the first > time, and everyone uses good references to keep track of how to > do it. > > First, the Linux HOWTO for serial programming is filled with > errors and the program examples are loaded with bugs, so it is > an interesting read for the experienced, and a horrible > reference for newbies. Avoid it. > > The number one reference you want is "Serial Programming Guide > for POSIX Operating Systems" by Michael Sweet at, > > http://www.easysw.com/~mike/serial/ > > There are probably a number of good examples of serial port > programming available. One is to get the source code for > /minicom/, and see how they did it. A production program is > necessarily a bit convoluted, but you can eventually track down > how to do almost anything. > > I have a few simpler examples posted on my web page, which might > be useful too. There are multiple examples of how to write a > simple terminal program (similar to the examples in the Linux > HOWTO for serial programming, except hopefully with fewer gross > errors, but unfortunately still with some unexplained "weird > stuff"). > > http://web.newsguy.com/floyd_davidson/code/terminal/ > > And some generic examples of diddling with ioctl's and serial > ports, > > http://web.newsguy.com/floyd_davidson/code/rs232/ > > -- > Floyd L. Davidson <http://www.apaflo.com/floyd_davidson> > Ukpeagvik (Barrow, Alaska) (E-Mail Removed) |
|
#7
|
|||
|
|||
|
"Paul Pridt" <(E-Mail Removed)> wrote:
>I use exactly the same cable as with the windows program. It is a >straight-thru cable. I had cut it and reconnected with 2 sniffer ends and >used linux/logserial to log all data. As I can see exactly the same data >as it is shown in Windows, speed, parity etc seem to be ok. >Btw I did started as sniffer with a windows machine and got the same result. >A db-9 cable is being used. I can disconnect all lines but 2,3,5,8 and it >works in Windows as before. Okay. First, I was thinking in 25 pin connector terms, and you are using 9 pin connectors. My fault. DB25 DB9 PIN PIN FUNCTION NAME 1 Frame Ground FG 2 3 Transmit Data TxD 3 2 Receive Data RxD 4 7 Request to Send RTS 5 8 Clear to Send CTS 6 6 Data Set Ready DSR 7 5 Signal Ground SG 8 1 Carrier Detect DCD 20 4 Data Terminal Ready DTR 22 9 Ring Indicator RI Hence, with that, your pin statements do make more sense, though there is still the problem with showing 0 volts. It is possible that your device is trying to use -5v for mark and 0 volts for space... which often enough works even if it is an abomination. With that configuration, connecting only 4 lines, you can't really do hardware flow control in the way the device driver will assume if it is used. It appears as if the RTS/CTS line is sourced at the device (RTS), and your program would sense (the CTS) that line to determine the state of the device. I guess one would assume that data should only be sent if it is asserted. Or at least that is a good starting point, and something you can verify relatively easy. There is code for sensing CTS in the RS-232 examples that I cited in the previous article, which you can use as a mind refresher if needed. It would appear that you have done that sort of thing previously, so it will all make sense quickly. >Obviously the device is wired as DCE. >I also tried to set RTS on and off via ioctl, no result. If what I suspect above is true, there would be no effect from changing RTS states. >When I set hardware flow on, nothing happens, the program appearently waits >for response that never comes. And that would also happen. >Somebody asked about my knowledge level in serial programming: once I wrote >a serial device monitor for a specific device in C, so I do have some, >problably not very deep knowledge. That is definitely a good start. I was assuming just about that. Otherwise you would not have been playing with ioctl calls! (And of course if you had lots of experience, you wouldn't have even bothered with that.) >This device now does provide some measurement values over a rs232 interface. >Again, I want to use C. Here's where we're at, I think: >> Welllll... Post your code for opening and configuring the >> serial port. Try to cut it down to the simplest, shortest >> program that you can. Maybe even just snippets with code >> to open and configure a port; though if you can do it nicely the >> best would be a short program that compiles and shoud send >> one command and receive a response from the device. I think we might be back to this. A lot of what you are probably doing depends on what examples you used to develop your code, and much of what is available on the net comes from the LINUX Howto, which means much of it is riddled with errors. I can go through your code and determine if it actually is doing what you want it to, and probably point out any weird possibilities that would cause strange results. -- Floyd L. Davidson <http://www.apaflo.com/floyd_davidson> Ukpeagvik (Barrow, Alaska) (E-Mail Removed) |
|
#8
|
|||
|
|||
|
Floyd,
I re-engineered my cable and connected line 7 (RTS) also. So the cable now looks like that: 2,3,5,7 and 8 are straight-thru. On the PC-side 6 and 4 are connected (did not make any difference). The sniffer ends are connected to 2 and 3 respectively and to 5. Then I repeated all the tests and noted down the measurements as follows: W WA WT LS0 LUSB 2 -7,1 -7,1 -7,2 -6,4 -7,2 3 0 -5,3 -5,3 0 -6,9 7 0 -5,3 +5,9 0 -7,3 8 -7,1 -7,1 -7,1 -6,7 -7,2 That means: W Windows only (no application started) WA Windows application program (provided with the device) WT Windows perminal program LS0 Linux ttyS0 LUSB Linux ttyUSB0 In all cases the same cable and hardware was used with the following exception: in Linux ttyS0 did not work at all (the sniffer program did not even see the initial character string sent) and I have to use an usb-serial adapter, while the Windows application program runs on com1 only. In Windows only the application program provided with the device works. Interesting is that when I use the Windows terminal program to send the initial character string line 7 shows +5,9 V, but there is no response from the device either. In Linux I made the same test with my application program and serlook. In both cases the sniffer program sees the initial character string but no response. These are the relevant parts of my program: fd = open(tty, O_RDWR | O_NOCTTY | O_NDELAY); tcgetattr(fd,&oldtio); bzero(&newtio, sizeof(newtio)); newtio.c_cflag = CLOCAL | CREAD | CS8; newtio.c_iflag = 0; newtio.c_cc[VMIN]=0; newtio.c_cc[VTIME]=0; cfsetospeed(&newtio, BAUDRATE); cfsetispeed(&newtio, BAUDRATE); tcflush(fd, TCIOFLUSH); tcsetattr(fd,TCSANOW,&newtio); fcntl(fd, F_SETOWN, getpid()); ioctl(fd,TIOCMGET,&status); status |= TIOCM_RTS; ioctl(fd,TIOCMSET,&status); write(fd,"UUUUU\xFF\xFF\x01\x5b\x8f\x00\x5A\x07\x0 1\x33\x00\x00\x95",18); I hope this all is readable to you. Thank you very much for your effort. Paul "Floyd L. Davidson" <(E-Mail Removed)> schrieb im Newsbeitrag news:(E-Mail Removed)... > "Paul Pridt" <(E-Mail Removed)> wrote: >>I use exactly the same cable as with the windows program. It is a >>straight-thru cable. I had cut it and reconnected with 2 sniffer ends and >>used linux/logserial to log all data. As I can see exactly the same data >>as it is shown in Windows, speed, parity etc seem to be ok. >>Btw I did started as sniffer with a windows machine and got the same >>result. >>A db-9 cable is being used. I can disconnect all lines but 2,3,5,8 and it >>works in Windows as before. > > Okay. First, I was thinking in 25 pin connector terms, and you > are using 9 pin connectors. My fault. > > DB25 DB9 > PIN PIN FUNCTION NAME > 1 Frame Ground FG > 2 3 Transmit Data TxD > 3 2 Receive Data RxD > 4 7 Request to Send RTS > 5 8 Clear to Send CTS > 6 6 Data Set Ready DSR > 7 5 Signal Ground SG > 8 1 Carrier Detect DCD > > 20 4 Data Terminal Ready DTR > 22 9 Ring Indicator RI > > Hence, with that, your pin statements do make more sense, though > there is still the problem with showing 0 volts. It is possible > that your device is trying to use -5v for mark and 0 volts for > space... which often enough works even if it is an abomination. > > With that configuration, connecting only 4 lines, you can't > really do hardware flow control in the way the device driver > will assume if it is used. > > It appears as if the RTS/CTS line is sourced at the device > (RTS), and your program would sense (the CTS) that line to > determine the state of the device. I guess one would assume > that data should only be sent if it is asserted. Or at least > that is a good starting point, and something you can verify > relatively easy. > > There is code for sensing CTS in the RS-232 examples that I > cited in the previous article, which you can use as a mind > refresher if needed. It would appear that you have done that > sort of thing previously, so it will all make sense quickly. > >>Obviously the device is wired as DCE. >>I also tried to set RTS on and off via ioctl, no result. > > If what I suspect above is true, there would be no effect from > changing RTS states. > >>When I set hardware flow on, nothing happens, the program appearently >>waits >>for response that never comes. > > And that would also happen. > >>Somebody asked about my knowledge level in serial programming: once I >>wrote >>a serial device monitor for a specific device in C, so I do have some, >>problably not very deep knowledge. > > That is definitely a good start. I was assuming just about > that. Otherwise you would not have been playing with ioctl > calls! (And of course if you had lots of experience, you > wouldn't have even bothered with that.) > >>This device now does provide some measurement values over a rs232 >>interface. >>Again, I want to use C. > > Here's where we're at, I think: > >>> Welllll... Post your code for opening and configuring the >>> serial port. Try to cut it down to the simplest, shortest >>> program that you can. Maybe even just snippets with code >>> to open and configure a port; though if you can do it nicely the >>> best would be a short program that compiles and shoud send >>> one command and receive a response from the device. > > I think we might be back to this. A lot of what you are > probably doing depends on what examples you used to develop your > code, and much of what is available on the net comes from the > LINUX Howto, which means much of it is riddled with errors. > > I can go through your code and determine if it actually is doing > what you want it to, and probably point out any weird > possibilities that would cause strange results. > > -- > Floyd L. Davidson <http://www.apaflo.com/floyd_davidson> > Ukpeagvik (Barrow, Alaska) (E-Mail Removed) |
|
#9
|
|||
|
|||
|
"Paul Pridt" <(E-Mail Removed)> wrote:
>Floyd, > >I re-engineered my cable and connected line 7 (RTS) also. >So the cable now looks like that: >2,3,5,7 and 8 are straight-thru. On the PC-side 6 and 4 are connected (did >not make any difference). >The sniffer ends are connected to 2 and 3 respectively and to 5. >Then I repeated all the tests and noted down the measurements as follows: > > W WA WT LS0 LUSB > >2 -7,1 -7,1 -7,2 -6,4 -7,2 >3 0 -5,3 -5,3 0 -6,9 >7 0 -5,3 +5,9 0 -7,3 >8 -7,1 -7,1 -7,1 -6,7 -7,2 > >That means: >W Windows only (no application started) Note the 0 voltage on pins that are sourced by the PC. That means your serial port is not active... and is not putting any "signal" on those pins yet. >WA Windows application program (provided with the device) Incidentally, I don't believe the voltages are calibrated! I'll bet you anything that what shows up there as -5 is more like -12. And your remote device isn't actually -7, but more like -15. >WT Windows perminal program Note the similarity to WA, which is exactly what it should be. >LS0 Linux ttyS0 This is the same as W, with no signal at all from the PC. The serial port is not enabled. What happens if you run /sbin/setserial /dev/ttyS0 >LUSB Linux ttyUSB0 The USB to serial port converter always has the RS232 port enabled. >In all cases the same cable and hardware was used with the following >exception: >in Linux ttyS0 did not work at all (the sniffer program did not even see the >initial character string sent) The voltages shown above indicate that it is not enabled, so that fits. Serial ports may not be enabled in your kernel??? >and I have to use an usb-serial adapter, while the Windows application >program runs on com1 only. >In Windows only the application program provided with the device works. >Interesting is that when I use the Windows terminal program to send the >initial character string line 7 shows +5,9 V, >but there is no response from the device either. That is the RTS line sourced by the PC. It is difficult to know what response there should be from the device. Typically the common usage today would be that if RTS is asserted, the remote device will send data if it wants to and if RTS is not asserted the device will not send data even if it wants to. The same effect, in the opposite direction, would be true of CTS. So you would not see anything happen when RTS is asserted _unless_ it just happens that the device has data ready to send (and of course full hardware flow control is enabled, so that it was inhibited from sending until RTS was asserted). It doesn't appear that the RTS line is actually being used. And I have a sneaking suspician that CTS is not being used for flow control as such. If you watch pin 8 for awhile when the Window application is running, does it ever flip to a positive voltage, even for a moment? If not, they might be using it as merely the equivalent of DTR, to indicate that the device is ready. If that is the case, you could strap pin 8 to the DCD input on pin 1 and cause the programming task to be easier... >In Linux I made the same test with my application program and serlook. >In both cases the sniffer program sees the initial character string but no >response. Your serial port is not enabled. >These are the relevant parts of my program: Unfortunately, that does not include many relevant parts! Don't make any attempt to edit on a line per line basis. Grab the entire function, because you probably have all sorts of odd things that have effects you aren't aware of... > fd = open(tty, O_RDWR | O_NOCTTY | O_NDELAY); Use O_NONBLOCK rather than O_NDELAY, just to make it more portable. They are precisely the same on Linux but might be different on other unix OS's. But here we don't have any error checking, so there is no way to tell of the call to open() failed or succeeded. If your serial port is not enabled in the kernel, it failed and that would cause exactly the symptoms you describe. Also, you are not re-enabling O_NONBLOCK, which is going to make reading data from this serial port a bit complicated. > tcgetattr(fd,&oldtio); There is no point in saving the original configuration. > bzero(&newtio, sizeof(newtio)); Use memset() instead of bzero(). > newtio.c_cflag = CLOCAL | CREAD | CS8; That is good, but you also probably want a few others, newtio.c_iflag = (IGNBRK | IGNPAR); > newtio.c_iflag = 0; > newtio.c_cc[VMIN]=0; > newtio.c_cc[VTIME]=0; Note that you have already zeroed the entire struct, and these are redundant. Also, I would not recomment setting both VMIN and VTIME elements of the c_cc array to zero. The easiest way to read data from a serial port is with blocking i/o, and then with one of VMIN/VTIME set to 0 and the other to 1, depending on the desired effects. If they are both set to 0, a call to read() will always return immediately. If VMIN is 1 and VTIME is 0, the call to read() block forever or until there is at least 1 byte of data or a interupt signal is received. If VTIME is 1 and VMIN is 0, the call to read() will return if data is available or will block for 1/10th of a second before returning with no data. One of the significant effects of the above is that if each call to read() can block, the process very nicely gives up its time slice and does not become a CPU hog. (If you use nonblocking i/o in a tight loop you'll beat the CPU to death at the needless expense of every other process running.) If you set VTIME to 0, then read() should only be called after the select() function has determined that there is data available. > cfsetospeed(&newtio, BAUDRATE); > cfsetispeed(&newtio, BAUDRATE); > tcflush(fd, TCIOFLUSH); > tcsetattr(fd,TCSANOW,&newtio); That needs to have error checking added to make sure that it has done something. (No error does not mean that it necessarily did what you wanted, but an error means it didn't do anything.) > fcntl(fd, F_SETOWN, getpid()); > > ioctl(fd,TIOCMGET,&status); > status |= TIOCM_RTS; > ioctl(fd,TIOCMSET,&status); > write(fd,"UUUUU\xFF\xFF\x01\x5b\x8f\x00\x5A\x07\x0 1\x33\x00\x00\x95",18); > >I hope this all is readable to you. >Thank you very much for your effort. No problem... other than I haven't been doing much of this in the last few years, so I'm a bit dull sometimes and miss obvious things. -- Floyd L. Davidson <http://www.apaflo.com/floyd_davidson> Ukpeagvik (Barrow, Alaska) (E-Mail Removed) |
|
#10
|
|||
|
|||
|
On Sat, 21 Apr 2007 17:50:25 +0200, Paul Pridt rearranged some electrons
to form: Here's a bit of code that works for me. I am not using flow control, in this particular application, the PC serial port is talking to a 68HC11 microcontroller. YMMV. #include <termios.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> /*********** open_com_port ***************************** * opens com port * port = char string defining what to open (ie. /dev/ttyxx) * fd = resulting file descriptor * returns: 0 (OK) non-zero (error) * ************************************************** **/ int open_com_port(char *port, int *fd) { *fd = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY); if (*fd < 0) return (*fd); /* bad fd, so return non-zero */ else { /* make fd non-blocking */ fcntl(*fd, F_SETFL, FNDELAY); } return 0; } /*********** init_com_port ***************************** * sets up com port * port = COMx (DOS) or file descriptor of open com port (LINUX) * baud = 300,1200,2400,4800,9600 * length = 5,6,7,8 * stop = 1,2 * parity = 0 (none) 1 (odd) 2 (even) * sets it up for raw non canonical input * returns 0 (OK) non-zero (error) * Also sets xmitdelay to an appropriate value based on baud rate ************************************************** *******/ int init_com_port(int port,int baud,int length,int stop,int parity) { extern int xmitdelay; unsigned int data,temp; float x; char tmp[30]; struct termios oldtio, newtio; /* figure about how many millisec. it will take to send a char */ x = (float)(length+stop+1)*1100.0/(float)baud; /* add 10% for luck */ x++; /* add one just to make sure it's not zero */ xmitdelay = (int) x; /* retrieve current port settings */ tcgetattr(port, &newtio); /* get baudrate */ switch (baud) { case 300: data=B300; break; case 1200: data=B1200; break; case 2400: data=B2400; break; case 4800: data=B4800; break; case 9600: data=B9600; break; default: return -2; } cfsetispeed(&newtio, data); /* sets input & output baud rate in structure */ cfsetospeed(&newtio, data); newtio.c_cflag &= ~CSIZE; /* mask word size bits */ switch (length) { case 5: newtio.c_cflag |= CS5; break; case 6: newtio.c_cflag |= CS6; break; case 7: newtio.c_cflag |= CS7; break; case 8: newtio.c_cflag |= CS8; break; default: return -3; } switch (stop) { case 1: /* default is 1 SB */ newtio.c_cflag &= ~CSTOPB; /* clear the bit */ break; case 2: newtio.c_cflag |= CSTOPB; /* set the bit for 2SB */ break; default: return -3; } switch (parity) { case 0: /* default is none */ newtio.c_cflag &= ~PARENB; /* clear the parity enable bit */ newtio.c_iflag &= ~INPCK; break; case 1: newtio.c_cflag |= PARENB; /* odd */ newtio.c_cflag |= PARODD; break; case 2: newtio.c_cflag |= PARENB; /* even */ newtio.c_cflag &= ~PARODD; break; default: return -4; } /* set the values in the termios struct */ newtio.c_cflag |= (CREAD | CLOCAL); /* enable RX*/ newtio.c_cflag &= ~(CRTSCTS); /* HW flow control off */ newtio.c_iflag |= IGNPAR; /* ignore parity errors */ newtio.c_iflag &= ~(IXON | IXOFF | IXANY | INLCR | ICRNL | IUCLC | IMAXBEL); /* switch off other options*/ newtio.c_oflag &= ~(OPOST); /* raw output */ newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHONL | ISIG); /* non canonical, no echo */ newtio.c_cc[VMIN] = 0; newtio.c_cc[VTIME] = 1; /* delay up to (N/10) seconds waiting for char on "read" */ temp = tcsetattr(port, TCSAFLUSH, &newtio); tcflush(port, TCIOFLUSH); return (int)temp; } Enjoy. -- David M (dmacchiarolo) http://home.triad.rr.com/redsled T/S 53 sled351 Linux 2.4.18-14 has been up 6 days 20:22 |
![]() |
| Tags |
| control, device, flow, serial |
| Thread Tools | |
| Display Modes | |
|
|