不好意思各位,最近两天没有时间上网,来晚了。
to jzrbcb(jzrbcb)
谢谢你的意见,你的这个类我也有,不过我也还是很感谢你的积极参与。
分我是会给的,不用担心:)只要问题解决。我现在使用的正好是 shornmao(死猫)现在的主意,所以已经不存在数据冲突了,所以我上位机的接收线程可以不用关闭了,但是又出现了新的问题,就是上次我提到的单片机接收数据的问题,可以给我个主意么?
to jerry921(jerry)
谢谢,能不能也帮我想一下:)
to hotxu()
我也是想要停下来处理按键事件,但是单片机要处理按键事件就必须发出按键中断请求,这时候不能够接收数据,要是这时候上位机正好发来查询请求单片机就会收不到,怎样平衡这两者(接收或者响应按键)?我原先的思路是判断固定上位机的查询和处理请求的时间,比如说是10毫秒,这时候单片机处于等待状态,这时候可以处理按键请求,等10毫秒后再重新开串口接收数据。但是这样做很浪费时间,因为上位机处理请求有时快有时慢,我只能按最慢的计算,耗时太大,不实用。有没有别的解决方法?
to shornmao(死猫)
你所说的方法我正在使用,我们可真是不谋而和啊:)
不过出现了上述问题,有什么好意见么?谢谢啦!
// add a null terminate if bytes_read < byteCount
// if the two are equal, there is no space to put a null terminator
if(bytes_read < MaxBytes)
buffer[bytes_read]='\0';
return bytes_read;
}
int TCommPort::ReadString(char *str, unsigned int MaxBytes)
{ //读字符串函数
VerifyOpen();
赶快加分!!!!!!
void TCommPort::SetByteSize(BYTE newByteSize) //设置端口缓冲区大小函数
{
BYTE oldByteSize = m_dcb.ByteSize; // make a backup of the old byte size
// 保存以前的缓冲区尺寸
m_dcb.ByteSize = newByteSize; // assign new size
// 重新设置缓冲器尺寸
if(m_CommOpen) // check for open comm port
{
if(!SetCommState(m_hCom,&m_dcb)) // try to set the new comm settings
{ // if failure
m_dcb.ByteSize = oldByteSize; // restore old byte size
// 如果设置未成功恢复以前的缓冲区尺寸
throw ECommError (ECommError::BAD_BYTESIZE); // bomb out
}
}
}
void TCommPort::SetParity(BYTE newParity) //设置端口奇偶为函数
{
BYTE oldParity = m_dcb.Parity; // make a backup of the old parity
//保存上一个奇偶位
m_dcb.Parity = newParity; // assign new parity
//设置新的奇偶位
if(m_CommOpen) // check for open comm port
{ // 判定串口是否打开
//SetCommState用于设置串口的所有可配置参数
//m_hCom设置串口句柄,m_dcb指向dcb结构指针,成功返回true,否则返回false
if(!SetCommState(m_hCom,&m_dcb)) // try to set the new comm settings
{ // if failure 表示设置参数失败
m_dcb.Parity = oldParity; // restore old parity
// 恢复设置前设置前的奇偶位
throw ECommError(ECommError::BAD_PARITY); // bomb out
// 抛出异常
}
}
}
void TCommPort::SetStopBits(BYTE newStopBits) //设置停止位函数
{
BYTE oldStopBits = m_dcb.StopBits; // make a backup of old #of stop bits
m_dcb.StopBits = newStopBits; // assign new # of stop bits
if(m_CommOpen) // check for open comm port
{
if(!SetCommState(m_hCom,&m_dcb)) // try to set the new comm settings
{ // if failure
m_dcb.StopBits = oldStopBits; // restore old # of stop bits
throw ECommError(ECommError::BAD_STOP_BITS); // bomb out
}
}
}
unsigned int TCommPort::GetBaudRate(void) //获得波特率函数
{
return m_dcb.BaudRate;
}
////////////////////////////////////////////////////////////////////////////////
///// TCommPort::TCommPort() (constructor)
/////
TCommPort::TCommPort() //构造函数
:m_CommOpen(false),
m_CommPort("COM1"),
m_hCom(0)
{
// initialize the comm port to N81 9600 baud communications. These values
// will be used to initialize the port if OpenCommPort is called before any
// of the SetXXXX functions are called.
m_dcb.DCBlength = sizeof(DCB); //初始化DCB结构的大小
m_dcb.BaudRate =9600; //初始化DCB结构的波特率为9600
m_dcb.ByteSize =8; //初始化UART发送和接收8位数
m_dcb.Parity =NOPARITY; //NOPARITY and friends are #defined in windows.h
//无奇偶位
m_dcb.StopBits =ONESTOPBIT; //ONESTOPBIT is also from windows.h
//无停止位
}
///// end of TCommPort::TCommPort (constructor)
////////////////////////////////////////////////////////////////////////////////
// we need to get the default settings while preserving the settings
// that we override. The DCB struct has 20 or so members. We override 4.
// Make of copy of the settings we care about.
DCB tempDCB;
tempDCB.BaudRate = m_dcb.BaudRate;
tempDCB.ByteSize = m_dcb.ByteSize;
tempDCB.Parity = m_dcb.Parity;
tempDCB.StopBits = m_dcb.StopBits;
m_hCom = CreateFile(m_CommPort.c_str(), //打开串口名
GENERIC_READ | GENERIC_WRITE, //设置文件读写
0, /* comm devices must be opened w/exclusive-access */
//文件共享选项在串口中必须设为零
NULL, /* no security attrs */
//安全性能设为NULL
OPEN_EXISTING, /* comm devices must use OPEN_EXISTING */
//通讯中不能创建新串口,只能使用现有参数
0, /* not overlapped I/O */
//不使用重叠I/O
NULL /* hTemplate must be NULL for comm devices */
//串口使用中无意义
);
// If CreateFile fails, throw an exception. CreateFile will fail if the
// port is already open, or if the com port does not exist.
if(m_hCom == INVALID_HANDLE_VALUE) //CreateFile()失败
throw ECommError(ECommError::OPEN_ERROR);
// Now get the DCB properties of the port we just opened
if(!GetCommState(m_hCom,&m_dcb)) //如果不能获得串口状态则关闭串口
{
// something is hay wire, close the port and return
CloseHandle(m_hCom);
throw ECommError(ECommError::GETCOMMSTATE);
}
// dcb contains the actual port properties. Now copy our settings into this dcb
m_dcb.BaudRate = tempDCB.BaudRate;
m_dcb.ByteSize = tempDCB.ByteSize;
m_dcb.Parity = tempDCB.Parity;
m_dcb.StopBits = tempDCB.StopBits;
// now we can set the properties of the port with our settings.
if(!SetCommState(m_hCom,&m_dcb)) //如果不能获得串口状态则关闭串口
{
// something is hay wire, close the port and return
CloseHandle(m_hCom);
throw ECommError(ECommError::SETCOMMSTATE);
}
// set the intial size of the transmit and receive queues. These are
// not exposed to outside clients of the class either. Perhaps they should be?
// I set the receive buffer to 32k, and the transmit buffer to 9k (a default).
// 通过SetupComm函数初始化端口,默认接收缓冲区32K,发送缓冲区9K
// SetupComm函数初始化端口成功位真,否则未假
if(!SetupComm(m_hCom, 1024*32, 1024*9))
{
// something is hay wire, close the port and return
CloseHandle(m_hCom);
throw ECommError(ECommError::SETUPCOMM);
}
// These values are just default values that I determined empirically.
// Adjust as necessary. I don't expose these to the outside because
// most people aren't sure how they work (uhhh, like me included).
m_TimeOuts.ReadIntervalTimeout = 15; //以毫秒为单位的空闲现超时
m_TimeOuts.ReadTotalTimeoutMultiplier = 1; //字符间的超时值
m_TimeOuts.ReadTotalTimeoutConstant = 250; //与上一字符相加为总超时
m_TimeOuts.WriteTotalTimeoutMultiplier = 1;
m_TimeOuts.WriteTotalTimeoutConstant = 250;
if(!SetCommTimeouts(m_hCom, &m_TimeOuts))
{
// something is hay wire, close the port and return
CloseHandle(m_hCom);
throw ECommError(ECommError::SETCOMMTIMEOUTS);
}
// if we made it to here then success
m_CommOpen = true; //如果到这里说明已经打开端口
}
///// end of TCommPort::OpenCommPort
////////////////////////////////////////////////////////////////////////////////
void TCommPort::SetCommDCBProperties(DCB &properties) //设置DCB属性函数
{
// we need to act differently based on whether the port is already open or
// not. If it is open, then attempt to change the ports properties.
// If not open, then just make a copy of the new properties.
if(m_CommOpen) // port is open
{
if(!SetCommState(m_hCom,&properties)) // try to set the state directly
throw ECommError(ECommError::SETCOMMSTATE); // bomb out if failed
else // copy the new properties
m_dcb = properties; // if success
}
else // comm port is not open
m_dcb = properties; // best we can do is save a copy
}
///// end of TCommPort::SetCommProperties()
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void TCommPort::GetCommDCBProperties(DCB &properties) //获得DCB属性函数
{
properties = m_dcb;
}
///// end of TCommPort::GetCommDCBProperties()
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///// TCommPort::SetBaudRate()
/////
void TCommPort::SetBaudRate(unsigned int newBaud) //设置波特率函数
{
unsigned int oldBaudRate = m_dcb.BaudRate; // make a backup of the old baud rate
m_dcb.BaudRate = newBaud; // assign new rate
if(m_CommOpen) // check for open comm port
{
if(!SetCommState(m_hCom,&m_dcb)) // try to set the new comm settings
{ // if failure
m_dcb.BaudRate = oldBaudRate; // restore old baud rate
throw ECommError(ECommError::BAD_BAUD_RAT
void SetCommPort(const std::string & port); //设置打开串口名函数
std::string GetCommPort(void); //获得正在使用串口名函数
void SetBaudRate(unsigned int newBaud); //设置波特率函数
unsigned int GetBaudRate(void); //获得正在使用串口波特率函数
void SetParity(BYTE newParity); // see source for possible values
// 设置端口奇偶为函数
BYTE GetParity(void); //获得奇偶位函数
void SetByteSize(BYTE newByteSize); //设置端口缓冲区大小函数
BYTE GetByteSize(void);
void SetStopBits(BYTE newStopBits);
BYTE GetStopBits(void);
void SetCommDCBProperties(DCB &properties); // avoid using DCB interface
void GetCommDCBProperties(DCB &properties); // Use SetBaudRate et al instead
void GetCommProperties(COMMPROP &properties);
void WriteString(const char *outString);
void WriteBuffer(BYTE *buffer, unsigned int ByteCount);
void WriteBufferSlowly(BYTE *buffer, unsigned int ByteCount);
int ReadString(char *string, unsigned int MaxBytes);
int ReadBytes(BYTE *bytes, unsigned int byteCount);
void DiscardBytes(unsigned int MaxBytes);
void PurgeCommPort(void);
void FlushCommPort(void);
void PutByte(BYTE value);
BYTE GetByte();
unsigned int BytesAvailable(void);
bool GetConnected()
{
return m_CommOpen;
}
HANDLE GetHandle() // allow access to the handle in case the user needs to
{ // do something hardcore. Avoid this if possible
return m_hCom;
}
private:
// Note: the destructor of the commport class automatically closes the
// port. This makes copy construction and assignment impossible.
// That is why I privatize them, and don't define them. In order
// to make copy construction and assignment feasible, we would need
// to employ a reference counting scheme.
TCommPort(const TCommPort &); // privatize copy construction
TCommPort & operator=(const TCommPort&); // and assignment.
// this stuff is private because we want to hide these details from clients
bool m_CommOpen; //布尔变量判定串口是否打开
COMMTIMEOUTS m_TimeOuts; //COMMTIMEOUTS结构设定读写时的超时值
std::string m_CommPort;
DCB m_dcb; // a DCB is a windows structure used for configuring the port
HANDLE m_hCom; // handle to the comm port.
};