當前位置:ag真人国际官网-ag旗舰厅官方网站 » 操作系統 » vc串口調試助手源碼

vc串口調試助手源碼-ag真人国际官网

發布時間: 2024-06-25 04:38:29

① 求串口調試助手的vc 源代碼

那個很簡單啊 自己寫一個也行 就是creatfile 然後把串口參數設好就行了

② 急!龔建偉關於串口通信的程序有問題的,期望高手解決!

粗略的看了一下,你的代碼沒有問題,我懷疑是其他的地方出現了問題。

給你一個我以前寫的,模仿串口調試助手用串口控制項的方法寫的程序,你參考一下吧。

代碼已發到你的郵箱。

補充:
接收就是在oncomm() 函數里啊,你的這段代碼沒有什麼問題。
有沒有做串口控制項的事件映射啊:
begin_eventsink_map(ccutecomdlg, cdialog)
on_event(ccutecomdlg, idc_mscomm1, 1 /* oncomm */, oncomm, vts_none)
end_eventsink_map()
如果有的話,那接收應該沒有問題的。況且即使只有發沒有收,那也不會點發送就會出錯的。

我發給你的代碼你看到了嗎,那是標准串口控制項的用法,裡面收發演示都有的,你詳細看一下吧,應該是對你有所幫助的。

有人說是因為龔建偉的串口初始化部分代碼有問題,才導致了後面的安全數組出現錯誤。

我一直是使用如下代碼進行串口控制項的初始化的,已經應用到過很多程序中沒有出現過問題,你可以試試:
if(m_ctrlcomm.get_portopen())
m_ctrlcomm.put_portopen(false);

m_ctrlcomm.put_commport(1); //選擇com1
//輸出方式為二進制方式
m_ctrlcomm.put_inputmode(1);//text,binary
//m_ctrlcomm.put_inbuffersize(64);
//m_ctrlcomm.put_outbuffersize(512);

m_ctrlcomm.put_settings("9600,n,8,1"); //波特率9600,無校驗ndo,8個數據位,1個停止位

if( !m_ctrlcomm.get_portopen())
m_ctrlcomm.put_portopen(true);//打開串口

m_ctrlcomm.put_rthreshold(1);
//參數1表示每當串口接收緩沖區中有多於或等於1個字元時將引發一個接收數據的oncomm事件

m_ctrlcomm.put_inputlen(0); //設置當前接收區數據長度為0
//0---讀接收緩沖區的所有內容
//n---讀接收緩沖區的 n 個字元(或二進制碼)

m_ctrlcomm.get_input();//先預讀緩沖區以清除殘留數據

這是vs2008中的代碼,在vc6.0中請把函數前綴get_替換為get、put_替換為set

③ 如何用c語言在vc 裡面編程使串口調試工具能接收到傳輸的內容

在vc 中有兩種方法可以進行串口通訊。一種是利用microsoft公司提供的activex控制項 microsoft communications control。另一種是直接用vc 訪問串口。
具體的方法在這http://blog.hehehehehe.cn/a/1480.htm

④ vc串口通信問題

串口的操作可以有兩種操作方式:同步操作方式和重疊操作方式(又稱為非同步操作方式)。同步操作時,api函數會阻塞直到操作完成以後才能返回(在多線程方式中,雖然不會阻塞主線程,但是仍然會阻塞監聽線程);而重疊操作方式,api函數會立即返回,操作在後台進行,避免線程的阻塞。

無論那種操作方式,一般都通過四個步驟來完成:
(1) 打開串口
(2) 配置串口
(3) 讀寫串口
(4) 關閉串口

(1) 打開串口

win32系統把文件的概念進行了擴展。無論是文件、通信設備、命名管道、郵件槽、磁碟、還是控制台,都是用api函數createfile來打開或創建的。該函數的原型為:
lpfilename:將要打開的串口邏輯名,如「com1」;
dwdesiredaccess:指定串口訪問的類型,可以是讀取、寫入或二者並列;
dwsharemode:指定共享屬性,由於串口不能共享,該參數必須置為0;
lpsecurityattributes:引用安全性屬性結構,預設值為null;
dwcreationdistribution:創建標志,對串口操作該參數必須置為open_existing;
dwflagsandattributes:屬性描述,用於指定該串口是否進行非同步操作,該值為file_flag_overlapped,表示使用非同步的i/o;該值為0,表示同步i/o操作;
htemplatefile:對串口而言該參數必須置為null;
同步i/o方式打開串口的示例代碼:

handle hcom; //全局變數,串口句柄
hcom=createfile("com1",//com1口
generic_read|generic_write, //允許讀和寫
0, //獨占方式
null,
open_existing, //打開而不是創建
0, //同步方式
null);
if(hcom==(handle)-1)
{
afxmessagebox("打開com失敗!");
return false;
}
return true;
(2)、配置串口
在打開通訊設備句柄後,常常需要對串口進行一些初始化配置工作。這需要通過一個dcb結構來進行。dcb結構包含了諸如波特率、數據位數、奇偶校驗和停止位數等信息。在查詢或配置串口的屬性時,都要用dcb結構來作為緩沖區。
一般用createfile打開串口後,可以調用getcommstate函數來獲取串口的初始配置。要修改串口的配置,應該先修改dcb結構,然後再調用setcommstate函數設置串口。
typedef struct _dcb{
………
//波特率,指定通信設備的傳輸速率。這個成員可以是實際波特率值或者下面的常量值之一:
dword baudrate;
cbr_110,cbr_300,cbr_600,cbr_1200,cbr_2400,cbr_4800,cbr_9600,cbr_19200, cbr_38400,
cbr_56000, cbr_57600, cbr_115200, cbr_128000, cbr_256000, cbr_14400

dword fparity; // 指定奇偶校驗使能。若此成員為1,允許奇偶校驗檢查

byte bytesize; // 通信位元組位數,4—8
byte parity; //指定奇偶校驗方法。此成員可以有下列值:
evenparity 偶校驗 noparity 無校驗
markparity 標記校驗 oddparity 奇校驗
byte stopbits; //指定停止位的位數。此成員可以有下列值:
onestopbit 1位停止位 twostopbits 2位停止位
one5stopbits 1.5位停止位
………
} dcb;
winbase.h文件中定義了以上用到的常量。如下:
#define noparity 0
#define oddparity 1
#define evenparity 2
#define onestopbit 0
#define one5stopbits 1
#define twostopbits 2
#define cbr_110 110
#define cbr_300 300
#define cbr_600 600
#define cbr_1200 1200
#define cbr_2400 2400
#define cbr_4800 4800
#define cbr_9600 9600
#define cbr_14400 14400
#define cbr_19200 19200
#define cbr_38400 38400
#define cbr_56000 56000
#define cbr_57600 57600
#define cbr_115200 115200
#define cbr_128000 128000
#define cbr_256000 256000

getcommstate函數可以獲得com口的設備控制塊,從而獲得相關參數: bool getcommstate(
handle hfile, //標識通訊埠的句柄
lpdcb lpdcb //指向一個設備控制塊(dcb結構)的指針
);
setcommstate函數設置com口的設備控制塊:
bool setcommstate(
handle hfile,
lpdcb lpdcb
);

除了在bcd中的設置外,程序一般還需要設置i/o緩沖區的大小和超時。windows用i/o緩沖區來暫存串口輸入和輸出的數據。如果通信的速率較高,則應該設置較大的緩沖區。調用setupcomm函數可以設置串列口的輸入和輸出緩沖區的大小。 bool setupcomm(

handle hfile, // 通信設備的句柄
dword dwinqueue, // 輸入緩沖區的大小(位元組數)
dword dwoutqueue // 輸出緩沖區的大小(位元組數)
);

在用readfile和writefile讀寫串列口時,需要考慮超時問題。超時的作用是在指定的時間內沒有讀入或發送指定數量的字元,readfile或writefile的操作仍然會結束。
要查詢當前的超時設置應調用getcommtimeouts函數,該函數會填充一個commtimeouts結構。調用setcommtimeouts可以用某一個commtimeouts結構的內容來設置超時。
讀寫串口的超時有兩種:間隔超時和總超時。間隔超時是指在接收時兩個字元之間的最大時延。總超時是指讀寫操作總共花費的最大時間。寫操作只支持總超時,而讀操作兩種超時均支持。用commtimeouts結構可以規定讀寫操作的超時。
commtimeouts結構的定義為: typedef struct _commtimeouts {
dword readintervaltimeout; //讀間隔超時
dword readtotaltimeoutmultiplier; //讀時間系數
dword readtotaltimeoutconstant; //讀時間常量
dword writetotaltimeoutmultiplier; // 寫時間系數
dword writetotaltimeoutconstant; //寫時間常量
} commtimeouts,*lpcommtimeouts;

commtimeouts結構的成員都以毫秒為單位。總超時的計算公式是:
總超時=時間系數×要求讀/寫的字元數+時間常量
例如,要讀入10個字元,那麼讀操作的總超時的計算公式為:
讀總超時=readtotaltimeoutmultiplier×10+readtotaltimeoutconstant
可以看出:間隔超時和總超時的設置是不相關的,這可以方便通信程序靈活地設置各種超時。

如果所有寫超時參數均為0,那麼就不使用寫超時。如果readintervaltimeout為0,那麼就不使用讀間隔超時。如果readtotaltimeoutmultiplier 和 readtotaltimeoutconstant 都為0,則不使用讀總超時。如果讀間隔超時被設置成maxdword並且讀時間系數和讀時間常量都為0,那麼在讀一次輸入緩沖區的內容後讀操作就立即返回,而不管是否讀入了要求的字元。
在用重疊方式讀寫串口時,雖然readfile和writefile在完成操作以前就可能返回,但超時仍然是起作用的。在這種情況下,超時規定的是操作的完成時間,而不是readfile和writefile的返回時間。
配置串口的示例代碼: setupcomm(hcom,1024,1024); //輸入緩沖區和輸出緩沖區的大小都是1024

commtimeouts timeouts;
//設定讀超時
timeouts.readintervaltimeout=1000;
timeouts.readtotaltimeoutmultiplier=500;
timeouts.readtotaltimeoutconstant=5000;
//設定寫超時
timeouts.writetotaltimeoutmultiplier=500;
timeouts.writetotaltimeoutconstant=2000;
setcommtimeouts(hcom,&timeouts); //設置超時

dcb dcb;
getcommstate(hcom,&dcb);
dcb.baudrate=9600; //波特率為9600
dcb.bytesize=8; //每個位元組有8位
dcb.parity=noparity; //無奇偶校驗位
dcb.stopbits=twostopbits; //兩個停止位
setcommstate(hcom,&dcb);

purgecomm(hcom,purge_txclear|purge_rxclear);

在讀寫串口之前,還要用purgecomm()函數清空緩沖區,該函數原型: bool purgecomm(

handle hfile, //串口句柄
dword dwflags // 需要完成的操作
);

參數dwflags指定要完成的操作,可以是下列值的組合: purge_txabort 中斷所有寫操作並立即返回,即使寫操作還沒有完成。
purge_rxabort 中斷所有讀操作並立即返回,即使讀操作還沒有完成。
purge_txclear 清除輸出緩沖區
purge_rxclear 清除輸入緩沖區

(3)、讀寫串口
我們使用readfile和writefile讀寫串口,下面是兩個函數的聲明:

bool readfile(

handle hfile, //串口的句柄

// 讀入的數據存儲的地址,
// 即讀入的數據將存儲在以該指針的值為首地址的一片內存區
lpvoid lpbuffer,
dword nnumberofbytestoread, // 要讀入的數據的位元組數

// 指向一個dword數值,該數值返回讀操作實際讀入的位元組數
lpdword lpnumberofbytesread,

// 重疊操作時,該參數指向一個overlapped結構,同步操作時,該參數為null。
lpoverlapped lpoverlapped
);
bool writefile(

handle hfile, //串口的句柄

// 寫入的數據存儲的地址,
// 即以該指針的值為首地址的nnumberofbytestowrite
// 個位元組的數據將要寫入串口的發送數據緩沖區。
lpcvoid lpbuffer,

dword nnumberofbytestowrite, //要寫入的數據的位元組數

// 指向指向一個dword數值,該數值返回實際寫入的位元組數
lpdword lpnumberofbyteswritten,

// 重疊操作時,該參數指向一個overlapped結構,
// 同步操作時,該參數為null。
lpoverlapped lpoverlapped
);

在用readfile和writefile讀寫串口時,既可以同步執行,也可以重疊執行。在同步執行時,函數直到操作完成後才返回。這意味著同步執行時線程會被阻塞,從而導致效率下降。在重疊執行時,即使操作還未完成,這兩個函數也會立即返回,費時的i/o操作在後台進行。
readfile和writefile函數是同步還是非同步由createfile函數決定,如果在調用createfile創建句柄時指定了file_flag_overlapped標志,那麼調用readfile和writefile對該句柄進行的操作就應該是重疊的;如果未指定重疊標志,則讀寫操作應該是同步的。readfile和writefile函數的同步或者非同步應該和createfile函數相一致。
readfile函數只要在串口輸入緩沖區中讀入指定數量的字元,就算完成操作。而writefile函數不但要把指定數量的字元拷入到輸出緩沖區,而且要等這些字元從串列口送出去後才算完成操作。
如果操作成功,這兩個函數都返回true。需要注意的是,當readfile和writefile返回false時,不一定就是操作失敗,線程應該調用getlasterror函數分析返回的結果。例如,在重疊操作時如果操作還未完成函數就返回,那麼函數就返回false,而且getlasterror函數返回error_io_pending。這說明重疊操作還未完成。
您可以觀察返回的字元串,其中有和儀表顯示值相同的部分,您可以進行相應的字元串操作取出儀表的顯示值。
打開classwizard,為靜態文本框idc_disp添加cstring類型變數m_disp,同時添加wm_close的相應函數: void crs485commdlg::onclose()
{
// todo: add your message handler code here and/or call default
closehandle(hcom); //程序退出時關閉串口
cdialog::onclose();
}

程序的相應部分已經在代碼內部作了詳細介紹。連接好硬體部分,編譯運行程序,細心體會串口同步操作部分。
常式2

打開vc 6.0,新建基於對話框的工程rs485comm,在主對話框窗口idd_rs485comm_dialog上添加兩個按鈕,id分別為idc_send和idc_receive,標題分別為「發送」和「接收」;添加一個靜態文本框idc_disp,用於顯示串口接收到的內容。在rs485commdlg.cpp文件中添加全局變數:

handle hcom; //全局變數,
串口句柄在rs485commdlg.cpp文件中的oninitdialog()函數添加如下代碼:

hcom=createfile("com1",//com1口
generic_read|generic_write, //允許讀和寫
0, //獨占方式
null,
open_existing, //打開而不是創建
file_attribute_normal|file_flag_overlapped, //重疊方式
null);
if(hcom==(handle)-1)
{
afxmessagebox("打開com失敗!");
return false;
}

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=twostopbits; //兩個停止位
setcommstate(hcom,&dcb);

purgecomm(hcom,purge_txclear|purge_rxclear);

分別雙擊idc_send按鈕和idc_receive按鈕,添加兩個按鈕的響應函數: void crs485commdlg::onsend()
{
// todo: add your control notification handler code here
overlapped m_oswrite;
memset(&m_oswrite,0,sizeof(overlapped));
m_oswrite.hevent=createevent(null,true,false,null);

char lpoutbuffer[7];
memset(lpoutbuffer,''\0'',7);
lpoutbuffer[0]=''\x11'';
lpoutbuffer[1]=''0'';
lpoutbuffer[2]=''0'';
lpoutbuffer[3]=''1'';
lpoutbuffer[4]=''0'';
lpoutbuffer[5]=''1'';
lpoutbuffer[6]=''\x03'';

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 crs485commdlg::onreceive()
{
// todo: add your control notification handler code here
overlapped m_osread;
memset(&m_osread,0,sizeof(overlapped));
m_osread.hevent=createevent(null,true,false,null);

comstat comstat;
dword dwerrorflags;

char str[100];
memset(str,''\0'',100);
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);
m_disp=str;
updatedata(false);
}

打開classwizard,為靜態文本框idc_disp添加cstring類型變數m_disp,同時添加wm_close的相應函數: void crs485commdlg::onclose()
{
// todo: add your message handler code here and/or call default
closehandle(hcom); //程序退出時關閉串口
cdialog::onclose();
}

這是我看過的一個資料。打開、設置和讀寫串口的方法都說的很詳細了。由於網路知道回答問題是有長度限制的。有些例子被我刪了。如果需要就加我qq。給你發信息了。

⑤ 如何用vc 寫串口調試助手

1.建立項目
2.在項目中插入mscomm控制項
3.利用classwizard定義cmscomm類控制變數
4.在對話框中添加控制項
5.添加串口事件消息處理函數oncomm()
6.打開和設置串口參數
7.發送數據
8.發送十六進制字元
9.在接收框中以十六進制顯示
10.如何設置自動發送
11.什麼是variant數據類型?如何使用variant數據類型?


1.建立項目:打開vc++6.0,建立一個基於對話框的mfc應用程序scommtest(與我源代碼一致,等會你會方便一點);

2.在項目中插入mscomm控制項 選擇project菜單下add to project子菜單中的 components and controls…選項,在彈出的對話框中雙擊registered activex controls項(稍等一會,這個過程較慢),則所有注冊過的activex控制項出現在列表框中。 選擇microsoft communications control, version 6.0,,單擊insert按鈕將它插入到我們的project中來,接受預設的選項。(如果你在控制項列表中看不到microsoft communications control, version 6.0,那可能是你在安裝vc6時沒有把activex一項選上,重新安裝vc6,選上activex就可以了),

這時在classview視窗中就可以看到cmscomm類了,(注意:此類在classwizard中看不到,重構clw文件也一樣),並且在控制項工具欄controls中出現了電話圖標(如圖1所示),現在要做的是用滑鼠將此圖標拖到對話框中,程序運行後,這個圖標是看不到的。

3.利用classwizard定義cmscomm類控制對象 打開classwizard->member viariables選項卡,選擇cscommtestdlg類,為idc_mscomm1添加控制變數:m_ctrlcomm,這時你可以看一看,在對話框頭文件中自動加入了//{{afx_includes() #i nclude "mscomm.h" //}}afx_includes (這時運行程序,如果有錯,那就再從頭開始)。

4.在對話框中添加控制項 向主對話框中添加兩個編輯框,一個用於接收顯示數據id為idc_edit_rxdata,另一個用於輸入發送數據,id為idc_edit_txdata,再添加一個按鈕,功能是按一次就把發送編輯框中的內容發送一次,將其id設為idc_button_manualsend。別忘記了將接收編輯框的properties->styles中把miltiline和vertical scroll屬性選上,發送編輯框若你想輸入多行文字,也可選上miltiline。

再打開classwizard->member viariables選項卡,選擇cscommtestdlg類, 為idc_edit_rxdata添加cstring變數m_strrxdata, 為idc_edit_txdata添加cstring變數m_strtxdata。說明: m_strrxdata和m_strtxdata分別用來放入接收和發送的字元數據。

5.添加串口事件消息處理函數oncomm() 打開classwizard->message maps,選擇類cscommtestdlg,選擇idc_mscomm1,雙擊消息oncomm,將彈出的對話框中將函數名改為oncomm,(好記而已)ok。

這個函數是用來處理串口消息事件的,如每當串口接收到數據,就會產生一個串口接收數據緩沖區中有字元的消息事件,我們剛才添加的函數就會執行,我們在oncomm()函數加入相應的處理代碼就能實現自已想要的功能了。請你在函數中加入如下代碼:

void cscommtestdlg::oncomm()
{
// todo: add your control notification handler code here
variant variant_inp;
colesafearray safearray_inp;
long len,k;
byte rxdata[2048]; //設置byte數組 an 8-bit integerthat is not signed.
cstring strtemp;
if(m_ctrlcomm.getcommevent()==2) //事件值為2表示接收緩沖區內有字元
{ ////////以下你可以根據自己的通信協議加入處理代碼
variant_inp=m_ctrlcomm.getinput(); //讀緩沖區
safearray_inp=variant_inp; //variant型變數轉換為colesafearray型變數
len=safearray_inp.getonedimsize(); //得到有效數據長度
for(k=0;k safearray_inp.getelement(&k,rxdata k);//轉換為byte型數組
for(k=0;k {
byte bt=*(char*)(rxdata k); //字元型
strtemp.format("%c",bt); //將字元送入臨時變數strtemp存放
m_strrxdata =strtemp; //加入接收編輯框對應字元串
}
}
updatedata(false); //更新編輯框內容
}

到目前為止還不能在接收編輯框中看到數據,因為我們還沒有打開串口,但運行程序不應該有任何錯誤,不然,你肯定哪兒沒看仔細,因為我是打開vc6對照著做一步寫一行的,運行試試。沒錯吧?那麼做下一步:

6.打開串口和設置串口參數 你可以在你需要的時候打開串口,例如在程序中做一個開始按鈕,在該按鈕的處理函數中打開串口。現在我們在主對話框的cscommtestdlg::oninitdialog()打開串口,加入如下代碼:

// todo: add extra initialization here
if(m_ctrlcomm.getportopen())
m_ctrlcomm.setportopen(false);

m_ctrlcomm.setcommport(1); //選擇com1
if( !m_ctrlcomm.getportopen())
m_ctrlcomm.setportopen(true);//打開串口
else
afxmessagebox("cannot open serial port");

m_ctrlcomm.setsettings("9600,n,8,1"); //波特率9600,無校驗,8個數據位,1個停止位

m_ctrlcomm.setinputmode(1); // 以二進制方式檢取數據
m_ctrlcomm.setrthreshold(1);
//參數1表示每當串口接收緩沖區中有多於或等於1個字元時將引發一個接收數據的oncomm事件
m_ctrlcomm.setinputlen(0); //設置當前接收區數據長度為0
m_ctrlcomm.getinput();//先預讀緩沖區以清除殘留數據

現在你可以試試程序了,將串口線接好後(不會接?去看看我寫的串口接線基本方法),打開串口調試助手,並將串口設在com2,選上自動發送,也可以等會手動發送。再執行你編寫的程序,接收框里應該有數據顯示了。

7.發送數據 先為發送按鈕添加一個單擊消息即bn_clicked處理函數,打開classwizard->message maps,選擇類cscommtestdlg,選擇idc_button_manualsend,雙擊bn_clicked添加onbuttonmanualsend()函數,並在函數中添加如下代碼:

void cscommtestdlg::onbuttonmanualsend()
{
// todo: add your control notification handler code here
updatedata(true); //讀取編輯框內容
m_ctrlcomm.setoutput(colevariant(m_strtxdata));//發送數據
}

運行程序,在發送編輯框中隨意輸入點什麼,單擊發送按鈕,啊!看看,在另一端的串口調試助手(或別的調試工具)接收框里出現了什麼。

如果你真是初次涉獵串口編程,又一次成功,那該說聲謝謝我了,因為我第一次做串口程序時可費勁了,那時網上的資料也不好找。開開玩笑,謝謝你的支持,有什麼好東西別忘了給我寄一份。

最後說明一下,由於用到vc控制項,在沒有安裝vc的計算機上運行時要從vc中把mscomm32.ocx、msvcrt.dll、mfc42.dll拷到windows目錄下的system子目錄中(win2000為system32)

8.發送十六進制字元
在主對話框中加入一個復選接鈕,id為idc_check_hexsend caption: 十六進制發送,再利用classwizard為其添加控制變數:m_ctrlhexsend;
在classview中為scommtestdlg類添加以下兩個public成員函數,並輸入相應代碼;

//由於這個轉換函數的格式限制,在發送框中的十六制字元應該每兩個字元之間插入一個空隔
//如:a1 23 45 0b 00 29
//cbytearray是一個動態位元組數組,可參看msdn幫助
int cscommtestdlg::string2hex(cstring str, cbytearray &senddata)
{
int hexdata,lowhexdata;
int hexdatalen=0;
int len=str.getlength();
senddata.setsize(len/2);
for(int i=0;i{
char lstr,hstr=str[i];
if(hstr==' ')
{
i ;
continue;
}
i ;
if(i>=len)
break;
lstr=str[i];
hexdata=converthexchar(hstr);
lowhexdata=converthexchar(lstr);
if((hexdata==16)||(lowhexdata==16))
break;
else
hexdata=hexdata*16 lowhexdata;
i ;
senddata[hexdatalen]=(char)hexdata;
hexdatalen ;
}
senddata.setsize(hexdatalen);
return hexdatalen;
}

//這是一個將字元轉換為相應的十六進制值的函數
//好多c語言書上都可以找到
//功能:若是在0-f之間的字元,則轉換為相應的十六進制字元,否則返回-1
char cscommtestdlg::converthexchar(char ch)
{
if((ch>='0')&&(ch<='9'))
return ch-0x30;
else if((ch>='a')&&(ch<='f'))
return ch-'a' 10;
else if((ch>='a')&&(ch<='f'))
return ch-'a' 10;
else return (-1);
}

再將cscommtestdlg::onbuttonmanualsend()修改成以下形式:
void cscommtestdlg::onbuttonmanualsend()
{
// todo: add your control notification handler code here
updatedata(true); //讀取編輯框內容
if(m_ctrlhexsend.getcheck())
{
cbytearray hexdata;
int len=string2hex(m_strtxdata,hexdata); //此處返回的len可以用於計算發送了多少個十六進制數
m_ctrlcomm.setoutput(colevariant(hexdata)); //發送十六進制數據
}
else
m_ctrlcomm.setoutput(colevariant(m_strtxdata));//發送ascii字元數據

}
現在,你先將串口線接好並打開串口調試助手v2.1,選上以十六制顯示,設置好相應串口,然後運行我們這個程序,在發送框中輸入00 01 02 03 a1 cc等十六進制字元,並選上以十六進制發送,單擊手動發送,在串口調試助手的接收框中應該可以看到00 01 02 03 a1 cc了。

9.在接收框中以十六進制顯示
這就容易多了: 在主對話框中加入一個復選接鈕,idc_check_hexdisplay caption: 十六進制顯示,再利用classwizard為其添加控制變數:m_ctrlhexdiaplay。 然後修改cscommtestdlg::oncomm()函數:
void cscommtestdlg::oncomm()
{
// todo: add your control notification handler code here
variant variant_inp;
colesafearray safearray_inp;
long len,k;
byte rxdata[2048]; //設置byte數組 an 8-bit integerthat is not signed.
cstring strtemp;
if(m_ctrlcomm.getcommevent()==2) //事件值為2表示接收緩沖區內有字元
{
variant_inp=m_ctrlcomm.getinput(); //讀緩沖區
safearray_inp=variant_inp; //variant型變數轉換為colesafearray型變數
len=safearray_inp.getonedimsize(); //得到有效數據長度
for(k=0;ksafearray_inp.getelement(&k,rxdata k);//轉換為byte型數組
for(k=0;k{
byte bt=*(char*)(rxdata k); //字元型
if(m_ctrlhexdisplay.getcheck())
strtemp.format("x ",bt); //將字元以十六進制方式送入臨時變數strtemp存放,注意這里加入一個空隔
else
strtemp.format("%c",bt); //將字元送入臨時變數strtemp存放

m_strrxdata =strtemp; //加入接收編輯框對應字元串
}
}
updatedata(false); //更新編輯框內容
}
測試:在串口調試助手發送框中輸入00 01 02 03 a1 cc等十六進制字元,並選上以十六進制發送,單擊手動發送,在本程序運行後選上以十六進制顯示,在串口調試助手中單擊手動發送或自動發送,則在本程序的接收框中應該可以看到00 01 02 03 a1 cc了。

10.如何設置自動發送
最簡單的設定自動發送周期是用settimer()函數,這在數據採集中很有用,在控制中指令的傳送也可能用到定時發送。
方法是:在classwizard中選上messagemap卡,然後在objects ids選中cscommtestdlg類,再在messages框中選上wm_timer消息,單擊add_加入void cscommtestdlg::ontimer(uint nidevent) 函數,這個函數是放入「時間到」後要處理的代碼:
void cscommtestdlg::ontimer(uint nidevent)
{
// todo: add your message handler code here and/or call default
onbuttonmanualsend();
cdialog::ontimer(nidevent);
}
再在在主對話框中加入一個復選接鈕,id為idc_check_autosend caption: 自動發送(周期1秒),再利用classwizard為其添加bn_click消息處理函數void cscommtestdlg::oncheckautosend():
void cscommtestdlg::oncheckautosend()
{
// todo: add your control notification handler code here
m_bautosend=!m_bautosend;
if(m_bautosend)
{
settimer(1,1000,null);//時間為1000毫秒
}
else
{
killtimer(1); //取消定時
}
}
其中:m_bautosend為bool型變數,在classview中為cscommtestdlg類加入,並在構造函數中初始化:
m_bautosen=false;
現在可以運行程序測試了。

熱點內容
發布:2024-07-17 17:13:27 瀏覽:872
phpjava交互 發布:2024-07-17 16:58:57 瀏覽:356
resin下jsp不能正常編譯 發布:2024-07-17 16:34:44 瀏覽:229
sqlserver如何切換主備伺服器 發布:2024-07-17 16:23:02 瀏覽:299
mc18伺服器ip 發布:2024-07-17 16:23:02 瀏覽:379
仙境傳說手游腳本 發布:2024-07-17 16:09:24 瀏覽:691
matlab命令窗口和新建腳本 發布:2024-07-17 15:51:26 瀏覽:375
建ftp文件夾 發布:2024-07-17 15:51:26 瀏覽:955
魔獸撿物腳本 發布:2024-07-17 15:27:56 瀏覽:130
開發ip伺服器 發布:2024-07-17 15:24:42 瀏覽:388
网站地图