扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
说起来挺麻烦了,建议你看看《Visual C++/Turbo C串口通信编程实践(第2版)》2007年9月第2版。会对你有些帮助。
公司主营业务:网站设计制作、成都网站建设、移动网站开发等业务。帮助企业客户真正实现互联网宣传,提高企业的竞争能力。成都创新互联是一支青春激扬、勤奋敬业、活力青春激扬、勤奋敬业、活力澎湃、和谐高效的团队。公司秉承以“开放、自由、严谨、自律”为核心的企业文化,感谢他们对我们的高要求,感谢他们从不同领域给我们带来的挑战,让我们激情的团队有机会用头脑与智慧不断的给客户带来惊喜。成都创新互联推出雨城免费做网站回馈大家。
如果你是用C++编程对串口进行通信的话,肯定要使用API函数,其中要用到创建线程和串口通信2种函数。
用二维数组char Arri[m][n]来说明,发送二维数组:如果你的长度不大的话,其实就是你有m个n个长的char型数据,可以
for(int i = 0; i m; i++) //这只是举例,真正传输时要看具体的情况
{
WriteFile(Arri[i]);
}
来完成。
你看看接收并回传给串口助手的数据是否正确
if(Rev_Data == "t")
{
Sector_erase(0x2000); //扇区擦除。。。。把这一句注释掉,再看看结果
P1 = 0x55;
delay(5);
flag = 1;
i = 0;
}
可以两个方式:
1、如果是 MSComm控件方式可以加入三个控件分别控制;在OnComm事件里面接收数据;用m_Comm.SetOutput(COleVariant(m_SendData));发送数据;
2、把 MSComm控件 打包在一个类里面,自己写初始化和发送接收函数;
编程原理
程序1为查询通信方式接口程序,为一典型的数据采集例程。其中bioscom()函数初始化COM1(此函数实际调用BIOS
INT
14H中断0号功能)。这样在程序中就避免了具体设置波特率因子等繁琐工作,只需直接访问发送/接收寄存器(3F8H)和线路状态寄存
我写的串口通信代码比较长,给几个关键函数你吧,可实现PC与单片机的双工通信
/*串口通讯 单片机晶振:11.0592MHz
T1工作于方式2 波特率=2^smod*fosc/32/12/(256-X)*/
#includecommon.h
void do_uart(void); //串口接收执字符时的操作
/*串口发送字符串 */
void sendstr(uchar *p)
{
while(*p!='\0')
{ SBUF=*p; //待发送的数据写入缓冲区
while(!TI); //等待发送完成
TI=0; //清零发送标志位
p++; //指针加1
cnt_s++; //发送计数
}
}
/*串口接收中断函数*/
void int_rec(void) interrupt 4 using 2
{
if(RI) //查询接收标志位(有数据发送过来时置为1)
{
RI = 0; //接收标志位清零
// sendchar(SBUF);//让从电脑上传到单片机的数据,传回的电脑显示
do_uart();//对接受到得字符操作
}
}
/*串口初始化*/
void com_init(uint baud)
{
SCON = 0x50; //串口工作方式为1,串行允许接受
TMOD = 0x21; //定时器1工作在方式2 定时器0工作在方式1
//PCON = 0x80; //SMOD = 1; 波特率加倍
TH1=256-fosc/32/12/baud;
TL1=TH1;
ES = 1; //开串口中断
TR1 = 1; //允许定时器1工作
EA = 1; //开总中断
}
void sendchar(uchar uart_dat) //串口发送字符函数
{
SBUF = uart_dat; //待发送的数据写入缓冲区
while(!TI); //等待发送完成
TI = 0; //清零发送标志位
cnt_s++; //发送计数
}
基本方法是使用CreateFile来建立一个串口文件,然后用overlap的方式进行读写
#define SERAIL_PORT_BUF_MAX (1024*8)
typedef HRESULT (*PFN_CMD_PARSE_DATA)(HANDLE hParseApp, LPCSTR szRspCmd, int nCmdLen);
class CUsbSrvApp// : public CWinApp
{
public:
CUsbSrvApp();
~CUsbSrvApp();
BOOL OnSendData(const char *szBuf, int nLen);// 发送数据
int ComConnect(CString strPort); // 连接COM口
HANDLE OpenComPort(CString strPort, int nBaudRate, int nDataBits, int nStopBits, int nParity, int nFlowCtrlType); // 打开串口
void Close(); // 关闭串口
HANDLE m_hCom;
BOOL m_bConnected;
OVERLAPPED m_OverlappedRead;
OVERLAPPED m_OverlappedWrite;
CWinThread *m_pThread;
PFN_CMD_PARSE_DATA m_pRspCmdFunc; // 用来处理接受数据的CALLBACK
HANDLE m_hParseApp;
};
CUsbSrvApp::CUsbSrvApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
m_bConnected = false;
m_hCom = NULL;
m_pRspCmdFunc = NULL;
}
CUsbSrvApp::~CUsbSrvApp()
{
}
//打开串口通信,并返回串口句柄
HANDLE CUsbSrvApp::OpenComPort(CString strPortName,
int nBaudRate,
int nDataBits,
int nStopBits,
int nParity,
int nFlowCtrlType)
{
DCB dcb;
COMMTIMEOUTS CommTimeOuts ;
COMMCONFIG ComConfig;
HANDLE hComPort;
CString strPort;
strPort.Format("\\\\.\\%s",strPortName); // COM口的文件名应该是 \\.\COMXX
//打开窗口其实就是创建一个文件
hComPort = CreateFile(strPort,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
NULL);
if (INVALID_HANDLE_VALUE == hComPort)
return INVALID_HANDLE_VALUE;
// 设置一些COM口通讯参数和OVERLAP
CommTimeOuts.ReadIntervalTimeout = -1;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0x1388;
SetCommTimeouts( m_hCom, CommTimeOuts ) ;
SetDefaultCommConfig(strPortName, ComConfig, sizeof(COMMCONFIG));
GetCommState(m_hCom, dcb ) ;
dcb.BaudRate = nBaudRate;
dcb.ByteSize = nDataBits;
dcb.StopBits = nStopBits;
dcb.fParity = (NOPARITY != nParity);
dcb.Parity = nParity;
//set the receive char
dcb.EvtChar = 0x0D;
switch(nFlowCtrlType)
{
case 0: //no flow control
break;
case 1://HARD_FLOW_CTRL:
dcb.fOutxCtsFlow = TRUE;
dcb.fOutxDsrFlow = TRUE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = TRUE;
dcb.fRtsControl = RTS_CONTROL_TOGGLE;
break;
case 2://SOFT_FLOW_CTRL:
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
break;
}
BuildCommDCB(_T("baud=115200 parity=N data=8 stop=1"),dcb);
SetCommState(hComPort, dcb ) ;
SetCommMask(hComPort, 0);
SetCommMask(hComPort, EV_RXCHAR|EV_CTS|EV_DSR|EV_RLSD|EV_RING);
SetupComm( hComPort, SERAIL_PORT_BUF_MAX,SERAIL_PORT_BUF_MAX) ;
//clear read and write buffer
PurgeComm( hComPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
return hComPort;
}
void CUsbSrvApp::Close()
{
if(m_bConnected)
{
m_bConnected = false;
CloseHandle(m_hCom);
m_hCom = NULL;
}
}
// 这个线程是监视串口数据,一旦有数据则读取并调用CALLBACK通知客户端
UINT ReceiveComData(LPVOID pParam)
{
CUsbSrvApp *pUsbSrv = (CUsbSrvApp *)pParam;
HANDLE hComPort = pUsbSrv-m_hCom;
DWORD dwEvtMask=0;
DWORD dwErrorFlags;
SetCommMask( hComPort, EV_RXCHAR);
OVERLAPPED osRead;
osRead.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
DWORD dwTransfer = 0;
while(pUsbSrv-m_bConnected)
{
if( !WaitCommEvent( hComPort, dwEvtMask,osRead))
{
if( GetLastError()== ERROR_IO_PENDING)
{
WaitForSingleObject(osRead.hEvent, INFINITE);
if(dwEvtMaskEV_RXCHAR==EV_RXCHAR)
{
COMSTAT ComStat={0} ;
DWORD dwReadLen = 0;
DWORD dwBytesRead = 0;
DWORD dwTotalLen = 0;
ClearCommError(hComPort, dwErrorFlags, ComStat );
dwTotalLen = ComStat.cbInQue;
dwReadLen = (SERAIL_PORT_BUF_MAX dwTotalLen)?dwTotalLen:SERAIL_PORT_BUF_MAX;
BYTE *pBuf = new BYTE[dwTotalLen+1];
memset(pBuf, 0 , dwTotalLen+1);
DWORD nReadBufLen=0;
while(dwTotalLen0)
{
if(FALSE == ReadFile( hComPort, pBuf+nReadBufLen,dwReadLen, dwBytesRead,pUsbSrv-m_OverlappedRead))
{
if(GetLastError() == ERROR_IO_PENDING)
{
GetOverlappedResult(hComPort,osRead, dwTransfer, TRUE );
}
break;
}
nReadBufLen +=dwBytesRead;
dwTotalLen -=dwBytesRead;
dwReadLen -= dwBytesRead;
dwReadLen = (SERAIL_PORT_BUF_MAXdwReadLen)?dwReadLen:SERAIL_PORT_BUF_MAX;
}
if(pUsbSrv-m_pRspCmdFunc!=NULLnReadBufLen!=0)
{
pUsbSrv-m_pRspCmdFunc(pUsbSrv-m_hParseApp, (char*)pBuf,nReadBufLen);
}
delete pBuf;
ClearCommError(hComPort, dwErrorFlags, ComStat );
int len =0;//= m_retList.GetSize();
}//endif if(dwEvtMaskEV_RXCHAR==EV_RXCHAR)
}//endif if( GetLastError()== ERROR_IO_PENDING)
}//endif if( !WaitCommEvent( hComPort, dwEvtMask,o))
else
{
if(GetLastError() == ERROR_IO_PENDING) {
GetOverlappedResult(hComPort, osRead, dwTransfer, TRUE ); // sleep thread
}
}
Sleep(1);
} //endwhile while(m_bConnected)
return 0;
}
int CUsbSrvApp::ComConnect(CString strPort)
{
int nBaudRate = 115200;
int nDataBits = 8;
int nStopBits = 1;
int nParity = 0;
int nFlowCtrl = 1;
if (NULL != m_hCom || m_bConnected)
{
return 0;
}
m_hCom = OpenComPort(strPort,nBaudRate,nDataBits,nStopBits,nParity,nFlowCtrl);
if( INVALID_HANDLE_VALUE == m_hCom)
{
m_hCom = NULL;
return 0;
}
memset( m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_pThread = AfxBeginThread( ReceiveComData,(void*)this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED ,NULL );
if( NULL == m_pThread )
{
CloseHandle( m_hCom );
m_hCom = NULL;
return FALSE;
}
else
{
m_bConnected = TRUE;
m_pThread-ResumeThread( );
}
return TRUE;
}
int CUsbSrvApp::OnSendData(const char *szBuf, int nLen)
{
BOOL bWriteStat;
BOOL bWrite = TRUE;
DWORD dwBytesWrite = 0;
DWORD dwBytesWritten = 0;
int dwByteswrittenTotal = 0;
if (NULL == m_hCom)
return 0;
int nSentTimes=0;
while(dwByteswrittenTotalnLennSentTimes10)
{
nSentTimes++;
dwBytesWrite = nLen-dwByteswrittenTotal;
bWriteStat = WriteFile( m_hCom, szBuf+dwByteswrittenTotal, dwBytesWrite, dwBytesWritten, m_OverlappedWrite );
if( !bWriteStat)
{
if ( GetLastError() == ERROR_IO_PENDING )
{
dwBytesWritten = 0;
bWrite = FALSE;
}
}
if (!bWrite)
{
bWrite = TRUE;
bWriteStat = GetOverlappedResult(m_hCom, // Handle to COMM port
m_OverlappedWrite, // Overlapped structure
dwBytesWritten, // Stores number of bytes sent
TRUE); // Wait flag
//deal with the error code
}
dwByteswrittenTotal += dwBytesWritten;
}
if(dwByteswrittenTotalnLen)
return 0;
else
return 1;
}
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流