LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

how to drive serial port? I want to write and to read data on the line CTS, RTS and DTR

I want to write and to read data on the CTS, RTS and DTR lines in order to programm EEPROM with i2c bus
0 Kudos
Message 1 of 12
(15,060 Views)
Those lines are NOT data lines they are control lines. You can set the mode of these lines with SetCTSMode in CVI, but you can't manually read and set them as data lines since that isn't what the serial bus uses them for. You may be able to do it with the Windows SDK serial programming, but you will not be able to with the CVI RS-232 library.

Best Regards,

Chris Matthews
National Instruments
0 Kudos
Message 2 of 12
(15,057 Views)
Hi,
Yes, we have to use the windows SKD to drive the RTS and DTR lines. But, for the code I tried (given below), the maximum frequency is 165Hz !
I tried to use direct memory write without success (but I use a USB-RS232 adapter, I don't know if the memory addresses used are correct).
Do you have any suggestions ?

Best regards,
Pascal DELROT

PS : For ports memory addresses, I've just find this topic : http://forums.ni.com/ni/board/message?board.id=180&message.id=15153


// P. DELROT    20070919
// Test de contrôle direct du port série pour émulation interface I2C
// Port use is COM4 (a USB-RS232 adapter)

#include <windows.h>
#include <ansi_c.h>
#include <rs232.h>
#include <utility.h>


// Windows API reference : http://msdn2.microsoft.com/en-us/library/aa383749.aspx
// http://www.beyondlogic.org/serial/serial.htm


#define ADDR_COM1    0x3F8
#define ADDR_COM2    0x2F8
#define ADDR_COM3    0x3E8
#define ADDR_COM4    0x2E8

#define COM_MCR    +4
#define COM_MSR    +6

int main (int argc, char *argv[])
{

unsigned char mcr = 0;
HANDLE SPort = NULL;   
COMMPROP commprop;
DCB commstatus;
COMMCONFIG commconfig;
int taille_commconfig = 0;

// Verify that outp and inp functions are available  
if (CVILowLevelSupportDriverLoaded () == 1)
{
    if ( ( SPort = CreateFile("\\COM4:", GENERIC_READ | GENERIC_WRITE,
    0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL) ) == INVALID_HANDLE_VALUE )
    {
        printf("COM port not opened\n");
        return -1;
    }

   
    GetCommConfig(SPort, &commconfig, &taille_commconfig);
    GetCommState(SPort,  &commstatus);
  
    commconfig.dcb.fParity=NOPARITY;   // Vérification de parité désactivée
    commconfig.dcb.ByteSize=8;             // La taille du mot donnée est de 8 bits
    commconfig.dcb.StopBits=ONESTOPBIT;    // Un bit de stop
    commconfig.dcb.fInX=FALSE;         // Désactive les Xon-Xoff
    commconfig.dcb.fOutX=FALSE;            
    commconfig.dcb.BaudRate= CBR_115200;   // Try to get the maximum speed
    SetCommConfig(SPort, &commconfig, taille_commconfig);
  
    printf("Port COM open, press a key to continue\n");
    while (getchar()==EOF) ;
  
    printf("RTS/DTR square wave. Press a key to stop\n");
    do
    {
/*      // Maximum frequency 22Hz
        commstatus.fRtsControl = !commstatus.fRtsControl;
        commstatus.fDtrControl = !commstatus.fDtrControl;
        SetCommState (SPort, &commstatus);*/

        // Maximum frequency : 166Hz, use of DTR+RTS change the duty cycle
        EscapeCommFunction(SPort, CLRDTR);
        EscapeCommFunction(SPort, SETDTR);

/*      // Use of CVI functions give the same results : 166Hz      
        ComSetEscape (4, SETDTR);
        ComSetEscape (4, CLRDTR);*/

      
/*      Direct address write (no function)
        mcr = inp (ADDR_COM4+COM_MCR);

        mcr = mcr | 0x02;    // Forcage de RTS à 1
        outp (ADDR_COM4+COM_MCR, mcr);

        Delay(1.0/100000.0);
       
        mcr = mcr & 0xFD;    // Forcage de RTS à 0
        outp (ADDR_COM4+COM_MCR, mcr);
           
        Delay(1.0/100000.0);*/
       
    } while (KeyHit ()==0);
    fflush(stdin);
  
    printf("Press a key to terminate\n");
    while (getchar()==0) ;
    CloseHandle(SPort);
}
return 0;
}




Message Edité par tigroo92 le 09-19-2007 11:36 AM

0 Kudos
Message 3 of 12
(14,731 Views)

Hello Pascal,

Since you have posted to a five year old post, could you please be more specific with your actual question?  To get you started, the Serial Instrument Control Tutorial and the Serial Communication Overview are very helpful. 

Thanks,

Meghan

 
0 Kudos
Message 4 of 12
(14,683 Views)
Dear Megan,
I'm working now since 1 year and a half with CVI, and have no problem with common RS232 transmissions between 2 devices (using callbacks, timeouts...). I will read the pages you sent me, just in case I missed something.

As the first post, I'd like to emulate an I2C bus with the pins available on the serial port  : RTS, DTR etc.
The goal is to create a GUI to program small I2C memories used with some of our products. As our customers will do this operation, I can't use the free software solutions available on internet, like this one : http://www.scienceprog.com/rs232-emulates-i2c-for-24cxx-memory-programming/
I don't want our customers to edit the memory in hexadecimal mode.

You will see on the page above that people already emulate I2C bus on the serial port since several years, so they are able to emulate the I2C clock line (at a frequency of 100kHz).
I'm just wondering why I can't, and how I will be able to do this in CVI.

I found several pages and program source code about the programming of serial ports to emulate an I2C bus with Linux (but I have to use Windows platforms), or with Visual Basic and MSCOMM.OCX library.
But nothing helps for CVI or Windows API.

Regards,

Pascal






0 Kudos
Message 5 of 12
(14,669 Views)

Hi Pascal,

There isn't any direct calls to make a serial port simulate I2C communication. I did notice that you said you were using a USB to Serial converter. If you are planning on using this you might look into the NI-USB-8451. It was made for I2C/SPI communication and has a documentation and function calls to do exactly what you are wanting to do. I thought this might be something you could look into while I am trying to find out more information about the possibilities of using Serial to communicate to an I2C device. Thanks

 

Regards
Krista S.
Applications Engineering
National Instruments
0 Kudos
Message 6 of 12
(14,641 Views)
Dear Krista,
Thanks for your answer.
I sure that I can build up an adaptator between the NI-USB-I2C OEM card and my product, and that it will perform as needed (we often use NI acquisitions cards here).
If I try to use the serial port as some others, it's mainly a matter of price, and circuits simplicity.

I've found to web pages today :
The first one is a tutorial about serial ports, from Microsoft : http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnfiles/html/msdn_serial.asp
The second one explains how to use .NET 2.0 class named "SerialPort" : http://msmvps.com/blogs/coad/archive/2005/03/23/39466.aspx

In the first one, I read that usually the Windows drivers keeps the control of DTR and RTS lines, it can explains the "delays" when I try to switch them "by hand".
The second one is interresting, because the .NET class allows to access virtual/USB serial ports. Before to try, I have to learn a bit how to use .NET classes in CVI (I know it's possible).
But I'm not sure it will gives better results.

Regards,

Pascal
0 Kudos
Message 7 of 12
(14,634 Views)
Hi Pascal,

The .NET programming won't directly work in CVI. The best place is to look on the MSDN for C+ or C++ programming help. The Windows SDK should have some help for this. I would search here and see if you can find anything that will help you with this.



Regards
Krista S.
Applications Engineering
National Instruments
0 Kudos
Message 8 of 12
(14,606 Views)
Hi,
The project was down for a moment but I take some hours to continue it.
The goal is to create an I2C protocol (100kbps) by controlling the RS232 SUBD9 pins.

I tried several ways to control the pins (DTR for example), on 2 COM ports : hardware one, on my motherboard, and an OEM USB-RS232 cable.

These are the results with a while loop looking like this one :
// open COM
while (KeyHit()==0)
{
    // Command to set DTR to 1
    // Command to set DTR to 0
    // no other calculation : KeyHit / write command / write command
}
// Close COM

I tried 5 different programming ways :
1. low level drivers (inp outp)
2. CVI functions (ComSetEscape)
3. API Windows (DCB structure, EscapeComFunction)
4. API Windows (DCB structure, SetCommState)
5. Inpout32.dll library to replace inp and outp

USB with inp/outp : inoperant
USB with API Windows (SetCommState) : 22Hz 50% duty cycle
USB with API Windows (EscapeComFunction) : 166Hz 50% duty cycle
USB with CVI (ComSetEscape) : 166Hz 50%
USB with inpout32.dll DLL : inopérant

COM1 with inp/outp : inoperant
COM1 with API Windows (SetCommState) : 16kHz 50% duty cycle
COM1 with API Windows (EscapeComFunction) : 35kHz 30%
COM1 with CVI (ComSetEscape) : 33kHz 25% duty cycle
COM1 with inpout32.dll DLL : 50kHz 25% duty cycle

For inpout32.dll, see http://logix4u.net/Legacy_Ports/Parallel_Port/Inpout32.dll_for_Windows_98/2000/NT/XP.html (with explanations, DLL source code and binary).
I think that without KeyHit function, when emulate the I2C protocol, the duty cycle will be better, bu the frequency lower, because of some calculations to read the next bits.
Controlling the USB-RS232 adapter may require the documentation of the adapter chip itself, and a special board. As I only buy OEM product, it's not possible for me.

Frequencies like 30kHz may be enough to program an I2C memory. I may try the LPT1 port.
Another way is to program a small chip to receive some ASCII commands, and translate them in I2C/SPI (...) protocol. See BL233 "chip" : http://www.i2cchip.com/

Regards,

Pascal


Message Edité par tigroo92 le 02-14-2008 08:11 AM
0 Kudos
Message 9 of 12
(13,920 Views)

Hi,

Finally I succesfully tested a complete CVI program to talk I2C over an RS232 port.

  • All the program is in C/CVI (but the solution may be reprogrammed with Labview),
  • I2C lines are done by controlling RS232 control lines with the Windows API functions as explained before,
  • It works for true RS232 port, and also for virtual COM ports (USB to RS232 adapters, like FDTI FT232R component),
  • I tested it on the PCF8574 component, DIP switch and LEDs (this component allows to control 8 DIO with an I2C bus).We can even use the /INT port of this componant connected to the "RING" RS232 line as an interrupt to avoid continuous reading over the I2C bus.

 

I can't gives the code as is it for my job.

 

These are the performance obtained :

  • RS232 hardware port : 22kHz for the SCL lineup to 2200kB/s as about 10 bits have to be transmitted for 1 byte)
  • RS232 port over USB : 150Hz for the SCL line (about 8 B/s, yes, it's SLOW, but it works).

 

If a 1ms delay is added after each SDA or SCL, the SCL frequency is about 100Hz.

The SCL frequency may vary a lot with the processor and disk usage of the computer. I don't recommand a such solution if a lot of data have to be transmitted. But the RS232 to I2C circuit is cheap and perfect to command slows devices as LED, lamps, motors, or readslow variation of temperature and so on.

 

If you want a reliable I2C bus, you should look for the FDTI FT2232 chip (USB to 2 RS232). This compagny gives free DLL for create various protocols with this chip (JTAG, SPI, I2C), and allows fast communications, as you can adjust the clock line up to several MHz.

 

Regards, Pascal

Message Edité par tigroo92 le 10-09-2008 02:56 AM
0 Kudos
Message 10 of 12
(12,934 Views)