Click here to Skip to main content
15,880,427 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I need to write a C code for serial communication for sending bytes of data from computer to external device.i am using USB RS232 convertor for transmission. What needs to be taken care of? Can someone give me advice??
Posted
Comments
Jan Bakker 18-Mar-15 6:41am    
Are you using .net ?
I'm using .net 4.5 system.IO in a C# wpf application.
vinod b v 18-Mar-15 9:27am    
@ Jan Bakker, no i am using C language to write it although i am new to serial programming, I am using Codeblocks IDE

The MSDN provides an article about this: SerialCommunications[^]. It is quite old (1995) but still valid.

An overview of serial communication functions can be also found in the MSDN: Communication Functions[^]. You may also read the other pages from the tree on the left.

There are usually no problems using the virtual COM port provided by an USB to RS232 converter.
 
Share this answer
 
Comments
CPallini 18-Mar-15 4:55am    
5.
vinod b v 18-Mar-15 9:09am    
@ Jochen Arndt, i have a question here i am using code blocks IDE console application and when i write this piece of code i am getting error invalid handle
#include<windows.h>

// For opening serial port//
HANDLE hSerial;
hSerial = CreateFile("COM1",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if(hSerial==INVALID_HANDLE_VALUE){
if(GetLastError()==ERROR_FILE_NOT_FOUND){
//serial port does not exist. Inform user.
}
Jochen Arndt 18-Mar-15 9:17am    
COM1 is usually the first serial port of your PC. Because most actual systems did not have a serial port nowadays, it may be not present.

Because you are using an USB to serial converter, you must pass the port provided by the driver of your converter. To check if it is present, open the device manager and select 'Ports'. There you should find an entry like 'USB serial port (COM4)'. Use the port shown there ("COM4" in my example).
vinod b v 18-Mar-15 10:08am    
I found out my system is using COM4, so i have changed it from COM1 to COM4, but still i get that error, and even did give entry like this:
HANDLE hSerial; // VARIABLE IS OF TYPE HANDLE AND INITILIZE WITH CALL TO CREATE FILE//
hSerial = createFile ("USB serial port(COM4)",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if(hSerial==INVALID_HANDLE_VALUE)
{
if(GetLastError()=ERROR_FILE_NOT_FOUND){
printf("//SERIAL PORT DOES NOT EXIST// ");
}
printf("//SOME OTHER ERROR OCCURED.//");
}

// SETTING PARAMETERS//

DCB dcbSerialParams = {0};
dcbSerial.DCBlength=Sizeof(dcbSerialParams);

if
(!GetCommState(hSerial, &dcbSerialParams))
{


// error getting state //
Printf("Error in getting state");
}
//SETTING PARAMETERS//
dcbSerialParams.BaudRate=CBR_9600;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
if(!SetCommState(hSerial, &dcbSerialParams)){
//error setting serial port state
printf("Error");
}

//SETTING TIMEOUTS //

COMMTIMEOUTS timeouts={0};
timeouts.ReadIntervalTimeout=50;
timeouts.ReadTotalTimeoutConstant=50;
timeouts.ReadTotalTimeoutMultiplier=10;
timeouts.WriteTotalTimeoutConstant=50;
timeouts.WriteTotalTimeoutMultiplier=10;
if(!SetCommTimeouts(hSerial, &timeouts)){
//error occureed. Inform user
printf("Error occuring in timeouts");
}

char szBuff[n + 1] = {0};
DWORD dwBytesRead = 0;
if(!ReadFile(hSerial, szBuff, n, &dwBytesRead, NULL)){
//error occurred. Report to user.
printf("Error occured in read/write byte");
}
// Close handle //
CloseHandle(hSerial);
Jochen Arndt 18-Mar-15 10:11am    
You must pass "COM4", not the full descriptive string.
Take a look on the article Win32 SDK Serial Comm Made Easy or Creating a Serial communication on Win32 amd its code. It isnt easy to start until you understand that theses ports are slow, so you and your app must wait for answers. I used than overlapped IO to solve that.
 
Share this answer
 
Comments
CPallini 18-Mar-15 4:55am    
5.
Here's some code from a simple win32 serial-port monitor I hacked-together for use with the Atmel family of micro-controllers, specifically, for use with Arduinos.

I'll leave it to you to extract the parts you want for your own console app. As you can see, I never bothered to implement the Stop button - I just kill then restart the program. (I did say it was hacked-together, remember! :) )

The code was also built using Code::Blocks

EDIT: pay attention to the onStartButton code - just realized I don't actually use the values for speed, stop bits etc - I should be setting these to the DCB.

1. main.cpp
C++
#include <ctype.h>
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "resource.h"

HINSTANCE hInst;


int availRates[] = {300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 38400, 57600, 115200, 230400, 460800, 921600};
int numBits[] = {7,8};
int stopBits[] = {1,2};
const char *parity[] = {"Even", "Odd", "None", "Mark", "Space"};
HWND dlgHwnd;

typedef struct threadData_t
{
    HWND callbackWnd;

};

void initIntCombo(HWND combo, int *dataArray, int numElements)
{
    int i;
    char tmpStr[16];
    for (i=0; i<numElements; i++)
    {
        sprintf(tmpStr, "%d", dataArray[i]);
        SendMessage(combo, CB_ADDSTRING, 0, (LPARAM)tmpStr);
    }
}

void initStrCombo(HWND combo, const char *dataArray[], int numElements)
{
    for (int i=0; i<numElements; i++)
        SendMessage(combo, CB_ADDSTRING, 0, (LPARAM)dataArray[i]);//tmpStr);
}

void initPortCombo(HWND combo)
{
    int curPort;
    char mPortName[16];
    HANDLE hCom;

    for (curPort=1; curPort<=20; curPort++)
    {
        sprintf(mPortName, "\\\\.\\COM%d", curPort);
        hCom = CreateFile(mPortName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
        if (hCom != INVALID_HANDLE_VALUE)
        {
            sprintf(mPortName, "COM%d", curPort);
            CloseHandle(hCom);
            SendMessage(combo, CB_ADDSTRING, 0, (LPARAM)mPortName);
        }
    }
}

void onStartButton()
{
    HWND baudCombo, dataBitsCombo, parityCombo, stopBitsCombo;
    int baud, nBits, stopBits;
    char parityLetter;
    char dcbString[32], dcbStrUsed[32];
    int selectedParityOption;

    baud = GetDlgItemInt(dlgHwnd, IDC_BAUDRATE_COMBO, NULL, true);
    nBits = GetDlgItemInt(dlgHwnd, IDC_DATABITS_COMBO, NULL, true);
    stopBits = GetDlgItemInt(dlgHwnd, IDC_STOPBITS_COMBO, NULL, true);

    selectedParityOption = SendDlgItemMessage(dlgHwnd, IDC_PARITY_COMBO, CB_GETCURSEL, 0, 0);
    parityLetter = tolower(parity[selectedParityOption][0]);

    sprintf(dcbString, "Success\r\n- %d,%c,%d,%d\r\n", baud, parityLetter, nBits, stopBits);
    sprintf(dcbStrUsed, "%d,%c,%d,%d", baud, parityLetter, nBits, stopBits);

    DCB dcb;
    FillMemory(&dcb, sizeof(dcb), 0);
    dcb.DCBlength = sizeof(dcb);
    if (!BuildCommDCB(dcbStrUsed, &dcb))
        SetWindowText(GetDlgItem(dlgHwnd, IDC_EDIT1) , "Failed");
    else
        //SetWindowText(GetDlgItem(dlgHwnd, IDC_EDIT1) , dcbString);
        SendDlgItemMessage(dlgHwnd, IDC_EDIT1, EM_REPLACESEL, true, (LPARAM)dcbString);
}


BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_INITDIALOG:
    {
        dlgHwnd = hwndDlg;
        initPortCombo(GetDlgItem(hwndDlg, IDC_PORTNAME_COMBO));

        initIntCombo(GetDlgItem(hwndDlg, IDC_BAUDRATE_COMBO), availRates, sizeof(availRates) / sizeof(availRates[0]));
        SendMessage(GetDlgItem(hwndDlg, IDC_BAUDRATE_COMBO), CB_SETCURSEL, 7, 0); // set 9600 bps

        initIntCombo(GetDlgItem(hwndDlg, IDC_DATABITS_COMBO), numBits, sizeof(numBits) / sizeof(numBits[0]));
        SendMessage(GetDlgItem(hwndDlg, IDC_DATABITS_COMBO), CB_SETCURSEL, 1, 0); // set 8 data bits

        initIntCombo(GetDlgItem(hwndDlg, IDC_STOPBITS_COMBO), stopBits, sizeof(stopBits) / sizeof(stopBits[0]));
        SendMessage(GetDlgItem(hwndDlg, IDC_STOPBITS_COMBO), CB_SETCURSEL, 0, 0); // set 1 stop bit

        initStrCombo(GetDlgItem(hwndDlg, IDC_PARITY_COMBO), parity, sizeof(parity) / sizeof(parity[0]));
        SendMessage(GetDlgItem(hwndDlg, IDC_PARITY_COMBO), CB_SETCURSEL, 2, 0); // set 9600 bps
    }
    return TRUE;

    case WM_CLOSE:
    {
        EndDialog(hwndDlg, 0);
    }
    return TRUE;

    case WM_DEVICECHANGE:
        SendDlgItemMessage(hwndDlg, IDC_PORTNAME_COMBO, CB_RESETCONTENT, 0, 0);
        initPortCombo(GetDlgItem(hwndDlg, IDC_PORTNAME_COMBO));
        break;

    case WM_COMMAND:
    {
        switch(LOWORD(wParam))
        {
            case IDC_BUTTON1:
                onStartButton();
                break;
            case IDC_BUTTON3:
                SetDlgItemText(hwndDlg, IDC_EDIT1, "");
                break;
        }
    }
    return TRUE;
    }
    return FALSE;
}


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    hInst=hInstance;
    InitCommonControls();
    return DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain);
}



2. resource.h
C++
#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif

#define DLG_MAIN                                100
#define IDC_BUTTON3                             1000
#define IDC_DATABITS_COMBO                      1007
#define IDC_PORTNAME_COMBO                      1008
#define IDC_BAUDRATE_COMBO                      1009
#define IDC_PARITY_COMBO                        1010
#define IDC_STOPBITS_COMBO                      1011
#define IDC_BUTTON1                             1012
#define IDC_BUTTON2                             1013
#define IDC_EDIT1                               1014


3. resource.rc
C++
// Generated by ResEdit 1.5.8
// Copyright (C) 2006-2011
// http://www.resedit.net

#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"

//
// Dialog resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
DLG_MAIN DIALOG 0, 0, 369, 303
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION "Serial Monitor v0.01"
FONT 8, "Ms Shell Dlg"
{
    GROUPBOX        "Serial Port settings", IDC_STATIC, 15, 14, 166, 116
    LTEXT           "Port Name", IDC_STATIC, 36, 29, 34, 8, SS_LEFT
    LTEXT           "Baud Rate", IDC_STATIC, 35, 48, 35, 8, SS_LEFT
    LTEXT           "Data Bits", IDC_STATIC, 40, 67, 30, 8, SS_LEFT
    LTEXT           "Parity", IDC_STATIC, 52, 88, 18, 8, SS_LEFT
    LTEXT           "Stop Bits", IDC_STATIC, 41, 107, 29, 8, SS_LEFT
    COMBOBOX        IDC_PORTNAME_COMBO, 93, 27, 75, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS
    COMBOBOX        IDC_BAUDRATE_COMBO, 93, 46, 75, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS
    COMBOBOX        IDC_DATABITS_COMBO, 93, 65, 75, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS
    COMBOBOX        IDC_PARITY_COMBO, 93, 86, 75, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS
    COMBOBOX        IDC_STOPBITS_COMBO, 93, 105, 75, 31, CBS_DROPDOWNLIST | CBS_HASSTRINGS
    PUSHBUTTON      "Start Listening", IDC_BUTTON1, 213, 30, 57, 14
    PUSHBUTTON      "Stop Listening", IDC_BUTTON2, 213, 48, 57, 14
    GROUPBOX        "Actions", IDC_STATIC, 196, 14, 158, 116
    EDITTEXT        IDC_EDIT1, 15, 143, 340, 147, ES_AUTOVSCROLL | ES_MULTILINE | ES_WANTRETURN
    PUSHBUTTON      "Clear", IDC_BUTTON3, 214, 66, 57, 14
}
 
Share this answer
 
v5

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900