CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    Mar 2003
    Location
    The Netherlands
    Posts
    586

    Controlling DTR line of serial port

    Hi,

    I have connected a led to the DTR line of the serial port just for testing purposes.

    Turning the led on/off works just fine with the EscapeCommFunction() function which sets or clears the DTR line.

    However, there is a problem. As soon as the serial port is opened with CreateFile(), there is a short pulse on the DTR line which causes the led to blink very shortly. Does someone knows how to prevent this startup pulse to occur?

    Thanks in advance.

    Code:
    m_hPort = CreateFile(
    		portName,						// Pointer to the name of the port
    		GENERIC_READ | GENERIC_WRITE,	// Access (read/write) mode
    		0,								// 0, serial ports can not be shared
    		NULL,							// Pointer to the security attribute
    		OPEN_EXISTING,					// How to open the serial port 
    		0,								// Port attributes 
    		NULL);							// Handle to port with attribute to copy
    
    	// If it fails to open the port, return false.
    	if (m_hPort == INVALID_HANDLE_VALUE) 
    		return false;
    	
    	return true;
    Time is fun when you're having flies

  2. #2
    Join Date
    Sep 1999
    Location
    Germany, Hessen
    Posts
    226
    Hey, great question.


    I've got a very similar problem on a embeddded device under WinCE (where the DTR/DSR lines are missued as additional control lines for a RS485-communication ...)

    If you find a solution please let me know here in the thread ...

  3. #3
    Join Date
    Mar 2003
    Location
    The Netherlands
    Posts
    586
    It seems that the DTR line output is standard set (+10V) when the port is opened. When the DTR line is cleared, a voltage of
    -10V is measured. This means current flows from GND to DTR.

    When DTR is positive:
    DTR o-------|>|-------o GND

    When DTR is negative:
    DTR o-------|<|-------o GND

    So, now i connect the LED with its anode to GND and kathode to DTR, which ensures that the LED stays off when opening the port.
    An other possibility is to invert the DTR signal.
    Last edited by hmc; April 16th, 2004 at 02:00 AM.
    Time is fun when you're having flies

  4. #4
    Join Date
    Jan 2004
    Location
    Earth
    Posts
    567
    What is the setting of the fDtrControl member of the DCB struct?
    If you set it to DTR_CONTROL_ENABLE it will enable the DTR line when the port is opened and leave it on.

    For the DTR line, enabled or "set" means a logic 0. In RS-232 voltage levels a logic 0 is between +3 and +15 volts DC. The DTR line is "asserted" (on, set, enabled....etc) when it is "low" or logic 0 or +3 to +15 volts DC in RS-232 which is 0.0 to 0.7 volts in TTL logic levels.

    Does that make sense?

    Originally posted by hmc
    It seems that the DTR line output is standard set (+10V) when the port is opened. When the DTR line is cleared, a voltage of
    -10V is measured. This means current flows from GND to DTR.
    From that behavior I can be reasonably certain that you are not setting the fDtrControl member of the DCB struct to DTR_CONTROL_ENABLE before opening the port. On my system the DTR signal is cleared (-3 to -15 volts DC) when the port is closed regargless of the setting of fDtrControl. If I set the fDtrControl to DTR_CONTROL_ENABLE and then open the serial port the DTR signal goes to (+3 to +15 volts DC) when the port is opened and stays there. This is the "set" state for the DTR line.

    So I think you just need to set the fDtrControl member of the DCB struct to DTR_CONTROL_ENABLE before opening the serial port and the DTR line should go to the set state and stay in the set state while the serial port remains open.

    RS-232D is a little confusing, just remember that a "logic 1" is between -3 and -15 volts DC and a logic 0 is between +3 and +15 volts DC. To be compatible with TTL you need a level converter like a MAX-232. This chip will invert the signal and brings the logic levels to TTL levels (0 to +5 volts).

    The data signals (TX and RX) assert high (logic 1) and the flow control lines (DTR,RTS,DSR and CTS) assert low (logic 0).


    TDM
    Last edited by TDM; April 16th, 2004 at 06:58 AM.

  5. #5
    Join Date
    Mar 2003
    Location
    The Netherlands
    Posts
    586
    From that behavior I can be reasonably certain that you are not setting the fDtrControl member of the DCB struct to DTR_CONTROL_ENABLE before opening the port. On my system the DTR signal is cleared (-3 to -15 volts DC) when the port is closed regargless of the setting of fDtrControl. If I set the fDtrControl to DTR_CONTROL_ENABLE and then open the serial port the DTR signal goes to (+3 to +15 volts DC) when the port is opened and stays there. This is the "set" state for the DTR line.
    How can i set the fDtrControl member in the DCB struct without opening the port. I used SetCommState(), but this function requires a handle to the port which can only be passed after opening the port. Please correct me if i am wrong.
    Time is fun when you're having flies

  6. #6
    Join Date
    Jan 2004
    Location
    Earth
    Posts
    567
    Before calling SetCommState, modify the fDtrControl of the DCB struct. You can set the members of the DCB struct to whatever values you want before opening the serial port. One example might be:


    Code:
    FillMemory(m_dcb, sizeof(DCB), 0);
    m_dcb->DCBlength = sizeof(DCB);
    m_dcb->fAbortOnError=TRUE;
    m_dcb->fBinary=TRUE;
    m_dcb->EvtChar='\xD';
    m_dcb->EofChar='\x1A';     
    m_dcb->ErrorChar=(BYTE)'¿';
    m_dcb->fErrorChar=1;
    m_dcb->Parity=NOPARITY;  
    m_dcb->BaudRate=CBR_9600;
    m_dcb->ByteSize=8;
    m_dcb->StopBits=ONESTOPBIT; 
    m_dcb->fNull=0;
    m_dcb->fParity=0;
    m_dcb->XonChar='\x11';   
    m_dcb->XoffChar='\x13';  
    m_dcb->fDsrSensitivity=0;
    m_dcb->fOutxCtsFlow=0;
    m_dcb->fOutxDsrFlow=0;
    m_dcb->fDtrControl=DTR_CONTROL_ENABLE;
    m_dcb->fRtsControl=RTS_CONTROL_DISABLE;
    m_dcb->fTXContinueOnXoff=0;
    m_dcb->fOutX=0;
    m_dcb->fInX=0;
    m_dcb->XonLim=512;
    m_dcb->XoffLim=512;
    
    h_Port = CreateFile(m_PortName,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
    
    SetupComm(h_Port,4096,4096);
       
    if (!SetCommState(h_Port,m_dcb))
    {
        MessageBox("Open serial port failed"); 
        return 0;
    }
    TDM

  7. #7
    Join Date
    Mar 2003
    Location
    The Netherlands
    Posts
    586
    But modifying the DCB struct does not have any effect until you call SetCommState(), which is after you opened the port.

    This means the DTR line has a predefined state which is caused by the hardware of the port.
    Time is fun when you're having flies

  8. #8
    Join Date
    Jan 2004
    Location
    Earth
    Posts
    567
    The previous post is a little bit of overkill. You could just use:

    Code:
    h_Port = CreateFile(m_PortName,GENERIC_READ |  GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
    
    GetCommState(h_Port,&m_dcb);
    
    m_dcb->fDtrControl=DTR_CONTROL_ENABLE;
    
    SetupComm(h_Port,4096,4096);
       
    if (!SetCommState(h_Port,m_dcb))
    {
        MessageBox("Open serial port failed"); 
        return 0;
    }
    I actually use property sheet/pages to allow the user to modify all member of the DCB. I just close the port when the property sheet is opened and then re-open the serial port with the new DCB when the property sheet is closed.

    TDM

  9. #9
    Join Date
    Jan 2004
    Location
    Earth
    Posts
    567
    Originally posted by hcm
    But modifying the DCB struct does not have any effect until you call SetCommState(), which is after you opened the port.
    Yes the serial port is opened at create file but the parameters for the hardware are applied when you call SetCommState.

    TDM
    Last edited by TDM; April 16th, 2004 at 09:34 AM.

  10. #10
    Join Date
    Sep 1999
    Location
    Germany, Hessen
    Posts
    226
    Sorry, that doesn't hit the point.

    A call to CreateFile opens the COM port. At that time the DTR signal will be DISABLED for a short time (we measured 100ms on a strongarm system / WinCE 4.1 ).

    If you don't use the serial port the "normal way" that could be a problem. (we "missuse" the DTR for a control line. in our case that "little switch time" could lead to serious damage of our hardware (some parts of the system are powered up before the control hardware is online).

    The point that it i exactly 100ms looks to me that this is a behaviour by design. I took a look into the COM driver routines in the BSP and the MS common soruces but couldn't locate the source of that 100ms switch there. But I'm not very used to that kind of code...

  11. #11
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125
    I would STRONGLY consider using a digital I/O board rather than mis-using the Serial port. The only other choice for 100% of what you want is to totally bypass the windows code and write your own driver.

    I have developed a number of commercial drivers for exactly this purpose. Unfortunately they are not trival, or open source...
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

  12. #12
    Join Date
    Jan 2004
    Location
    Earth
    Posts
    567
    Yes, Since my original responses in this thread I have investigated different serial ports and different operating systems. The behavior of the DTR line differed with different UARTS and operating systems. The correct behavior would be for the DTR line to be cleared whenever the port is not open because the data terminal is not ready to receive data. It is completely understandable that there will be a short perfiod between the opening of the port and the setting of the DTR line. Perhaps I spoke too quickly in my previous posts before considering the nature of the problem.

    That is a pretty ugly failure mode if your hardware gets smoked from such a short delay in the activation of the DTR line. Any method for sourcing the signal, DIO card or otherwise, would be subject to such a failure mode. Maybe consider a redesign of the hardware(if that is an option) where there is a delay or make the hardware remain in standby until the DTR signal is set.

    TDM
    Last edited by TDM; April 26th, 2004 at 08:36 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured