Windows Serial Port Programming in C.

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.

时间: 2024-08-13 11:59:33

Windows Serial Port Programming in C.的相关文章

Serial Port Programming on Linux(转载)

This is a tutorial on how to program the Serial Ports on your Linux box.Serial Ports are nice little interfaces on the PC which helps you to interface your embedded system projects using a minimum number of wires.In this tutorial we will write a smal

Serial Port Programming using Win32 API(转载)

In this tutorial we will learn How to communicate with an external device like a microcontroller board or modem using the Serial port of a windows PC(Windows XP,7). The software is written using C language and communicates with the Serial Port using 

Python windows serial

Python windows serial 一.参考文章: Serial port programming http://www.cnblogs.com/2zhyi/p/3405339.html python pyserial 2.7 https://pypi.python.org/pypi/pyserial 串口通讯的python模块——pySerial http://blog.csdn.net/dainiao01/article/details/5885122 Welcome to pySe

串口总是报&#39;Error opening serial port&#39;

Comm1.CommName := '//./' + Trim(combx_Port.Text); 目前串口大于20  用上面方法解决的 网上也有上面方法解决如下错误的. 若是您已会应用SPCOMM且涌现10个以上的串心题目 请改一下串心名 COM1.CommName='//./com18'; 便如许减'//./'就好了我也没有晓得甚么回事....... 比方 Comm1.CommName := '//./'+ComboBox1.Text; //./com18是win] 如果你已经会使用SPCO

select/poll/epoll on serial port

In this article, I will use three asynchronous conferencing--select, poll and epoll on serial port to transmit data between PC and Raspberry pi. Outline Character device file of serial port Naive serial communication Asynchronous conferencing Select

Unable to open serial port /dev/ttyUSB0

ubuntu12.04使用USB转串口时出现权限不够问题,如下 权限不够 解决办法: 通过增加udev规则来实现.步骤如下:创建文件/etc/udev/rules.d/70-ttyusb.rules在文件内增加一行KERNEL=="ttyUSB[0-9]*", MODE="0666"重新插入USB转串口设备,普通用户就有权限访问了. 70-ttyusb.rules文件还有另一种写法,先用lsusb查看USB转串口芯片的idVendor和idProduct#lsusb

Android 操作串口 (android serial port api)

前几天公司有通过搭载Android系统的开发板来使用打卡机统计数据的需求,对于攻城狮来说就需要在Android平台上读写打卡机的串口,在网上搜索一些东西之后发现了在google code 上的android serial port api可以用,墙了之后拿到源码发现还有demo,不错不错,我这个帖子就通过serial port api的源码简单得实现一个读写串口,这个当然是在native写的,如果还有哪些童鞋不清楚android上使用jni和native的话可以跳转到我的上篇帖子 点我点我 在A

Non-standard serial port baud rate setting

////combuad_recv.cpp #include <stdio.h> /*标准输入输出定义*/ #include <stdlib.h> /*标准函数库定义*/ #include <unistd.h> /*Unix 标准函数定义*/ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> /*文件控制定义*/ #include <termios.h&

windows系统port监听

通常情况下.假设想发现全部已经使用的和正在监听的port,我们能够使用netstat命令. netstat并不是一个port扫描工具.假设你想扫描计算机开放了哪些port的话.建议使用本文介绍的方法. Netstat命令基础 Netstat命令主要用于显示协议统计信息和当前 TCP/IP 网络连接. 其格式例如以下: NETSTAT [-a] [-b] [-e] [-n] [-o] [-p proto] [-r] [-s] [-v] [interval] 以下简单说明各个參数的含义: -a 显示