終于搞定了!我想我只能這么說(shuō),這兩天熬夜的成果啊。
自從去年校電子競(jìng)賽之后一直想要做些計(jì)算機(jī)控制的東西,和鄭子含老師聊了聊,她推薦我去學(xué)習(xí)VB,但是我對(duì)C++情有獨(dú)鐘,因?yàn)閷W(xué)過(guò)C上手可能快。一直沒(méi)有時(shí)間搞。這次比賽搞小車(chē),想把上學(xué)期的想法實(shí)現(xiàn)一下。但是電腦控制小車(chē)必須要一個(gè)良好的人機(jī)交換界面。于是開(kāi)學(xué)想要系統(tǒng)的學(xué)習(xí)下C++語(yǔ)言,看了半本鄭阿奇的書(shū)結(jié)果發(fā)現(xiàn)內(nèi)容竟然和C一模一樣,關(guān)鍵的后半本介紹了類(lèi)的概念,我粗略的看了。找了孫鑫老師的視頻和書(shū),了解了下MFC的編程方式,但是這個(gè)都和串口沒(méi)什么關(guān)系,我知道MFC封裝了WIN API,但是誰(shuí)可以告訴我用哪個(gè)函數(shù)打開(kāi)PC上的串口?
終于找了一本書(shū)叫做《Visual C++實(shí)踐與提高——串口通信與工程應(yīng)用篇》(中國(guó)鐵道出版社,張?bào)蘩?劉書(shū)智主編)。首先按著上面的程序做了個(gè)串口調(diào)試助手,理解了下,但是好用嗎?不見(jiàn)得,單片機(jī)端的程序的設(shè)計(jì)和書(shū)上的不同(書(shū)上匯編,寫(xiě)了3頁(yè)還不如我用C十幾行就夠了)加上頻繁的啟動(dòng)PC定時(shí)器,導(dǎo)致老是檢測(cè)延時(shí),我測(cè)過(guò)只要按上7下,就會(huì)直接卡死。
做了一個(gè)星期左右時(shí)間的準(zhǔn)備工作,做壞了幾個(gè)程序,藍(lán)屏很多次之后,前天晚上斷網(wǎng)后開(kāi)工,搞到凌晨四點(diǎn)鐘,終于把雛形做出來(lái)了,昨天下午主要的目的是要把編輯框里的數(shù)據(jù)(人工設(shè)置小車(chē)速度)讀到程序中再發(fā)到單片機(jī)上,但是書(shū)上并沒(méi)有把編輯框的數(shù)據(jù)讀到程序中的函數(shù),找了很久找到
UpdateData(true);
GetDlgItemText(IDC_EDIT4,a);
用了一下不錯(cuò),可以用。最難的就是發(fā)送了,因?yàn)槲沂褂昧撕芏喟粹o每次執(zhí)行按鈕都要有返回值確認(rèn)單片機(jī)是否是正常收到,為了簡(jiǎn)便起見(jiàn)我PC發(fā)到單片機(jī)上的都是1個(gè)字節(jié),而單片機(jī)發(fā)到PC上的都是2個(gè)字節(jié)。而發(fā)送小車(chē)的速度值是不能超過(guò)1個(gè)字節(jié),為了不和之前確認(rèn)數(shù)發(fā)生檢測(cè)錯(cuò)誤,所以我將編輯框的數(shù)據(jù)先加上11再在單片機(jī)里減去11。這個(gè)涉及到數(shù)據(jù)類(lèi)型轉(zhuǎn)換的問(wèn)題,int char VARIANT CString CByteArray,我終于明白了,為什么數(shù)據(jù)類(lèi)型也是一門(mén)課。。。
當(dāng)時(shí)比較混亂問(wèn)了很多學(xué)計(jì)算機(jī)的同學(xué),但是沒(méi)有得到答案,最后問(wèn)了下瀟,她給了我C++老師的qq,叫“曾哥”。我*,曾哥如此閃亮名字刺瞎了我的狗眼!于是速度加為好友,不過(guò)最后都沒(méi)有拜托他們,瀟今早給程序前我已經(jīng)想好怎么解決了,這個(gè)方法避開(kāi)了CString 和CByteArray的轉(zhuǎn)換。
不廢話了,現(xiàn)在就貼制作過(guò)程(使用工具Visual C++ 6.0,9針RS232串口線一條,P0口帶上拉的LED的51最小系統(tǒng)版。)
打開(kāi)軟件,新建——>MFC AppWizard[exe]再填寫(xiě)工程名和路徑——>基于對(duì)話框(不需要太好看,對(duì)話框足矣)——>確定。
最右邊是可以添加的控件,但是我們可以看到?jīng)]有MSCOMM控件,因?yàn)閷?duì)于搞高級(jí)軟件的程序員來(lái)說(shuō)一般用不到的,所以串口不是默認(rèn)控件,需要添加。
工程——>增加到工程——>Components and Controls會(huì)彈出一個(gè)叫做Components and Controls Gallery的對(duì)話框,打開(kāi)Registered ActiveX Controls文件夾會(huì)看到很多可以添加的控件,找到Microsoft Communications Comtrol,version 6.0選項(xiàng),單擊Insert——>確定。跳出Confirm Classes對(duì)話框,這個(gè)不需要修改,直接點(diǎn)OK就好了,然后就可以看到控件已經(jīng)加到空間框里了。
這個(gè)電話狀的就是MSComm控件,你可以右擊這個(gè)圖標(biāo)點(diǎn)屬性修改ID,當(dāng)然也可以用默認(rèn)的。再把編輯框和按鈕等等拖到界面上,生成的就是最后界面的樣子,所以可以隨意搞(下圖是我做的界面)
再在對(duì)話框的頭文件集中的×××Dlg.h(×××是你的文件名)的最開(kāi)頭添加mscomm頭文件#include "mscomm.h"(如下圖)
然后找到對(duì)話框 類(lèi)的定義代碼中加入CMSComm類(lèi)變量聲明
class CxxxDlg.h : public CDialog
{
...
protected:
CMSComm myComm;//(你也可以用其他的)
}
如下圖
接著在xxxDlg.cpp中所有函數(shù)外面添加全局變量(注意是全局),當(dāng)然也可以不添加。
因?yàn)槲易龅谋容^簡(jiǎn)單,所以對(duì)于串口的選擇并沒(méi)有設(shè)置,直接是com1,,9600bps,0(無(wú)校驗(yàn)),8(位),1(停止位)當(dāng)然這個(gè)都在程序中寫(xiě)入。并在點(diǎn)開(kāi)exe文件之后就設(shè)置好了。這個(gè)只需在初始化函數(shù)CxxxDlg :: OnInitDialog()中寫(xiě)入以下程序即可。
DWORD style=WS_VISIBLE|WS_CHILD;
if(!myComm.Create(NULL,style,CRect(0,0,0,0),this,IDC_MSCOMM1))
{
AfxMessageBox("創(chuàng)建MSComm控件失敗!");
return -1;
}
else//創(chuàng)建成功則執(zhí)行初始化及打開(kāi)串口操作
{
myComm.SetCommPort(1);//指定串口號(hào)
myComm.SetSettings("9600,N,8,1");//通信參數(shù)設(shè)置
myComm.SetInBufferSize(1024);//指定接收緩沖區(qū)大小
myComm.SetInBufferCount(0);//清空接收緩沖區(qū)
myComm.SetInputMode(1);//設(shè)置數(shù)據(jù)獲取方式
myComm.SetInputLen(0);//設(shè)置每次讀取長(zhǎng)度,0為全部讀取
myComm.SetRThreshold(2);//設(shè)置接收OnComm事件字符門(mén)限值在收到2字節(jié)時(shí)候觸發(fā)事件
myComm.SetPortOpen(1);//打開(kāi)串口
}
這樣就創(chuàng)建串口了,接下里就處理按鍵、顯示和處理收發(fā)數(shù)據(jù)的事情了。
其做法和做普通的MFC一樣就不贅述了,我介紹一下一些用到的MSComm控件的一些函數(shù)屬性。
輸入(串口接收)函數(shù)VARIANT GetInput();
例子:VARIANT int1;
int1 = myComm.GetInput();
即可接收來(lái)自串口的數(shù)據(jù),但是注意變量,想要顯示就要轉(zhuǎn)化。
輸出(串口發(fā)送)函數(shù)void SetOutput(const VARIANT&newValue);
例子:CSting aa;
aa="at";
myComm.SetOutput(COleVariant(aa));
即可將數(shù)據(jù)寫(xiě)入輸出緩沖區(qū),COleVariant(aa)是將CString 轉(zhuǎn)換為VARIANT類(lèi)型數(shù)據(jù)。
關(guān)于串口事件CommEvent的屬性就像單片機(jī)中的中斷一樣。只要串口有事件發(fā)生,就會(huì)去響應(yīng),當(dāng)然必須設(shè)置響應(yīng)的條件和方式。下圖是事件發(fā)生時(shí)返回到CommEvent的值
如果要添加處理方式就在xxxDlg.app中的void CxxxDlg :: OnOnCommMscomm1()
{
...
}
這個(gè)函數(shù)中添加。
最重要的是不要忘記使用完串口之后要關(guān)閉它。在界面按Ctrl+W彈出MFC ClassWizard類(lèi)向?qū)?duì)話框
點(diǎn)擊Object IDs列表中的xxxDlg再點(diǎn)Messages列表框中的WM_CLOSE單擊Add Function單擊Edit Code
就會(huì)跳到void CxxxDlg :: OnClose()函數(shù)在里面添加
if(myComm.GetPortOpen())
myComm.SetPortOpen(0);
CDialog::OnClose();
即可。
這樣一個(gè)串口通信的基本流程就做完了。當(dāng)然如果你不喜歡MFC這三個(gè)正方體組成的圖標(biāo)你可以改,最簡(jiǎn)單的方法是找一張圖轉(zhuǎn)成ico格式的,將工程文件夾里res文件夾下的默認(rèn)ico換掉,只要名字改成一樣即可。
看一下效果圖。
按下【串口匹配】匹配串口
按下【收發(fā)模式】這是工作在小車(chē)自動(dòng)跑的模式下,將當(dāng)前的數(shù)據(jù)發(fā)動(dòng)到上位機(jī)顯示出來(lái)。每隔半秒收發(fā)一次。
按下【遙控模式】可以看到右邊的編輯框內(nèi)顯示:?jiǎn)?dòng)遙控模式,并且按左邊的按鈕出現(xiàn)相對(duì)應(yīng)的前進(jìn)、左轉(zhuǎn)、右轉(zhuǎn)、停止(此時(shí)自動(dòng)收發(fā)已經(jīng)停止)。
【左轉(zhuǎn)】左邊有一盞亮了
【右轉(zhuǎn)】右邊有一盞亮了
【停止】全滅了,桌子有點(diǎn)亂,呵呵?慈珗D更亂,線奇多。。。— —!
修改“設(shè)置速度”編輯框里的數(shù)據(jù),按下【發(fā)送】,看到上面顯示“速度已修改!”,即將23發(fā)送到單片機(jī)上。
從圖中可以看到。本來(lái)有8個(gè)LED燈,現(xiàn)在是“亮亮亮滅亮滅滅滅”因?yàn)槭枪碴?yáng)極的,所以亮的是'0'滅的是'1'轉(zhuǎn)化成二進(jìn)制就是00010111可以用科學(xué)計(jì)算器算一下就是十進(jìn)制23
后記:還得搞一下無(wú)線發(fā)送和接受。。。還有一個(gè)禮拜答辯。。明天FPGA實(shí)驗(yàn)課,老師這么看好我,還得搞一下FPGA。。。悲劇。。。