TTYDoc.cpp
上传用户:seaboy_04
上传日期:2013-02-24
资源大小:284k
文件大小:9k
源码类别:

其他行业

开发平台:

Visual C++

  1. // TTYDoc.cpp : implementation of the CTTYDoc class
  2. //
  3. #include "stdafx.h"
  4. #include "TTY.h"
  5. #include "commsetDlg.h"
  6. #include "TTYDoc.h"
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12. /////////////////////////////////////////////////////////////////////////////
  13. // CTTYDoc
  14. IMPLEMENT_DYNCREATE(CTTYDoc, CDocument)
  15. BEGIN_MESSAGE_MAP(CTTYDoc, CDocument)
  16. //{{AFX_MSG_MAP(CTTYDoc)
  17. ON_COMMAND(ID_API_CONNECT, OnApiConnect)
  18. ON_UPDATE_COMMAND_UI(ID_API_CONNECT, OnUpdateApiConnect)
  19. ON_COMMAND(ID_API_DISCONNECT, OnApiDisconnect)
  20. ON_UPDATE_COMMAND_UI(ID_API_DISCONNECT, OnUpdateApiDisconnect)
  21. ON_COMMAND(ID_API_SETTINGS, OnApiSettings)
  22. ON_UPDATE_COMMAND_UI(ID_API_SETTINGS, OnUpdateApiSettings)
  23. //}}AFX_MSG_MAP
  24. END_MESSAGE_MAP()
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CTTYDoc construction/destruction
  27. CTTYDoc::CTTYDoc()
  28. {
  29. // TODO: add one-time construction code here
  30. //初始化操作
  31. m_bConnected=FALSE;//断开连接菜单项无效
  32. m_pThread=NULL;
  33. m_nBaud = 9600;
  34. m_nDataBits = 8;
  35. m_bEcho = FALSE;
  36. m_bNewLine = FALSE;
  37. m_nParity = 0;
  38. m_sPort = "COM1";
  39. m_nStopBits = 0;
  40. }
  41. CTTYDoc::~CTTYDoc()
  42. {
  43. //程序结束时删除线程、关闭串口的操作
  44. if(m_bConnected)
  45. CloseConnection();
  46. // 删除事件句柄
  47. if(m_hPostMsgEvent)
  48. CloseHandle(m_hPostMsgEvent);
  49. if(m_osRead.hEvent)
  50. CloseHandle(m_osRead.hEvent);
  51. if(m_osWrite.hEvent)
  52. CloseHandle(m_osWrite.hEvent);
  53. }
  54. BOOL CTTYDoc::OnNewDocument()
  55. {
  56. if (!CDocument::OnNewDocument())
  57. return FALSE;
  58. ((CEditView*)m_viewList.GetHead())->SetWindowText(NULL);
  59. // TODO: add reinitialization code here
  60. // (SDI documents will reuse this document)
  61. // 为WM_COMMNOTIFY消息创建事件对象,手工重置,初始化为有信号的
  62. if((m_hPostMsgEvent=CreateEvent(NULL, TRUE, TRUE, NULL))==NULL)
  63. return FALSE;
  64. memset(&m_osRead, 0, sizeof(OVERLAPPED));
  65. memset(&m_osWrite, 0, sizeof(OVERLAPPED));
  66. // 为重叠读创建事件对象,手工重置,初始化为无信号的
  67. if((m_osRead.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL))==NULL)
  68. return FALSE;
  69. // 为重叠写创建事件对象,手工重置,初始化为无信号的
  70. if((m_osWrite.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL))==NULL)
  71. return FALSE;
  72. return TRUE;
  73. }
  74. /////////////////////////////////////////////////////////////////////////////
  75. // CTTYDoc serialization
  76. void CTTYDoc::Serialize(CArchive& ar)
  77. {
  78. // CEditView contains an edit control which handles all serialization
  79. ((CEditView*)m_viewList.GetHead())->SerializeRaw(ar);
  80. }
  81. /////////////////////////////////////////////////////////////////////////////
  82. // CTTYDoc diagnostics
  83. #ifdef _DEBUG
  84. void CTTYDoc::AssertValid() const
  85. {
  86. CDocument::AssertValid();
  87. }
  88. void CTTYDoc::Dump(CDumpContext& dc) const
  89. {
  90. CDocument::Dump(dc);
  91. }
  92. #endif //_DEBUG
  93. /////////////////////////////////////////////////////////////////////////////
  94. // CTTYDoc commands
  95. BOOL CTTYDoc::CanCloseFrame(CFrameWnd* pFrame) 
  96. {
  97. // TODO: Add your specialized code here and/or call the base class
  98. SetModifiedFlag(FALSE); // 将文档的修改标志设置成未修改
  99. return CDocument::CanCloseFrame(pFrame);
  100. }
  101. // 工作者线程,负责监视串行口
  102. UINT CommProc(LPVOID pParam)
  103. {
  104. OVERLAPPED os;
  105. DWORD dwMask, dwTrans;
  106. COMSTAT ComStat;
  107. DWORD dwErrorFlags;
  108. CTTYDoc *pDoc=(CTTYDoc*)pParam;
  109. memset(&os, 0, sizeof(OVERLAPPED));
  110. os.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL);
  111. if(os.hEvent==NULL)
  112. {
  113. AfxMessageBox("Can't create event object!");
  114. return (UINT)-1;
  115. }
  116. // Clear comm buffers at startup
  117. if (pDoc->m_hCom) // check if the port is opened
  118. PurgeComm(pDoc->m_hCom, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
  119. while(pDoc->m_bConnected)
  120. {
  121. ClearCommError(pDoc->m_hCom,&dwErrorFlags,&ComStat);
  122. if(ComStat.cbInQue)
  123. {
  124. // 无限等待WM_COMMNOTIFY消息被处理完
  125. WaitForSingleObject(pDoc->m_hPostMsgEvent, INFINITE);
  126. ResetEvent(pDoc->m_hPostMsgEvent);
  127. // 通知视图
  128. PostMessage(pDoc->m_hTermWnd, WM_COMMNOTIFY, EV_RXCHAR, 0);
  129. continue;
  130. }
  131. dwMask=0;
  132. if(!WaitCommEvent(pDoc->m_hCom, &dwMask, &os)) // 重叠操作
  133. {
  134. if(GetLastError()==ERROR_IO_PENDING)
  135. // 无限等待重叠操作结果
  136. GetOverlappedResult(pDoc->m_hCom, &os, &dwTrans, TRUE);
  137. else
  138. {
  139. CloseHandle(os.hEvent);
  140. return (UINT)-1;
  141. }
  142. }
  143. }
  144. CloseHandle(os.hEvent);
  145. return 0;
  146. }
  147. // 将指定数量的字符从串行口输出
  148. DWORD CTTYDoc::WriteComm(unsigned char *buf, DWORD dwLength)
  149. {
  150. BOOL fState;
  151. DWORD length=dwLength;
  152. COMSTAT ComStat;
  153. DWORD dwErrorFlags;
  154. ClearCommError(m_hCom,&dwErrorFlags,&ComStat);
  155. fState=WriteFile(m_hCom,buf,length,&length,&m_osWrite);
  156. if(!fState)
  157. {
  158. if(GetLastError()==ERROR_IO_PENDING)
  159. {
  160. GetOverlappedResult(m_hCom,&m_osWrite,&length,TRUE);// 等待
  161. }
  162. else
  163. length=0;
  164. }
  165. return length;
  166. }
  167. // 从串行口输入缓冲区中读入指定数量的字符
  168. DWORD CTTYDoc::ReadComm(unsigned char *buf, DWORD dwLength)
  169. {
  170. DWORD length=0;
  171. COMSTAT ComStat;
  172. DWORD dwErrorFlags;
  173. ClearCommError(m_hCom,&dwErrorFlags,&ComStat);
  174. length=min(dwLength, ComStat.cbInQue);
  175. ReadFile(m_hCom,buf,length,&length,&m_osRead);
  176. return length;
  177. }
  178. //菜单项"串口连接"的响应
  179. void CTTYDoc::OnApiConnect() 
  180. {
  181. // TODO: Add your command handler code here
  182. if(!OpenConnection())
  183. AfxMessageBox("Can't open connection");
  184. }
  185. //更新"串口连接"菜单项
  186. void CTTYDoc::OnUpdateApiConnect(CCmdUI* pCmdUI) 
  187. {
  188. // TODO: Add your command update UI handler code here
  189. pCmdUI->Enable(!m_bConnected);
  190. }
  191. //菜单项"断开连接"的响应函数
  192. void CTTYDoc::OnApiDisconnect() 
  193. {
  194. // TODO: Add your command handler code here
  195. CloseConnection(); 
  196. }
  197. //更新菜单项"断开连接"
  198. void CTTYDoc::OnUpdateApiDisconnect(CCmdUI* pCmdUI) 
  199. {
  200. // TODO: Add your command update UI handler code here
  201. pCmdUI->Enable(m_bConnected);
  202. }
  203. //菜单项"串行口设置" 的响应函数
  204. void CTTYDoc::OnApiSettings() 
  205. {
  206. // TODO: Add your command handler code here
  207. CCommSetDlg dlg;
  208. CString str;
  209. dlg.m_bConnected = m_bConnected;
  210. dlg.m_sPort = m_sPort;
  211. str.Format("%d", m_nBaud);
  212. dlg.m_sBaud = str;
  213. str.Format("%d", m_nDataBits);
  214. dlg.m_sDataBits = str;
  215. dlg.m_nParity = m_nParity;
  216. dlg.m_nStopBits = m_nStopBits;
  217. dlg.m_bEcho = m_bEcho;
  218. dlg.m_bNewLine = m_bNewLine;
  219. if(dlg.DoModal() == IDOK)
  220. {
  221. m_sPort = dlg.m_sPort;
  222. m_nBaud = atoi(dlg.m_sBaud);
  223. m_nDataBits = atoi(dlg.m_sDataBits);
  224. m_nParity = dlg.m_nParity;
  225. m_nStopBits = dlg.m_nStopBits;
  226. m_bEcho=dlg.m_bEcho;
  227. m_bNewLine=dlg.m_bNewLine;
  228. if(m_bConnected)
  229. if(!ConfigConnection())
  230. AfxMessageBox("Can't realize the settings!");
  231. }
  232. }
  233. //更新"串行口设置"菜单项
  234. void CTTYDoc::OnUpdateApiSettings(CCmdUI* pCmdUI) 
  235. {
  236. // TODO: Add your command update UI handler code here
  237. }
  238.  //配置串口连接
  239. BOOL CTTYDoc::ConfigConnection()
  240. {
  241. DCB dcb;
  242. if(!GetCommState(m_hCom, &dcb))
  243. return FALSE;
  244. dcb.fBinary=TRUE;
  245. dcb.BaudRate = m_nBaud; // 数据传输速率
  246. dcb.ByteSize = m_nDataBits; // 每字节位数
  247. dcb.fParity = TRUE;
  248. switch(m_nParity) // 校验设置
  249. {
  250. case 0: 
  251. dcb.Parity=NOPARITY;
  252. break;
  253. case 1: 
  254. dcb.Parity=EVENPARITY;
  255. break;
  256. case 2: 
  257. dcb.Parity=ODDPARITY;
  258. break;
  259. default:;
  260. }
  261. switch(m_nStopBits) // 停止位
  262. {
  263. case 0: 
  264. dcb.StopBits=ONESTOPBIT;
  265. break;
  266. case 1: 
  267. dcb.StopBits=ONE5STOPBITS;
  268. break;
  269. case 2:
  270. dcb.StopBits=TWOSTOPBITS;
  271. break;
  272. default:;
  273. }
  274. // 硬件流控制设置
  275. dcb.fOutxCtsFlow = FALSE;  //如果仅使用TX、RX、GND三根线连接设置为FALSE,否则为TRUE
  276. dcb.fRtsControl = RTS_CONTROL_ENABLE;
  277. // XON/XOFF流控制设置
  278. dcb.fInX=dcb.fOutX = FALSE; //如果仅使用TX、RX、GND三根线连接设置为FALSE,否则为TRUE
  279. dcb.XonChar = XON;
  280. dcb.XoffChar = XOFF;
  281. dcb.XonLim = 50;
  282. dcb.XoffLim = 50;
  283. return SetCommState(m_hCom, &dcb);
  284. }
  285. // 打开并配置串行口,建立工作者线程
  286. BOOL CTTYDoc::OpenConnection()
  287. {
  288. COMMTIMEOUTS TimeOuts;
  289. POSITION firstViewPos;
  290. CView *pView;
  291. firstViewPos=GetFirstViewPosition();
  292. pView=GetNextView(firstViewPos);
  293. m_hTermWnd=pView->GetSafeHwnd();
  294. if(m_bConnected)
  295. return FALSE;
  296. m_hCom=CreateFile(m_sPort, GENERIC_READ | GENERIC_WRITE, 0, NULL,
  297. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 
  298. NULL); // 重叠方式
  299. if(m_hCom==INVALID_HANDLE_VALUE)
  300. return FALSE;
  301. SetupComm(m_hCom,MAXBLOCK,MAXBLOCK);
  302. SetCommMask(m_hCom, EV_RXCHAR);
  303. // 把间隔超时设为最大,把总超时设为0将导致ReadFile立即返回并完成操作
  304. TimeOuts.ReadIntervalTimeout=MAXDWORD; 
  305. TimeOuts.ReadTotalTimeoutMultiplier=0; 
  306. TimeOuts.ReadTotalTimeoutConstant=0; 
  307. /* 设置写超时以指定WriteComm成员函数中的GetOverlappedResult函数的等待时间*/
  308. TimeOuts.WriteTotalTimeoutMultiplier=50;
  309. TimeOuts.WriteTotalTimeoutConstant=2000;
  310. SetCommTimeouts(m_hCom, &TimeOuts);
  311. if(ConfigConnection())
  312. {
  313. m_pThread=AfxBeginThread(CommProc, this, THREAD_PRIORITY_NORMAL, 
  314. 0, CREATE_SUSPENDED, NULL); // 创建并挂起线程
  315. if(m_pThread==NULL)
  316. {
  317. CloseHandle(m_hCom);
  318. return FALSE;
  319. }
  320. else
  321. {
  322. m_bConnected=TRUE;
  323. m_pThread->ResumeThread(); // 恢复线程运行
  324. }
  325. }
  326. else
  327. {
  328. CloseHandle(m_hCom);
  329. return FALSE;
  330. }
  331. return TRUE;
  332. }
  333. //关闭连接,关闭工作线程
  334. void CTTYDoc::CloseConnection()
  335. {
  336. if(!m_bConnected)
  337. return;
  338. m_bConnected=FALSE;
  339. //结束CommProc线程中WaitSingleObject函数的等待
  340. SetEvent(m_hPostMsgEvent); 
  341. //结束CommProc线程中WaitCommEvent的等待
  342. SetCommMask(m_hCom, 0); 
  343. //等待辅助线程终止
  344. WaitForSingleObject(m_pThread->m_hThread, INFINITE);
  345. m_pThread=NULL;
  346. CloseHandle(m_hCom);
  347. }