Cómo programar la interfaz del microordenador en VC
Para usar el puerto serie, puede usar winapi. Usar el puerto serie aquí es como leer y escribir archivos. Abra el puerto serie al principio, luego lea y escriba datos y cierre el puerto serie. puerto después del final.
En VC, el puerto serie y los archivos de disco se pueden leer y escribir fácilmente de manera unificada. Casi no hay diferencia entre los dos, excepto que en WINDOWS 9X, solo se puede acceder a los archivos del disco de forma sincrónica, mientras que al puerto serie solo se puede acceder de forma asíncrona.
CreateFile: abre el puerto serie especificado en el método especificado. El método habitual es
m_hCom = CreateFile( "COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
m_hCom es el identificador del archivo. GENERIC_READ | GENERIC_WRITE especifica que el puerto serie se puede leer y escribir. El tercer parámetro 0 indica que el puerto serie está abierto exclusivamente. OPEN_EXISTING significa que cuando el puerto serie especificado no existe, el programa devolverá un error. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED representa los atributos del archivo. Al abrir un puerto serie, se debe especificar FILE_FLAG_OVERLAPPED, lo que indica que el archivo o dispositivo no mantiene un puntero de acceso Al leer y escribir, se debe usar la estructura OVERLAPPED para especificar el desplazamiento del archivo al que se accederá.
ReadFile: Lee datos del puerto serie.
WriteFile: Escribe datos en el puerto serie.
CloseHandle: Cierra el puerto serie.
COMMTIMEOUTS: COMMTIMEOUTS se utiliza principalmente para la configuración de parámetros de tiempo de espera del puerto serie. La estructura de COMMTIMEOUTS es la siguiente:
typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout
DWORD ReadTotalTimeoutMultiplier
DWORD ReadTotalTimeoutConstant <; /p>
DWORD WriteTotalTimeoutMultiplier;
DWORD WriteTotalTimeoutConstant;
} COMMTIMEOUTS, *LPCOMMTIMEOUTS
ReadIntervalTimeout: el retraso máximo entre dos caracteres, al leer; los datos del puerto serie, una vez que la diferencia de tiempo entre dos transmisiones de caracteres excede este tiempo, la función de lectura devolverá los datos existentes. Establecer en 0 significa que este parámetro no tiene ningún efecto.
ReadTotalTimeoutMultiplier: Lee el tiempo de espera entre cada carácter.
ReadTotalTimeoutConstant: Se corrigió el tiempo de espera para leer datos del puerto serie a la vez. Por lo tanto, en una operación de lectura del puerto serie, el tiempo de espera es ReadTotalTimeoutMultiplier multiplicado por el número de bytes leídos más ReadTotalTimeoutConstant. Establezca ReadIntervalTimeout en MAXDWORD y establezca ReadTotalTimeoutMultiplier y ReadTotalTimeoutConstant en 0, lo que indica que la operación de lectura devolverá inmediatamente los caracteres almacenados en el búfer de entrada.
WriteTotalTimeoutMultiplier: Escribe el tiempo de espera entre cada carácter.
WriteTotalTimeoutConstant: Se corrigió el tiempo de espera para escribir datos del puerto serie a la vez. Por lo tanto, en una operación de escritura en el puerto serie, el tiempo de espera es WriteTotalTimeoutMultiplier multiplicado por el número de bytes escritos más WriteTotalTimeoutConstant.
La función SetCommTimeouts puede establecer el parámetro de tiempo de espera de un determinado identificador de dispositivo. Para obtener el parámetro de tiempo de espera de un determinado identificador de dispositivo, puede utilizar la función GetCommTimeouts.
DCB: La estructura DCB se utiliza principalmente para la configuración de parámetros del puerto serie. La estructura es demasiado grande, por lo que no la describiré una por una aquí. Aquellos que estén interesados pueden consultar la descripción de DCB en MSDN. Los dos siguientes son los atributos más importantes.
BaudRate: La velocidad de comunicación del puerto serie. Generalmente configurado en 9600.
ByteSize: Número de bytes. Generalmente establecido en 8.
La estructura DCB se puede configurar usando la función SetCommState y GetCommState se puede usar para obtener las propiedades del puerto serie existente.
SetupComm: Configura el buffer de entrada y salida del puerto serie.
SUPERPUESTO: Guarda información de comunicación asíncrona del puerto serie. La estructura específica es la siguiente:
typedef struct _OVERLAPPED {
DWORD Internal;
DWORD InternalHigh
DWORD Offset; p>
DWORD OffsetHigh;
HANDLE hEvent;
} OVERLAPPED;
Internal e InternalHigh están reservados para uso del sistema y los usuarios no necesitan configurarlos. a ellos.
Offset y OffsetHigh son los desplazamientos para leer y escribir en el puerto serie. Generalmente, configurar OffsetHigh en NULL puede admitir datos de 2 GB.
hEvento de lectura y escritura, debido a que el puerto serie es comunicación asíncrona, la operación puede ser bloqueada por otros procesos, el programa puede verificar el tiempo para saber si se completó la lectura y escritura. El evento se configurará automáticamente como válido después de que se completen la lectura y la escritura.
A través de las funciones y estructuras anteriores, podemos comunicarnos a través del puerto serie. Ahora veamos el siguiente ejemplo:
BOOL CSerial::Open(int nPort, int nBaud) <. /p>
{
if( m_bOpened ) return( VERDADERO
char szPort[15]
DCB dcb;
wsprintf( szPort, "COMd", nPort );
m_hComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
if( m_hComDev == NULL ) return( FALSE );
memset( amp; m_OverlappedRead, 0, sizeof( OVERLAPPED )
memset( amp; m_OverlappedWrite, 0, sizeof ); ( SUPERPUESTO ) );
COMMTIMEOUTS CommTimeOuts
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF
CommTimeOuts.ReadTotalTimeoutMultiplier = 0
CommTimeOuts . ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 5000;
SetCommTimeouts( m_hComDev, amp; CommTimeOuts);
m_OverlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_OverlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
dcblength. = tamaño de (DCB);
GetCommState( m_hComDev, amp; dcb;
dcb.BaudRate = nBaud; p>
if( !SetCommState( m_hComDev, amp; dcb) ||
!SetupComm( m_hComDev, 10000, 10000) ||
m_OverlappedRead.hEvent == NULL | |
m_OverlappedWrite.hEvent == NULL ){
DWORD dwError = GetLastError();
if( m_Overla
ppedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent
CloseHandle( m_hComDev );
devuelve FALSO;
}
m_bAbierto = VERDADERO;
devuelve m_bAbierto;
}
int CSerial::InBufferCount( void )
{
if( !m_bOpened || m_hComDev == NULL ) return(
DWORD); dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, y; dwErrorFlags, y ComStat);
return (int)ComStat.cbInQue
}
DWORD CSerial::ReadData( void *buffer, DWORD dwBytesRead)
{
if( !m_bOpened || m_hComDev == NULL ) devuelve 0;
BOOL bReadStatus;
DWORD dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hComDev, amp; dwErrorFlags, amp ;ComStat );
if( !ComStat.cbInQue ) devuelve 0;
dwBytesRead = min(dwBytesRead, (DWORD) ComStat.cbInQue);
bReadStatus = ReadFile( m_hComDev, buffer, dwBytesRead, y dwBytesRead, y m_OverlappedRead
if( !bReadStatus ){
if( GetLastError() == ERROR_IO_PENDING ){ p>
WaitForSingleObject( m_OverlappedRead.hEvent, 2000
return dwBytesRead
}
return 0;
return dwBytesRead;
}
DWORD CSerial::SendData( const char *buffer, DWORD dwBytesWritten)
{
if( !m_bOpened || m_hComDev == NULL ) return( 0
BOOL bWriteStat
bWri;
teStat = WriteFile( m_hComDev, buffer, dwBytesWritten, & dwBytesWritten, & m_OverlappedWrite);
if( !bWriteStat){
if ( GetLastError() == ERROR_IO_PENDING ) {
WaitForSingleObject( m_OverlappedWrite.hEvent, 1000);
devuelve dwBytesWritten
}
devuelve 0; /p>
devuelve dwBytesEscrito;
}