Merge pull request #19 from BenjaminPritchard/win32_examples

initial commit; add win32 example
This commit is contained in:
Valerio De Benedetto 2023-01-23 18:24:58 +01:00 committed by GitHub
commit 9964a63d49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 447 additions and 0 deletions

136
examples/win32/comm.c Normal file
View File

@ -0,0 +1,136 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <windows.h>
UINT WriteToCommPort(HANDLE hComm, uint8_t* data_ptr, int data_length) {
int actual_length;
PurgeComm(hComm, PURGE_RXCLEAR | PURGE_TXCLEAR);
bool Status = WriteFile(hComm, // Handle to the Serialport
data_ptr, // Data to be written to the port
data_length,
&actual_length, // No of bytes written to the port
NULL);
if (!Status)
printf("\nWriteFile() failed with error %d.\n", GetLastError());
if (data_length != actual_length)
printf("\nWriteFile() failed to write all bytes.\n");
return data_length;
}
bool SetLocalBaudRate(HANDLE hComm, DWORD baudrate) {
bool Status;
DCB dcb = {0};
// Setting the Parameters for the SerialPort
// but first grab the current settings
dcb.DCBlength = sizeof(dcb);
Status = GetCommState(hComm, &dcb);
if (!Status)
return false;
dcb.BaudRate = baudrate;
dcb.ByteSize = 8; // ByteSize = 8
dcb.StopBits = ONESTOPBIT; // StopBits = 1
dcb.Parity = NOPARITY; // Parity = None
Status = SetCommState(hComm, &dcb);
return Status;
}
bool InitCommPort(HANDLE* hComm, int PortNumber) {
uint8_t SerialBuffer[2048] = {0};
COMMTIMEOUTS timeouts = {0};
bool Status;
char commName[50] = {0};
int serialPort = 9;
// special syntax needed for comm ports > 10, but syntax also works for comm ports < 10
sprintf_s(commName, sizeof(commName), "\\\\.\\COM%d", PortNumber);
// Open the serial com port
*hComm = CreateFileA(commName,
GENERIC_READ | GENERIC_WRITE, // Read/Write Access
0, // No Sharing, ports cant be shared
NULL, // No Security
OPEN_EXISTING, // Open existing port only
0,
NULL); // Null for Comm Devices
if (*hComm == INVALID_HANDLE_VALUE)
return false;
Status = SetLocalBaudRate(*hComm, 9600);
if (!Status)
return false;
// setup the timeouts for the SerialPort
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-commtimeouts
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
if (!SetCommTimeouts(*hComm, &timeouts))
return false;
Status = PurgeComm(*hComm, PURGE_RXCLEAR | PURGE_TXCLEAR); // clear the buffers before we start
if (!Status)
return false;
return true;
}
bool CloseCommPort(HANDLE* hComm) {
if (hComm != INVALID_HANDLE_VALUE)
CloseHandle(hComm);
else
return false;
return true;
}
int32_t ReadCommPort(HANDLE hComm, uint8_t* buf, uint16_t count, int32_t byte_timeout_ms) {
int TotalBytesRead = 0;
bool Status = false;
bool TimedOut = false;
ULONGLONG StartTime = 0;
uint8_t b;
int tmpByteCount;
StartTime = GetTickCount64();
do {
// read one byte
Status = ReadFile(hComm, &b, 1, &tmpByteCount, NULL);
// can't read from port at all??
if (!Status)
return false;
// put one byte into our buffer
if (tmpByteCount == 1) {
buf[TotalBytesRead++] = b;
}
// did we time out yet??
if (GetTickCount64() - StartTime > byte_timeout_ms) {
TimedOut = true;
break;
}
} while (TotalBytesRead < count);
return TotalBytesRead;
}

12
examples/win32/comm.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <windows.h>
// function prototypes
bool SetLocalBaudRate(HANDLE hComm, DWORD baudrate);
bool InitCommPort(HANDLE* hComm, int PortNumber);
bool CloseCommPort(HANDLE* hComm);
int32_t WriteToCommPort(HANDLE hComm, uint8_t* data_ptr, int data_length);
int32_t ReadCommPort(HANDLE hComm, uint8_t* buf, uint16_t count, int32_t byte_timeout_ms);

View File

@ -0,0 +1,87 @@
/*
* This example application uses the win32 API to read a single modbus
* register from a server.
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <windows.h>
#define NMBS_LITTLE_ENDIAN 1
#include "..\..\nanomodbus.h"
#include "comm.h"
#define NMBS_DEBUG 1
#define RTU_SERVER_ADDRESS 1
HANDLE hComm;
int reg_to_read;
int commPort_In;
void parseCmdLine(int argc, char** argv) {
if (argc > 1) {
commPort_In = atoi(argv[1]);
reg_to_read = atoi(argv[2]);
}
if (reg_to_read == 0 || commPort_In == 0) {
printf("please specify both a comm port and a register to read\n");
exit(0);
}
}
int32_t read_serial(uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg) {
return ReadCommPort(hComm, buf, count, byte_timeout_ms);
}
int32_t write_serial(const uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg) {
return WriteToCommPort(hComm, buf, count);
}
void onError(nmbs_error err) {
printf("error: %d\n", err);
exit(0);
}
void ReadRegister(uint16_t reg) {
nmbs_platform_conf platform_conf;
platform_conf.transport = NMBS_TRANSPORT_RTU;
platform_conf.read = read_serial;
platform_conf.write = write_serial;
nmbs_t nmbs;
nmbs_error err = nmbs_client_create(&nmbs, &platform_conf);
if (err != NMBS_ERROR_NONE)
onError(err);
nmbs_set_read_timeout(&nmbs, 1000);
nmbs_set_byte_timeout(&nmbs, 100);
nmbs_set_destination_rtu_address(&nmbs, RTU_SERVER_ADDRESS);
uint16_t r_regs[2];
err = nmbs_read_holding_registers(&nmbs, reg, 1, r_regs);
if (err != NMBS_ERROR_NONE)
onError(err);
printf("register %d is set to: %d\n", reg, r_regs[0]);
}
int main(int argc, char** argv) {
printf("modbus_cli - CLI to read modbus registers\n");
printf("Usage: modbus_cli comport register\n\n");
parseCmdLine(argc, argv);
if (!InitCommPort(&hComm, commPort_In)) {
printf("error opening output comm port %d\n", commPort_In);
exit(0);
}
ReadRegister(reg_to_read);
}

3
examples/win32/vs2022/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
x64/
Debug/
.vs/

View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.32916.344
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "modbus_cli", "modbus_cli.vcxproj", "{CBA78147-81C5-4DED-B716-F6363421298B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CBA78147-81C5-4DED-B716-F6363421298B}.Debug|x64.ActiveCfg = Debug|x64
{CBA78147-81C5-4DED-B716-F6363421298B}.Debug|x64.Build.0 = Debug|x64
{CBA78147-81C5-4DED-B716-F6363421298B}.Debug|x86.ActiveCfg = Debug|Win32
{CBA78147-81C5-4DED-B716-F6363421298B}.Debug|x86.Build.0 = Debug|Win32
{CBA78147-81C5-4DED-B716-F6363421298B}.Release|x64.ActiveCfg = Release|x64
{CBA78147-81C5-4DED-B716-F6363421298B}.Release|x64.Build.0 = Release|x64
{CBA78147-81C5-4DED-B716-F6363421298B}.Release|x86.ActiveCfg = Release|Win32
{CBA78147-81C5-4DED-B716-F6363421298B}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8835A584-0C6B-42CA-B3F8-0CEAB23D83A7}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\nanomodbus.c" />
<ClCompile Include="..\comm.c" />
<ClCompile Include="..\modbus_cli.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\comm.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{cba78147-81c5-4ded-b716-f6363421298b}</ProjectGuid>
<RootNamespace>modbuscli</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NMBS_BIG_ENDIAN=1WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NMBS_LITTLE_ENDIAN=1;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<UndefineAllPreprocessorDefinitions>false</UndefineAllPreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\comm.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\modbus_cli.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\nanomodbus.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\comm.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>