Compare commits

...

3 Commits

4
.gitignore vendored

@ -1 +1,5 @@
Project/Objects
Window Tool/TimeSet/.vs/TimeSet/v15/ipch
*.db
*.zip
Window Tool/TimeSet/TimeSet/Debug

File diff suppressed because one or more lines are too long

@ -148,24 +148,7 @@
<Name>UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN2 -FF0A31G12x_series_FLASH -FS00 -FL010000 -FF1A31G12x_series_CFG -FS11FFFF200 -FL1600 -FP0($$Device:A31G123$A31G12x\Flashloader\A31G12x_series_FLASH.FLM) -FP1($$Device:A31G123$A31G12x\Flashloader\A31G12x_series_CFG.FLM))</Name>
</SetRegEntry>
</TargetDriverDllRegistry>
<Breakpoint>
<Bp>
<Number>0</Number>
<Type>0</Type>
<LineNumber>403</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>2750</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount>
<Filename>.\Application\action_process.c</Filename>
<ExecCommand></ExecCommand>
<Expression>\\S_DustSensorView\Application/action_process.c\403</Expression>
</Bp>
</Breakpoint>
<Breakpoint/>
<WatchWindow1>
<Ww>
<count>0</count>

@ -11,9 +11,6 @@
#include "rtc_process.h"
#include "save_file.h"
#define KEY_POWER KEY_PUSH_SW1
#define KEY_MODE_SET KEY_PUSH_SW2
#define KEY_UP KEY_PUSH_SW3
@ -30,16 +27,11 @@ typedef enum _control_step
CONTROL_STEP_INIT_POWER_ON_KEY_SET,
CONTROL_STEP_INIT_COMPLETE,
CONTROL_STEP_ACTION_IDLE,
CONTROL_STEP_ACTION_RUN_NOW_SENSOR_DATA,
CONTROL_STEP_ACTION_RUN_MAX_SENSOR_DATA,
CONTROL_STEP_ACTION_RUN_MIN_SENSOR_DATA,
CONTROL_STEP_ACTION_RUN_SET_MAX_SENSOR_DATA,
CONTROL_STEP_ACTION_RUN_SET_MIN_SENSOR_DATA,
CONTROL_STEP_ACTION_RUN_COMPLETE,
}CONTROL_STEP;
@ -48,18 +40,19 @@ typedef struct _control_info
{
bool isInitView;
bool isActionRun;
bool isRelayOn;
CONTROL_STEP Step;
uint32_t StartTickCount;
uint32_t GetSensorDataTickCount;
uint32_t returnMainViewTickCount;
uint16_t Co2_Now;
uint16_t Co2_SaveData;
uint16_t Co2_MaxValue;
uint16_t Co2_MinValue;
uint16_t Co2_TempValue;
SET_INDEX SetIndex;
uint16_t Co2_TempMax;
uint16_t Co2_TempMin;
}CONTROL_INFO;
@ -72,41 +65,28 @@ uint16_t SaveSensorCo2[100];
static CONTROL_INFO Control_Info;
static void Action_Process(void);
static void Action_PowerOn_Init_Process(void);
static void Action_PowerOn_Process(void);
static void Action_Get_SensorData(void);
static void Action_Get_SensorReadProcess(void);
static void Action_SaveSensorData(void);
static void Action_Power_On_Key_Set(void);
static void Action_Power_On_Key_Push_Callback(void);
static void Action_Power_Off_Key_Set(void);
static void Action_Power_Off_Key_Push_Callback(void);
static void Action_Mode_Key_Push(void);
static void Action_Set_Key_Push(void);
static void Action_Up_Key_Push(void);
static void Action_Down_Key_Push(void);
static void Action_ReturnMainViewCheck(void);
static void Action_Relay_Output_Check(void);
static void Action_RelayOn(void);
static void Action_RelayOff(void);
#if 0
static void Action_PowerKey_Push(void);
static void Action_PowerKey_LongPush(void);
static void Action_Sensor_Read_Process(void);
#endif
void Action_Initialization(void)
{
@ -200,8 +180,11 @@ static void Action_PowerOn_Process(void)
Gpio_Led_OutputSet(GPIO_LED_D1, GPIO_LED_MODE_OFF, 0, 0);
Gpio_Led_OutputSet(GPIO_LED_D2, GPIO_LED_MODE_ON, 0, 0);
Gpio_Led_OutputSet(GPIO_LED_D3, GPIO_LED_MODE_OFF, 0, 0);
Action_RelayOff();
GPIO_SENSOR_PWR_ON;
SaveCheckSec = 0xFF;
Control_Info.Co2_Now = 0xFFFF;
Control_Info.Co2_SaveData = 0xFFFF;
Action_Get_SensorData();
if(EEPROM_Read_SettingValue(&Control_Info.Co2_MaxValue, &Control_Info.Co2_MinValue) == false)
{
@ -212,7 +195,7 @@ static void Action_PowerOn_Process(void)
Control_Info.Co2_TempMax = 0;
Control_Info.Co2_TempMin = 0xFFFF;
printf("Data, Time, Average(Now)_Co2, Max_Co2, Min_Co2\r\n");
printf("Data, Time, Average(Now)_Co2, Max_Co2, Min_Co2, Relay\r\n");
Control_Info.Step = CONTROL_STEP_ACTION_RUN_NOW_SENSOR_DATA;
break;
case CONTROL_STEP_ACTION_RUN_NOW_SENSOR_DATA:
@ -242,6 +225,7 @@ static void Action_PowerOn_Process(void)
GPIO_SENSOR_PWR_OFF;
Action_Power_On_Key_Set();
Segment_All_Set_Data(0x00);
Action_RelayOff();
EEPROM_Write_SettingValue(Control_Info.Co2_MaxValue, Control_Info.Co2_MinValue);
Control_Info.Step = CONTROL_STEP_ACTION_IDLE;
Control_Info.isActionRun = false;
@ -287,6 +271,7 @@ static void Action_Get_SensorData(void)
KCD_HP100_Tx_Get_MeasurmentData();
}
static void Action_Get_SensorReadProcess(void)
{
KCD_HP100_STATE nowSensorState = KCD_HP100_GetState();
@ -294,6 +279,16 @@ static void Action_Get_SensorReadProcess(void)
if(nowSensorState == KCD_HP100_SUCCESS)
{
KCD_HP100_Get_Co2((uint16_t *)&Control_Info.Co2_Now);
Control_Info.Co2_SaveData = Control_Info.Co2_Now;
if(Control_Info.Co2_Now >= Control_Info.Co2_MaxValue)
{
Action_RelayOff();
}
else if(Control_Info.Co2_Now <= Control_Info.Co2_MinValue)
{
Action_RelayOn();
}
}
else if(nowSensorState == KCD_HP100_ERROR_TIMEOUT)
{
@ -313,7 +308,7 @@ static void Action_Get_SensorReadProcess(void)
if(Control_Info.Co2_TempMin > Control_Info.Co2_Now)
Control_Info.Co2_TempMin = Control_Info.Co2_Now;
printf("Now, %04d-%02d-%02d %02d:%02d:%02d, %d, %d, %d\r\n", nowTime.rtc_Year, nowTime.rtc_Month, nowTime.rtc_Date, nowTime.rtc_Hour, nowTime.rtc_Min, nowTime.rtc_Sec, Control_Info.Co2_Now, Control_Info.Co2_TempMax, Control_Info.Co2_TempMin);
printf("Now, %04d-%02d-%02d %02d:%02d:%02d, %d, %d, %d, %d\r\n", nowTime.rtc_Year, nowTime.rtc_Month, nowTime.rtc_Date, nowTime.rtc_Hour, nowTime.rtc_Min, nowTime.rtc_Sec, Control_Info.Co2_Now, Control_Info.Co2_TempMax, Control_Info.Co2_TempMin, Control_Info.isRelayOn);
}
Action_Get_SensorData();
@ -331,12 +326,10 @@ static void Action_SaveSensorData(void)
SaveCheckSec = nowTime.rtc_Sec;
if(nowTime.rtc_Sec == 0)
{
if(Control_Info.Co2_Now != 0xFFFF){
SaveSensorCo2[SaveSensorIndex++] = Control_Info.Co2_Now;
if(Control_Info.Co2_SaveData != 0xFFFF){
SaveSensorCo2[SaveSensorIndex++] = Control_Info.Co2_SaveData;
}
if(nowTime.rtc_Min % 5 == 0)
{
if(SaveSensorIndex >= 5)
@ -364,10 +357,14 @@ static void Action_SaveSensorData(void)
Sum_Co2 -= Max_Co2;
Sum_Co2 -= Min_Co2;
Sum_Co2 /= (SaveSensorIndex - 2);
printf("Save, %04d-%02d-%02d %02d:%02d:%02d, %d, %d, %d\r\n", nowTime.rtc_Year, nowTime.rtc_Month, nowTime.rtc_Date, nowTime.rtc_Hour, nowTime.rtc_Min, nowTime.rtc_Sec, Sum_Co2, Max_Co2, Min_Co2);
if(Save_SensorData_SDCard(Sum_Co2, Max_Co2, Min_Co2, 0xFF) == false)
{
if(Save_SensorData_SDCard(Sum_Co2, Max_Co2, Min_Co2, Control_Info.isRelayOn ? 0xFF : 0x00) == false)
{
printf("Save fail, %04d-%02d-%02d %02d:%02d:%02d, %d, %d, %d, %d\r\n", nowTime.rtc_Year, nowTime.rtc_Month, nowTime.rtc_Date, nowTime.rtc_Hour, nowTime.rtc_Min, nowTime.rtc_Sec, Sum_Co2, Max_Co2, Min_Co2, Control_Info.isRelayOn);
}
else
{
printf("Save, %04d-%02d-%02d %02d:%02d:%02d, %d, %d, %d, %d\r\n", nowTime.rtc_Year, nowTime.rtc_Month, nowTime.rtc_Date, nowTime.rtc_Hour, nowTime.rtc_Min, nowTime.rtc_Sec, Sum_Co2, Max_Co2, Min_Co2, Control_Info.isRelayOn);
}
}
SaveSensorIndex = 0;
@ -381,10 +378,8 @@ static void Action_SaveSensorData(void)
static void Action_ReturnMainViewCheck(void)
{
if(Control_Info.Step != CONTROL_STEP_ACTION_RUN_NOW_SENSOR_DATA)
{
if(millis() - Control_Info.returnMainViewTickCount >= ACTION_RETURN_MAINVIEW_TIME)
{
if(Control_Info.Step != CONTROL_STEP_ACTION_RUN_NOW_SENSOR_DATA){
if(millis() - Control_Info.returnMainViewTickCount >= ACTION_RETURN_MAINVIEW_TIME){
Gpio_Led_OutputSet(GPIO_LED_D1, GPIO_LED_MODE_OFF, 0, 0);
Gpio_Led_OutputSet(GPIO_LED_D2, GPIO_LED_MODE_ON, 0, 0);
Gpio_Led_OutputSet(GPIO_LED_D3, GPIO_LED_MODE_OFF, 0, 0);
@ -394,9 +389,30 @@ static void Action_ReturnMainViewCheck(void)
}
}
static void Action_RelayOn(void)
{
if(Control_Info.isRelayOn == false){
Control_Info.isRelayOn = true;
Gpio_Led_OutputSet(GPIO_LED_D4, GPIO_LED_MODE_ON, 0, 0);
GPIO_RELAY_ON;
}
}
static void Action_RelayOff(void)
{
if(Control_Info.isRelayOn == true){
Control_Info.isRelayOn = false;
Gpio_Led_OutputSet(GPIO_LED_D4, GPIO_LED_MODE_OFF, 0, 0);
GPIO_RELAY_OFF;
}
}
void Action_Set_MaxMin_Value(uint16_t MaxValue, uint16_t MinValue)
{
Control_Info.Co2_MaxValue = MaxValue;
Control_Info.Co2_MinValue = MinValue;
EEPROM_Write_SettingValue(Control_Info.Co2_MaxValue, Control_Info.Co2_MinValue);
}
@ -456,7 +472,6 @@ static void Action_Set_Key_Push(void)
Control_Info.Step = CONTROL_STEP_ACTION_RUN_SET_MAX_SENSOR_DATA;
}
else if(Control_Info.Step == CONTROL_STEP_ACTION_RUN_MIN_SENSOR_DATA){
Buzzer_On(DEFAULT_KEY_PUSH_BUZZER_TIME_COUNT);
Control_Info.Co2_TempValue = Control_Info.Co2_MinValue;
Control_Info.SetIndex = SET_1000;

@ -18,7 +18,7 @@ typedef enum
void Action_Initialization(void);
void Action_Set_MaxMin_Value(uint16_t MaxValue, uint16_t MinValue);

@ -8,3 +8,9 @@ void Gpio_Sensor_PWR_Initialization(void)
GPIO_SENSOR_PWR_OFF;
}
void Gpio_Relay_Initialization(void)
{
HAL_GPIO_ConfigOutput(GPIO_RELAY_PORT, GPIO_RELAY_PIN_NUM, PUSH_PULL_OUTPUT);
HAL_GPIO_ConfigPullup(GPIO_RELAY_PORT, GPIO_RELAY_PIN_NUM, PUPDx_EnablePU);
GPIO_RELAY_OFF;
}

@ -11,8 +11,17 @@
#define GPIO_SENSOR_PWR_OFF HAL_GPIO_ClearPin(GPIO_SENSOR_PWR_PORT, _BIT(GPIO_SENSOR_PWR_PIN_NUM))
#define GPIO_SENSOR_PWR_T HAL_GPIO_TogglePin(GPIO_SENSOR_PWR_PORT, _BIT(GPIO_SENSOR_PWR_PIN_NUM))
void Gpio_Sensor_PWR_Initialization(void);
#define GPIO_RELAY_PORT (Pn_Type*)PD
#define GPIO_RELAY_PIN_NUM 5
#define GPIO_RELAY_ON HAL_GPIO_SetPin(GPIO_RELAY_PORT, _BIT(GPIO_RELAY_PIN_NUM))
#define GPIO_RELAY_OFF HAL_GPIO_ClearPin(GPIO_RELAY_PORT, _BIT(GPIO_RELAY_PIN_NUM))
#define GPIO_RELAY_T HAL_GPIO_TogglePin(GPIO_RELAY_PORT, _BIT(GPIO_RELAY_PIN_NUM))
void Gpio_Sensor_PWR_Initialization(void);
void Gpio_Relay_Initialization(void);
#endif

@ -22,7 +22,7 @@
void timer_test(void)
{
// GPIO_RELAY_T;
}
@ -45,6 +45,7 @@ int main(void)
Buzzer_Initialization();
Gpio_Sensor_PWR_Initialization();
Gpio_Relay_Initialization();
Gpio_Switch_Port_Initialization();
Gpio_StateLed_Initialization();
@ -61,7 +62,7 @@ int main(void)
__enable_irq();
//SW_Timer_Callback_Register(SW_TIMER_RUN_CONTINUE, 1000, timer_test);
//SW_Timer_Callback_Register(SW_TIMER_RUN_CONTINUE, 100, timer_test);
while(true)

@ -3,6 +3,7 @@
#include "uart1.h"
#include "driver_ds3231_basic.h"
#include "buzzer.h"
#include "action_process.h"
#define PACKET_BUFF_SIZE 100
@ -125,6 +126,22 @@ static void Uart_Packet_Process(uint8_t* pRxBuff)
Buzzer_On(100);
}
else if(cmd == UART_CMD_SET_THRESHOLD && DataLen == 4)
{
uint16_t Max_Threshold;
uint16_t Min_Threshold;
uint8_t index = 0;
Max_Threshold = pRxBuff[PACK_INDEX_DATA + index++] << 8;
Max_Threshold += pRxBuff[PACK_INDEX_DATA + index++];
Min_Threshold = pRxBuff[PACK_INDEX_DATA + index++] << 8;
Min_Threshold += pRxBuff[PACK_INDEX_DATA + index++];
Action_Set_MaxMin_Value(Max_Threshold, Min_Threshold);
Buzzer_On(100);
}

@ -21,7 +21,8 @@ typedef enum
typedef enum
{
UART_CMD_SET_TIME = 0x00,
UART_CMD_SET_TIME = 0x00,
UART_CMD_SET_THRESHOLD = 0x01,
UART_CMD_MAX,
}UART_CMD;

File diff suppressed because it is too large Load Diff

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.1401
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TimeSet", "TimeSet\TimeSet.vcxproj", "{12662F45-5722-45B9-8C02-2863C436C1F6}"
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
{12662F45-5722-45B9-8C02-2863C436C1F6}.Debug|x64.ActiveCfg = Debug|x64
{12662F45-5722-45B9-8C02-2863C436C1F6}.Debug|x64.Build.0 = Debug|x64
{12662F45-5722-45B9-8C02-2863C436C1F6}.Debug|x86.ActiveCfg = Debug|Win32
{12662F45-5722-45B9-8C02-2863C436C1F6}.Debug|x86.Build.0 = Debug|Win32
{12662F45-5722-45B9-8C02-2863C436C1F6}.Release|x64.ActiveCfg = Release|x64
{12662F45-5722-45B9-8C02-2863C436C1F6}.Release|x64.Build.0 = Release|x64
{12662F45-5722-45B9-8C02-2863C436C1F6}.Release|x86.ActiveCfg = Release|Win32
{12662F45-5722-45B9-8C02-2863C436C1F6}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A2480CF4-9A89-4EA6-9387-EA6A5BBCAD06}
EndGlobalSection
EndGlobal

File diff suppressed because it is too large Load Diff

@ -0,0 +1,367 @@
// Serial.h - Definition of the CSerial class
//
// Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifndef __SERIAL_H
#define __SERIAL_H
//////////////////////////////////////////////////////////////////////
// The SERIAL_DEFAULT_OVERLAPPED defines if the default open mode uses
// overlapped I/O. When overlapped I/O is available (normal Win32
// platforms) it uses overlapped I/O. Windows CE doesn't allow the use
// of overlapped I/O, so it is disabled there by default.
#ifndef SERIAL_DEFAULT_OVERLAPPED
#ifndef SERIAL_NO_OVERLAPPED
#define SERIAL_DEFAULT_OVERLAPPED true
#else
#define SERIAL_DEFAULT_OVERLAPPED false
#endif
#endif
//////////////////////////////////////////////////////////////////////
//
// CSerial - Win32 wrapper for serial communications
//
// Serial communication often causes a lot of problems. This class
// tries to supply an easy to use interface to deal with serial
// devices.
//
// The class is actually pretty ease to use. You only need to open
// the COM-port, where you need to specify the basic serial
// communication parameters. You can also choose to setup handshaking
// and read timeout behaviour.
//
// The following serial classes are available:
//
// CSerial - Serial communication support.
// CSerialEx - Serial communication with listener thread for events
// CSerialSync - Serial communication with synchronized event handler
// CSerialWnd - Asynchronous serial support, which uses the Win32
// message queue for event notification.
// CSerialMFC - Preferred class to use in MFC-based GUI windows.
//
//
// Pros:
// -----
// - Easy to use (hides a lot of nasty Win32 stuff)
// - Fully ANSI and Unicode aware
//
// Cons:
// -----
// - Little less flexibility then native Win32 API, however you can
// use this API at the same time for features which are missing
// from this class.
// - Incompatible with Windows 95 or Windows NT v3.51 (or earlier),
// because CancelIo isn't support on these platforms. Define the
// SERIAL_NO_CANCELIO macro for support of these platforms as
// well. When this macro is defined, then only time-out values of
// 0 or INFINITE are valid.
//
//
// Copyright (C) 1999-2003 Ramon de Klein
// (Ramon.de.Klein@ict.nl)
class CSerial
{
// Class enumerations
public:
// Communication event
typedef enum
{
EEventUnknown = -1, // Unknown event
EEventNone = 0, // Event trigged without cause
EEventBreak = EV_BREAK, // A break was detected on input
EEventCTS = EV_CTS, // The CTS signal changed state
EEventDSR = EV_DSR, // The DSR signal changed state
EEventError = EV_ERR, // A line-status error occurred
EEventRing = EV_RING, // A ring indicator was detected
EEventRLSD = EV_RLSD, // The RLSD signal changed state
EEventRecv = EV_RXCHAR, // Data is received on input
EEventRcvEv = EV_RXFLAG, // Event character was received on input
EEventSend = EV_TXEMPTY, // Last character on output was sent
EEventPrinterError = EV_PERR, // Printer error occured
EEventRx80Full = EV_RX80FULL, // Receive buffer is 80 percent full
EEventProviderEvt1 = EV_EVENT1, // Provider specific event 1
EEventProviderEvt2 = EV_EVENT2, // Provider specific event 2
}
EEvent;
// Baudrate
typedef enum
{
EBaudUnknown = -1, // Unknown
EBaud110 = CBR_110, // 110 bits/sec
EBaud300 = CBR_300, // 300 bits/sec
EBaud600 = CBR_600, // 600 bits/sec
EBaud1200 = CBR_1200, // 1200 bits/sec
EBaud2400 = CBR_2400, // 2400 bits/sec
EBaud4800 = CBR_4800, // 4800 bits/sec
EBaud9600 = CBR_9600, // 9600 bits/sec
EBaud14400 = CBR_14400, // 14400 bits/sec
EBaud19200 = CBR_19200, // 19200 bits/sec (default)
EBaud38400 = CBR_38400, // 38400 bits/sec
EBaud56000 = CBR_56000, // 56000 bits/sec
EBaud57600 = CBR_57600, // 57600 bits/sec
EBaud115200 = CBR_115200, // 115200 bits/sec
EBaud128000 = CBR_128000, // 128000 bits/sec
EBaud256000 = CBR_256000, // 256000 bits/sec
}
EBaudrate;
// Data bits (5-8)
typedef enum
{
EDataUnknown = -1, // Unknown
EData5 = 5, // 5 bits per byte
EData6 = 6, // 6 bits per byte
EData7 = 7, // 7 bits per byte
EData8 = 8 // 8 bits per byte (default)
}
EDataBits;
// Parity scheme
typedef enum
{
EParUnknown = -1, // Unknown
EParNone = NOPARITY, // No parity (default)
EParOdd = ODDPARITY, // Odd parity
EParEven = EVENPARITY, // Even parity
EParMark = MARKPARITY, // Mark parity
EParSpace = SPACEPARITY // Space parity
}
EParity;
// Stop bits
typedef enum
{
EStopUnknown = -1, // Unknown
EStop1 = ONESTOPBIT, // 1 stopbit (default)
EStop1_5 = ONE5STOPBITS,// 1.5 stopbit
EStop2 = TWOSTOPBITS // 2 stopbits
}
EStopBits;
// Handshaking
typedef enum
{
EHandshakeUnknown = -1, // Unknown
EHandshakeOff = 0, // No handshaking
EHandshakeHardware = 1, // Hardware handshaking (RTS/CTS)
EHandshakeSoftware = 2 // Software handshaking (XON/XOFF)
}
EHandshake;
// Timeout settings
typedef enum
{
EReadTimeoutUnknown = -1, // Unknown
EReadTimeoutNonblocking = 0, // Always return immediately
EReadTimeoutBlocking = 1 // Block until everything is retrieved
}
EReadTimeout;
// Communication errors
typedef enum
{
EErrorUnknown = 0, // Unknown
EErrorBreak = CE_BREAK, // Break condition detected
EErrorFrame = CE_FRAME, // Framing error
EErrorIOE = CE_IOE, // I/O device error
EErrorMode = CE_MODE, // Unsupported mode
EErrorOverrun = CE_OVERRUN, // Character buffer overrun, next byte is lost
EErrorRxOver = CE_RXOVER, // Input buffer overflow, byte lost
EErrorParity = CE_RXPARITY,// Input parity error
EErrorTxFull = CE_TXFULL // Output buffer full
}
EError;
// Port availability
typedef enum
{
EPortUnknownError = -1, // Unknown error occurred
EPortAvailable = 0, // Port is available
EPortNotAvailable = 1, // Port is not present
EPortInUse = 2 // Port is in use
}
EPort;
// Construction
public:
CSerial();
virtual ~CSerial();
// Operations
public:
// Check if particular COM-port is available (static method).
static EPort CheckPort (LPCTSTR lpszDevice);
// Open the serial communications for a particular COM port. You
// need to use the full devicename (i.e. "COM1") to open the port.
// It's possible to specify the size of the input/output queues.
virtual LONG Open (LPCTSTR lpszDevice, DWORD dwInQueue = 0, DWORD dwOutQueue = 0, bool fOverlapped = SERIAL_DEFAULT_OVERLAPPED);
// Close the serial port.
virtual LONG Close (void);
// Setup the communication settings such as baudrate, databits,
// parity and stopbits. The default settings are applied when the
// device has been opened. Call this function if these settings do
// not apply for your application. If you prefer to use integers
// instead of the enumerated types then just cast the integer to
// the required type. So the following two initializations are
// equivalent:
//
// Setup(EBaud9600,EData8,EParNone,EStop1)
//
// or
//
// Setup(EBaudrate(9600),EDataBits(8),EParity(NOPARITY),EStopBits(ONESTOPBIT))
//
// In the latter case, the types are not validated. So make sure
// that you specify the appropriate values.
virtual LONG Setup (EBaudrate eBaudrate = EBaud9600,
EDataBits eDataBits = EData8,
EParity eParity = EParNone,
EStopBits eStopBits = EStop1);
// Set/clear the event character. When this byte is being received
// on the serial port then the EEventRcvEv event is signalled,
// when the mask has been set appropriately. If the fAdjustMask flag
// has been set, then the event mask is automatically adjusted.
virtual LONG SetEventChar (BYTE bEventChar, bool fAdjustMask = true);
// Set the event mask, which indicates what events should be
// monitored. The WaitEvent method can only monitor events that
// have been enabled. The default setting only monitors the
// error events and data events. An application may choose to
// monitor CTS. DSR, RLSD, etc as well.
virtual LONG SetMask (DWORD dwMask = EEventBreak|EEventError|EEventRecv);
// The WaitEvent method waits for one of the events that are
// enabled (see SetMask).
virtual LONG WaitEvent (LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);
// Setup the handshaking protocol. There are three forms of
// handshaking:
//
// 1) No handshaking, so data is always send even if the receiver
// cannot handle the data anymore. This can lead to data loss,
// when the sender is able to transmit data faster then the
// receiver can handle.
// 2) Hardware handshaking, where the RTS/CTS lines are used to
// indicate if data can be sent. This mode requires that both
// ports and the cable support hardware handshaking. Hardware
// handshaking is the most reliable and efficient form of
// handshaking available, but is hardware dependant.
// 3) Software handshaking, where the XON/XOFF characters are used
// to throttle the data. A major drawback of this method is that
// these characters cannot be used for data anymore.
virtual LONG SetupHandshaking (EHandshake eHandshake);
// Read operations can be blocking or non-blocking. You can use
// this method to setup wether to use blocking or non-blocking
// reads. Non-blocking reads is the default, which is required
// for most applications.
//
// 1) Blocking reads, which will cause the 'Read' method to block
// until the requested number of bytes have been read. This is
// useful if you know how many data you will receive.
// 2) Non-blocking reads, which will read as many bytes into your
// buffer and returns almost immediately. This is often the
// preferred setting.
virtual LONG SetupReadTimeouts (EReadTimeout eReadTimeout);
// Obtain communication settings
virtual EBaudrate GetBaudrate (void);
virtual EDataBits GetDataBits (void);
virtual EParity GetParity (void);
virtual EStopBits GetStopBits (void);
virtual EHandshake GetHandshaking (void);
virtual DWORD GetEventMask (void);
virtual BYTE GetEventChar (void);
// Write data to the serial port. Note that we are only able to
// send ANSI strings, because it probably doesn't make sense to
// transmit Unicode strings to an application.
virtual LONG Write (const void* pData, size_t iLen, DWORD* pdwWritten = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);
virtual LONG Write (LPCSTR pString, DWORD* pdwWritten = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);
// Read data from the serial port. Refer to the description of
// the 'SetupReadTimeouts' for an explanation about (non) blocking
// reads and how to use this.
virtual LONG Read (void* pData, size_t iLen, DWORD* pdwRead = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);
// Send a break
LONG Break (void);
// Determine what caused the event to trigger
EEvent GetEventType (void);
// Obtain the error
EError GetError (void);
// Obtain the COMM and event handle
HANDLE GetCommHandle (void) { return m_hFile; }
// Check if com-port is opened
bool IsOpen (void) const { return (m_hFile != 0); }
// Obtain last error status
LONG GetLastError (void) const { return m_lLastError; }
// Obtain CTS/DSR/RING/RLSD settings
bool GetCTS (void);
bool GetDSR (void);
bool GetRing (void);
bool GetRLSD (void);
// Purge all buffers
LONG Purge (void);
protected:
// Internal helper class which wraps DCB structure
class CDCB : public DCB
{
public:
CDCB() { DCBlength = sizeof(DCB); }
};
// Attributes
protected:
LONG m_lLastError; // Last serial error
HANDLE m_hFile; // File handle
EEvent m_eEvent; // Event type
DWORD m_dwEventMask; // Event mask
#ifndef SERIAL_NO_OVERLAPPED
HANDLE m_hevtOverlapped; // Event handle for internal overlapped operations
#endif
protected:
// Check the requirements
void CheckRequirements (LPOVERLAPPED lpOverlapped, DWORD dwTimeout) const;
// CancelIo wrapper (for Win95 compatibility)
BOOL CancelCommIo (void);
};
#endif // __SERIAL_H

@ -0,0 +1,277 @@
// SerialEx.cpp - Implementation of the CSerialEx class
//
// Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//////////////////////////////////////////////////////////////////////
// Include the standard header files
#include <crtdbg.h>
#include <tchar.h>
#include <windows.h>
//////////////////////////////////////////////////////////////////////
// Include module headerfile
#include "pch.h"
#include "SerialEx.h"
//////////////////////////////////////////////////////////////////////
// Disable warning C4127: conditional expression is constant, which
// is generated when using the _RPTF and _ASSERTE macros.
#pragma warning(disable: 4127)
//////////////////////////////////////////////////////////////////////
// Enable debug memory manager
#ifdef _DEBUG
#ifdef THIS_FILE
#undef THIS_FILE
#endif
static const char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Code
CSerialEx::CSerialEx()
: m_fStopping(false)
, m_hThread(0)
#ifndef SERIAL_NO_OVERLAPPED
, m_hevtOverlappedWorkerThread(0)
#endif
{
}
CSerialEx::~CSerialEx()
{
// Check if the thread handle is still there. If so, then we
// didn't close the serial port. We cannot depend on the
// CSerial destructor, because if it calls Close then it
// won't call our overridden Close.
if (m_hThread)
{
// Display a warning
_RPTF0(_CRT_WARN, "CSerialEx::~CSerialEx - Serial port not closed\n");
// Close implicitly
Close();
}
}
LONG CSerialEx::Open (LPCTSTR lpszDevice, DWORD dwInQueue, DWORD dwOutQueue, bool fStartListener)
{
// Call the base class first
long lLastError = CSerial::Open(lpszDevice,dwInQueue,dwOutQueue,SERIAL_DEFAULT_OVERLAPPED);
if (lLastError != ERROR_SUCCESS)
return lLastError;
#ifndef SERIAL_NO_OVERLAPPED
// Create an event that is used for the workerthread. The globally
// used event is used by the main-thread and cannot be reused
// for this thread.
m_hevtOverlappedWorkerThread = ::CreateEvent(0,true,false,0);
if (m_hevtOverlappedWorkerThread == 0)
{
// Obtain the error information
m_lLastError = ::GetLastError();
_RPTF0(_CRT_WARN,"CSerialEx::Open - Unable to create event\n");
// Close the serial port again
CSerial::Close();
// Return the error
return m_lLastError;
}
#endif
// Start the listener thread (only on request)
if (fStartListener)
{
lLastError = StartListener();
if (lLastError != ERROR_SUCCESS)
return lLastError;
}
// Return the error
return m_lLastError;
}
LONG CSerialEx::Close (void)
{
// Stop listener thread (wait until it ends)
//StopListener(INFINITE);
StopListener(100);
#ifndef SERIAL_NO_OVERLAPPED
// Free event handle
if (m_hevtOverlappedWorkerThread)
{
::CloseHandle(m_hevtOverlappedWorkerThread);
m_hevtOverlappedWorkerThread = 0;
}
#endif
// Call the base class
return CSerial::Close();
}
LONG CSerialEx::StartListener (void)
{
// Check if the watcher thread was already running
if (m_hThread == 0)
{
// Make sure the thread has stopped
_ASSERTE(!m_fStopping);
// Start the watcher thread
DWORD dwThreadId = 0;
m_hThread = ::CreateThread(0,0,ThreadProc,LPVOID(this),0,&dwThreadId);
if (m_hThread == 0)
{
// Display a warning
_RPTF0(_CRT_WARN, "CSerialEx::StartListener - Unable to start COMM watcher thread\n");
// Set the error code and exit
m_lLastError = ::GetLastError();
return m_lLastError;
}
}
// Return the error
m_lLastError = ERROR_SUCCESS;
return m_lLastError;
}
LONG CSerialEx::StopListener (DWORD dwTimeout)
{
// Check if the thread is running
if (m_hThread)
{
// Set the flag that the thread must be stopped
m_fStopping = true;
// Cancel the pending WaitEvent, but we won't do this using
// CancelIo. This would break Win95 compatibility and some
// USB serial dongles cannot handle CancelIo correctly. By
// setting the event mask again, the call will also be
// completed before the thread exits.
SetMask(GetEventMask());
// Wait until the watcher thread has stopped
::WaitForSingleObject(m_hThread,dwTimeout);
// The thread has stopped
m_fStopping = false;
// Close handle to the thread
::CloseHandle(m_hThread);
m_hThread = 0;
}
// Return the error
m_lLastError = ERROR_SUCCESS;
return m_lLastError;
}
DWORD WINAPI CSerialEx::ThreadProc (LPVOID lpArg)
{
// Route the method to the actual object
CSerialEx* pThis = reinterpret_cast<CSerialEx*>(lpArg);
return pThis->ThreadProc();
}
DWORD CSerialEx::ThreadProc (void)
{
// Use overlapped structure
LPOVERLAPPED lpOverlapped = 0;
// Keep looping
do
{
#ifndef SERIAL_NO_OVERLAPPED
// Reset the event handle
::ResetEvent(m_hevtOverlappedWorkerThread);
// Initialize the overlapped structure
OVERLAPPED ovInternal = {0};
ovInternal.hEvent = m_hevtOverlappedWorkerThread;
// Start the WaitEvent (use our own overlapped structure)
if (WaitEvent(&ovInternal) != ERROR_SUCCESS)
return m_lLastError;
// Wait for the overlapped operation to complete
if (::WaitForSingleObject(m_hevtOverlappedWorkerThread,INFINITE) != WAIT_OBJECT_0)
{
// Set the internal error code
m_lLastError = ::GetLastError();
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerialEx::ThreadProc - Unable to wait until COM event has arrived\n");
return m_lLastError;
}
#else
// Start the WaitEvent (don't need to specify an overlapped structure)
if (WaitEvent() != ERROR_SUCCESS)
return m_lLastError;
#endif
// Wait until one of the events happens
if (!m_fStopping)
{
// Determine the event
EEvent eEvent = GetEventType();
// Obtain the error status during this event
DWORD dwErrors = 0;
if (!::ClearCommError(m_hFile,&dwErrors,0))
{
// Set the internal error code
m_lLastError = ::GetLastError();
// Issue an error and quit
_RPTF0(_CRT_WARN, "CSerialEx::ThreadProc - Unable to obtain COM status\n");
}
// Convert the error
EError eError = EError(dwErrors);
// There was a COMM event, which needs handling. We'll call the
// event handler. We can receive a "zero" event, when the
// mask or event character has been set. We won't pass this
// down to the window.
if (eEvent)
OnEvent(eEvent,eError);
}
}
while (!m_fStopping);
// Bye bye
return 0;
}

@ -0,0 +1,118 @@
// SerialEx.h - Definition of the CSerialEx class
//
// Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifndef __SERIAL_EX_H
#define __SERIAL_EX_H
//////////////////////////////////////////////////////////////////////
// Include CSerial base class
#include "Serial.h"
//////////////////////////////////////////////////////////////////////
//
// CSerialEx - Win32 message-based wrapper for serial communications
//
// A lot of MS-Windows GUI based programs use a central message
// loop, so the application cannot block to wait for objects. This
// make serial communication difficult, because it isn't event
// driven using a message queue. This class makes the CSerial based
// classes suitable for use with such a messagequeue. Whenever
// an event occurs on the serial port, a user-defined message will
// be sent to a user-defined window. It can then use the standard
// message dispatching to handle the event.
//
// Pros:
// -----
// - Easy to use
// - Fully ANSI and Unicode aware
// - Integrates easily in GUI applications and is intuitive to
// use for GUI application programmers
//
// Cons:
// -----
// - Uses a thread for each COM-port, which has been opened.
// - More overhead, due to thread switching and message queues.
// - Requires a window, but that's probably why you're using
// this class.
//
// Copyright (C) 1999-2003 Ramon de Klein
// (Ramon.de.Klein@ict.nl)
class CSerialEx : public CSerial
{
// Construction
public:
CSerialEx();
virtual ~CSerialEx();
// Operations
public:
// Open the serial communications for a particular COM port. You
// need to use the full devicename (i.e. "COM1") to open the port.
virtual LONG Open (LPCTSTR lpszDevice, DWORD dwInQueue = 0, DWORD dwOutQueue = 0, bool fStartListener = false);
// Close the serial port.
virtual LONG Close (void);
// Start the listener thread
virtual LONG StartListener (void);
// Stop the listener thread. Because the other thread might be
// busy processing data it might take a while, so you can specify
// a time-out.
virtual LONG StopListener (DWORD dwTimeout = INFINITE);
protected:
// Each opened COM-port uses its own specific thread, which will
// wait for one of the events to happen. When an event happens,
// then the client window is send a message informing about the
// event.
static DWORD WINAPI ThreadProc (LPVOID lpArg);
DWORD ThreadProc (void);
// Event handler
virtual void OnEvent (EEvent eEvent, EError eError) = 0;
protected:
// The WaitEvent method is being used by this class internally
// and shouldn't be used by client applications. Client
// application should monior the messages.
using CSerial::WaitEvent;
// The event-type is send in the WPARAM of the message and
// the GetEventType method returns the wrong data, so we'll
// hide this method for client applications to avoid problems.
using CSerial::GetEventType;
using CSerial::GetError;
protected:
// Internal attributes
bool m_fStopping;
HANDLE m_hThread;
#ifndef SERIAL_NO_OVERLAPPED
// Handle for overlapped operations in worker-thread
HANDLE m_hevtOverlappedWorkerThread;
#endif
};
#endif // __SERIAL_EX_H

@ -0,0 +1,135 @@
// SerialMFC.h - Definition of the CSerialMFC class
//
// Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifndef __SERIAL_MFC_H
#define __SERIAL_MFC_H
//////////////////////////////////////////////////////////////////////
// Include CSerialWnd base class
#include "SerialWnd.h"
//////////////////////////////////////////////////////////////////////
// Make sure that MFC is already loaded
//
// We don't include it here, because MFC based applications typically
// use a precompiled header file.
#ifndef __AFXWIN_H__
#error "CWnd class isn't included (include AFXWIN.H)"
#endif
//////////////////////////////////////////////////////////////////////
//
// CSerialMFC - MFC wrapper for serial communication handling
//
// CSerialMFC is a very thing wrapper around the CSerialWnd class,
// which makes it more suitable for use in MFC-based applications.
// Unfortenately, the MFC framework isn't very flexible when it comes
// to adding custom message handlers. We cannot add our own types to
// the message handlers, but we're stuck to use 32-bit integers.
//
// Add the following entry to the window's message map to make sure
// that MFC calls your handler, when a serial message comes in.
//
// DECLARE_MESSAGE_MAP(CMyClass,CWnd)
// ...
// ON_WM_SERIAL(OnSerialMsg)
// ...
// END_MESSAGE_MAP()
//
// A typical handler could look like this:
//
// afx_msg LRESULT CMyClass::OnSerialMsg (WPARAM wParam, LPARAM lParam)
// {
// CSerial::EEvent eEvent = CSerial::EEvent(LOWORD(wParam));
// CSerial::EError eError = CSerial::EError(HIWORD(wParam));
//
// // lParam: User-defined 32-bit integer (type LPARAM)
// switch (eEvent)
// {
// case CSerialMFC::EEventRecv:
// // TODO: Read data from the port
// break;
// ...
// }
//
// // Return successful
// return 0;
// }
//
//
// Pros:
// -----
// - Easy to use
// - Fully ANSI and Unicode aware
// - Integrates seamless in MFC applications
//
// Cons:
// -----
// - No more then CSerialWnd, except that you need MFC
//
// Copyright (C) 1999-2003 Ramon de Klein
// (Ramon.de.Klein@ict.nl)
class CSerialMFC : public CSerialWnd
{
// Operations
public:
// Open the serial communications for a particular COM port. You
// need to use the full devicename (i.e. "COM1") to open the port.
virtual LONG Open (LPCTSTR lpszDevice, CWnd* pwndDest, UINT nComMsg = WM_NULL, LPARAM lParam = 0, DWORD dwInQueue = 0, DWORD dwOutQueue = 0)
{
CString strTemp = _T("\\\\.\\");
strTemp += lpszDevice;
return CSerialWnd::Open(strTemp.GetBuffer(0), pwndDest->GetSafeHwnd(), nComMsg, lParam, dwInQueue, dwOutQueue);
//return CSerialWnd::Open(lpszDevice, pwndDest->GetSafeHwnd(), nComMsg, lParam, dwInQueue, dwOutQueue);
}
};
//////////////////////////////////////////////////////////////////////
// Message map macro for the default COM message
#define ON_WM_SERIAL(memberFxn) \
ON_REGISTERED_MESSAGE(CSerialMFC::mg_nDefaultComMsg,memberFxn)
//////////////////////////////////////////////////////////////////////
// Don't link to the default runtime libraries, because this will
// give a warning during link-time.
#ifdef _DEBUG
#pragma comment(linker,"/nodefaultlib:LIBCD")
#else
#pragma comment(linker,"/nodefaultlib:LIBC")
#endif
#endif // __SERIAL_MFC_H

@ -0,0 +1,131 @@
// SerialWnd.cpp - Implementation of the CSerialWnd class
//
// Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//////////////////////////////////////////////////////////////////////
// Include the standard header files
#include "pch.h"
#include <crtdbg.h>
#include <tchar.h>
#include <windows.h>
//////////////////////////////////////////////////////////////////////
// Include module headerfile
#include "SerialWnd.h"
//////////////////////////////////////////////////////////////////////
// Disable warning C4127: conditional expression is constant, which
// is generated when using the _RPTF and _ASSERTE macros.
#pragma warning(disable: 4127)
//////////////////////////////////////////////////////////////////////
// Enable debug memory manager
#ifdef _DEBUG
#ifdef THIS_FILE
#undef THIS_FILE
#endif
static const char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Code
// Register the standard CSerialWnd COM message
const UINT CSerialWnd::mg_nDefaultComMsg = ::RegisterWindowMessage(_T("CSerialWnd_DefaultComMsg"));
CSerialWnd::CSerialWnd()
: m_hwndDest(0)
, m_nComMsg(WM_NULL)
, m_lParam(0)
{
}
CSerialWnd::~CSerialWnd()
{
// Check if the thread handle is still there. If so, then we
// didn't close the serial port. We cannot depend on the
// CSerial destructor, because if it calls Close then it
// won't call our overridden Close.
if (m_hThread)
{
// Display a warning
_RPTF0(_CRT_WARN, "CSerialWnd::~CSerialWnd - Serial port not closed\n");
// Close implicitly
Close();
}
}
LONG CSerialWnd::Open (LPCTSTR lpszDevice, HWND hwndDest, UINT nComMsg, LPARAM lParam, DWORD dwInQueue, DWORD dwOutQueue)
{
// Call the base class first
long lLastError = CSerialEx::Open(lpszDevice,dwInQueue,dwOutQueue);
if (lLastError != ERROR_SUCCESS)
return lLastError;
// Save the window handle, notification message and user message
m_hwndDest = hwndDest;
m_nComMsg = nComMsg?nComMsg:mg_nDefaultComMsg;
m_lParam = lParam;
// Start the listener thread
lLastError = StartListener();
if (lLastError != ERROR_SUCCESS)
{
// Close the serial port
Close();
// Return the error-code
m_lLastError = lLastError;
return m_lLastError;
}
// Return the error
m_lLastError = ERROR_SUCCESS;
return m_lLastError;
}
LONG CSerialWnd::Close (void)
{
// Reset all members
m_hwndDest = 0;
m_nComMsg = WM_NULL;
// Call the base class
return CSerialEx::Close();
}
void CSerialWnd::OnEvent (EEvent eEvent, EError eError)
{
// Post message to the client window
::PostMessage(m_hwndDest,m_nComMsg,MAKEWPARAM(eEvent,eError),LPARAM(m_lParam));
}

@ -0,0 +1,91 @@
// SerialWnd.h - Definition of the CSerialWnd class
//
// Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifndef __SERIAL_WND_H
#define __SERIAL_WND_H
//////////////////////////////////////////////////////////////////////
// Include CSerialEx base class
#include "SerialEx.h"
//////////////////////////////////////////////////////////////////////
//
// CSerialWnd - Win32 message-based wrapper for serial communications
//
// A lot of MS-Windows GUI based programs use a central message
// loop, so the application cannot block to wait for objects. This
// make serial communication difficult, because it isn't event
// driven using a message queue. This class makes the CSerial based
// classes suitable for use with such a messagequeue. Whenever
// an event occurs on the serial port, a user-defined message will
// be sent to a user-defined window. It can then use the standard
// message dispatching to handle the event.
//
// Pros:
// -----
// - Easy to use
// - Fully ANSI and Unicode aware
// - Integrates easily in GUI applications and is intuitive to
// use for GUI application programmers
//
// Cons:
// -----
// - Uses a thread for each COM-port, which has been opened.
// - More overhead, due to thread switching and message queues.
// - Requires a window, but that's probably why you're using
// this class.
//
// Copyright (C) 1999-2003 Ramon de Klein
// (Ramon.de.Klein@ict.nl)
class CSerialWnd : public CSerialEx
{
// Construction
public:
CSerialWnd();
virtual ~CSerialWnd();
// Operations
public:
// Open the serial communications for a particular COM port. You
// need to use the full devicename (i.e. "COM1") to open the port.
virtual LONG Open (LPCTSTR lpszDevice, HWND hwndDest, UINT nComMsg=WM_NULL, LPARAM lParam=0, DWORD dwInQueue = 0, DWORD dwOutQueue = 0);
// Close the serial port.
virtual LONG Close (void);
protected:
// Event handler that is called when
virtual void OnEvent (EEvent eEvent, EError eError);
public:
// Default Serial notification message
static const UINT mg_nDefaultComMsg;
protected:
// Internal attributes
HWND m_hwndDest;
UINT m_nComMsg;
LONG m_lParam;
};
#endif // __SERIAL_WND_H

@ -0,0 +1,107 @@

// TimeSet.cpp: 응용 프로그램에 대한 클래스 동작을 정의합니다.
//
#include "pch.h"
#include "framework.h"
#include "TimeSet.h"
#include "TimeSetDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CTimeSetApp
BEGIN_MESSAGE_MAP(CTimeSetApp, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
// CTimeSetApp 생성
CTimeSetApp::CTimeSetApp()
{
// 다시 시작 관리자 지원
m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
// TODO: 여기에 생성 코드를 추가합니다.
// InitInstance에 모든 중요한 초기화 작업을 배치합니다.
}
// 유일한 CTimeSetApp 개체입니다.
CTimeSetApp theApp;
// CTimeSetApp 초기화
BOOL CTimeSetApp::InitInstance()
{
// 응용 프로그램 매니페스트가 ComCtl32.dll 버전 6 이상을 사용하여 비주얼 스타일을
// 사용하도록 지정하는 경우, Windows XP 상에서 반드시 InitCommonControlsEx()가 필요합니다.
// InitCommonControlsEx()를 사용하지 않으면 창을 만들 수 없습니다.
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 응용 프로그램에서 사용할 모든 공용 컨트롤 클래스를 포함하도록
// 이 항목을 설정하십시오.
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
AfxEnableControlContainer();
// 대화 상자에 셸 트리 뷰 또는
// 셸 목록 뷰 컨트롤이 포함되어 있는 경우 셸 관리자를 만듭니다.
CShellManager *pShellManager = new CShellManager;
// MFC 컨트롤의 테마를 사용하기 위해 "Windows 원형" 비주얼 관리자 활성화
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
// 표준 초기화
// 이들 기능을 사용하지 않고 최종 실행 파일의 크기를 줄이려면
// 아래에서 필요 없는 특정 초기화
// 루틴을 제거해야 합니다.
// 해당 설정이 저장된 레지스트리 키를 변경하십시오.
// TODO: 이 문자열을 회사 또는 조직의 이름과 같은
// 적절한 내용으로 수정해야 합니다.
SetRegistryKey(_T("로컬 응용 프로그램 마법사에서 생성된 응용 프로그램"));
CTimeSetDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: 여기에 [확인]을 클릭하여 대화 상자가 없어질 때 처리할
// 코드를 배치합니다.
}
else if (nResponse == IDCANCEL)
{
// TODO: 여기에 [취소]를 클릭하여 대화 상자가 없어질 때 처리할
// 코드를 배치합니다.
}
else if (nResponse == -1)
{
TRACE(traceAppMsg, 0, "경고: 대화 상자를 만들지 못했으므로 응용 프로그램이 예기치 않게 종료됩니다.\n");
TRACE(traceAppMsg, 0, "경고: 대화 상자에서 MFC 컨트롤을 사용하는 경우 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS를 수행할 수 없습니다.\n");
}
// 위에서 만든 셸 관리자를 삭제합니다.
if (pShellManager != nullptr)
{
delete pShellManager;
}
#if !defined(_AFXDLL) && !defined(_AFX_NO_MFC_CONTROLS_IN_DIALOGS)
ControlBarCleanUp();
#endif
// 대화 상자가 닫혔으므로 응용 프로그램의 메시지 펌프를 시작하지 않고 응용 프로그램을 끝낼 수 있도록 FALSE를
// 반환합니다.
return FALSE;
}

@ -0,0 +1,32 @@

// TimeSet.h: PROJECT_NAME 응용 프로그램에 대한 주 헤더 파일입니다.
//
#pragma once
#ifndef __AFXWIN_H__
#error "include 'pch.h' before including this file for PCH"
#endif
#include "resource.h" // 주 기호입니다.
// CTimeSetApp:
// 이 클래스의 구현에 대해서는 TimeSet.cpp을(를) 참조하세요.
//
class CTimeSetApp : public CWinApp
{
public:
CTimeSetApp();
// 재정의입니다.
public:
virtual BOOL InitInstance();
// 구현입니다.
DECLARE_MESSAGE_MAP()
};
extern CTimeSetApp theApp;

@ -0,0 +1,226 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" 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>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{12662F45-5722-45B9-8C02-2863C436C1F6}</ProjectGuid>
<Keyword>MFCProj</Keyword>
<RootNamespace>TimeSet</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.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>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<UseOfMfc>Static</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<UseOfMfc>Static</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>Static</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>Static</UseOfMfc>
</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" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
</Link>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<ValidateAllParameters>true</ValidateAllParameters>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</Midl>
<ResourceCompile>
<Culture>0x0412</Culture>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
</Link>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<ValidateAllParameters>true</ValidateAllParameters>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</Midl>
<ResourceCompile>
<Culture>0x0412</Culture>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<ValidateAllParameters>true</ValidateAllParameters>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</Midl>
<ResourceCompile>
<Culture>0x0412</Culture>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<ValidateAllParameters>true</ValidateAllParameters>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</Midl>
<ResourceCompile>
<Culture>0x0412</Culture>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="Serial.h" />
<ClInclude Include="SerialEx.h" />
<ClInclude Include="SerialMFC.h" />
<ClInclude Include="SerialWnd.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="TimeSet.h" />
<ClInclude Include="TimeSetDlg.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="Serial.cpp" />
<ClCompile Include="SerialEx.cpp" />
<ClCompile Include="SerialWnd.cpp" />
<ClCompile Include="TimeSet.cpp" />
<ClCompile Include="TimeSetDlg.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="TimeSet.rc" />
</ItemGroup>
<ItemGroup>
<None Include="res\TimeSet.rc2" />
</ItemGroup>
<ItemGroup>
<Image Include="res\TimeSet.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="소스 파일">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="헤더 파일">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="리소스 파일">
<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>
<ClInclude Include="TimeSet.h">
<Filter>헤더 파일</Filter>
</ClInclude>
<ClInclude Include="TimeSetDlg.h">
<Filter>헤더 파일</Filter>
</ClInclude>
<ClInclude Include="framework.h">
<Filter>헤더 파일</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>헤더 파일</Filter>
</ClInclude>
<ClInclude Include="Resource.h">
<Filter>헤더 파일</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>헤더 파일</Filter>
</ClInclude>
<ClInclude Include="Serial.h">
<Filter>헤더 파일</Filter>
</ClInclude>
<ClInclude Include="SerialEx.h">
<Filter>헤더 파일</Filter>
</ClInclude>
<ClInclude Include="SerialMFC.h">
<Filter>헤더 파일</Filter>
</ClInclude>
<ClInclude Include="SerialWnd.h">
<Filter>헤더 파일</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="TimeSet.cpp">
<Filter>소스 파일</Filter>
</ClCompile>
<ClCompile Include="TimeSetDlg.cpp">
<Filter>소스 파일</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>소스 파일</Filter>
</ClCompile>
<ClCompile Include="Serial.cpp">
<Filter>소스 파일</Filter>
</ClCompile>
<ClCompile Include="SerialEx.cpp">
<Filter>소스 파일</Filter>
</ClCompile>
<ClCompile Include="SerialWnd.cpp">
<Filter>소스 파일</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="TimeSet.rc">
<Filter>리소스 파일</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<None Include="res\TimeSet.rc2">
<Filter>리소스 파일</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Image Include="res\TimeSet.ico">
<Filter>리소스 파일</Filter>
</Image>
</ItemGroup>
</Project>

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

@ -0,0 +1,684 @@

// TimeSetDlg.cpp: 구현 파일
//
#include "pch.h"
#include "framework.h"
#include "TimeSet.h"
#include "TimeSetDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#include <setupapi.h>
#pragma comment(lib, "setupapi.lib")
// CTimeSetDlg 대화 상자
void GetDeviceInstanceID(HDEVINFO hDevInfo, SP_DEVINFO_DATA* pspDevInfoData, TCHAR *szInstanceID)
{
if (!SetupDiGetDeviceInstanceId(hDevInfo,
pspDevInfoData,
szInstanceID,
LINE_LEN,
0))
{
;
}
};
void GetDeviceInterfaceInfo(HDEVINFO hDevInfo, SP_DEVINFO_DATA spDevInfoData, TCHAR *szPath)
{
SP_DEVICE_INTERFACE_DATA spDevInterfaceData = { 0 };
//
spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
if (!SetupDiCreateDeviceInterface(hDevInfo,
&spDevInfoData,
&spDevInfoData.ClassGuid,
0L,
0L,
&spDevInterfaceData))
;
else
{
SP_DEVICE_INTERFACE_DETAIL_DATA *pspDevInterfaceDetail = 0L;
DWORD dwRequire = 0L;
//
if (!SetupDiGetDeviceInterfaceDetail(hDevInfo,
&spDevInterfaceData,
0L,
0,
&dwRequire,
0L))
{
DWORD dwError = GetLastError();
//
if (dwError != ERROR_INSUFFICIENT_BUFFER)
{
return;
};
};
//
pspDevInterfaceDetail = (SP_DEVICE_INTERFACE_DETAIL_DATA*)LocalAlloc(LPTR,
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA)*dwRequire);
pspDevInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(hDevInfo,
&spDevInterfaceData,
pspDevInterfaceDetail,
dwRequire,
&dwRequire,
0L))
{
DWORD dwError = GetLastError();
//
if (dwError != ERROR_INSUFFICIENT_BUFFER)
{
int a = 3;
}
}
else
{
memcpy(szPath, pspDevInterfaceDetail->DevicePath, strlen(pspDevInterfaceDetail->DevicePath));
};
if (pspDevInterfaceDetail)
LocalFree(pspDevInterfaceDetail);
};
};
void PrintError(CString strErrorName, DWORD dwErrorNo)
{
LPVOID lpMsgBuf;
CString strMessage;
if (!FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwErrorNo,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),// Default language
(LPTSTR)&lpMsgBuf,
0,
NULL))
{
// Handle the error.
return;
}
//_cprintf("WIN_ERR(%d): %s\n", dwErrorNo, (LPCTSTR)lpMsgBuf);
strMessage.Format(_T("%s\nWIN_ERR(%d): %s\n"), strErrorName, dwErrorNo, (LPCTSTR)lpMsgBuf);
::AfxMessageBox(strMessage, MB_OK | MB_ICONERROR);
LocalFree(lpMsgBuf);
}
CTimeSetDlg::CTimeSetDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_TIMESET_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CTimeSetDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CTimeSetDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_CONNECT, &CTimeSetDlg::OnBnClickedButtonConnect)
ON_BN_CLICKED(IDC_BUTTON_SET_LOCAL_TIME, &CTimeSetDlg::OnBnClickedButtonSetLocalTime)
ON_BN_CLICKED(IDC_BUTTON_SET_USER_TIME, &CTimeSetDlg::OnBnClickedButtonSetUserTime)
ON_BN_CLICKED(IDC_BUTTON_SET_THRESHOLD, &CTimeSetDlg::OnBnClickedButtonSetThreshold)
END_MESSAGE_MAP()
// CTimeSetDlg 메시지 처리기
BOOL CTimeSetDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 이 대화 상자의 아이콘을 설정합니다. 응용 프로그램의 주 창이 대화 상자가 아닐 경우에는
// 프레임워크가 이 작업을 자동으로 수행합니다.
SetIcon(m_hIcon, TRUE); // 큰 아이콘을 설정합니다.
SetIcon(m_hIcon, FALSE); // 작은 아이콘을 설정합니다.
//ShowWindow(SW_MINIMIZE);
// TODO: 여기에 추가 초기화 작업을 추가합니다.
PortSearch();
return TRUE; // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다.
}
// 대화 상자에 최소화 단추를 추가할 경우 아이콘을 그리려면
// 아래 코드가 필요합니다. 문서/뷰 모델을 사용하는 MFC 응용 프로그램의 경우에는
// 프레임워크에서 이 작업을 자동으로 수행합니다.
void CTimeSetDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트입니다.
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 클라이언트 사각형에서 아이콘을 가운데에 맞춥니다.
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 아이콘을 그립니다.
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
// 사용자가 최소화된 창을 끄는 동안에 커서가 표시되도록 시스템에서
// 이 함수를 호출합니다.
HCURSOR CTimeSetDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CTimeSetDlg::PortSearch()
{
HDEVINFO hDevInfo = 0L;
SP_DEVINFO_DATA spDevInfoData = { 0 };
short wIndex = 0;
CString strPortName = _T("");
SERIAL_PORT stPortInfo;
DWORD dwRequireSize;
deque<CString> deqPort;
deque<CString> deqDeviceName;
TCHAR szName[64] = { 0 };
HKEY hKey;
DWORD dwResult;
CString strTemp;
CString strTemp1;
deque<CString>::iterator itrPortName;
deque<CString>::iterator itrDeviceName;
int nComboIndex = 0;
int i;
CComboBox* pCombo = (CComboBox *)GetDlgItem(IDC_COMBO_SERIAL_LIST);
pCombo->LockWindowUpdate();
nComboIndex = pCombo->GetCount();
m_mapPortSearch.clear();
for (i = 0; i < nComboIndex; i++)
{
pCombo->DeleteString(0);
}
hDevInfo = SetupDiGetClassDevs(0L, 0L, this->GetParent()->GetSafeHwnd(), DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_PROFILE);
if (hDevInfo != (void*)-1)
{
wIndex = 0;
spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
while (1)
{
if (SetupDiEnumDeviceInfo(hDevInfo, wIndex, &spDevInfoData))
{
TCHAR szBuf[MAX_PATH] = { 0 };
short wImageIdx = 0;
short wItem = 0;
if (!SetupDiGetDeviceRegistryProperty(hDevInfo,
&spDevInfoData,
SPDRP_CLASS, //SPDRP_DEVICEDESC,
0L,
(PBYTE)szBuf,
2048,
0))
{
wIndex++;
continue;
};
strTemp.Format(_T("%s"), szBuf);
if (strTemp.Find(_T("Ports")) == -1)
{
wIndex++;
continue;
}
if (!SetupDiGetClassDescription(&spDevInfoData.ClassGuid,
szBuf,
MAX_PATH,
&dwRequireSize))
{
wIndex++;
continue;
};
TCHAR szID[LINE_LEN] = { 0 };
TCHAR szPath[MAX_PATH] = { 0 };
GetDeviceInstanceID(hDevInfo, &spDevInfoData, szID);
GetDeviceInterfaceInfo(hDevInfo, spDevInfoData, szPath);
if (SetupDiGetDeviceRegistryProperty(hDevInfo,
&spDevInfoData,
SPDRP_FRIENDLYNAME,
0L,
(PBYTE)szName,
63,
0))
{
}
else if (SetupDiGetDeviceRegistryProperty(hDevInfo,
&spDevInfoData,
SPDRP_DEVICEDESC,
0L,
(PBYTE)szName,
63,
0))
{
};
strTemp.Format(_T("%s"), szName);
if (strTemp.Find(_T("COM")) != -1)
{
TRACE("%s\n", strTemp);
deqDeviceName.push_back(strTemp);
}
}
else
break;
wIndex++;
};
SetupDiDestroyDeviceInfoList(hDevInfo);
};
dwResult = RegOpenKey(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"), &hKey);
if (dwResult == ERROR_SUCCESS)
{
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
DWORD cchClassName = MAX_PATH; // size of class string
DWORD cSubKeys = 0; // number of subkeys
DWORD cValues; // number of values for key
DWORD i, retCode;
TCHAR achValue[MAX_VALUE_NAME];
DWORD cchValue = MAX_VALUE_NAME;
// Get the class name and the value count.
retCode = RegQueryInfoKey(hKey, // key handle
NULL, // buffer for class name
NULL, // size of class string
NULL, // reserved
NULL, // number of subkeys
NULL, // longest subkey size
NULL, // longest class string
&cValues, // number of values for this key
NULL, // longest value name
NULL, // longest value data
NULL, // security descriptor
NULL); // last write time
// Enumerate the key values.
if (cValues)
{
for (i = 0, retCode = ERROR_SUCCESS; i < cValues; i++)
{
cchValue = MAX_VALUE_NAME;
achValue[0] = '\0';
retCode = RegEnumValue(hKey, i,
achValue,
&cchValue,
NULL,
NULL,
NULL,
NULL);
if (retCode == ERROR_SUCCESS)
{
TCHAR chTemp[MAX_VALUE_NAME];
DWORD dwBufSize;
chTemp[0] = '\0';
retCode = RegQueryValueEx(hKey, achValue, NULL, NULL, (PBYTE)chTemp, &dwBufSize);
if (retCode == ERROR_SUCCESS)
{
strTemp.Format(_T("COM%.3d"), _ttoi(chTemp + _tcslen(_T("COM"))));
deqPort.push_back(strTemp);
}
else
{
retCode = RegQueryValueEx(hKey, achValue, NULL, NULL, (PBYTE)chTemp, &dwBufSize);
if (ERROR_SUCCESS == retCode)
{
strTemp.Format(_T("COM%.3d"), _ttoi(chTemp + _tcslen(_T("COM"))));
deqPort.push_back(strTemp);
}
}
}
}
}
RegCloseKey(hKey);
}
sort(deqPort.begin(), deqPort.end());
itrPortName = deqPort.begin();
nComboIndex = 0;
while (itrPortName != deqPort.end())
{
TRACE("%s\n", (*itrPortName));
int nPort = _ttoi((*itrPortName).Mid(3, 3));
strTemp.Format(_T("COM%d"), nPort);
stPortInfo.nPort = nPort;
stPortInfo.strPortName = strTemp;
stPortInfo.strDeviceName = _T("");
itrDeviceName = deqDeviceName.begin();
while (itrDeviceName != deqDeviceName.end())
{
if ((*itrDeviceName).Find(_T("(") + strTemp + _T(")")) != -1)
{
stPortInfo.strDeviceName = (*itrDeviceName);
}
itrDeviceName++;
}
if (stPortInfo.strDeviceName.GetLength() == 0)
{
pCombo->InsertString(nComboIndex, stPortInfo.strPortName);
}
else
{
pCombo->InsertString(nComboIndex, stPortInfo.strDeviceName);
}
m_mapPortSearch[nComboIndex++] = stPortInfo;
itrPortName++;
}
pCombo->SetCurSel(0);
pCombo->UnlockWindowUpdate();
}
void CTimeSetDlg::OnBnClickedButtonConnect()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
CComboBox* pCombo = (CComboBox *)GetDlgItem(IDC_COMBO_SERIAL_LIST);
if (m_Serial.IsOpen() == true)
{
m_Serial.Close();
GetDlgItem(IDC_BUTTON_CONNECT)->SetWindowText(_T("Connect"));
GetDlgItem(IDC_COMBO_SERIAL_LIST)->EnableWindow(true);
GetDlgItem(IDC_BUTTON_SET_LOCAL_TIME)->EnableWindow(false);
GetDlgItem(IDC_BUTTON_SET_USER_TIME)->EnableWindow(false);
GetDlgItem(IDC_BUTTON_SET_THRESHOLD)->EnableWindow(false);
}
else
{
int nPortSelect = -1;
CString strPort;
DWORD dwResult;
nPortSelect = pCombo->GetCurSel();
if (nPortSelect >= 0)
{
strPort.Format(_T("COM%d"), m_mapPortSearch[nPortSelect].nPort);
dwResult = m_Serial.Open(strPort, this);
if (dwResult != ERROR_SUCCESS)
{
CString strMessage = _T("Serial Port Open Failed\n");
PrintError(strMessage, GetLastError());
return;
}
if (m_Serial.Setup(CSerial::EBaud115200, CSerial::EData8, CSerial::EParNone, CSerial::EStop1) != ERROR_SUCCESS)
{
CString strMessage = _T("Serial Setup Error\n");
PrintError(strMessage, GetLastError());
m_Serial.Close();
return;
}
if (m_Serial.SetupHandshaking(CSerial::EHandshakeOff))
{
CString strMessage = _T("Serial SetupHandshaking Error\n");
PrintError(strMessage, GetLastError());
m_Serial.Close();
return;
}
CTime time = CTime::GetCurrentTime();
CString strtemp;
strtemp.Format("%d", time.GetYear());
GetDlgItem(IDC_EDIT_YEAR)->SetWindowText(strtemp);
strtemp.Format("%d", time.GetMonth());
GetDlgItem(IDC_EDIT_MONTH)->SetWindowText(strtemp);
strtemp.Format("%d", time.GetDay());
GetDlgItem(IDC_EDIT_DATE)->SetWindowText(strtemp);
strtemp.Format("%d", time.GetHour());
GetDlgItem(IDC_EDIT_HOUR)->SetWindowText(strtemp);
strtemp.Format("%d", time.GetMinute());
GetDlgItem(IDC_EDIT_MIN)->SetWindowText(strtemp);
strtemp.Format("%d", time.GetSecond());
GetDlgItem(IDC_EDIT_SEC)->SetWindowText(strtemp);
GetDlgItem(IDC_BUTTON_CONNECT)->SetWindowText(_T("Disconnect"));
GetDlgItem(IDC_COMBO_SERIAL_LIST)->EnableWindow(false);
GetDlgItem(IDC_BUTTON_SET_LOCAL_TIME)->EnableWindow(true);
GetDlgItem(IDC_BUTTON_SET_USER_TIME)->EnableWindow(true);
GetDlgItem(IDC_BUTTON_SET_THRESHOLD)->EnableWindow(true);
}
}
}
void CTimeSetDlg::OnBnClickedButtonSetLocalTime()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
uint8_t TxData[100];
uint8_t TxIndex = 0;
CTime time = CTime::GetCurrentTime();
uint16_t TimeData;
uint8_t i;
uint8_t checksum = 0;
TxData[TxIndex++] = 0x02;
TxData[TxIndex++] = 0x00;
TxData[TxIndex++] = 0x07;
TimeData = time.GetYear();
TxData[TxIndex++] = (TimeData >> 8) & 0xFF;
TxData[TxIndex++] = (TimeData >> 0) & 0xFF;
TimeData = time.GetMonth();
TxData[TxIndex++] = (TimeData >> 0) & 0xFF;
TimeData = time.GetDay();
TxData[TxIndex++] = (TimeData >> 0) & 0xFF;
TimeData = time.GetHour();
TxData[TxIndex++] = (TimeData >> 0) & 0xFF;
TimeData = time.GetMinute();
TxData[TxIndex++] = (TimeData >> 0) & 0xFF;
TimeData = time.GetSecond();
TxData[TxIndex++] = (TimeData >> 0) & 0xFF;
checksum = 0;
for (i = 0; i < TxIndex; i++)
{
checksum += TxData[i];
}
TxData[TxIndex++] = checksum;
TxData[TxIndex++] = 0x03;
if (m_Serial.IsOpen())
{
m_Serial.Write(TxData, TxIndex);
}
}
void CTimeSetDlg::OnBnClickedButtonSetUserTime()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
uint8_t TxData[100];
uint8_t TxIndex = 0;
uint16_t TimeData;
uint8_t i;
uint8_t checksum = 0;
TxData[TxIndex++] = 0x02;
TxData[TxIndex++] = 0x00;
TxData[TxIndex++] = 0x07;
CString strtemp;
GetDlgItem(IDC_EDIT_YEAR)->GetWindowText(strtemp);
TimeData = atoi(strtemp);
TxData[TxIndex++] = (TimeData >> 8) & 0xFF;
TxData[TxIndex++] = (TimeData >> 0) & 0xFF;
GetDlgItem(IDC_EDIT_MONTH)->GetWindowText(strtemp);
TimeData = atoi(strtemp);
TxData[TxIndex++] = (TimeData >> 0) & 0xFF;
GetDlgItem(IDC_EDIT_DATE)->GetWindowText(strtemp);
TimeData = atoi(strtemp);
TxData[TxIndex++] = (TimeData >> 0) & 0xFF;
GetDlgItem(IDC_EDIT_HOUR)->GetWindowText(strtemp);
TimeData = atoi(strtemp);
TxData[TxIndex++] = (TimeData >> 0) & 0xFF;
GetDlgItem(IDC_EDIT_MIN)->GetWindowText(strtemp);
TimeData = atoi(strtemp);
TxData[TxIndex++] = (TimeData >> 0) & 0xFF;
GetDlgItem(IDC_EDIT_SEC)->GetWindowText(strtemp);
TimeData = atoi(strtemp);
TxData[TxIndex++] = (TimeData >> 0) & 0xFF;
checksum = 0;
for (i = 0; i < TxIndex; i++)
{
checksum += TxData[i];
}
TxData[TxIndex++] = checksum;
TxData[TxIndex++] = 0x03;
if (m_Serial.IsOpen())
{
m_Serial.Write(TxData, TxIndex);
}
}
void CTimeSetDlg::OnBnClickedButtonSetThreshold()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
uint8_t TxData[100];
uint8_t TxIndex = 0;
uint16_t MaxData;
uint16_t MinData;
uint8_t i;
uint8_t checksum = 0;
TxData[TxIndex++] = 0x02;
TxData[TxIndex++] = 0x01;
TxData[TxIndex++] = 0x04;
CString strtemp;
GetDlgItem(IDC_EDIT_CO2_MAX)->GetWindowText(strtemp);
MaxData = atoi(strtemp);
TxData[TxIndex++] = (MaxData >> 8) & 0xFF;
TxData[TxIndex++] = (MaxData >> 0) & 0xFF;
GetDlgItem(IDC_EDIT_CO2_MIN)->GetWindowText(strtemp);
MinData = atoi(strtemp);
TxData[TxIndex++] = (MinData >> 8) & 0xFF;
TxData[TxIndex++] = (MinData >> 0) & 0xFF;
if (MaxData <= MinData)
{
MessageBox("Max / Min settings are incorrect.\r\nThe Max value must be greater than the Min value.", NULL, MB_ICONERROR);
return;
}
checksum = 0;
for (i = 0; i < TxIndex; i++)
{
checksum += TxData[i];
}
TxData[TxIndex++] = checksum;
TxData[TxIndex++] = 0x03;
if (m_Serial.IsOpen())
{
m_Serial.Write(TxData, TxIndex);
}
}

@ -0,0 +1,64 @@

// TimeSetDlg.h: 헤더 파일
//
#pragma once
#include <deque>
#include <map>
#include <algorithm>
#include <vector>
#include "SerialMFC.h"
using namespace std;
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383
typedef struct _Serial_Port
{
int nPort;
CString strDeviceName;
CString strPortName;
}SERIAL_PORT;
// CTimeSetDlg 대화 상자
class CTimeSetDlg : public CDialogEx
{
// 생성입니다.
public:
CTimeSetDlg(CWnd* pParent = nullptr); // 표준 생성자입니다.
// 대화 상자 데이터입니다.
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_TIMESET_DIALOG };
#endif
CSerialMFC m_Serial;
vector<SERIAL_PORT> m_SerialPort;
map<UINT, SERIAL_PORT> m_mapPortSearch; //포트 리스트
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 지원입니다.
void PortSearch();
// 구현입니다.
protected:
HICON m_hIcon;
// 생성된 메시지 맵 함수
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedButtonConnect();
afx_msg void OnBnClickedButtonSetLocalTime();
afx_msg void OnBnClickedButtonSetUserTime();
afx_msg void OnBnClickedButtonSetThreshold();
};

@ -0,0 +1,49 @@
#pragma once
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN // 거의 사용되지 않는 내용은 Windows 헤더에서 제외합니다.
#endif
#include "targetver.h"
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 일부 CString 생성자는 명시적으로 선언됩니다.
// MFC의 공통 부분과 무시 가능한 경고 메시지에 대한 숨기기를 해제합니다.
#define _AFX_ALL_WARNINGS
#include <afxwin.h> // MFC 핵심 및 표준 구성 요소입니다.
#include <afxext.h> // MFC 확장입니다.
#include <afxdisp.h> // MFC 자동화 클래스입니다.
#ifndef _AFX_NO_OLE_SUPPORT
#include <afxdtctl.h> // Internet Explorer 4 공용 컨트롤에 대한 MFC 지원입니다.
#endif
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // Windows 공용 컨트롤에 대한 MFC 지원입니다.
#endif // _AFX_NO_AFXCMN_SUPPORT
#include <afxcontrolbars.h> // MFC의 리본 및 컨트롤 막대 지원
#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#endif

@ -0,0 +1,5 @@
// pch.cpp: 미리 컴파일된 헤더에 해당하는 소스 파일
#include "pch.h"
// 미리 컴파일된 헤더를 사용하는 경우 컴파일이 성공하려면 이 소스 파일이 필요합니다.

@ -0,0 +1,13 @@
// pch.h: 미리 컴파일된 헤더 파일입니다.
// 아래 나열된 파일은 한 번만 컴파일되었으며, 향후 빌드에 대한 빌드 성능을 향상합니다.
// 코드 컴파일 및 여러 코드 검색 기능을 포함하여 IntelliSense 성능에도 영향을 미칩니다.
// 그러나 여기에 나열된 파일은 빌드 간 업데이트되는 경우 모두 다시 컴파일됩니다.
// 여기에 자주 업데이트할 파일을 추가하지 마세요. 그러면 성능이 저하됩니다.
#ifndef PCH_H
#define PCH_H
// 여기에 미리 컴파일하려는 헤더 추가
#include "framework.h"
#endif //PCH_H

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

@ -0,0 +1,30 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++에서 생성한 포함 파일입니다.
// TimeSet.rc에서 사용되고 있습니다.
//
#define IDD_TIMESET_DIALOG 102
#define IDR_MAINFRAME 128
#define IDC_BUTTON_CONNECT 1000
#define IDC_COMBO_SERIAL_LIST 1001
#define IDC_EDIT_YEAR 1003
#define IDC_EDIT_MONTH 1004
#define IDC_EDIT_DATE 1005
#define IDC_EDIT_HOUR 1006
#define IDC_EDIT_MIN 1007
#define IDC_EDIT_SEC 1008
#define IDC_BUTTON_SET_USER_TIME 1009
#define IDC_BUTTON_SET_LOCAL_TIME 1010
#define IDC_EDIT_CO2_MIN 1011
#define IDC_EDIT_CO2_MAX 1012
#define IDC_BUTTON_SET_THRESHOLD 1013
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1012
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

@ -0,0 +1,8 @@
#pragma once
// SDKDDKVer.h를 포함하면 최고 수준의 가용성을 가진 Windows 플랫폼이 정의됩니다.
// 이전 Windows 플랫폼에 대해 응용 프로그램을 빌드하려는 경우에는 SDKDDKVer.h를 포함하기 전에
// WinSDKVer.h를 포함하고 _WIN32_WINNT 매크로를 지원하려는 플랫폼으로 설정하십시오.
#include <SDKDDKVer.h>
Loading…
Cancel
Save