VC++6.0上实现PC机与单片机串口通信的PC端上位机软件
1.簡介
我做這個的主要原因是選了一個PC和單片機的全雙工串口通信作為課設題目,單片機端是用匯編語言編程且要預先下載到板子里,關于這個這里我就不多說,主要說說怎么實現PC端的上位機軟件。早知道要寫軟件,鬼才選這個課題。但是自己選的路哭著也要走完。
做的時候我也感覺到,C++真難啊,,,但不可否認它確實是個好東西。
寫這樣的軟件也是有幾種方法思路的,因為我怕太難的學不會的話,到時候課設就涼涼了。所以我選擇了較為親民的ActiveX控件的方法。
Microsoft Communications Control(以下簡稱MSComm)是Microsoft公司提供的簡化Windows下串行通信編程的ActiveX控件,它為應用程序提供了通過串行接口收發數據的簡便方法。
MSComm 控件通過串行端口傳輸和接收數據,為應用程序提供串行通訊功能。MSComm控件在串口編程時非常方便,所以我們不必花時間去了解較為復雜的API函數,而且在VC、VB、什么什么等語言中都可以使用。具體來說,它提供了兩種處理通信問題的方法:一是事件驅動(Event-driven)方法,另一個是查詢法。
1.通訊方式
MSComm控件提供下列兩種處理通訊的方式:事件驅動方式和查詢方式。
1.事件驅動方式
事件驅動通訊是處理串行端口交互作用的一種非常有效的方法。在許多情況下,在事件發生時需要得到通知,就比如,在串口接收緩沖區中有字符,或者 Carrier Detect (CD) 或 Request To Send (RTS) 線上一個字符到達或一個變化發生時。在這些情況下,可以利用MSComm控件的OnComm事件捕獲并處理這些通訊事件。OnComm事件還可以檢查和處理通訊錯誤。所有通訊事件和通訊錯誤的列表,參閱CommEvent 屬性。在編程過程中,就可以在OnComm事件處理函數中加入自己的處理代碼。這種方法的優點是程序響應及時,可靠性高。每個MSComm控件對應著一個串行端口。如果應用程序需要訪問多個串行端口,必須使用多個 MSComm 控件。
2.查詢方式
查詢方式本質上還是事件驅動,但在有些情況下,這種方式顯得更為便捷。在程序的每個關鍵功能之后,可以通過檢查CommEvent屬性的值來查詢事件和錯誤。如果應用程序較小,并且是自保持的,這種方法可能是更可取的。比如,如果寫一個簡單的電話撥號程序,則沒有必要對每接收一個字符都產生事件,因為唯一等待接收的字符是調制解調器的“確定”響應。?
2.MSComm控件常用屬性
MSComm 控件有很多重要的屬性,但首先必須熟悉幾個屬性。知道這幾個幾乎就能橫著走了。
CommPort? ? 設置并返回通訊端口號。?
Settings? ? ? ? 以字符串的形式設置并返回波特率、奇偶校驗、數據位、停止位。?
PortOpen? ? ? 設置并返回通訊端口的狀態。也可以打開和關閉端口。?
Input? ? ? ? ? ? ?從接收緩沖區返回和刪除字符。?
Output? ? ? ? ? 向傳輸緩沖區寫一個字符串。
1.CommPort屬性
設置并返回通訊端口號。
語法:object.CommPort[value ] (value 一整型值,說明端口號。)?
說明:在設計時,value可以設置成從 1 到 16 的任何數(缺省值為 1)。但是如果用PortOpen屬性打開一個并不存在的端口時,MSComm 控件會產生錯誤 68(設備無效)。
注意:必須在打開端口之前設置 CommPort 屬性。
2.PortOpen屬性
設置并返回通訊端口的狀態(開或關)。該屬性在設計時無效。
MSComm.PortOpen=true; //打開端口MSComm.PortOpen=false; //關閉端口并清除接收和傳輸緩沖區說明:
設置PortOpen屬性為True打開端口。設置為False關閉端口并清除接收和傳輸緩沖區。當應用程序終止時,MSComm 控件自動關閉串行端口。
在打開端口之前,確定 CommPort 屬性設置為一個合法的端口號。如果 CommPort 屬性設置為一個非法的端口號,則當打開該端口時,MSComm 控件產生錯誤68(設備無效)。
另外,串行端口設備必須支持Settings 屬性當前的設置值。如果 Settings 屬性包含硬件不支持的通訊設置值,那么硬件可能不會正常工作。
如果在端口打開之前,DTREnable或RTSEnable屬性設置為True,當關閉端口時,該屬性設置為False。否則,DTR和RTS線保持其先前的狀態。
數據類型:Boolean
3.RThreshold 屬性
在MSComm控件設置CommEvent屬性為comEvReceive并產生OnComm之前,設置并返回的要接收的字符數。
語法:object.Rthreshold [ = value ](value 整型表達式,說明在產生OnComm 事件之前要接收的字符數。)
說明:當接收字符后,若Rthreshold屬性設置為0(缺省值)則不產生 OnComm事件。例如,設置Rthreshold為1,接收緩沖區收到每一個字符都會使MSComm控件產生OnComm事件。
4.CTSHolding 屬性
確定是否可通過查詢Clear To Send (CTS)線的狀態發送數據。Clear To Send 是調制解調器發送到相聯計算機的信號,指示傳輸可以進行。該屬性在設計時無效,在運行時為只讀。
語法:object.CTSHolding(Boolean)
Mscomm 控件的 CTSHolding 屬性設置值:True Clear To Send 線為高電平。?False Clear To Send 線為低電平。?
說明:如果Clear To Send線為低電平 (CTSHolding = False)并且超時時,MSComm控件設置CommEvent?屬性為comEventCTSTO (Clear To Send Timeout) 并產生OnComm事件。
Clear To Send 線用于RTS/CTS (Request To Send/Clear To Send) 硬件握手。如果需要確定Clear To Send 線的狀態,CTSHolding 屬性給出一種手工查詢的方法。更詳細有關握手協議在?Handshaking 屬性。
5.SThreshold 屬性
MSComm控件設置CommEvent屬性為comEvSend并產生OnComm事件之前,設置并返回傳輸緩沖區中允許的最小字符數。
語法:object.SThreshold [ = value ],value整形表達式,代表在OnComm事件產生之前在傳輸緩沖區中的最小字符數。?
說明:若設置Sthreshold屬性為0(缺省值),數據傳輸事件不會產生OnComm 事件。若設置Sthreshold 屬性為 1,當傳輸緩沖區完全空時,MSComm控件產生OnComm事件。如果在傳輸緩沖區中的字符數小于value,CommEvent?屬性設置為comEvSend,并產生OnComm事件。comEvSend 事件僅當字符數與 Sthreshold 交叉時被激活一次。例如,如果 Sthreshold 等于5,僅當在輸出隊列中字符數從 5 降到 4 時,comEvSend 才發生。如果在輸出隊列中從沒有比 Sthreshold 多的字符,comEvSend事件將絕不會發生。
6.Handshake 常數
| 常數 | 值 ?? | 描述? |
| comNone ?? | ? ?0 ? | ?無握手 |
| comXonXoff | ? ?1 ? | ?XOn/Xoff 握手 |
| comRTS ? | ? ? ? 2 ?????? | ?Request-to-send/clear-to-send 握手 |
| comRTSXOnXOff | ? ? 3 ??? | ?Request-to-send 和 clear-to-send 握手皆可 |
? ? ? ? ??? ??
7.OnComm 常數
| 常數 | ?值 | ?描述? |
| comEvSend??? | ? ? 1 ? | ???發送事件 |
| comEvReceive? | ? 2 | ???接收事件 |
| comEvCTS | ? ? 3 ?? | clear-to-send線變化 |
| comEvDSR? | ? 4 | data-set ready線變化 |
| comEvCD ? | ???5 ? | ?carrier detect 線變化 |
| comEvRing ? | ? ? ?6 ??? | ????振鈴檢測 |
| comEvEOF | ? ? 7 ???? | 文件結束 |
8.?Error 常數
| 常數 | 值 | 描述 |
| comEventBreak | ?1001 | 接收到中斷信號? |
| comEventCTSTO | 1002 ? | Clear-to-send 超時? |
| comEventDSRTO | 1003 ? | ?Data-set ready 超時 |
| comEventFrame ? | ?1004 ? | ??幀錯誤? |
| comEventOverrun | 1006 ?? | ???端口超速? |
| comEventCDTO | 1007 | ??Carrier detect 超時? |
| comEventRxOver?? | 1008 ? | ?接收緩沖區溢出? |
| comEventRxParity | 1009 | ?Parity 錯誤? |
| comEventTxFull ?? | 1010 | 傳輸緩沖區滿 |
| comEventDCB | ?1011 | 檢索端口設備控制塊 (DCB) 時的意外錯誤? |
9.InputMode 常數
| 常數 | 值 | 描述? |
| ????comInputModeText | ??0 ?? | ?(缺省)通過 Input 屬性以文本方式取回數據 |
| ?comInputModeBinary ? | ?1?? | ??通過 Input 屬性以二進制方式檢取回數據 |
10.CDHolding屬性
通過查詢Carrier Detect (CD)線的狀態確定當前是否有傳輸。Carrier Detect 是從調制解調器發送到相聯計算機的一個信號,指示調制解調器正在聯機。該屬性在設計時無效,在運行時為只讀。
語法:object.CDHolding
設置值:CDHolding屬性的設置值為:?
| 設置 | ?????描述? |
| True Carrier Detect ? | ?線為高電平? |
| False Carrier Detect | 線為低電平 |
說明:注意當Carrier Detect線為高電平(CDHolding = True)且超時時,MSComm控件設置CommEvent屬性為comEventCDTO(Carrier Detect 超時錯誤),并產生OnComm事件。
注意:在主機應用程序中捕獲一個丟失的傳輸是特別重要的,例如一個公告板,因為呼叫者可以隨時掛起(放棄傳輸)。
Carrier Detect也被稱為 Receive Line Signal Detect (RLSD)
數據類型 Boolean
11.DSRHolding 屬性
確定Data Set Ready (DSR)線的狀態。Data Set Ready 信號由調制解調器發送到相連計算機,指示作好操作準備。該屬性在設計時無效,在運行時為只讀。
語法:object.DSRHolding
object 所在處表示對象表達式,其值是“應用于”列表中的對象。
DSRHolding屬性返回以下值:
| 值 ??? | ??????描述? |
| True Data Set Ready | ??線高? |
| False Data Set Ready | ??線低? |
說明:當Data Set Ready線為高電平(DSRHolding = True)且超時時,MSComm 控件設置CommEvent屬性為comEventDSRTO(數據準備超時)并產生OnComm 事件。
當為Data Terminal Equipment (DTE)機器寫Data Set Ready/Data Terminal Ready握手例程時該屬性是十分有用的。
數據類型:Boolean
12.Settings 屬性
設置并返回波特率、奇偶校驗、數據位、停止位參數。
語法:object.Settings[ = value]
說明:當端口打開時,如果 value 非法,則 MSComm 控件產生錯誤 380(非法屬性值)。
Value 由四個設置值組成,有如下的格式:"BBBB,P,D,S"。BBBB為波特率,P為奇偶校驗,D為數據位數,S為停止位數。value 的缺省值是:"9600,N,8,1"。
(1)下表列出合法的波特率:
設置值:110、300、600、1200、2400、9600(缺省)、14400、19200、28800、38400、56000、128000、256000
(2)下表說明合法的奇偶校驗值:
設置值??????描述
E ?????????偶數 (Even)
M??????????標記 (Mark)
N ?????????缺省 (Default) None
O ?????????奇數 (Odd)
S ??????????空格 (Space)
(3)下表列出合法的數據位值。
設置值:4、5、6、7、8 (缺省)
(4)下表列出合法的停止位值。
設置值:1(缺省)、1.5、2
13.InputLen 屬性
設置并返回 Input 屬性從接收緩沖區讀取的字符數。該屬性在設計時無效,在運行時為只讀。
語法:object.InputLen [ = value]
InputLen 屬性語法包括下列部分:
value 整型表達式,說明 Input 屬性從接收緩沖區中讀取的字符數。?
說明:InputLen 屬性的缺省值是 0。設置 InputLen 為 0 時,使用 Input 將使 MSComm 控件讀取接收緩沖區中全部的內容。
InputLen屬性確定被Input屬性讀取的字符數。設置 InputLen 為 0,則 Input 屬性讀取緩沖區中全部的內容。
InputMode 屬性確定用 Input 屬性讀取的數據類型。如果設置 InputMode 為comInputModeText,Input屬性通過一個Variant返回文本數據。如果設置 InputMode為comInputModeBinary,Input 屬性通過一個Variant。返回一二進制數據的數組。
若接收緩沖區中 InputLen字符無效,Input屬性返回一個零長度字符串 ("")。在使用 Input 前,用戶可以選擇檢查 InBufferCount 屬性來確定緩沖區中是否已有需要數目的字符。該屬性在從輸出格式為定長數據的機器讀取數據時非常有用。
數據類型:Variant
14.Output 屬性
往傳輸緩沖區寫數據流。該屬性在設計時無效,在運行時為只讀。
語法:
object.Output [ = value]
Output屬性語法包括下列部分:
| 部分 | ???描述 |
| object | ??對象表達式,其值是“應用于”列表中的對象 |
| value | 要寫到傳輸緩沖區中的一個字符串 |
???
說明:
Output 屬性可以傳輸文本數據或二進制數據。用 Output 屬性傳輸文本數據,必須定義一個包含一個字符串的 Variant。發送二進制數據,必須傳遞一個包含字節數組的 Variant 到 Output 屬性。
正常情況下,如果發送一個 ANSI 字符串到應用程序,可以以文本數據的形式發送。如果發送包含嵌入控制字符、Null 字符等等的數據,要以二進制形式發送。
數據類型:Variant
15. EOFEnable 屬性
確定在輸入過程中 MSComm 控件是否尋找文件結尾 (EOF) 字符。如果找到EOF字符,將停止輸入并激活OnComm事件,此時 CommEvent 屬性設置為 comEvEOF。
語法:object.EOFEnable [= value]
EOFEnable屬性語法包括下列部分:
value 布爾表達式,確定當找到 EOF 字符時,OnComm 事件是否被激活,如“設置值”中所描述。?
value 的設置值:
True? ? 當 EOF 字符找到時 OnComm 事件被激活。?
False(缺省)當EOF 字符找到時OnComm 事件不被激活。?
說明:當 EOFEnable 屬性設置為 False,OnComm 控件將不在輸入流中尋找 EOF 字符。
16. 錯誤消息(MS Comm 控件)
下表列出 MSComm 控件可以捕獲的錯誤,我們可以通過錯誤代碼知道具體出錯點
| 值 | 描述 |
| 380 | ??無效屬性值 comInvalidPropertyValue |
| 383 | ?屬性為只讀 comSetNotSupported |
| 394 | 屬性為只讀 comGetNotSupported? |
| 8000 | 端口打開時操作不合法 comPortOpen |
| 8001 | 超時值必須大于 0? |
| 8002 | ?無效端口號 comPortInvalid |
| 8003 | 屬性只在運行時有效? |
| 8004 | 屬性在運行時為只讀? |
| 8005 | 端口已經打開 comPortAlreadyOpen |
| 8006 | ?設備標識符無效或不支持該標識符? |
| 8007 | 不支持設備的波特率? |
| 8008 | 指定的字節大小無效? |
| 8009 | 缺省參數錯誤? |
| 8010 | 硬件不可用(被其它設備鎖定)? |
| 8011 | 函數不能分配隊列? |
| 8012 | ??設備沒有打開 comNoOpen? |
| 8013 | 設備已經打開? |
| 8014 | 不能使用 comm 通知? |
| 8015 | 不能設置 comm 狀態 comSetCommStateFailed |
| 8016 | 不能設置 comm 事件屏蔽? |
| 8018 | 僅當端口打開時操作才有效 comPortNotOpen? |
| 8019 | ?設備忙? |
| 8020 | ?讀 comm 設備錯誤 comReadError |
| 8021 | ??為該端口檢索設備控制塊時的內部錯誤 comDCBError? |
2.具體實現(附部分代碼)
MSComm控件進行串行通信的一般步驟主要就以下幾點
(1)設置通信對象、通信端口號及其它屬性;
(2)設定通信協議;
(3)打開通信端口,進行數據的傳送;
(4)關閉通信端口。
怎么引入控件的具體步驟在這里我就不詳細介紹,自己下Visual C++6.0熟悉以下就知道了。下面是我設計的一個程序界面,包含串口數據發送和接收顯示以及前期數碼管顯示的測試程序。
大家可能對這個控件沒有具體的概念,簡單就上面開始測試的按鍵來說,打開它的屬性如下
?它有一個ID號,這在代碼里表現為一個函數的實現
?我們可以發現代碼中含有由choosenum為判斷條件的判斷語句,到這相信大家可以猜到這個是使數碼管顯示指定數字的實現代碼,這些控件都是包含在CDpjDlg類里的。
?這每個值又對應著相應的控件,就說C++這個語言是一個面向對象的編程,這也是它的一個優越性,也是最值得學習的一點。再看那個小按鈕的屬性界面就應該明白程序界面是怎么和代碼相關聯的了。但是使用控件之前要在對象里初始化才能用。
?上面就是是簡單介紹了一下基本的操作方式,增進以下了解。接下來是比較重要的幾段代碼,源碼我會在課設答辯完成后再放到平臺上。
首先是頭文件里類的定義
/ // CDpjDlg dialogclass CDpjDlg : public CDialog { // Construction public:int Str2Hex(CString str, CByteArray &senddata);char HexChar(char c);CDpjDlg(CWnd* pParent = NULL); // standard constructor// Dialog Data//{{AFX_DATA(CDpjDlg)enum { IDD = IDD_DPJ_DIALOG };CEdit m_ctrlsend;CMSComm m_ctrlComm;CString m_send;CString m_receive;CString m_state;//}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CDpjDlg)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support//}}AFX_VIRTUAL// Implementation protected:HICON m_hIcon;// Generated message map functions//{{AFX_MSG(CDpjDlg)virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();virtual void OnOK();afx_msg void OnTest();afx_msg void OnRadio1();afx_msg void OnRadio2();afx_msg void OnRadio3();afx_msg void OnRadio4();afx_msg void OnRadio5();afx_msg void OnButton1();afx_msg void OnButton2();afx_msg void OnOnCommMscomm();virtual void OnCancel();afx_msg void OnSetfocusEdit1();afx_msg void OnChangeEdit2();DECLARE_EVENTSINK_MAP()//}}AFX_MSGDECLARE_MESSAGE_MAP() };實現向串口發送由text控件得到的數據的代碼,上面的是從控件得到數據的函數
void CDpjDlg::OnSetfocusEdit1() //Edit1文本框得到焦點 {// TODO: Add your control notification handler code herem_ctrlsend.SetSel(0,-1);//Edit1文本框中字符全選中m_ctrlsend.Clear(); //清除Edit1文本框中的所有字符 } void CDpjDlg::OnOK() {// TODO: Add extra validation hereCByteArray hexdata; UpdateData(TRUE); //讀編輯框內容 int len=Str2Hex(m_send,hexdata);UpdateData(FALSE); //更新編輯框內容m_ctrlComm.SetOutput(COleVariant(hexdata));}實現接收到的消息的處理程序
/ // 消息處理程序BOOL CDpjDlg::OnInitDialog() {CDialog::OnInitDialog();// Add "About..." menu item to system menu.// IDM_ABOUTBOX must be in the system command range.ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){CString strAboutMenu;strAboutMenu.LoadString(IDS_ABOUTBOX);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// Set the icon for this dialog. The framework does this automatically// when the application's main window is not a dialogSetIcon(m_hIcon, TRUE); // Set big iconSetIcon(m_hIcon, FALSE); // Set small icon// TODO: Add extra initialization herem_ctrlComm.SetCommPort(1); //選擇的COM口m_ctrlComm.SetInputMode(1); //輸入方式為二進制方式m_ctrlComm.SetInBufferSize(1024); //設置輸入緩沖區大小m_ctrlComm.SetRThreshold(1); //參數1表示每當串口接收緩沖區中有多于或等于1個字符時將引發一個接收數據的OnComm事件m_ctrlComm.SetSThreshold(1);//參數1表示當傳輸緩沖區完全空時將引發一個接收數據的OnComm事件m_ctrlComm.SetSettings("9600,n,8,1"); //波特率/數據位/停止位m_ctrlComm.SetPortOpen(TRUE);//打開串口m_send="00";UpdateData(FALSE); //更新編輯框內容return TRUE; // return TRUE unless you set the focus to a control }?主要實現各種狀態判斷的函數
void CDpjDlg::OnOnCommMscomm() {// TODO: Add your control notification handler code hereVARIANT variant_inp;COleSafeArray safearray_inp;LONG len,k;BYTE rxdata[512]; //設置BYTE數組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<len;k++)safearray_inp.GetElement(&k,rxdata+k);//轉換為BYTE型數組for(k=0;k<len;k++) //將數組轉換為Cstring型變量{BYTE bt=*(char*)(rxdata+k); //字符型strtemp.Format("%02X",bt); //將字符送入臨時變量strtemp存放m_receive=strtemp;//加入對應字符串m_receive中}}elsem_receive="數據未收到 "; if(strtemp=="00"){ m_state="開始通信!";}else if(strtemp==m_send){ m_state="通信正常!";}else{ m_state="通信不正常!";}if(strtemp=="FF"){ m_state="通信結束,輸入00重新開始!";}UpdateData(FALSE); //更新編輯框內容 }一個測試單片機的程序,用數碼管
void CDpjDlg::OnTest() {m_receive="";//05 57 01 00 00 00 04 57 數碼管顯示00//05 57 01 00 00 01 04 56 數碼管顯示01//05 57 01 00 00 02 04 55 數碼管顯示02//05 57 01 00 00 03 04 54 數碼管顯示03//05 57 01 00 00 04 04 53 數碼管顯示04//05 57 01 00 00 05 04 52 數碼管顯示05//05 57 01 00 00 06 04 51 數碼管顯示06//05 57 01 00 00 07 04 50 數碼管顯示07//05 57 01 00 00 08 04 5F 數碼管顯示08//05 57 01 00 00 09 04 5E 數碼管顯示09//05 57 01 00 00 0A 04 5D 數碼管顯示10//使數碼管顯示從0-4 CByteArray hexdata; //05 57 01 00 00 00 04 57 數碼管顯示00 m_send="05 57 01 00 00 00 04 57";int len=Str2Hex(m_send,hexdata);m_ctrlComm.SetOutput(COleVariant(hexdata));Sleep(100);//等待100毫秒//05 57 01 00 00 01 04 56 數碼管顯示01m_send="05 57 01 00 00 01 04 56";len=Str2Hex(m_send,hexdata);m_ctrlComm.SetOutput(COleVariant(hexdata));//發送數據Sleep(100);//等待100毫秒//05 57 01 00 00 02 04 55 數碼管顯示02m_send="05 57 01 00 00 02 04 55";len=Str2Hex(m_send,hexdata);m_ctrlComm.SetOutput(COleVariant(hexdata));//發送數據Sleep(100);//等待100毫秒//05 57 01 00 00 03 04 54 數碼管顯示03m_send="05 57 01 00 00 03 04 54";len=Str2Hex(m_send,hexdata);m_ctrlComm.SetOutput(COleVariant(hexdata));//發送數據Sleep(100);//等待100毫秒//05 57 01 00 00 04 04 53 數碼管顯示04m_send="05 57 01 00 00 04 04 53";len=Str2Hex(m_send,hexdata);m_ctrlComm.SetOutput(COleVariant(hexdata));//發送數據Sleep(100);//等待100毫秒//05 52 01 03 00 01 04 50 讀取地址03H中的值m_send="05 52 01 03 00 01 04 50 ";len=Str2Hex(m_send,hexdata);m_ctrlComm.SetOutput(COleVariant(hexdata));//發送數據 }這個程序發的只是數字1,2,3,4,,但要想單片機端匯編編程簡單一點,我實際用的是直接發送使數碼管顯示相應數字的兩位16進制數。其中關于串口數據傳輸協議我覺得有必要提一下,從上面的代碼也可以看到傳的數據是一組由八個兩位16進制數組成的東西。
這個我也不太懂,簡單來說就比如
m_send="05 57 01 00 00 C0 04 97";//05-協議引導字節,可以說是默認的,基本不用改 //57-表示寫,若是52的話表示讀 //01-也是固定的東西 //00-數據的位置 //00-固定的 //C0-要傳輸的數據 //04-固定的 //97-進行一個異或校驗,57和數據的位置和要傳的數據的二進制異或結果應該大概率會需要一個轉16進制的代碼,這個改一下對象應該就能拿去用
//將字符轉換十六進制 char CDpjDlg::HexChar(char c) {if((c>='0')&&(c<='9'))return c-0x30;else if((c>='A')&&(c<='F'))return c-'A'+10;else if((c>='a')&&(c<='f'))return c-'a'+10;else return -1; }//將字符串轉換成十六進制 int CDpjDlg::Str2Hex(CString str, CByteArray &senddata) {int hexdata,lowhexdata;int hexdatalen=0;int len=str.GetLength();senddata.SetSize(len/2);for(int i=0;i<len;){char lstr,hstr=str[i];if(hstr==' '){i++;continue;}i++;if(i>=len)break;lstr=str[i];hexdata=HexChar(hstr); //高位轉換lowhexdata=HexChar(lstr); //低位轉換if((hexdata==16)||(lowhexdata==16))break;else hexdata=hexdata*16+lowhexdata;i++;senddata[hexdatalen]=(char)hexdata;hexdatalen++;}return hexdatalen; }最后是關閉串口的函數,是“關閉”按鈕控件的實現
void CDpjDlg::OnCancel() {// TODO: Add extra cleanup herem_ctrlComm.SetPortOpen(FALSE);//關閉串口CDialog::OnCancel(); }最后,溫馨提示,上面的代碼只是主要實現框架的代碼,實際實現遠不止于此。
總結
以上是生活随笔為你收集整理的VC++6.0上实现PC机与单片机串口通信的PC端上位机软件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: YDOOK: ANSYS Maxwell
- 下一篇: PLL锁相环简介