<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應用 > PC與單片機RS-232串口的通訊和控制

          PC與單片機RS-232串口的通訊和控制

          作者: 時間:2016-12-03 來源:網(wǎng)絡(luò) 收藏
          這次我們來試著一步步的去掌握PC單片機通過RS-232進行通訊和控制

          先說說我硬件的情況。我用的PC是個二手的IBM240小本本,十寸屏,賽揚400,機子很老了。但也有它的優(yōu)點:1、串口,并口,PS鼠標口、USB口、PCM插槽全有。 調(diào)試硬件電路最好還是用真實串、并口好些,因為用USB轉(zhuǎn)換的串、并口有時會出現(xiàn)兼容性上的問題,就會增加你調(diào)試上的復雜性。

          本文引用地址:http://www.ex-cimer.com/article/201612/325233.htm

          下圖為本人的IBM 240及各種接口圖:


          下圖是PC的大小對比圖

          單片機還是我一步步做出來的那個了,USB-ISP編程線也是我前面秀過,好!現(xiàn)在我放上PC與單片機連接圖:

          用本本的好處就是調(diào)整方便,接口、器件都在旁邊,假若是用臺式機,你還得鉆到桌子底下去插拔那些接口,而現(xiàn)在本本卻又沒有串、并口了。
          言歸正傳,單片機的RS-232串口通過9針串口線接到本本的串口上,單片機的ISP編程口通過USB-ISP編程器接到本本的USB口。

          另外本本要接電源,單片機也要接5V電源,還有千萬千要記得,本本是要插上鼠標才玩得轉(zhuǎn)哦!

          我將這個一步一步掌握串口的通訊與控制分為五步:

          1、測試單片機與PC的串口連接是否正確好用。

          2、用VB自己編寫的程序替換掉串口調(diào)試器軟件來接收單片機發(fā)送的數(shù)據(jù)。

          3、掌握單片機端如何發(fā)送字符和數(shù)值數(shù)據(jù)。

          4、掌握PC端程序如何接收發(fā)送字符和數(shù)值型數(shù)據(jù)。

          5、做一個A/D轉(zhuǎn)換(ADC0809)獲取數(shù)據(jù)發(fā)送到PC,并在PC上顯示實時趨勢的例子。

          我們要用到的四個軟件:

          1、USB接口編程軟件:是PC機給單片機進行燒寫編程用的

          2、串口調(diào)試軟件:用來測試單片機內(nèi)串口電路、程序工作是否正常。

          3、單片機程序的編程軟件KEIL:用于編寫單片機內(nèi)的程序并生成HEX文件。

          4、VB6.0:用于編寫PC機上的應用程序

          先進行第一步工作:

          在前面一篇《板子上最一個部件——RS232串口》講過如何對單片機上的串口進行調(diào)試,我們還是先對這個連接進行測試,我們首先得確認連接正確,電路正常,才能進行后面程序編寫和調(diào)試工作。
            依舊是那個最簡單的程序,AT89S52從串口不停地發(fā)送“hello world!”

          #include
          #include
          void main(void)
          {
          SCON=0x50; //串口方式1
          TMOD=0x20; //定時器1,定時方式為2
          PCON=0x80; //設(shè)定串口工作方式為1
          TCON=0x40; //設(shè)定時器1開始計數(shù)
          TH1=0xfd; //設(shè)定波特率為19200
          TL1=0xfd; //
          TI=1;
          TR1=1; //啟動定時器
          while(1)
          {
          printf("hello world!n");
          }
          }

          把原先生成好的這個HEX文件用上面講到的Progisp軟件寫到AT89S52里。

          然后打開sscom32串口調(diào)試器,設(shè)定好串口號、波特率和數(shù)據(jù)位,按下“打開串口”鈕,應該就能收到那個一行行的“hello world!”了。能看到這一行行的文字,說明電路、連接和程序都正常了。

          如果是亂碼,則要將單片機上的復位鈕按一下。如果還是亂碼,那一般就是波特率不對,晶振應為11.0592MHZ或串口接觸不良,線過長等原因。如果跟本就收不到任何字符,就說明電路或連接有故障,或者程序有問題。那就要好好查查了。
            好!現(xiàn)在電路、連接、程序都可以正常工作。但在串口調(diào)試器接收框里看到接收到的一行行“hello world!”顯示太快,不容易看出它一次一次發(fā)送的過程,不便于分析問題,我們得給它加點延時。

          #include
          #include

          void delay(void) //定義一個延時子程序
          {
          unsigned int i;
          for (i=65535;i>0;i--);
          }

          void main(void) //主程序
          {
          SCON=0x50; //串口方式1
          TMOD=0x20; //定時器1,定時方式為2
          PCON=0x80; //設(shè)定串口工作方式為1
          TCON=0x40; //設(shè)定時器1開始計數(shù)
          TH1=0xfd; //設(shè)定波特率為19200
          TL1=0xfd; //
          TI=1;
          TR1=1; //啟動定時器
          while(1)
          {
          printf("hello world!n"); //向串口送出數(shù)據(jù)
          delay(); //調(diào)用延時
          delay();
          }

          }

          程序?qū)懞昧?,在KEIL里添加上延時語句后,重新生成HEX文件。再用Progisp將它寫進AT89S52里,這時,你就可以看到串口調(diào)試器已經(jīng)接收到大約一秒一次的“Hello world!”了。
            在這里說明一下,只要像最上面我圖上給出的那樣把單片機和PC連接好后,無論你往AT89S52里燒寫程序,還是單片機連接到PC并向PC串口發(fā)送數(shù)據(jù),都不用再插拔器件了,只需要在這幾個程序間切換工作便可以了。(是不是很方便呢


          這樣第一項工作就完成了,確認電路的連接及單片機程序都工作正常。


          下面要進行第二項工作:

          目的:用我自己的PC程序把串口調(diào)試器軟件替換掉。因為我最終要的是接收單片機上的數(shù)據(jù),并將接收的數(shù)據(jù)在PC上進行處理、存儲,而串口調(diào)試器只能接收固定的內(nèi)容,你也不無法把收到的數(shù)據(jù)接管過來,僅僅能做連接測試而已。

          我用的是最簡單易用的Visual Basic 6.0。具體如何操作運用,網(wǎng)上有很多教程,也很容易上手。

          打開VB6.0,新建一個工程,也就是要建立一個新的程序。

          這是個標準的VB6.0界面,我們要進行串口的操作需要添加一個串口控件MSCOMM32.OCX,或許你的機子上有,也許沒有,沒有的在網(wǎng)上搜了下一個裝在你c:winntsystem32 。然后你用鼠標右鍵點擊VB界面左側(cè)的工具箱,彈出菜單后選部件,或者在上部的主菜單上點“工程”--“部件”,就會彈出如下界面:

          在列出的項里找到Microsoft Comm Control 6.0。在前面的小方框里點上鉤。注意看下面的提示欄里就告訴你這個控件的文件名和所在的目錄。點“確定”鈕,這時在VB主界面的工具箱里就會多出個小電話的控件圖標了:

          接下來點擊這個控件圖標,然后在Form1的窗口上拉出個框(或者雙擊小電話圖標)把圖標放到Form1窗口上去。如下圖:

          如果你的圖標放不上去并彈出如下提示框:

          就說明你的VB6.0是簡化版,不是正式安裝的。解決方法如下:
          首先把MSComm32.OCX拷進C:WINNTSYSTEM32 (我的機器一開始并沒有這個控件,我去網(wǎng)上下了一個,機器里面有此控件的此步不做!)(注:路徑以我機器的winXP系統(tǒng)為例)
          然后點擊 開始>運行>regsvr32 c:winntsystem32mscomm32.ocx 成功后,開始>運行>regedit,進入注冊表,找到HKEY_CLASSES_ROOTLicenses,然后新建一個項,命名為:“4250E830-6AC2-11cf-8ADB-00AA00C00905”,值為:“kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun”。一切就OK了。

          VB6.0設(shè)置正常后,我由簡入繁地進行程序的編寫。在窗體上先放上一個串口控件,一個文本框,一個按鈕,一個定時器。如下圖:

          串口控件是單片機串口和PC串口進行通訊的橋梁;文本框用來顯示我們收到的數(shù)據(jù),按鈕用來啟動這個接收,定時器用來定時檢查每一小段時間檢查是否有串口數(shù)據(jù)收到。
          我們先對串口控件進行屬性設(shè)置,Commport是串口號設(shè)置,一般設(shè)置為1,Settings是對串口的波特率、有無奇偶校驗,數(shù)據(jù)位數(shù),停止位數(shù)進行設(shè)置,因為我的單片機程序上用的波特率是19200,所以在這兒我只對波特率進行調(diào)整,其它都是都用默認值。如下圖:

          對按鈕控鍵進行設(shè)置:只是將“Caption”標題屬性改為“接收數(shù)據(jù)”。
          對定時器進行設(shè)置,將“Interval”間歇時間改為400。這樣就是每400毫秒檢查一次有無數(shù)據(jù)收到。
          對文本框進行設(shè)置:將“MultiLine”多行顯示設(shè)為“True”允許。
          控件的屬性設(shè)置完了,下面我們?yōu)槌绦驅(qū)懘a,先雙擊“接收數(shù)據(jù)”按鈕。會彈出代碼窗口,我了如下代碼,如圖:

          上面就是我們編寫的按鈕事件代碼。寫完后我們在鍵盤上按“Shift”+“F7”,回到對象窗口。再雙擊那個定時器控件,界面就切換到定時器的代碼窗口,我們寫程序如下圖:

          現(xiàn)在我們的這個VB程序就寫好了。接著就試著運行一下這個程序,且慢!我們還是要先啟動串口調(diào)試器看看單片機是否還在不斷的發(fā)送著“hello world!”,確認它還是在不停地顯示著那行“hello world!”,就可以關(guān)了串口調(diào)試器。然后在VB6.0的主界面點擊那個小三角的播放鈕。我的程序就運行如下了:

          第二項任務完成!我自己接管了接收的數(shù)據(jù)。點菜單的保存這項工程。

          第三項任務:掌握單片機端如何發(fā)送字符和數(shù)值數(shù)據(jù)。

          接下來我要做的是對AT89S52內(nèi)串行數(shù)據(jù)的發(fā)送進行解和掌握,以便我們能隨心所欲地將單片機獲得的數(shù)值數(shù)據(jù)或字符數(shù)據(jù)發(fā)送給PC機進行處理或存儲。

          先來看看原來我寫的AT89S52不斷發(fā)送“hello world!”的那段程序。

          #include
          #include
          void delay(void) //定義一個延時子程序
          {
          unsigned int i;
          for (i=65535;i>0;i--);
          }

          void main(void) //主程序
          {
          SCON=0x50; //串口方式1
          TMOD=0x20; //定時器1,定時方式為2
          PCON=0x80; //設(shè)定串口工作方式為1
          TCON=0x40; //設(shè)定時器1開始計數(shù)
          TH1=0xfd; //設(shè)定波特率為19200
          TL1=0xfd; //
          TI=1;
          TR1=1; //啟動定時器
          while(1)
          {
          printf("hello world!n"); //向串口送出數(shù)據(jù)
          delay(); //調(diào)用延時
          delay();
          }

          }

          上面的程序中除了設(shè)置串口的語句和延時語句外,負責向串口發(fā)送的語句只有一行,即“printf("helleo world!n")”。學習過編程的一般都知道,print語句的作用是輸出字符串的,但我們?nèi)绻麖膯纹瑱C的A/D模塊上獲得了數(shù)據(jù)想發(fā)送到PC,應該怎么做呢?雖然你也可以先將這些數(shù)據(jù)轉(zhuǎn)換成數(shù)字字符串,例如我們從一個8位的A/D模塊上獲得的數(shù)據(jù)是個數(shù)值從0-255的8位的數(shù)值,如果數(shù)值是1,那你得先將1這個數(shù)值轉(zhuǎn)換成“1”字符對應的代碼49(二進制110001,十六進制31H),再用printf語句發(fā)送出去。如果值是255,那你得先把它轉(zhuǎn)換成3個字符“2”、“5”、“5”,再用printf發(fā)送出去。但這樣既復雜又不規(guī)范,“1”是一個字符,“2”、“5”、“5”是三個字符,隨著數(shù)值的不同,發(fā)送的數(shù)據(jù)的字節(jié)數(shù)據(jù)也不同,這樣可不行。

          我們還是先蹲蹲馬步,了解一下單片機串口發(fā)送數(shù)據(jù)的實質(zhì):

          上圖是串口的發(fā)送時序示意圖,最上面的TX表示的是單片機串口的發(fā)送線,,第二根CLK是內(nèi)部時鐘線,最下面的是發(fā)送標志信號TI。

          我們以最常用的串行方式1,即10位異步通信方式來簡單分析一下。它規(guī)定了1位起始位、8位數(shù)據(jù)位和1位停止位。其中第一位(起始位)和最后一位(停止位)是在你設(shè)定好串口的方式,打開串口后由芯片內(nèi)串口模塊自動插入的,不用人為加。

          當你想通過串口發(fā)送數(shù)據(jù)時,只需要向AT89S52內(nèi)的一個8位的特殊功能寄存器SBUF(99H)送入一個字節(jié)你想要發(fā)送給PC的數(shù)據(jù),它就會自動連同起始位,數(shù)據(jù)位,停止位一起產(chǎn)生10位串行的電位信號送出。在第10個脈沖后將TX線的電位拉高,同時將標志位TI置1,告訴自己的程序發(fā)送結(jié)束。

          接收方也是以規(guī)定好的相同的波特率時鐘脈沖為基準,當某一個脈沖到來后檢測到RX線上的電位被拉低,就知道對方開始發(fā)送數(shù)據(jù)了,然后從下一個脈沖起計數(shù)并在每個脈沖后檢查RX線上的電位,若是高電位便記做1,低電位便記做0,如此得到8個位的數(shù)據(jù),然后在第10個脈沖后,檢測到RX線上的電位為1就知道這幀數(shù)據(jù)傳送完畢。(注意:單片機的串行發(fā)送口(TX)和PC的接收口(RX)是通過串行線直接連接的,所以這兩點的信號是相同的)

          例如要發(fā)送“1”這個字符,代碼是49(二進制110001,十六進制31H),串口發(fā)送時低位在前,如下圖

          歸納起來,若想發(fā)送數(shù)據(jù)只要向SBUF送一個字節(jié)的數(shù)據(jù),然后等TI變?yōu)?后,就再發(fā)第二個字節(jié)依,此類推。

          再說說字符和數(shù)值的關(guān)系,對于電路來說,它不知道什么是字符,什么是數(shù)值,只是按高低電位發(fā)送一幀幀的電信號。例如00000000代表0(00H),10101010代表170(AAH),11111111代表255(FF),但對于接收方PC就有不同了,大家都知道,電腦下載文本比下載一幅圖像的數(shù)據(jù)量要小得多,原因就是文本只是用一個代碼來代表一個將要顯示的文字圖像,而這個文字的圖像數(shù)據(jù)就預先存在自己的電腦里,就是所說的字庫。而你下載一幅圖像,則需要每一個陣點的數(shù)據(jù)都得傳送,所以數(shù)據(jù)量很大。西文也是一樣的,也是用代碼來代表一個需要顯示的西文字符圖像,這就是ACSII碼。這樣用一個字節(jié)的數(shù)(0-255)的范圍就能代表所有的西文字符和常用符號了,例如用數(shù)值65(十六進制為41H)代表“A”。用數(shù)值49(十六進制為31H)代表“1”,我只要向SBUF里輸入值65,PC只要以字符方式接收,就會顯示“A”字。如果以數(shù)值方式接收,變量的值就是65。這里面也包括有一些非字符的功能控制符號。例如13代表回車,10代表換行。

          下面我們就來試試改寫一下發(fā)送程序:試著用送數(shù)值和送字符兩種方式發(fā)送。同樣是“A”“B”“C”“D”四個字符。

          #include
          #include
          void delay(void) //定義一個延時子程序
          {
          unsigned int i;
          for (i=65535;i>0;i--);
          }

          void main(void) //主程序
          {
          SCON=0x50; //串口方式1
          TMOD=0x20; //定時器1,定時方式為2
          PCON=0x80; //設(shè)定串口工作方式為1
          TCON=0x40; //設(shè)定時器1開始計數(shù)
          TH1=0xfd; //設(shè)定波特率為19200
          TL1=0xfd; //
          TI=1;
          TR1=1; //啟動定時器
          while(1)
          {

          SBUF=65; //向SBUF內(nèi)寫入65的數(shù)值,也就是字符“A”的代碼

          while(TI==0); //檢測TI,當TI=0時,說明還沒發(fā)送完,就循環(huán)等待。

          TI=0; //當TI=1時,就把TI的值置0,以便下一組發(fā)送。

          SBUF=66; //向SBUF送數(shù)值66.即字符“B”的代碼

          while(TI==0);

          TI=0;

          SBUF=C; //向SBUF送字符“C”

          while(TI==0);

          TI=0;

          SBUF=D"; //向SBUF送字符“D”

          while(TI==0);

          TI=0;

          delay(); //調(diào)用延時
          delay();
          }

          }

          將程序編譯生成HEX文件后寫入AT89S52。打開我上面用VB6編好那個程序,點擊“接收數(shù)據(jù)”鈕。如下圖:

          它的確按我預想的執(zhí)行了。只要是節(jié)字數(shù)據(jù),無論是數(shù)值還是字符代友都是可以進行發(fā)送的。這是C語言的優(yōu)點。

          另外我們順便看一下原先用printf函數(shù)發(fā)送生成HEX和直接寫SBUF來成HEX的差別:


          上圖的提示顯示了生成的代碼共用了1120個字節(jié)。這是用printf函數(shù)發(fā)送的。

          下圖是直接寫SBUF后的編譯提示信息:

          哈!直接操作串口緩沖寄存器只用了89個字節(jié)。這是直接進行底層操作的優(yōu)勢。

          上面的程序發(fā)送“A”“B”“C”“D”四個數(shù)據(jù),因為沒有發(fā)送回車符,所以一次次的字符都是連續(xù)顯示的。我們再修改一下,把要發(fā)送的ABCD這四個數(shù)據(jù)再加兩個代表回車的控制字符數(shù)據(jù)定義到一個字節(jié)數(shù)組中變量中,再改用循環(huán)的方式來發(fā)送,程序如下:

          #include
          #include
          void delay(void) //定義一個延時子程序
          {
          unsigned int i;
          for (i=65535;i>0;i--);
          }

          void main(void)
          {
          unsigned char buf[ ]={65,66,C,D,13,10}; //定義一個單字節(jié)數(shù)組最后兩個數(shù)值13和10是回車符。
          unsigned char i;
          SCON=0x50; //串口方式1
          TMOD=0x20; //定時器1,定時方式為2
          PCON=0x80; //設(shè)定串口工作方式為1
          TCON=0x40; //設(shè)定時器1開始計數(shù)
          TH1=0xfd; //設(shè)定波特率為19200
          TL1=0xfd; //
          //TI=1;
          TR1=1; //啟動定時器
          while(1)
          {
          for(i=0;i<6;i++)
          {
          SBUF=buf[i]; //向串口送出數(shù)據(jù)
          while(TI==0);
          TI=0;
          }
          delay(); //調(diào)用延時
          delay();
          }

          }

          下面是運行結(jié)果:


          這樣就和原先printf函數(shù)輸出的效果一樣了。

          從上面程序我們知道了,如果我們想發(fā)送測量的數(shù)值數(shù)據(jù),可以把用A/D模塊獲得的測量數(shù)據(jù)賦給buf[ ]數(shù)組里的變量,然后就可以進行發(fā)送處理了。字符直接用上面的發(fā)送方法就行了。

          這樣第三項工作也完成!(?。±哿?,要歇歇,歇歇!

          第四步:掌握PC端程序如何接收發(fā)送字符和數(shù)值型數(shù)據(jù)。

          接下來我們來看看PC端的程序如何正常接收并處理收到的數(shù)據(jù)。字符沒有問題,因為剛才就是顯示的字符,但我主要是想看看采用字符方式接收對于0-255范圍內(nèi)那些非字符數(shù)值能否正常接收和處理。
          打開VB6,調(diào)出我們原先編寫的程序,在串口控件的屬性中有個InputMode屬性,如果是0就是以字符方式接收,如果是1就是以二進制方式接收。

          原先我們就是用了缺省的字符方式。為了便于分析收到的數(shù)據(jù),我們得分別修改一下單片機和PC里的程序,首先不能讓單片機不停的發(fā)送,而是從PC機先向AT89S52發(fā)送一個字符“s”,AT89S52收到并確認是“s”字符后再發(fā)送一組數(shù)據(jù),發(fā)完后停下,等待PC的下次請求。這樣我們可以準確和穩(wěn)定地看到這組數(shù)據(jù)的情況。

          VB程序的修改如下:

          我們在Command1+_Click事件的代碼里添加了一行MSComm1.Output="s",也就是每當我按下“接收數(shù)據(jù)”鈕時向AT89S52發(fā)送了一個"s"字符,然后清空文本框內(nèi)容,然后啟動定時器子程序Timer1每100毫秒檢查一次有無收到數(shù)據(jù),收到數(shù)據(jù)便顯示出來。

          對AT89S52內(nèi)的程序做修改,程序循環(huán)檢查有無收到數(shù)據(jù),當?shù)腞I=1時便有數(shù)據(jù)收到,確認收到的數(shù)據(jù)為字符“s”時,便送出數(shù)組內(nèi)數(shù)據(jù)。修改程序如下:
          #include

          void delay(void) //定義一個延時子程序
          {
          unsigned int i;
          for (i=65535;i>0;i--);
          }

          void main(void)
          {
          unsigned char buf[]={65,66,C,D,E,F};//定義一個單字節(jié)數(shù)組
          unsigned char i;
          SCON=0x50; //串口方式1
          TMOD=0x20; //定時器1,定時方式為2
          PCON=0x80; //設(shè)定串口工作方式為1
          TCON=0x40; //設(shè)定時器1開始計數(shù)
          TH1=0xfd; //設(shè)定波特率為19200
          TL1=0xfd; //
          //TI=1;
          TR1=1; //啟動定時器
          while(1)
          { if(RI==1) //如果接收到數(shù)據(jù)則進入以下操作
          {if(SBUF==s) //如果收到的數(shù)據(jù)為“s”字符則進入發(fā)送操作
          {
             for(i=0;i<6;i++)//循環(huán)發(fā)送出數(shù)組buf[ ]的6個數(shù)據(jù)
          {
          SBUF=buf[i]; //向串口送出數(shù)據(jù)
          while(TI==0);
          TI=0;
          delay(); //調(diào)用延時子程序
          }
          RI=0;//上面的發(fā)送操作完畢后將標志RI清0等待PC下次請求
          }
          }
          }
          }
          編譯、生成HEX文件然后將文件寫進AT89S52。我們運行VB6編寫的Scom1程序。

          現(xiàn)在我點擊“接收數(shù)據(jù)”鈕后,文本框內(nèi)一個字符一個字符的依次顯示出“ABCDEF”如下圖:


          當我再次點擊“接收數(shù)據(jù)”鈕時,文本框先清空,然后再重復上面的顯示。達到我們的要求。PC機每請求一次,單片機就發(fā)送一次數(shù)據(jù)。


          接下來我要做的是讓文本框里不再顯示“ABCDEF”這幾個字符,而是要顯示AT89S52發(fā)過來的數(shù)值,例如我發(fā)送65的值,文本框里就顯示65,我發(fā)送255,文本框就顯示255,這樣我就能測試出用字符接收的方法能否將一個字節(jié)的值(0-255)都能正確接收和顯示。我們把那句Text1.Text = Text1.Text + MSComm1.Input 。改成Text1.Text = Text1.Text + str(asc(MSComm1.Input )),就是把原先字符串變量MSComm1.Input先轉(zhuǎn)換成ASCII值,再把這個值顯示出來。改完了。我們運行下試試。


          上圖顯示的確可以正確顯示出數(shù)值,但這僅僅只是有相對應字符幾個代碼數(shù)值,我再來試試,非字符的ASCII值,看是否都能正確收到并顯示。先修改AT89S52里我們原先發(fā)送的那些數(shù)組buf[ ]里的值,讓它們部分不在字符范圍里,看能不能正確接收到顯示。我們將數(shù)組unsigned char buf[]={65,66,C,D,E,F};改寫為既有字符也有非字符范圍的數(shù)組unsigned char buf[]={0,1,2,D,254,255};


          從上圖來看,后兩個數(shù)據(jù)顯示不對,254沒有顯示出來,255顯示為63,經(jīng)過修改AT89S52程序,把0-255的數(shù)值都發(fā)送一遍,發(fā)現(xiàn)大于128的數(shù)值幾乎都不能正確接收。所以,得出結(jié)論:以字符方式接收數(shù)值數(shù)據(jù)是不可行的!

          如下圖:


          接下來我改變串口控件的InputMode屬性,將它的值改為1,即用二進制讀取來試試。但二進制方式怎么讀取呢,看了很多資料,也試了很多次,終于弄明白了,原來先要定義一個字節(jié)型的可變數(shù)組,這樣當接收到數(shù)據(jù)時把接收到的一個或多個數(shù)值的首地址變量Mscomm1.input賦給這個字節(jié)數(shù)組名。于是你就可以運用這個字節(jié)數(shù)組里的變量了。

          我先在VB里修改串口控件的InputMode屬性,如下圖:

          然后我要在VB程序里先定義一個單字節(jié)Byte類型的數(shù)組,將收到的數(shù)據(jù)變量(Mscomm1.Input)賦給inbuff這個數(shù)組名,程序修改如下圖:

          AT89S52里程序,基本不動,只是等待PC機發(fā)來請求字符“s”。收到請求后,發(fā)送0-255的全部數(shù)值。
          修改的程序如下:

          #include

          void delay(void) //定義一個延時子程序
          {
          unsigned int i;
          for (i=15535;i>0;i--);
          }

          void main(void)
          {
          unsigned char buf[]={3,4,5,D,255,253};//定義一個單字節(jié)數(shù)組
          unsigned char i;
          SCON=0x50; //串口方式1
          TMOD=0x20; //定時器1,定時方式為2
          PCON=0x80; //設(shè)定串口工作方式為1
          TCON=0x40; //設(shè)定時器1開始計數(shù)
          TH1=0xfd; //設(shè)定波特率為19200
          TL1=0xfd; //
          //TI=1;
          TR1=1; //啟動定時器
          while(1)
          { if(RI==1) //如果接收到數(shù)據(jù)則進入以下操作
          {if(SBUF==s) //如果收到的數(shù)據(jù)為“s”字符則進入發(fā)送操作
          {for(i=0;i<255;i++)//循環(huán)發(fā)送出數(shù),這里做為調(diào)試,我們先發(fā)0-255的數(shù)值。

          {
          SBUF=i; //向串口送出數(shù)據(jù),這里不發(fā)buf [ ]數(shù)組的數(shù)據(jù),而是直接發(fā)送循環(huán)體里的i 值(0-254)。
          while(TI==0);
          TI=0;
          delay(); //調(diào)用延時
          }

          SBUF=255; //上面循環(huán)里沒有包括255這個值,這里補發(fā)送一次

          while(TI==0);
          TI=0;
          RI=0;//發(fā)送完畢將收到請求標志清0等待PC下次請求
          }
          }
          }

          }

          顯示結(jié)果如下:

          這樣,所有的數(shù)值都是可以正確接收并顯示了。

          結(jié)論:要接收數(shù)值數(shù)據(jù),串口控件必須修改為二進制的接收屬性。即:InputMode=1



          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();