串口

来源:互联网 发布:奥登生涯数据 编辑:程序博客网 时间:2024/04/29 03:20


// serialDlg.cpp : 实现文件
//


#include "stdafx.h"
#include "serial.h"
#include "serialDlg.h"
#include "afxdialogex.h"
#include "io.h"
#include "windows.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#endif




// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
HANDLE hCom;
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();


// 对话框数据
enum { IDD = IDD_ABOUTBOX };


protected:
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持


// 实现
protected:
DECLARE_MESSAGE_MAP()
};


CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}


void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()




// CserialDlg 对话框








CserialDlg::CserialDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CserialDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_disp = _T("");
m_receive = _T("");
}


void CserialDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
//  DDX_Control(pDX, IDC_diplay, m_disp);
// DDX_Text(pDX, IDC_diplay, m_disp);
DDX_Text(pDX, IDC_receive, m_receive);
DDX_Control(pDX, IDC_send, m_send);
DDX_Control(pDX, IDC_PORT, m_port);
DDX_Control(pDX, IDC_Databit, m_databit);
DDX_Control(pDX, IDC_SPEED, m_speed);
DDX_Control(pDX, IDC_stop, m_stop);
DDX_Control(pDX, IDC_check, m_check);
}


BEGIN_MESSAGE_MAP(CserialDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
// ON_CBN_SELCHANGE(IDC_COMBO1, &CserialDlg::OnCbnSelchangeCombo1)
ON_BN_CLICKED(IDC_BUTTON2, &CserialDlg::OnBnClickedButton2)
ON_BN_CLICKED(IDC_BUTTON1, &CserialDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON3, &CserialDlg::OnBnClickedButton3)
ON_WM_CLOSE()
ON_EN_CHANGE(IDC_send, &CserialDlg::OnEnChangesend)
ON_CBN_SELCHANGE(IDC_PORT, &CserialDlg::OnCbnSelchangePort)
END_MESSAGE_MAP()




// CserialDlg 消息处理程序


BOOL CserialDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();


// 将“关于...”菜单项添加到系统菜单中。


// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);


CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}


// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
//  执行此操作
SetIcon(m_hIcon, TRUE);// 设置大图标
SetIcon(m_hIcon, FALSE);// 设置小图标


// TODO: 在此添加额外的初始化代码


// HANDLE hComm;
hCom=CreateFile(_T("COM2"),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
/* hComm=CreateFile("COM1", //串口号
GENERIC_READ|GENERIC_WRITE, //允许读写
0, //通讯设备必须以独占方式打开
NULL, //无安全属性
OPEN_EXISTING, //通讯设备已存在
FILE_FLAG_OVERLAPPED, //异步I/O
0); //通讯设备不能用模板打开
*/
if(hCom==(HANDLE)-1)
{
MessageBox(_T("打开COM失败!"));
return FALSE;
}
MessageBox(_T("打开COM成功!"));


SetupComm(hCom,100,100);//输入缓冲区和输出缓冲区的大小都是100
COMMTIMEOUTS TimeOuts;
//设定读超时
TimeOuts.ReadIntervalTimeout=MAXDWORD;
TimeOuts.ReadTotalTimeoutMultiplier=0;
TimeOuts.ReadTotalTimeoutConstant=0;
//在读一次输入缓冲区的内容后读操作就立即返回,
//而不管是否读入了要求的字符.
//设定写超时
TimeOuts.WriteTotalTimeoutMultiplier=100;
TimeOuts.WriteTotalTimeoutConstant=500;
SetCommTimeouts(hCom,&TimeOuts);//设置超时
DCB dcb;
GetCommState(hCom,&dcb);
dcb.BaudRate=9600;//波特率为9600
dcb.ByteSize=8;//每个字节有8 位
dcb.Parity=NOPARITY;//无奇偶校验位
//dcb.StopBits=ONE5STOPBITS;//一个停止位
    dcb.StopBits=1;//一个停止位
SetCommState(hCom,&dcb);
PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);


return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}


void CserialDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}


// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。


void CserialDlg::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 CserialDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}






void CserialDlg::OnCbnSelchangeCombo1()
{
// TODO: 在此添加控件通知处理程序代码
}




void CserialDlg::OnBnClickedButton2()//打开关闭串口
{
// TODO: 在此添加控件通知处理程序代码
// HANDLE hComm;
// hComm=CreateFile(_T("COM1"),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
/* hComm=CreateFile("COM1", //串口号
GENERIC_READ|GENERIC_WRITE, //允许读写
0, //通讯设备必须以独占方式打开
NULL, //无安全属性
OPEN_EXISTING, //通讯设备已存在
FILE_FLAG_OVERLAPPED, //异步I/O
0); //通讯设备不能用模板打开
*/
/* if(hComm==(HANDLE)-1)
{
MessageBox(_T("打开COM失败!"));
return FALSE;
}
return TURE;*/
/* if(hCom==(HANDLE)-1) 

     MessageBox("打开COM失败!");
return FALSE;

    return TRUE;*/
//串口号
int nIndex1 = m_port.GetCurSel();
CString str_port;
m_port.GetLBText(nIndex1,str_port);
//波特率
int nIndex2 = m_speed.GetCurSel();
CString str_speed;
m_speed.GetLBText(nIndex2,str_speed);   
//数据位
int nIndex3 = m_databit.GetCurSel();
CString str_databit;
m_databit.GetLBText(nIndex3,str_databit); 
//校验位
int nIndex4 = m_check.GetCurSel();
CString str_check;
m_check.GetLBText(nIndex4,str_check);
//停止位
int nIndex5 = m_stop.GetCurSel();
CString str_stop;
m_stop.GetLBText(nIndex5,str_stop);
 //  m_cbExample.GetLBText( nIndex, strCBText);
 //  这样,得到的内容就保存在 strCBText 中。
//  GetWindowText(strCBText);
}




void CserialDlg::OnBnClickedButton1()//发送数据
{
// TODO: 在此添加控件通知处理程序代码
OVERLAPPED m_osWrite;
memset(&m_osWrite,0,sizeof(OVERLAPPED));
m_osWrite.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
// char lpOutBuffer[7];
//
/* lpOutBuffer[0]='w';
lpOutBuffer[1]='e';
lpOutBuffer[2]='l';
lpOutBuffer[3]='c';
lpOutBuffer[4]='o';
lpOutBuffer[5]='m';
lpOutBuffer[6]='e';*/
CString lpOutBuffer;
    GetDlgItem(IDC_send)->GetWindowText(lpOutBuffer);
// memset(lpOutBuffer,'\0',7);
DWORD dwBytesWrite=7;
COMSTAT ComStat;
DWORD dwErrorFlags;
BOOL bWriteStat;
ClearCommError(hCom,&dwErrorFlags,&ComStat);
bWriteStat=WriteFile(hCom,lpOutBuffer,
dwBytesWrite,& dwBytesWrite,&m_osWrite);
if(!bWriteStat)
{
if(GetLastError()==ERROR_IO_PENDING)
{
 WaitForSingleObject(m_osWrite.hEvent,1000);
}
}


}




void CserialDlg::OnBnClickedButton3()//接收数据
{
// TODO: 在此添加控件通知处理程序代码
OVERLAPPED m_osRead;
memset(&m_osRead,0,sizeof(OVERLAPPED));
m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
COMSTAT ComStat;
DWORD dwErrorFlags;
char str[100];
  //  char* str=0;
CString ch;
memset(str,'\0',100);
// strncpy(m_szWriteBuffer, string, n);
// memcpy(m_szWriteBuffer, string, n);


DWORD dwBytesRead=100;//读取的字节数
BOOL bReadStat;
ClearCommError(hCom,&dwErrorFlags,&ComStat);
dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);
bReadStat=ReadFile(hCom,str,
dwBytesRead,&dwBytesRead,&m_osRead);
if(!bReadStat)
{
if(GetLastError()==ERROR_IO_PENDING)
//GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作
{
WaitForSingleObject(m_osRead.hEvent,2000);
//使用WaitForSingleObject 函数等待,直到读操作完成或延时已达到2 秒钟
//当串口读操作进行完毕后,m_osRead 的hEvent 事件会变为有信号
}
}
PurgeComm(hCom,PURGE_TXABORT|
PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
//如果选择了"十六进制显示",则显示十六进制值
// CString str;
// if(m_ctrlHexReceieve.GetCheck())
// str.Format("%02X ",ch);
// else 
// str.Format("%c",ch);
// strncpy(ch, str, 100);
// (L"%c", bt);
// memcpy(ch, str, 100);
// sprintf(ch, "%c",str);


ch.Format("%s\n",str);
m_receive=ch;
UpdateData(FALSE);


}




void CserialDlg::OnClose()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CloseHandle(hCom);//程序退出时关闭串口
CDialogEx::OnClose();
}




void CserialDlg::OnEnChangesend()
{
// TODO:  如果该控件是 RICHEDIT 控件,它将不
// 发送此通知,除非重写 CDialogEx::OnInitDialog()
// 函数并调用 CRichEditCtrl().SetEventMask(),
// 同时将 ENM_CHANGE 标志“或”运算到掩码中。


// TODO:  在此添加控件通知处理程序代码
}




void CserialDlg::OnCbnSelchangePort()
{
// TODO: 在此添加控件通知处理程序代码
}
0 0