码迷,mamicode.com
首页 > Windows程序 > 详细

Windows Serial Port Programming in C.

时间:2015-05-09 15:02:11      阅读:199      评论:0      收藏:0      [点我收藏+]

标签:winapi   thread   


    Similar with the linux version , this article would demonstrate how to write a simple windows .

    I divide the 2 operations : write and read into 2 threads. Of course, one could call ReadFile and WriteFile (those are mapping to read/wrrite function in linux) at the same thread.
    Be prudent, if you would like to create more than 2 threads, do not be annoyed to lock/unlock the threads.


#include <windows.h>
#include <stdio.h>

#define MAX_STR_LEN      (512)
#define UART_TRANS_BUFFER    (128)

#define MILLI_SEC      (1)

BOOL isLeaveThread;

CRITICAL_SECTION UARTThreadCriticalSection;


TCHAR *GetLastErrorMessage(DWORD lastError)
{
   static TCHAR errmsg[MAX_STR_LEN];

   if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, lastError,
      MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT) /*american empire language*/,
      errmsg,  MAX_STR_LEN - 1, NULL))
   {
      /* if we fail, call ourself to find out why and return that error */
      return (GetLastErrorMessage(GetLastError()));  
   }
  
   return errmsg;
}/*GetLastErrorMessage*/


DWORD WINAPI ReadThread(LPVOID  lpParameter)
{
 HANDLE hSerial; 
 char readBuffer[UART_TRANS_BUFFER];
 
 
 

 hSerial = *((HANDLE*)lpParameter);
 
 do
 { 
  BOOL isSuc;
  DWORD bytesRead;
  unsigned int i;

  ZeroMemory(&readBuffer[0], UART_TRANS_BUFFER);

  EnterCriticalSection(&UARTThreadCriticalSection);
  isSuc = ReadFile(hSerial, &readBuffer[0], UART_TRANS_BUFFER, &bytesRead, NULL);

  if(FALSE == isSuc)
  {
   printf("ERROR : %s : %s\n", __FUNCTION__, 
    GetLastErrorMessage( GetLastError()) );
  }/*if*/


  Sleep(5);

  if(0 == bytesRead)
  {
   printf("  No Ack!\n");
   continue;
  }
  
   for(i = 0; i< bytesRead; i++)
   printf("%c(%d %#x)\t", readBuffer[i], readBuffer[i], readBuffer[i]);
  
  LeaveCriticalSection(&UARTThreadCriticalSection);
 }while(FALSE == isLeaveThread);
 
 printf("leaving %s\n", __FUNCTION__);

 ExitThread((DWORD)0);
}/*ConfirmThread*/


DWORD WINAPI WriteThread(LPVOID  lpParameter)
{
 HANDLE hSerial;
 char sendBuffer[UART_TRANS_BUFFER];
 
 DWORD bytesWritten; 
 BOOL isSuc;


 hSerial = *((HANDLE*)lpParameter);

 sprintf_s(&sendBuffer[0], UART_TRANS_BUFFER, "hello!");

 do
 {

  EnterCriticalSection(&UARTThreadCriticalSection);

  isSuc = WriteFile(hSerial, &sendBuffer[0], strlen(&sendBuffer[0]), &bytesWritten, NULL);  

  if(FALSE == isSuc)
  {
   printf("ERROR : %s : %s\n", __FUNCTION__, 
    GetLastErrorMessage( GetLastError()) );
  }/*if*/

  Sleep(5); 
  LeaveCriticalSection(&UARTThreadCriticalSection);
 }while(FALSE == isLeaveThread);

 printf("leaving %s\n", __FUNCTION__);

 ExitThread((DWORD)0);
}/*CommandThread*/



BOOL SetSerialProperties( HANDLE hSerial, DWORD baudRate, BYTE stopBits, 
       BYTE parity, int timeoutInterval)
{
 DCB dcbSerialParams;
 COMMTIMEOUTS timeouts;

 ZeroMemory(&dcbSerialParams, sizeof(DCB));
 ZeroMemory(&timeouts, sizeof(COMMTIMEOUTS));


 if(FALSE == GetCommState(hSerial, &dcbSerialParams))
 {
  fprintf(stderr, "ERROR : GetCommState , ");
        return FALSE;
    }/*if FALSE == isSuc*/


 
 dcbSerialParams.BaudRate = baudRate;
    dcbSerialParams.ByteSize = 8;
    dcbSerialParams.StopBits = stopBits;
    dcbSerialParams.Parity = parity;

 if(FALSE == SetCommState(hSerial, &dcbSerialParams))
    {
  fprintf(stderr, "Error : setting device parameters , ");
  return FALSE;
    }/*if */


 if(0 == timeoutInterval)
 {
  //return immediately 
  timeouts.ReadIntervalTimeout = MAXDWORD;
  timeouts.ReadTotalTimeoutMultiplier = 0; 
  timeouts.ReadTotalTimeoutConstant = 0; 
 }
 else if( 0 > timeoutInterval || timeoutInterval > MAXBYTE*100*MILLI_SEC ) /*compatible with linux*/
 {
  //block mode 
  timeouts.ReadIntervalTimeout = 0;
  timeouts.ReadTotalTimeoutMultiplier = 0 ; /*timeout for per read*/
  timeouts.ReadTotalTimeoutConstant = 0 ; 
 }
 else
 {
  timeouts.ReadIntervalTimeout = 1; /* time per byte,  milli-sec*/
  timeouts.ReadTotalTimeoutMultiplier = 1; /*timeout for per read*/
  timeouts.ReadTotalTimeoutConstant = (DWORD)timeoutInterval; /*ertra time for read timeout*/
 }/*if timeoutInterval*/
 
 /*WriteTotalTimeoutConstant = WriteTotalTimeoutMultiplier = 0 : write operation is without timeout*/

 timeouts.WriteTotalTimeoutConstant = 0; /*timeout for per write*/
 timeouts.WriteTotalTimeoutMultiplier = 0; /*extra time for write timeout*/
 
 if(FALSE == SetCommTimeouts(hSerial, &timeouts)) 
    {
  fprintf(stderr, "error : setting port state , ");
  return FALSE;
    }/*if */

 return TRUE;
}/*SetSerialProperties*/


BOOL CtrlHandler( DWORD fdwCtrlType ) 
{
 switch( fdwCtrlType ) 
 { 
 // Handle the CTRL-C signal. 
 case CTRL_C_EVENT: 
   printf( "Ctrl-C event\n\n" );
   Beep( 750, 300);
   isLeaveThread = TRUE;
   return( TRUE );
#if(0)
 // CTRL-CLOSE: confirm that the user wants to exit. 
 case CTRL_CLOSE_EVENT: 
   Beep( 600, 200); 
   printf( "Ctrl-Close event\n\n" );
   return( TRUE ); 

 // Pass other signals to the next handler. 
 case CTRL_BREAK_EVENT: 
   Beep( 900, 200); 
   printf( "Ctrl-Break event\n\n" );
   return FALSE; 

 case CTRL_LOGOFF_EVENT: 
   Beep( 1000, 200); 
   printf( "Ctrl-Logoff event\n\n" );
   return FALSE; 

 case CTRL_SHUTDOWN_EVENT: 
   Beep( 750, 500); 
   printf( "Ctrl-Shutdown event\n\n" );
   return FALSE; 
#endif
 default: 
   break;
 }/*switch*/ 

 return FALSE; 
}/*CtrlHandler*/


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

 HANDLE hSerial; 
 BOOL  isSuc;

 char comPortName[MAX_STR_LEN];

 HANDLE hWriteThread, hReadThread;

 isSuc = FALSE;

 sprintf_s(&comPortName[0], MAX_STR_LEN, "\\\\.\\COM14");

 
 

 isLeaveThread = FALSE;

 if( FALSE == SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ) ) 
 { 
  printf("ERROR : SetConsoleCtrlHandler , ");
  goto Flag_CloseSerial;
 }/*if */

 
 
 hSerial = CreateFile(&comPortName[0], GENERIC_READ|GENERIC_WRITE, 0, NULL,
                OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );

 if (hSerial == INVALID_HANDLE_VALUE) 
 {
  printf("ERROR : open %s , ", &comPortName[0]);
  goto Flag_CloseSerial;
 }/*if */

 
 if(FALSE == SetSerialProperties(hSerial, CBR_57600, ONESTOPBIT, NOPARITY, 2000*MILLI_SEC))
  goto Flag_CloseSerial;
 

 InitializeCriticalSection(&UARTThreadCriticalSection);

 hWriteThread = (HANDLE)_beginthreadex(NULL, 0, WriteThread, 
  &hSerial,  0/*or CREATE_SUSPENDED*/, NULL);
 
 if (NULL == hWriteThread) 
 {
  fprintf(stderr, "error : create confirming thread : ");
  goto Flag_CloseSerial;
 }/*if NULL == hConfirmThread*/
 
 hReadThread = (HANDLE)_beginthreadex(NULL, 0, ReadThread, 
  &hSerial,  0/*or CREATE_SUSPENDED*/, NULL);

 if (NULL == hReadThread) 
 {
  fprintf(stderr, "error : create command thread : ");
  goto Flag_CloseSerial;
 }/*if NULL == hConfirmThread*/
 

 if(FALSE == SetThreadPriority(hWriteThread, THREAD_PRIORITY_LOWEST))
 {
  fprintf(stderr, "error :SetThreadPriority : ");
  goto Flag_CloseSerial;
 }/*if*/

 WaitForSingleObject(hWriteThread, INFINITE); 
 WaitForSingleObject(hReadThread, INFINITE); 
 

 DeleteCriticalSection(&UARTThreadCriticalSection); 
 isSuc = TRUE;

Flag_CloseSerial:
 if(FALSE == isSuc) 
  printf("%s\n", GetLastErrorMessage( GetLastError() ));


 isSuc = CloseHandle(hSerial);

 if(FALSE == isSuc) 
 {
  printf("ERROR : close %s , %s\n", &comPortName[0], 
   GetLastErrorMessage( GetLastError()) );
 }/*if FALSE == isSuc*/

 return 0;
}/*main*/


    The key functions are in function SetSerialProperties, which sets baud rate, time out interval and so forth parameters.

Windows Serial Port Programming in C.

标签:winapi   thread   

原文地址:http://blog.csdn.net/u013606170/article/details/45601187

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!