国产综合高清-a视频-高清全高清-国产黄a三级三级三级70年后|www.whhswh.com

您現(xiàn)在所在的是:

串口通信

回帖:1個(gè),閱讀:1712 [上一頁(yè)] [1] [下一頁(yè)]
986
ya5751
文章數(shù):4
年度積分:50
歷史總積分:986
注冊(cè)時(shí)間:2006/8/5
發(fā)站內(nèi)信
發(fā)表于:2008/11/25 22:21:00
#0樓

串口數(shù)據(jù)接收方式


1、 在oncomm 事件中接收數(shù)據(jù):


這種方式能充分mscomm控件的特性。oncomm 事件還可以檢查和處理通訊錯(cuò)誤;可以通過(guò)檢查 commevent 屬性的值來(lái)查詢(xún)事件和錯(cuò)誤;對(duì)于不定長(zhǎng)數(shù)據(jù)以及對(duì)數(shù)據(jù)進(jìn)行處理比較復(fù)雜的情況,此法不是很方便。


private sub mscomm_oncomm ()


select case mscomm1.commevent


錯(cuò)誤


case comeventbreak  收到 break。


case comeventcdto  cd (rlsd) 超時(shí)。


case comeventctsto  cts timeout。


case comeventdsrto  dsr timeout。


case comeventframe  framing error


case comeventoverrun 數(shù)據(jù)丟失。


case comeventrxover接收緩沖區(qū)溢出。


case comeventrxparity parity 錯(cuò)誤。


case comeventtxfull 傳輸緩沖區(qū)已滿(mǎn)。


case comeventdcb 獲取 dcb] 時(shí)意外錯(cuò)誤


事件


case comevcd  cd 線(xiàn)狀態(tài)變化。


case comevcts  cts 線(xiàn)狀態(tài)變化。


case comevdsr  dsr 線(xiàn)狀態(tài)變化。


case comevring  ring indicator 變化。


case comevreceive  收到 rthreshold # of chars.


case comevsend  傳輸緩沖區(qū)有 sthreshold 個(gè)字符


case comeveof  輸入數(shù)據(jù)流中發(fā)現(xiàn) eof 字符


end select


end sub


2.輪循法采集數(shù)據(jù):


a、定時(shí)器輪循法


對(duì)于數(shù)據(jù)包方式收發(fā)數(shù)據(jù)以及不需即時(shí)響應(yīng)情況,用輪循法更好些。實(shí)際上輪循法最大的好處在于集中處理數(shù)據(jù)而且不太占用cpu。輪循法要注意定時(shí)采集的時(shí)間片段大小;這里用二進(jìn)制收發(fā)模式;使屬性rthreshold、sthreshold為0,屏蔽oncomm事件。


inputmode = cominputmodebinary


rthreshold = 0


sthreshold = 0


private sub tmrcomm_timer()


采用輪循法采集數(shù)據(jù)


dim rx_buff() as byte


dim okstring as string


dim receivedlen as integer


on error goto errorhandler


tmrcomm.enabled = false 關(guān)閉定時(shí)器


if commport.inbuffercount > 0 then


receivedlen = commport.inbuffercount


rx_buff = commport.input


okstring = strconv(tempbyte, vbunicode)


if receivedlen = 6 then


if chr(tempbyte(0)) = : and tempbyte(3) = &h0a then


....


end if


if instr(okstring ,:@end*,vbbinarycompare) then


....


end if


end if


tmrcomm.enabled = true 打開(kāi)定時(shí)器


end sub


b、直接輪循法


此法用于接收少量控制命令字;


保存輸入子串的緩沖區(qū)


dim instring as string


使用 com1。


mscomm1.commport = 1


9600 波特,無(wú)奇偶校驗(yàn),8 位數(shù)據(jù),一個(gè)停止位。


mscomm1.settings = 9600,n,8,1


當(dāng)輸入占用時(shí),


告訴控件讀入整個(gè)緩沖區(qū)。


mscomm1.inputlen = 0


打開(kāi)端口。


mscomm1.portopen = true


將 attention 命令送到調(diào)制解調(diào)器。


mscomm1.output = atv1q0 & chr$(13)


確保


調(diào)制解調(diào)器以ok響應(yīng)。


等待數(shù)據(jù)返回到串行端口。


do


doevents


buffer$ = buffer$ & mscomm1.input


loop until instr(buffer$, ok & vbcrlf)


從串行端口讀 ok 響應(yīng)。


關(guān)閉串行端口。


mscomm1.portopen = false


如何處理不定長(zhǎng)數(shù)據(jù)的接收


在處理串口通訊時(shí),經(jīng)常會(huì)遇到不定長(zhǎng)數(shù)據(jù)的接收。由于通訊任務(wù)不同及編程要求的差異所以采用的方法也有所不同。本文就此問(wèn)題進(jìn)行探討。不定長(zhǎng)數(shù)據(jù)從數(shù)據(jù)格式上分,可分為有格式和無(wú)格式。


一、無(wú)格式不定長(zhǎng)數(shù)據(jù)的接收


這種格式在實(shí)際串口通訊中用得不多,一般只用傳送字符串?dāng)?shù)據(jù)。問(wèn)題在于怎么判斷接收結(jié)束。一般用時(shí)間延遲的方法解決。


a、對(duì)于非握手式通訊,可用一個(gè)定時(shí)器定時(shí)輪循接收,并假定每個(gè)輪循接收完成。用oncomm事件接收也可,只是不如定時(shí)器定時(shí)輪循接收簡(jiǎn)便。


b、對(duì)于握手方式通訊,可用直接輪循法提高接收的準(zhǔn)確性。下面是實(shí)現(xiàn)此法的函數(shù):


function scomm(scommand as string, comreceive as mscomm) as string


dim nreceivecount as integer


if comreceive.portopen = false then


comreceive.portopen = true


end if


comreceive.output = scommand


do


nreceivecount = comreceive.inbuffercount


sleep (2) api 函數(shù),掛起當(dāng)前進(jìn)程一段時(shí)間


loop until comreceive.inbuffercount = nreceivecount


if comreceive.portopen = true then


scomm = comreceive.input


end if


end function


注:此函數(shù)參照了xth一文。


此法一般是能確保數(shù)據(jù)接收的正確,但由于windows是多任務(wù)操作系統(tǒng),當(dāng)有耗時(shí)的進(jìn)程運(yùn)行時(shí)會(huì)丟失數(shù)據(jù)。如果系統(tǒng)會(huì)出現(xiàn)這種情況,可增大函數(shù)sleep()的參數(shù)值。


二、不定長(zhǎng)格式數(shù)據(jù)的接收


對(duì)于不定長(zhǎng)數(shù)據(jù)接收最好的方法是制定通訊協(xié)議,比如定義開(kāi)始字符和結(jié)束字符。由于單片機(jī)系統(tǒng)通訊一般不太復(fù)雜,沒(méi)必要去制定一套象通用計(jì)算機(jī)間通訊的協(xié)議,而根據(jù)單片機(jī)系統(tǒng)的大小和性能要求制定通訊協(xié)議。實(shí)際上為便于交流、維護(hù)以及一致性,可制定一套可伸縮的通訊協(xié)議。定義了開(kāi)始字符和結(jié)束字符就容易實(shí)現(xiàn)不定長(zhǎng)格式數(shù)據(jù)通訊,但在實(shí)際通訊編程還是容易出現(xiàn)一些比較隱蔽的通訊錯(cuò)誤。下面就常用方法分別進(jìn)行分析。


a、定時(shí)器輪循法。


假定每個(gè)輪循期數(shù)據(jù)接收完畢,并在每個(gè)輪循期處理數(shù)據(jù),由于有開(kāi)始字符和結(jié)束字符很容易確定接收數(shù)據(jù)的完整性。好象合理設(shè)定輪循時(shí)間值就萬(wàn)無(wú)一失了,但被動(dòng)接收數(shù)據(jù)時(shí)無(wú)論如何也找不合適的輪循時(shí)間值,因?yàn)閱?dòng)定時(shí)器和數(shù)據(jù)到來(lái)基本不同步,這就會(huì)出現(xiàn)一次發(fā)送的數(shù)據(jù)被分在兩個(gè)輪循期接收,所以被動(dòng)接收數(shù)據(jù)時(shí)不能假定每個(gè)輪循期數(shù)據(jù)接收完畢。在接收到結(jié)束字符后才確定一次數(shù)據(jù)接收完畢就可解決此問(wèn)題。


b、oncomm事件法。


方法和定時(shí)器輪循法基本相同,因?yàn)槊看蝟ncommg事件也只能接收到一部分?jǐn)?shù)據(jù)。在vb的在線(xiàn)幫助中這樣注解“設(shè)置 rthreshold 為 1,接收緩沖區(qū)收到每一個(gè)字符都會(huì)使 mscomm 控件產(chǎn)生 oncomm 事件。”。但實(shí)際上oncomm事件并不是每收到一個(gè)字符便觸發(fā)一次 oncomm 事件。oncomm事件是在緩沖區(qū)收到幾個(gè)甚至幾十個(gè)字節(jié)數(shù)據(jù)后才被觸發(fā)的。版主認(rèn)為這是windows多任務(wù)使操作系統(tǒng)不能實(shí)時(shí)響應(yīng)造成的。如果要在每次oncomm事件接收一個(gè)字符似乎可設(shè)inputlen屬性為1,但實(shí)際行不通。vb在線(xiàn)幫助中“有該屬性在從輸出格式為定長(zhǎng)數(shù)據(jù)的機(jī)器讀取數(shù)據(jù)時(shí)非常有用”的注解,好象在說(shuō)對(duì)定長(zhǎng)字符有效,但版主發(fā)現(xiàn)inputlen設(shè)為16,接收16個(gè)字符定長(zhǎng)數(shù)據(jù)時(shí)卻被當(dāng)作兩次接收了,一次12個(gè),一次4個(gè)。建議在oncomm事件中接收數(shù)據(jù)要定義通訊協(xié)議并檢測(cè)數(shù)據(jù)的完整性。 對(duì)于不定長(zhǎng)格式數(shù)據(jù)的接收程序員更喜歡定時(shí)器輪循法,也許oncomm事件不好控制吧。


對(duì)于不定長(zhǎng)數(shù)據(jù)的接收,最佳方法可能是在oncomm事件中啟動(dòng)定時(shí)器輪循接收,并同時(shí)停止oncomm事件的觸發(fā),接收完畢后或超時(shí)開(kāi)啟oncomm事件。


用字符方式收發(fā)碼值大于127的字符數(shù)據(jù)


vb的通訊控件友好、功能強(qiáng)大,編程速度快是眾人皆知的。加上vb的易學(xué)、易用,快速開(kāi)發(fā)等特點(diǎn),數(shù)據(jù)通訊量不是很大時(shí),在單片機(jī)通訊領(lǐng)域廣泛地使用vb開(kāi)發(fā)pc上層通訊軟件。實(shí)際開(kāi)發(fā)時(shí)會(huì)有不少問(wèn)題,這里就用字符方式收發(fā)碼值大127的字符數(shù)據(jù)進(jìn)行討論。


在實(shí)際開(kāi)發(fā)中經(jīng)常遇到通訊只是用來(lái)發(fā)送一些控制字符命令和少量數(shù)據(jù)。在vb的中文在線(xiàn)幫助中有“若數(shù)據(jù)只用 ansi 字符集,則用 cominputmodetext”的表述。 ansi字符集是0-127這容易使人誤解為&h88也可用“inputmide=cominputmodetext”方式收發(fā)。我剛開(kāi)始用vb編通訊模塊時(shí)就為此迷惑過(guò),網(wǎng)上不少網(wǎng)友也時(shí)常問(wèn)及這種問(wèn)題。實(shí)際上在vb中0-127是可以正常收發(fā)的,大于127即&h7f的只有&h80和&hff能夠收發(fā),其余ansi字符都被過(guò)濾為0。由于串口通訊是以字節(jié)收發(fā)的,數(shù)據(jù)如以cominputmodetext模式收發(fā)則非字符串?dāng)?shù)據(jù)會(huì)被過(guò)濾。在vb中用“inputmide = cominputmodebinary” 就可以解決這個(gè)問(wèn)題,只是收發(fā)都必須用動(dòng)態(tài)數(shù)組來(lái)完成。用cominputmodebinary模式編程稍有點(diǎn)復(fù)雜,調(diào)試也不直觀(guān),對(duì)于初學(xué)者不易掌握。另外軟件完成后,在實(shí)際應(yīng)用時(shí)會(huì)增加工程維護(hù)難度,因?yàn)閷?duì)于二進(jìn)制代碼不是易于理解的。比如下端機(jī)發(fā)送現(xiàn)場(chǎng)統(tǒng)計(jì)數(shù)據(jù)233,cominputmodebinary模式下串口監(jiān)測(cè)到“:a &h233;,它代表a探針的溫度。一般串口監(jiān)測(cè)軟件要么用ascii方式顯示,要么用二進(jìn)制方式顯示。用ascii方式則不能看到&h233,而二進(jìn)制方式則示不好理解,如果顯示58 65 233 59,我想沒(méi)有人喜歡這種方式(如果有更好的方式的話(huà))。但如果顯示“:a 2 3 3 ;”不就解決問(wèn)題了!用cominputmodetext方式就可完成任務(wù)了,只是多了一段數(shù)據(jù)分離程序。對(duì)于一般通訊要求這種方法不為是一種好方法。由于通訊任務(wù)是多種多樣的,有時(shí)候這種方法就有點(diǎn)力不從心了,如傳送較多的的數(shù)據(jù)時(shí),這會(huì)顯著地增加通訊量,通訊變得復(fù)雜了,對(duì)于單片機(jī)系統(tǒng)就不太合適了;還有一些特殊要求,如數(shù)據(jù)包的識(shí)別符也不適此法,但能確定傳送數(shù)據(jù)碼值范圍也可用此法。下面介紹另一種方法,此法適用比較廣,傳送二進(jìn)制數(shù)據(jù)通訊量增加也不大。


這種方法實(shí)際上很簡(jiǎn)單,實(shí)際運(yùn)用中有不少采用此法。原理是一碼分為二碼。如設(shè)7e為臨界字符,對(duì)于7e則分為7e和0兩個(gè)ascii碼,依此類(lèi)推,8f分為7e和11。接收合并時(shí)遇到7e則將7e和后一個(gè)ascii碼相加為下字符。下面給出c語(yǔ)言函數(shù),vb轉(zhuǎn)換一下便可。


由于c語(yǔ)言不能返回兩個(gè)參數(shù),所以用數(shù)組指針。


void filt(char code[],char c)


{


if(c==f)


{


if(code[0]>=0x7e)


{


code[1]=code[0]-0x7e;


code[0]=0x7e;


}


else


{


code[1]=0xff; /*0xff作為標(biāo)記code[1]不可能產(chǎn)生0xff*/


}


}


else if(c==h)


{


if(code[0]!=0x7e)


{


code[1]=0xfe; /*轉(zhuǎn)換完成標(biāo)記*/


}


else


{


if(code[1]==0xfe)


{


code[1]=0xff; /*接收下一個(gè)碼的標(biāo)記*/


}


else


{


code[0]=code[0]+code[1];


code[1]=0xfe;


}


}


}


發(fā)送時(shí):


char sendchar[2]; /*存儲(chǔ)發(fā)送的值*/


....


sendchar[0]=c; /*c為待發(fā)ascii碼*/


filt(sendchar,f);


if(sendchar(1)==0xff)


{


..... /*發(fā)送sendchar[0]*/


}


else


{


...... /*發(fā)送sendchar[0],sendchar[1]*/


}


接收時(shí):


char receivechar[2]; /*存儲(chǔ)接收的值*/


.....


receivechar[0]=c0; /*c0接收的ascii碼*/


filt(receivechar,h);


if(receivechar[1]==0xff)


{


receivechar[1]=c1; /*c1為下一個(gè)*/


filt(receivechar,h);


}


else if(receivechar[1]==0xfe)


{


...... /*存儲(chǔ)轉(zhuǎn)換后的receivechar[0]*/


}


以上代碼僅提供一種思路,實(shí)際情況視編程需要而定。


串口通訊問(wèn)答錄


1、q:各位vb高手:我有一個(gè)問(wèn)題想請(qǐng)教一下。我從com口用bin方式接收到數(shù)據(jù)(一串漢字),存入一byte數(shù)組,但無(wú)法還原為一串漢字,我認(rèn)為是ansi和unicode的轉(zhuǎn)換,請(qǐng)問(wèn)如何轉(zhuǎn)換。


例:字符串“我”,按bin方式接收成一byte數(shù)組,其值為“206,210”,如用“chr(206)+chr(210)”卻無(wú)法得到“我”,實(shí)際上“我”=chr(-12860)請(qǐng)問(wèn)如何能實(shí)現(xiàn)byte數(shù)組(206,210)與字符串“我”之間的轉(zhuǎn)換?萬(wàn)分感謝!!!


jy


1999.10


a:經(jīng)chr(206)+chr(210)轉(zhuǎn)換后實(shí)際上變成了兩個(gè)unicode字符,四個(gè)字節(jié)了。漢字的收發(fā)必須用binary方式。下面的程序能實(shí)現(xiàn)漢字收發(fā)。


發(fā):


dim ytemp() as byte


dim stemp as string


stemp = 你好!


ytemp = strconv(stemp, vbfromunicode)


debug.print ubound(ytemp)


mscomm1.output = ytemp


收:


private sub msctest_oncomm()


中文收發(fā)


dim ytemp() as byte


dim stemp as string


dim i as integer


if msctest.inbuffercount > 0 then


i = msctest.inbuffercount


ytemp = msctest.input


stemp = strconv(ytemp, vbunicode)


txttest1.text = stemp


end if


end sub


deson


1999-10-16


--------------------------------------------------------------------------------


2、q:各位大俠,在下被兩個(gè)問(wèn)題困擾多時(shí),實(shí)在無(wú)法找到答案,請(qǐng)各位多多指教。


1、在用mscomm控件設(shè)計(jì)通訊程序時(shí),我始終無(wú)法將asc碼大于127的值發(fā)送出去,查閱了vb論壇以前的文章,按部就班也不行,部分 vb 程序如下,請(qǐng)指教:


private sub okbtn_click()


dim data() as byte


dim temp as variant


redim data(10)


for i = 0 to 10


data(i) = int(rnd()*256)


next


temp = data


mscomm.output = temp


end sub


a:接收方式使用了文本方式,用二進(jìn)制方式即可。

----------------------------------------------
此篇文章從博客轉(zhuǎn)發(fā)
原文地址: Http://blog.gkong.com/more.asp?id=69123&Name=yangyongxiang
17578
ahljj
文章數(shù):3386
年度積分:50
歷史總積分:17578
注冊(cè)時(shí)間:2002/3/23
發(fā)站內(nèi)信
發(fā)表于:2010/3/18 13:44:23
#1樓
再學(xué)習(xí)

關(guān)于我們 | 聯(lián)系我們 | 廣告服務(wù) | 本站動(dòng)態(tài) | 友情鏈接 | 法律聲明 | 非法和不良信息舉報(bào)

工控網(wǎng)客服熱線(xiàn):0755-86369299
版權(quán)所有 工控網(wǎng) Copyright©2025 Gkong.com, All Rights Reserved

78.0005