C语言摘录.docx

上传人:b****6 文档编号:6667118 上传时间:2023-01-08 格式:DOCX 页数:32 大小:76.80KB
下载 相关 举报
C语言摘录.docx_第1页
第1页 / 共32页
C语言摘录.docx_第2页
第2页 / 共32页
C语言摘录.docx_第3页
第3页 / 共32页
C语言摘录.docx_第4页
第4页 / 共32页
C语言摘录.docx_第5页
第5页 / 共32页
点击查看更多>>
下载资源
资源描述

C语言摘录.docx

《C语言摘录.docx》由会员分享,可在线阅读,更多相关《C语言摘录.docx(32页珍藏版)》请在冰豆网上搜索。

C语言摘录.docx

C语言摘录

VC读串口方法

时间:

2011-11-1915:

39来源:

未知作者:

admin点击:

1311次

------分隔线----------------------------

  VC串口通信技术网曾经发表过一篇文章叫:

《VC串口编程基础之如何用VC打开串口和关闭串口》,这里说说在用VC打开串口后怎么再用VC读串口数据。

  《VC串口编程基础之如何用VC打开串口和关闭串口》一文只是说的用API方法,实际上用VC读串口根据编程方法不一样,打开方法也不一样,串口编程方法有基于activex控件的,也有基于动态链接库的,还有使用串口类的,用这些方法读串口都非常简单,只需要调用其提供的相关接口就可以了(有时需要映射消息),不管用何种方法,其实质是串口控件最终都调用了底层API函数ReadFile来读串口,下面分别讲讲常用控件的读串口方法和直接利用串口API读串口的方法。

1、ActiveX控件Mscomm读串口

  先正确打开并配置好串口,具体内容不是这里的重点,相关内容在本站里也有,但有个属性是重点,那就是RThreshold属性,当接收字符后,若Rthreshold属性设置为0(缺省值)则不产生OnComm事件。

例如,设置Rthreshold为1,接收缓冲区收到每一个字符都会使MSComm控件产生OnComm事件。

  添加串口事件消息处理函数OnComm(),打开ClassWizard->MessageMaps,选择类CSCommTestDlg,选择IDC_MSCOMM1,双击消息OnComm,将弹出的对话框中将函数名改为OnComm。

我们在OnComm()函数加入相应的处理代码就能实现自已想要的功能了,以下一个实例:

 

1.void CDemoDlg:

:

OnComm()     

2.{    

3. 

4.    VARIANT variant_inp;    

5.    COleSafeArray safearray_inp;    

6.    LONG len,k;    

7.    BYTE rxdata[2048]; //用于存放接收到的数据,BYTE格式(即CHAR格式) 

8.    CString strtemp;   //可将转换成字符串格式后的串口数据存入此变量 

9.    //读缓冲区数据并进行转换 

10.    if(m_ctrlComm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符    

11.    {                

12.        variant_inp=m_ctrlComm.GetInput(); //读缓冲区    

13.        safearray_inp=variant_inp; //将VARIANT型变量转换为ColeSafeArray型变量    

14.        len="safearray"_inp.GetOneDimSize(); //得到有效数据长度    

15.        for(k=0;k

16.            safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组    

17.        for(k=0;k

18.        {    

19.            BYTE bt=*(char*)(rxdata+k); //字符型    

20.            strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放    

21.            m_strRXData+=strtemp; //加入接收编辑框对应字符串     

22.        }    

23.    }    

24.     

25.    //以下可根据需要处理接收到的数据 

26.    .... 

27.}  

由于用Mscomm控件的GetInput方法读到的串口缓冲区数据为VARIANT格式,需要用一个COleSafeArray类型来转换,具体步骤按上面的示例来就是了。

 

2、动态链接库dll读串口方法

  不同的串口dll有不同的方法,应该根据其手册来,如VC串口通信技术网的VC串口通信技术资料集里的一个例子用到的串口dll-ThreadSerial.dll,它是通过查询成员变量m_LastIndex的值是否大于1来判断是否接串口缓冲区中数据的,VC串口通信技术资料集的一个例子串口调试助手EasySerialAssistant就是用的这个dll,

 

 

 这个示例专门为读串口开了一个线程,在线程里不断地读m_LastIndex的值,如果大于代表串口缓冲区中有数据,然后将数据显示到显示区:

 

1.UINT CEasySerialAssistantDlg:

:

ProDispThread(LPVOID pParam) 

2.{    

3.    CEasySerialAssistantDlg* pParlPro=(CEasySerialAssistantDlg*)pParam; 

4.    pParlPro->m_bThread=TRUE; 

5.    CString c="",d=""; 

6.    char b[4]; 

7. 

8.    while

(1) 

9.    { 

10.        Sleep

(1); 

11.         

12.        if(pParlPro->m_LastIndex > 0) 

13.        { 

14.            c.Format("RX:

%d t:

%d n:

%d",pParlPro->m_RecvCount,pParlPro->m_nCurLen,pParlPro->m_nRecvTimes); 

15.            (pParlPro->GetDlgItem(IDC_STATIC_RX))->SetWindowText(c); 

16. 

17.            if(pParlPro->m_bDispRecv == FALSE) 

18.            { 

19.                pParlPro->m_LastIndex=0; 

20.            } 

21.            else 

22.            { 

23.                CEdit *pList =(CEdit *)(pParlPro->GetDlgItem(IDC_EDIT_RX_DISP)); 

24.                 

25.                if(pParlPro->m_bAutoClearn == FALSE) c=pParlPro->m_StrBuf;   

26.                else c=""; 

27. 

28.                if(pParlPro->m_bHexDispMode == TRUE) 

29.                { 

30.                    for(int i=0;i<(int)pParlPro->m_LastIndex;i++) 

31.                    { 

32.                      :

:

sprintf(b,"%2.2X",pParlPro->m_RecvBuf[i]); 

33.                       c+=" "; 

34.                       c+=b; 

35.                    } 

36.                    pParlPro->m_LastIndex=0; 

37.                } 

38.                else 

39.                { 

40.                    pParlPro->m_RecvBuf[pParlPro->m_LastIndex+1]='\0'; 

41.                    d.Format("%s",pParlPro->m_RecvBuf); 

42.                    if(pParlPro->m_bAutoChangRow == TRUE) 

43.                    { 

44.                        d.Insert(c.GetLength(),"\r\n"); 

45.                    } 

46.                    c+=d; 

47.                    pParlPro->m_LastIndex=0; 

48.                } 

49. 

50.                if(pParlPro->m_bAutoClearn == FALSE) pParlPro->m_StrBuf=c; 

51. 

52.                pList->SetWindowText(c); 

53. 

54.                unsigned int nVScrollPos=pList->GetLineCount(); 

55.                pList->LineScroll(nVScrollPos);  

56.            }    

57.        } 

58.    } 

59. 

60.    pParlPro->m_bThread=false; //工作标志复位 

61.    return 0; 

62.} 

4、串口类读串口方法

  同样不同串口类有不同方法和接口,这里只说说最常用的串口类CSerialPort的读串口方法。

  启动串口通信监测线程函数StartMonitoring(),串口初始化成功后,就可以调用BOOLStartMonitoring()启动串口监测线程。

线程启动成功,返回TRUE。

  串口收到的字符会向主线程或父窗口发送WM_COMM_RXCHAR消息,我们需要在主线程或父窗口中手动映射这个消息,手动映射消息的方法属于VC基础性内容,就不在这里讲解了,本站VC串口通信技术资料集有很多CSerialPort类的应用实例,大家可以参考,以下本资料中一个实例 串口调试助手SComAssistant的串口接收源代码,OnCommunication函数是WM_COMM_RXCHAR消息的映射函数:

 

1.LONG CSCOMMDlg:

:

OnCommunication(WPARAM ch, LPARAM port) 

2.{ 

3.    if (port <= 0 || port > 4) 

4.        return -1; 

5.    rxdatacount++;   //接收的字节计数 

6.    CString strTemp; 

7.    strTemp.Format("%ld",rxdatacount); 

8.    strTemp="RX:

"+strTemp; 

9.    m_ctrlRXCOUNT.SetWindowText(strTemp);  //显示接收计数 

10.     

11.    if(m_bStopDispRXData)   //如果选择了“停止显示”接收数据,则返回 

12.        return -1;          //注意,这种情况下,计数仍在继续,只是不显示 

13.    //若设置了“自动清空”,则达到50行后,自动清空接收编辑框中显示的数据 

14.    if((m_ctrlAutoClear.GetCheck())&&(m_ctrlReceiveData.GetLineCount()>=50)) 

15.    { 

16.        m_ReceiveData.Empty(); 

17.        UpdateData(FALSE); 

18.    } 

19.    //如果没有“自动清空”,数据行达到400后,也自动清空 

20.    //因为数据过多,影响接收速度,显示是最费CPU时间的操作 

21.    if(m_ctrlReceiveData.GetLineCount()>400) 

22.    { 

23.        m_ReceiveData.Empty(); 

24.        m_ReceiveData="***The Length of the Text is too long, Emptied Automaticly!

!

!

***\r\n";         

25.        UpdateData(FALSE); 

26.    } 

27. 

28.    //如果选择了"十六进制显示",则显示十六进制值 

29.    CString str; 

30.    if(m_ctrlHexReceieve.GetCheck()) 

31.        str.Format("%02X ",ch); 

32.    else  

33.        str.Format("%c",ch); 

34.    //以下是将接收的字符加在字符串的最后,这里费时很多 

35.    //但考虑到数据需要保存成文件,所以没有用List Control 

36.    int nLen=m_ctrlReceiveData.GetWindowTextLength(); 

37.    m_ctrlReceiveData.SetSel(nLen, nLen); 

38.    m_ctrlReceiveData.ReplaceSel(str); 

39.    nLen+=str.GetLength(); 

40. 

41.    m_ReceiveData+=str; 

42.    return 0; 

43.} 

4、串口API如何读串口

  以上各串口编程方法的实质都是调用了API的,只是被封装了而已,读串口的API函数是ReadFile,由于不知道何时串口收到数据,所以一般需要开一个线程不停地用ReadFile来读串口。

  在用ReadFile读串口时,既可以同步执行,也可以重叠执行。

在同步执行时,函数直到操作完成后才返回。

这意味着同步执行时线程会被阻塞,从而导致效率下降。

在重叠执行时,即使操作还未完成,这个函数也会立即返回,费时的I/O操作在后台进行。

  ReadFile函数是同步还是异步由CreateFile函数决定,如果在调用CreateFile创建句柄时指定了FILE_FLAG_OVERLAPPED标志,那么调用ReadFile对该句柄进行的操作就应该是重叠的;如果未指定重叠标志,则读写操作应该是同步的。

ReadFile和WriteFile函数的同步或者异步应该和CreateFile函数相一致。

  ReadFile函数只要在串口输入缓冲区中读入指定数量的字符,就算完成操作。

如果操作成功,这个函数返回TRUE。

需要注意的是,当ReadFile返回FALSE时,不一定就是操作失败,线程应该调用GetLastError函数分析返回的结果。

例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR_IO_PENDING。

这说明重叠操作还未完成。

同步方式读写串口比较简单,下面先是同步方式读写串口的代码示例:

 

1.//同步读串口 

2.char str[100]; 

3.DWORD wCount;//读取的字节数 

4.BOOL bReadStat; 

5.bReadStat=ReadFile(hCom,str,100,&wCount,NULL); 

6.if(!

bReadStat) 

7.{ 

8.    AfxMessageBox("读串口失败!

"); 

9.    return FALSE; 

10.} 

11.return TRUE; 

12. 

13.//同步写串口 

14. 

15.    char lpOutBuffer[100]; 

16.    DWORD dwBytesWrite=100; 

17.    COMSTAT ComStat; 

18.    DWORD dwErrorFlags; 

19.    BOOL bWriteStat; 

20.    ClearCommError(hCom,&dwErrorFlags,&ComStat); 

21.    bWriteStat=WriteFile(hCom,lpOutBuffer,dwBytesWrite,& dwBytesWrite,NULL); 

22.    if(!

bWriteStat) 

23.    { 

24.        AfxMessageBox("写串口失败!

"); 

25.    } 

26.    PurgeComm(hCom, PURGE_TXABORT| 

27.        PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); 

在重叠操作时,操作还未完成函数就返回。

  重叠I/O非常灵活,它也可以实现阻塞(例如我们可以设置一定要读取到一个数据才能进行到下一步操作)。

有两种方法可以等待操作完成:

一种方法是用象WaitForSingleObject这样的等待函数来等待OVERLAPPED结构的hEvent成员;另一种方法是调用GetOverlappedResult函数等待。

OVERLAPPED结构和GetOverlappedResult函数请查看MSDN,本站VC串口通信资料集中也有详细详述。

异步读串口的示例代码:

 

1.char lpInBuffer[1024]; 

2.DWORD dwBytesRead=1024; 

3.COMSTAT ComStat; 

4.DWORD dwErrorFlags; 

5.OVERLAPPED m_osRead; 

6.memset(&m_osRead,0,sizeof(OVERLAPPED)); 

7.m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL); 

8. 

9.ClearCommError(hCom,&dwErrorFlags,&ComStat); 

10.dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue); 

11.if(!

dwBytesRead) 

12.return FALSE; 

13.BOOL bReadStatus; 

14.bReadStatus=ReadFile(hCom,lpInBuffer, 

15.                     dwBytesRead,&dwBytesRead,&m_osRead); 

16. 

17.if(!

bReadStatus) //如果ReadFile函数返回FALSE 

18.{ 

19.    if(GetLastError()==ERROR_IO_PENDING) 

20.    //GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作     

21.    { 

22.        WaitForSingleObject(m_osRead.hEvent,2000); 

23.        //使用WaitForSingleObject函数等待,直到读操作完成或延时已达到2秒钟 

24.        //当串口读操作进行完毕后,m_osRead的hEvent事件会变为有信号 

25.        PurgeComm(hCom, PURGE_TXABORT| 

26.            PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); 

27.        return dwBytesRead; 

28.    } 

29.    return 0; 

30.} 

31.PurgeComm(hCom, PURGE_TXABORT| 

32.          PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); 

33.return dwBytesRead; 

  对以上代码再作简要说明:

在使用ReadFile函数进行读操作前,应先使用ClearCommError函数清除错误。

ClearCommError函数的原型如下:

1.BOOL ClearCommError(    

2.   

3.    HANDLE hFile,   // 串口句柄    

4.    LPDWORD lpErrors,   // 指向接收错误码的变量    

5.    LPCOMSTAT lpStat    // 指向通讯状态缓冲区    

6.   );      

 该函数获得通信错误并报告串口的当前状态,同时,该函数清除串口的错误标志以便继续输入、输出操作。

参数lpStat指向一个COMSTAT结构,该结构返回串口状态信息。

COMSTAT结构COMSTAT结构包含串口的信息,结构定义如下:

1.typedef struct _COMSTAT { // cst   

2.    DWORD fCtsHold :

 1;   // Tx waiting for CTS signal  

3.    DWORD fDsrHold :

 1;   // Tx waiting for DSR signal  

4.    DWORD fRlsdHold :

 1;  // Tx waiting for RLSD signal  

5.    DWO

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 总结汇报 > 学习总结

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1