📄 comm.cpp
字号:
// comm.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "comm.h"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
int ExecSQL(char *SqlText); //声明数据库添加,删除,更新操作的函数无需返回记录集
int SelectSQL(char *SqlText, int n, char Ret[][200], int *RowCount);//声明数据库查询的函数,返回类型为记录集
int GetPF(int xh, char *pfbh0, float pzl0, int chn[2], float *tjjzl, float *oilzl, int *oilmc, float *oildw);//函数声明
void SaveXL();
struct TJJ{
int bh;
char mc[40];
float llz;
float sjz;
float xsz;
int n;
}tjj[50]; //定义结构体TJJ,TJJ类型一维数组tjj
struct PF{
int xh;
int ch;
int jlh;
char mc[30];
float bl;
float llz;///////////
long hh;
long hi;
long ll;
float tql;//////////////
float tql0;
float bpz;//////////////
float sjz;
float csz;
float xsz;
float bjwc;///////////////
float yxwc;/////////////////
} pf1[5][20],pf2[5][20],pf3[5][20],pf4[5][20],pf5[5][20];//定义结构体PF,PF类型二维数组pf1,pf2,pf3,pf4,pf5
static int end1[5],end2[5],end3[5],end4[5],end5[5], ppend1, ppend2; //定义一维整数数组用于保存每个仪表称的称重次数
static int start1, pover1, pl1 ,pp1,pp2, stch[6]; //定义一号系统的开始及批次数据
//static int start10, start20;
static int start2, pover2, pl2;
static int start3, pover3, pl3;
static int start4, pover4, pl4;
static int start5, pover5, pl5;
static float w_jcz1;//仪表检测值,误差值,变频值
static float w_jcz2;
static float w_jcz3;
static float w_jcz4;
static float w_jcz5;
static float w_jcz6;
static float ybwc1,ybwc2,ybwc3,ybwc4,ybwc5,ybwc6;
static int hc_sj, hhj1_flsj, hhj2_flsj;
static int hcd1_flsj, hcd2_flsj;
static int c5_flsj, c6_flsj;
static int c_flsj, cm_sj, hhm_sj;
static int fl_n1,fl_n2,fl_n3,fl_n4,fl_n5; //一号系统各秤放料标志
static int fl_end1,fl_end2,fl_end3,fl_end4,fl_end5;//一号系统各秤批次
static float pzl1,pzl2;
static int scpf_XH=1, hhsj1,hhsj2;
char pfbh1[5],pfmc1[30],pfbh2[5],pfmc2[30];
static BOOL tql_chk=0, tql_mod=0;
static int PL_END1, PL_END2;
static HANDLE m_hComFile=0, m_hCom1=0, m_hCom2=0, m_hCom3=0, m_hCom4=0, m_hCom5=0, m_hCom6=0;
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// This is an example of an exported variable
COMM_API int nComm=0;
// This is an example of an exported function.
COMM_API int fnComm(void)
{
return 42;
}
// This is the constructor of a class that has been exported.
// see comm.h for the class definition
CComm::CComm()
{
return;
}
//=================================================
void delay(long DealyTime)
{
SYSTEMTIME sysTime;
long End_time, Start_time;
GetLocalTime(&sysTime);
Start_time= (sysTime.wHour*3600 + sysTime.wMinute*60 +
sysTime.wSecond)*1000 + sysTime.wMilliseconds;
End_time=Start_time;
while((End_time-Start_time) < DealyTime)
{
GetLocalTime(&sysTime);
End_time= (sysTime.wHour*3600 + sysTime.wMinute*60 +
sysTime.wSecond)*1000 + sysTime.wMilliseconds;
}
}
//=================================================
int CloseCom(void)
{
if(m_hComFile==0)return 0;
CloseHandle(m_hComFile);
m_hComFile=0;
return 0;
}
//=================================================
int SetCom(char *comport)
{
DCB dcb ; //定义设备控制块结构
COMMTIMEOUTS timeouts ; //定义超时结构,并填写该结构
char Msg[30];
/*1. 打开串行通信设备。在VC中使用CreateFile函数打开串口,CreateFile将返回串口的句柄。
该句柄将被用于后续的通信操作,并贯穿整个通信过程。当采用异步方式时,
CreateFile函数的参数fdwAttrsAndFlags必须设为FILE_FLAG_ OVERLAPPED*/
if(m_hComFile!=0) return 0;
m_hComFile =CreateFile(comport,
GENERIC_READ | GENERIC_WRITE, // 允许读写操作
0, //此项必须为0
NULL, // 安全设置
OPEN_EXISTING, //设置打开方式
NULL, //FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,//使用异步通信标志 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED
NULL );
strcpy(Msg,comport);
strcat(Msg, "通信口打开错误!");
if(m_hComFile<=0)
{
MessageBox(NULL,"错误信息",Msg,MB_OK);
return 1;
}
/*2. 指定并初始化读写缓冲区。程序通过调用SetupComm函数来指定读写缓冲区的大小,
并执行重新分配内部输入和输出缓冲的任务,用PurgeComm函数对输入和输出缓冲进行初始化*/
//设置事件驱动的类型
SetCommMask(m_hComFile, EV_RXCHAR | EV_TXEMPTY );
//设置输入、输出缓冲区的大小
SetupComm(m_hComFile, 128,128) ;
//清空输入、输出缓冲区
PurgeComm(m_hComFile, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
/*3.设置串口属性,配置DCB结构。当用CreateFile函数完成串口打开操作时,
默认继承设备控制块(DCB结构)设置。通过调用GetCommState函数读取当前串口设备控制块DCB设置,
修改后通过SetCommState函数将其写入。也可以使用GetCommProperties获取COMMPROP结构,
其中记载了系统支持的各项设置,包括当前所使用的串行设备、数据传输波特率、输入输出缓冲区大小等。*/
GetCommState(m_hComFile, &dcb ) ; //读取串口原来的参数设置
dcb.BaudRate =9600;
dcb.ByteSize =7;
dcb.Parity = EVENPARITY;
dcb.StopBits = ONESTOPBIT ;
//dcb.fBinary = TRUE ;
//dcb.fParity = FALSE;
SetCommState(m_hComFile, &dcb ) ; //串口参数配置
/*4. 设置超时值。串口打开后,I/O操作的超时值采用默认值。超时值的设置与结构COMMTIMEOUTS及
函数GetCommTimeouts和SetCommTimeouts有关。用GetCommTimeouts函数可以获得当前I/O操作的超时
值配置,而调用SetCommTimeouts函数可以修改此配置,*/
timeouts.ReadIntervalTimeout = 1000;
timeouts.ReadTotalTimeoutMultiplier = 100;
timeouts.ReadTotalTimeoutConstant = 1000;
timeouts.WriteTotalTimeoutMultiplier = 1;
timeouts.WriteTotalTimeoutConstant=1000;
SetCommTimeouts(m_hComFile, &timeouts); //设置读写操作所允许的超时
/*其中,区间超时(ReadIntervalTimeout)指的是在读取两个字符之间的时间间隔,它仅对从端口中
读取数据有效;总超时指的是当读或写特定的字节数需要的总时间超过某一阈值时,超时触发。
超时的计算公式如下:
ReadTotalTimeout= (ReadTotalTimeoutMultiplier * bytes_to_read)+ ReadToTaltimeoutConstant
WriteTotalTimeout = (WriteTotalTimeoutMuliplier * bytes_to_write) + WritetoTotalTimeoutConstant */
return 0;
}
//=================================================
int CloseCom1(char *Com)
{
if(strcmp(Com, "com1")==0) CloseHandle(m_hCom1);
if(strcmp(Com, "com2")==0) CloseHandle(m_hCom2);
if(strcmp(Com, "com3")==0) CloseHandle(m_hCom3);
if(strcmp(Com, "com4")==0) CloseHandle(m_hCom4);
if(strcmp(Com, "com5")==0) CloseHandle(m_hCom5);
if(strcmp(Com, "com6")==0) CloseHandle(m_hCom6);
return 0;
}
//=====================================================
//Parity==0, NOPARITY(无效验);==1, ODDPARITY(奇效验);==2, EVENPARITY(偶效验)
int SetCom1(char *comport, int BaudRate, int Parity, int ByteSize)
{
DCB dcb ; //定义设备控制块结构
COMMTIMEOUTS timeouts ; //定义超时结构,并填写该结构
char Msg[30];
HANDLE m_hCom=0;
/*1. 打开串行通信设备。在VC中使用CreateFile函数打开串口,CreateFile将返回串口的句柄。
该句柄将被用于后续的通信操作,并贯穿整个通信过程。当采用异步方式时,
CreateFile函数的参数fdwAttrsAndFlags必须设为FILE_FLAG_ OVERLAPPED*/
if(m_hCom!=0) return 0;
m_hCom =CreateFile(comport,
GENERIC_READ | GENERIC_WRITE, // 允许读写操作
0, //此项必须为0
NULL, // 安全设置
OPEN_EXISTING, //设置打开方式
NULL, //FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,//使用异步通信标志 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED
NULL );
strcpy(Msg,comport);
strcat(Msg, "通信口打开错误!");
if(m_hCom<=0)
{
MessageBox(NULL,"错误信息",Msg,MB_OK);
return 1;
}
/*2. 指定并初始化读写缓冲区。程序通过调用SetupComm函数来指定读写缓冲区的大小,
并执行重新分配内部输入和输出缓冲的任务,用PurgeComm函数对输入和输出缓冲进行初始化*/
//设置事件驱动的类型
SetCommMask(m_hCom, EV_RXCHAR | EV_TXEMPTY );
//设置输入、输出缓冲区的大小
SetupComm(m_hCom, 128,128) ;
//清空输入、输出缓冲区
PurgeComm(m_hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
/*3.设置串口属性,配置DCB结构。当用CreateFile函数完成串口打开操作时,
默认继承设备控制块(DCB结构)设置。通过调用GetCommState函数读取当前串口设备控制块DCB设置,
修改后通过SetCommState函数将其写入。也可以使用GetCommProperties获取COMMPROP结构,
其中记载了系统支持的各项设置,包括当前所使用的串行设备、数据传输波特率、输入输出缓冲区大小等。*/
GetCommState(m_hCom, &dcb ) ; //读取串口原来的参数设置
dcb.BaudRate =BaudRate;
dcb.ByteSize =ByteSize;
dcb.Parity = Parity;
dcb.StopBits = ONESTOPBIT ;
//dcb.fBinary = TRUE ;
//dcb.fParity = FALSE;
SetCommState(m_hCom, &dcb ) ; //串口参数配置
/*4. 设置超时值。串口打开后,I/O操作的超时值采用默认值。超时值的设置与结构COMMTIMEOUTS及
函数GetCommTimeouts和SetCommTimeouts有关。用GetCommTimeouts函数可以获得当前I/O操作的超时
值配置,而调用SetCommTimeouts函数可以修改此配置,*/
timeouts.ReadIntervalTimeout = 1000;
timeouts.ReadTotalTimeoutMultiplier = 100;
timeouts.ReadTotalTimeoutConstant = 3000;
timeouts.WriteTotalTimeoutMultiplier = 1;
timeouts.WriteTotalTimeoutConstant=2000;
SetCommTimeouts(m_hCom, &timeouts); //设置读写操作所允许的超时
/*其中,区间超时(ReadIntervalTimeout)指的是在读取两个字符之间的时间间隔,它仅对从端口中
读取数据有效;总超时指的是当读或写特定的字节数需要的总时间超过某一阈值时,超时触发。
超时的计算公式如下:
ReadTotalTimeout= (ReadTotalTimeoutMultiplier * bytes_to_read)+ ReadToTaltimeoutConstant
WriteTotalTimeout = (WriteTotalTimeoutMuliplier * bytes_to_write) + WritetoTotalTimeoutConstant */
if(strcmp(comport, "com1")==0) m_hCom1=m_hCom;
if(strcmp(comport, "com2")==0) m_hCom2=m_hCom;
if(strcmp(comport, "com3")==0) m_hCom3=m_hCom;
if(strcmp(comport, "com4")==0) m_hCom4=m_hCom;
if(strcmp(comport, "com5")==0) m_hCom5=m_hCom;
if(strcmp(comport, "com6")==0) m_hCom6=m_hCom;
return 0;
}
//=====================================================
int yb_tx1(char *Com, char *ComSend, char *ComRecceive, long delaytime, int sendlen)
{
BOOL fWriteStat;
OVERLAPPED overwrite,overread;
BOOL fReadStat;
DWORD dwBytesToWrite, dwBytesWritten;
DWORD dwLength,dwBytesRead;
char lpBuffer[5],ss[50];
long k=0, ErrCode=0;
HANDLE m_hCom=0;
if(strcmp(Com, "com1")==0) m_hCom=m_hCom1;
if(strcmp(Com, "com2")==0) m_hCom=m_hCom2;
if(strcmp(Com, "com3")==0) m_hCom=m_hCom3;
if(strcmp(Com, "com4")==0) m_hCom=m_hCom4;
if(strcmp(Com, "com5")==0) m_hCom=m_hCom5;
if(strcmp(Com, "com6")==0) m_hCom=m_hCom6;
if(m_hCom==0)
{
// MessageBox(NULL,"通信口没有打开!","错误信息",MB_OK);
return 1;
}
// *ComSend 存放待发送的数据
//清空输入、输出缓冲区
PurgeComm(m_hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
/*5. 进行串行数据通信。调用函数ReadFile和WriteFile读写串口。若采用异步通信方式,
两函数中最后一个参数为指向OVERLAPPED结构的非空指针,在读写函数返回值为FALSE的情况下,
调用GetLastError函数,返回值为ERROR_IO_PENDING,表明I/O操作悬挂,即操作转入后台继续执行。
此时,可以用WaitForSingleObject函数来等待结束信号并设置最长等待时间。下面的例子中,
在主线程中发送命令,用一个辅助线程来监视串口,有数据到达时依靠事件驱动读入数据并向主线程报告。*/
//设置用于异步操作的OVERLAPPED结构
overwrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
//写数据
dwBytesToWrite=sendlen; //要发送的数据的长度
//fWriteStat = WriteFile(m_hCom, ComSend, dwBytesToWrite, &dwBytesWritten, &overwrite);
fWriteStat = WriteFile(m_hCom, ComSend, dwBytesToWrite, &dwBytesWritten, NULL);
//sprintf(ss,"%d",dwBytesWritten);
//MessageBox(NULL,ComSend,ss,MB_OK);
if (!fWriteStat){
if (GetLastError() == ERROR_IO_PENDING)
{
// MessageBox(NULL,"发送数据错误!","错误信息",MB_OK);
}
}
//延时读
delay(delaytime);
//读数据
/*
overread.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
dwLength=1;
lpBuffer[0]=0;
ComRecceive[0]=0;
while(lpBuffer[0]!=10)
{
k++;
//fReadStat = ReadFile(m_hCom,lpBuffer,dwLength, &dwBytesRead,&overread);
fReadStat = ReadFile(m_hCom,lpBuffer,dwLength, &dwBytesRead, NULL);
if (!fReadStat){
if (GetLastError() == ERROR_IO_PENDING)
{
MessageBox(NULL,"未接收到数据,请加大延时时间","错误信息",MB_OK);
}
}
if(k>30) break;
if(dwBytesRead>0)
{
lpBuffer[1]=0;
strcat(ComRecceive,lpBuffer);
}
}
// MessageBox(NULL,ComRecceive,"已经接收的数据",MB_OK);
*/
return 0;
}
//=====================================================
int yb_tx(int id, char *ComSend, char *ComRecceive, long delaytime)
{
BOOL fWriteStat;
OVERLAPPED overwrite,overread;
BOOL fReadStat;
DWORD dwBytesToWrite, dwBytesWritten;
DWORD dwLength,dwBytesRead;
char lpBuffer[5];
long k=0, ErrCode=0;
//==================== 绕过晚上12点 ===============================
char strTime[30];
SYSTEMTIME sysTime;
GetLocalTime(&sysTime);
while(sysTime.wHour==23 && sysTime.wMinute==59 && (sysTime.wSecond>57))
{
GetLocalTime(&sysTime);
}
//=================================================================
if(id==1) m_hComFile = m_hCom1;
if(id==2) m_hComFile = m_hCom2;
if(id==3) m_hComFile = m_hCom3;
if(id==4) m_hComFile = m_hCom4;
if(m_hComFile==0)
{
MessageBox(NULL,"通信口没有打开!","错误信息",MB_OK);
return 1;
}
// *ComSend 存放待发送的数据
//清空输入、输出缓冲区
PurgeComm(m_hComFile, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
/*5. 进行串行数据通信。调用函数ReadFile和WriteFile读写串口。若采用异步通信方式,
两函数中最后一个参数为指向OVERLAPPED结构的非空指针,在读写函数返回值为FALSE的情况下,
调用GetLastError函数,返回值为ERROR_IO_PENDING,表明I/O操作悬挂,即操作转入后台继续执行。
此时,可以用WaitForSingleObject函数来等待结束信号并设置最长等待时间。下面的例子中,
在主线程中发送命令,用一个辅助线程来监视串口,有数据到达时依靠事件驱动读入数据并向主线程报告。*/
//设置用于异步操作的OVERLAPPED结构
//overwrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
//写数据
dwBytesToWrite=strlen(ComSend); //要发送的数据的长度
//fWriteStat = WriteFile(m_hComFile, ComSend, dwBytesToWrite, &dwBytesWritten, &overwrite);
fWriteStat = WriteFile(m_hComFile, ComSend, dwBytesToWrite, &dwBytesWritten, NULL);
if (!fWriteStat){
if (GetLastError() == ERROR_IO_PENDING)
{
MessageBox(NULL,"发 送 数 错 误!","错误信息",MB_OK);
}
}
//延时读
delay(delaytime);
//读数据
//overread.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
dwLength=1;
lpBuffer[0]=0;
ComRecceive[0]=0;
k=0;
while(lpBuffer[0]!=10)
{
k++;
// fReadStat = ReadFile(m_hComFile,lpBuffer,dwLength, &dwBytesRead,&overread);
fReadStat = ReadFile(m_hComFile,lpBuffer,dwLength, &dwBytesRead, NULL);
if (!fReadStat){
if (GetLastError() == ERROR_IO_PENDING)
{
// MessageBox(NULL,"未接收到数据,请加大延时时间","错误信息",MB_OK);
}
}
if(k>40)
{
MessageBox(NULL,"","仪表通信错误!",MB_OK);
return 1;
}
if(dwBytesRead>0)
{
lpBuffer[1]=0;
strcat(ComRecceive,lpBuffer);
}
else
{
// MessageBox(NULL,ComRecceive,"接收数据错误!",MB_OK);
return 1;
}
}
// MessageBox(NULL,ComRecceive,"已经接收的数据",MB_OK);
return 0;
}
//=============================================
int yb_read(int id, double *zl)
{
char yb_id[]={5,'I','D','1','8',13,10,0};
char yb_send[]={'R','E','A','D',13,10,0};
char yb_out[30];
int len, n1, n2;
if(id==2)yb_id[3]='2';
if(id==3)yb_id[3]='3';
if(id==4)yb_id[3]='4';
if(id==5)yb_id[3]='5';
// n1=yb_tx(id, yb_id, yb_out,200);
// if(n1==1)
// {
// MessageBox(NULL,"" ,"读仪表数据000",MB_OK);
// return 1;
// }
n2=yb_tx(id, yb_send, yb_out,200);
if(n2==1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -