用C#一步步寫串口通信(共25頁)_第1頁
用C#一步步寫串口通信(共25頁)_第2頁
用C#一步步寫串口通信(共25頁)_第3頁
用C#一步步寫串口通信(共25頁)_第4頁
用C#一步步寫串口通信(共25頁)_第5頁
已閱讀5頁,還剩20頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、精選優質文檔-傾情為你奉上 我們來看具體的實現步驟。 公司要求實現以下幾個功能:1):實現兩臺計算機之前的串口通信,以16進制形式和字符串兩種形式傳送和接收。2):根據需要設置串口通信的必要參數。3):定時發送數據。4):保存串口設置。 看著好像挺復雜,其實都是紙老虎,一戳就破,前提是你敢去戳。我盡量講的詳細一些,爭取說到每個知識點。 在編寫程序前,需要將你要測試的COM口短接,就是收發信息都在本地計算機,短接的方式是將COM口的2、3號針接起來。COM口各針的具體作用,度娘是這么說的:。記住2、3針連接一定要連接牢固,我就是因為接觸不良,導致本身就不通,白白花掉了一大半天時間調試代碼。下面給

2、出主要的操作界面,如下:順便,我將所有控件對應的代碼名字也附上了,相信對初學者來說,再看下面的代碼會輕松很多。控件名字命名的方法是“控件名+作用”的形式,例如“打開串口”的開關按鈕,其名字是btnSwitch (btn就是button的簡寫了)。我認為這種命名控件的方式比較好,建議大家使用,如果你有好的命名方式,希望你能告訴我!下面我們將各個功能按照從主到次的順序逐個實現。(我分塊給出代碼實現,詳細代碼見鏈接:)一、獲取計算機的COM口總個數,將它們列為控件cbSerial的候選項,并將第一個設為cbSerial的默認選項。這部分是在窗體加載時完成的。請看代碼:(很多信息代碼的注釋里講的很清楚

3、,我就不贅述了。)csharp1. /檢查是否含有串口2. stringstr=SerialPort.GetPortNames();3. if(str=null)4. 5. MessageBox.Show(本機沒有串口!,Error);6. return;7. 8. 9. /添加串口項目10. foreach(stringsinSystem.IO.Ports.SerialPort.GetPortNames()11. /獲取有多少個COM口12. cbSerial.Items.Add(s);13. 14. 15. /串口設置默認選擇項16. cbSerial.SelectedIndex=0;/設

4、置cbSerial的默認選項二、“串口設置”這面我沒代碼編程,直接從窗體上按照串口信息設置就行。我們僅設置它們的默認選項,但這里我用到了ini文件,暫時不講,我們先以下面形式設置默認。csharp1. cbBaudRate.SelectedIndex=5;2. cbDataBits.SelectedIndex=3;3. cbStop.SelectedIndex=0;4. cbParity.SelectedIndex=0;5. radio1.Checked=true;/發送數據的“16進制”單選按鈕(這里我忘了改名,現在看著很不舒服!)6. rbRcvStr.Checked=true;三、打開串

5、口在發送信息之前,我們需要根據選中的選項設置串口信息,并設置一些控件的屬性,最后將串口打開。csharp1. privatevoidbtnSwitch_Click(objectsender,EventArgse)2. 3. /sp1是全局變量。SerialPortsp1=newSerialPort();4. if(!sp1.IsOpen)5. 6. try7. 8. /設置串口號9. stringserialName=cbSerial.SelectedItem.ToString();10. sp1.PortName=serialName;11. 12. /設置各“串口設置”13. string

6、strBaudRate=cbBaudRate.Text;14. stringstrDateBits=cbDataBits.Text;15. stringstrStopBits=cbStop.Text;16. Int32iBaudRate=Convert.ToInt32(strBaudRate);17. Int32iDateBits=Convert.ToInt32(strDateBits);18. 19. sp1.BaudRate=iBaudRate;/波特率20. sp1.DataBits=iDateBits;/數據位21. switch(cbStop.Text)/停止位22. 23. cas

7、e1:24. sp1.StopBits=StopBits.One;25. break;26. case1.5:27. sp1.StopBits=StopBits.OnePointFive;28. break;29. case2:30. sp1.StopBits=StopBits.Two;31. break;32. default:33. MessageBox.Show(Error:參數不正確!,Error);34. break;35. 36. switch(cbParity.Text)/校驗位37. 38. case無:39. sp1.Parity=Parity.None;40. break;

8、41. case奇校驗:42. sp1.Parity=Parity.Odd;43. break;44. case偶校驗:45. sp1.Parity=Parity.Even;46. break;47. default:48. MessageBox.Show(Error:參數不正確!,Error);49. break;50. 51. 52. if(sp1.IsOpen=true)/如果打開狀態,則先關閉一下53. 54. sp1.Close();55. 56. /狀態欄設置57. tsSpNum.Text=串口號:+sp1.PortName+|;58. tsBaudRate.Text=波特率:+

9、sp1.BaudRate+|;59. tsDataBits.Text=數據位:+sp1.DataBits+|;60. tsStopBits.Text=停止位:+sp1.StopBits+|;61. tsParity.Text=校驗位:+sp1.Parity+|;62. 63. /設置必要控件不可用64. cbSerial.Enabled=false;65. cbBaudRate.Enabled=false;66. cbDataBits.Enabled=false;67. cbStop.Enabled=false;68. cbParity.Enabled=false;69. 70. sp1.Op

10、en();/打開串口71. btnSwitch.Text=關閉串口;72. 73. catch(System.Exceptionex)74. 75. MessageBox.Show(Error:+ex.Message,Error);76. return;77. 78. 79. else80. 81. /狀態欄設置82. tsSpNum.Text=串口號:未指定|;83. tsBaudRate.Text=波特率:未指定|;84. tsDataBits.Text=數據位:未指定|;85. tsStopBits.Text=停止位:未指定|;86. tsParity.Text=校驗位:未指定|;87.

11、 /恢復控件功能88. /設置必要控件不可用89. cbSerial.Enabled=true;90. cbBaudRate.Enabled=true;91. cbDataBits.Enabled=true;92. cbStop.Enabled=true;93. cbParity.Enabled=true;94. 95. sp1.Close();/關閉串口96. btnSwitch.Text=打開串口;97. 98. 四、發送信息因為這里涉及到字符的轉換,難點在于,在發送16進制數據時,如何將文本框中的字符數據在內存中以同樣的形式表現出來,例如我們輸入16進制的“eb 90”顯示到內存中,也就

12、是如下形式: 或輸入我們想要的任何字節,如上面的“12 34 56 78 90”.內存中的數據時16進制顯示的,而我們輸入的數據時字符串,我們需要將字符串轉換為對應的16進制數據,然后將這個16進制數據轉換為字節數據,用到的主要方法是:Convert.ToInt32 (String, Int32);Convert.ToByte (Int32);這是我想到的,如果你有好的方法,希望你能告訴我。下面看代碼:csharp1. privatevoidbtnSend_Click(objectsender,EventArgse)2. 3. if(!sp1.IsOpen)/如果沒打開4. 5. Messag

13、eBox.Show(請先打開串口!,Error);6. return;7. 8. 9. StringstrSend=txtSend.Text;10. if(radio1.Checked=true)/“16進制發送”按鈕11. 12. /處理數字轉換,目的是將輸入的字符按空格、“,”等分組,以便發送數據時的方便(此處轉的比較麻煩,有高見者,請指點!)13. stringsendBuf=strSend;14. stringsendnoNull=sendBuf.Trim();15. stringsendNOComma=sendnoNull.Replace(,);/去掉英文逗號16. stringse

14、ndNOComma1=sendNOComma.Replace(,,);/去掉中文逗號17. stringstrSendNoComma2=sendNOComma1.Replace(0x,);/去掉0x18. strSendNoComma2.Replace(0X,);/去掉0X19. stringstrArray=strSendNoComma2.Split();20. 21. /strArray數組中會出現“”空字符的情況,影響下面的賦值操作,故將byteBufferLength相應減小22. intbyteBufferLength=strArray.Length;23. for(inti=0;i

15、strArray.Length;i+)24. 25. if(strArrayi=)26. 27. byteBufferLength-;28. 29. 30. 31. bytebyteBuffer=newbytebyteBufferLength;32. intii=0;/用于給byteBuffer賦值33. for(inti=0;istrArray.Length;i+)/對獲取的字符做相加運算34. 35. 36. BytebytesOfStr=Encoding.Default.GetBytes(strArrayi);37. 38. intdecNum=0;39. if(strArrayi=)4

16、0. 41. continue;42. 43. else44. 45. decNum=Convert.ToInt32(strArrayi,16);/atrArrayi=12時,temp=1846. 47. 48. try/防止輸錯,使其只能輸入一個字節的字符,即只能在txtSend里輸入“eb90”等字符串,不能輸入“1232345”等超出字節范圍的數字49. 50. byteBufferii=Convert.ToByte(decNum);51. 52. catch(System.Exceptionex)53. 54. MessageBox.Show(字節越界,請逐個字節輸入!,Error);

17、55. return;56. 57. 58. ii+;59. 60. sp1.Write(byteBuffer,0,byteBuffer.Length);61. 62. else/以字符串形式發送時63. 64. sp1.WriteLine(txtSend.Text);/寫入數據65. 66. 五、數據的接收亮點來了,看到這里,如果你還沒吐(可能是我的代碼比較拙劣!),那么下面的知識點對你也不成問題。這里需要用到 委托 的知識,我是搞C/C+出身,剛碰到這個知識點還真有點不適應。為了不偏離主題,關于委托,我僅給出兩條比較好的鏈接,需要的網友可以去加深學習:、。 在窗體加載時就訂閱上委托是比較好

18、的,所以在Form1_Load中添加以下代碼:csharp1. Control.CheckForIllegalCrossThreadCalls=false;/意圖見解釋2. sp1.DataReceived+=newSerialDataReceivedEventHandler(sp1_DataReceived);/訂閱委托 注意,因為自.net 2.0以后加強了安全機制,,不允許在winform中直接跨線程(事件觸發需要產生一個線程處理)訪問控件的屬性,第一條代碼的意圖是說在這個類中我們強制不檢查跨線程的調用是否合法。處理這種問題的解決方案有很多,具體可參閱以下內容:。 好了,訂閱委托之后,我

19、們就可以處理接收數據的事件了。csharp1. voidsp1_DataReceived(objectsender,SerialDataReceivedEventArgse)2. 3. if(sp1.IsOpen)/此處可能沒有必要判斷是否打開串口,但為了嚴謹性,我還是加上了4. 5. bytebyteRead=newbytesp1.BytesToRead;/BytesToRead:sp1接收的字符個數6. if(rdSendStr.Checked)/發送字符串單選按鈕7. 8. txtReceive.Text+=sp1.ReadLine()+rn;/注意:回車換行必須這樣寫,單獨使用r和n都

20、不會有效果9. sp1.DiscardInBuffer();/清空SerialPort控件的Buffer10. 11. else/發送16進制按鈕12. 13. try14. 15. BytereceivedData=newBytesp1.BytesToRead;/創建接收字節數組16. sp1.Read(receivedData,0,receivedData.Length);/讀取數據17. sp1.DiscardInBuffer();/清空SerialPort控件的Buffer18. stringstrRcv=null;19. 20. for(inti=0;ireceivedData.Le

21、ngth;i+)/窗體顯示21. 22. 23. strRcv+=receivedDatai.ToString(X2);/16進制顯示24. 25. txtReceive.Text+=strRcv+rn;26. 27. catch(System.Exceptionex)28. 29. MessageBox.Show(ex.Message,出錯提示);30. txtSend.Text=;31. 32. 33. 34. else35. 36. MessageBox.Show(請打開某個串口,錯誤提示);37. 38. 為了友好和美觀,我將當前時間也顯示出來,又將顯示字體的顏色做了修改:csharp

22、1. /輸出當前時間2. DateTimedt=DateTime.Now;3. txtReceive.Text+=dt.GetDateTimeFormats(f)0.ToString()+rn;4. txtReceive.SelectAll();5. txtReceive.SelectionColor=Color.Blue;/改變字體的顏色做到這里,大部分功能就已實現了,剩下的工作就是些簡單的操作設置了,有保存設置、定時發送信息、控制文本框輸入內容等。六、保存設置這部分相對簡單,但當時我沒接觸過,也花了點時間,現在想想,也不過如此。保存用戶設置用ini文件是個不錯的選擇,雖然大部分都用注冊表實

23、現,但ini文件保存還是有比較廣泛的使用。.ini 文件是Initialization File的縮寫,也就是初始化文件。為了不偏離正題,也不過多說明,可參考相關內容(網上資源都不錯,因人而異,就不加鏈接了)。使用Inifile讀寫ini文件,這里我用到了兩個主要方法:csharp1. /讀出ini文件2. a:=inifile.Readstring(節點,關鍵字,缺省值);/string類型3. b:=inifile.Readinteger(節點,關鍵字,缺省值);/integer類型4. c:=inifile.Readbool(節點,關鍵字,缺省值);/boolean類型5. 其中缺省值為

24、該INI文件不存在該關鍵字時返回的缺省值。6. /寫入INI文件:7. inifile.writestring(節點,關鍵字,變量或字符串值);8. inifile.writeinteger(節點,關鍵字,變量或整型值);9. inifile.writebool(節點,關鍵字,變量或True或False);請看代碼:csharp1. /using省寫了2. namespaceINIFILE3. 4. classProfile5. 6. publicstaticvoidLoadProfile()7. 8. stringstrPath=AppDomain.CurrentDomain.BaseDir

25、ectory;9. _file=newIniFile(strPath+Cfg.ini);10. G_BAUDRATE=_file.ReadString(CONFIG,BaudRate,4800);/讀數據,下同11. G_DATABITS=_file.ReadString(CONFIG,DataBits,8);12. G_STOP=_file.ReadString(CONFIG,StopBits,1);13. G_PARITY=_file.ReadString(CONFIG,Parity,NONE);14. 15. 16. 17. publicstaticvoidSaveProfile()18

26、. 19. stringstrPath=AppDomain.CurrentDomain.BaseDirectory;20. _file=newIniFile(strPath+Cfg.ini);21. _file.WriteString(CONFIG,BaudRate,G_BAUDRATE);/寫數據,下同22. _file.WriteString(CONFIG,DataBits,G_DATABITS);23. _file.WriteString(CONFIG,StopBits,G_STOP);24. _file.WriteString(CONFIG,G_PARITY,G_PARITY);25.

27、 26. 27. privatestaticIniFile_file;/內置了一個對象28. 29. publicstaticstringG_BAUDRATE=1200;/給ini文件賦新值,并且影響界面下拉框的顯示30. publicstaticstringG_DATABITS=8;31. publicstaticstringG_STOP=1;32. publicstaticstringG_PARITY=NONE;33. 34. _file聲明成了內置對象,可以方便各函數的調用。下面是“保存設置”的部分代碼:csharp1. privatevoidbtnSave_Click(objectse

28、nder,EventArgse)2. 3. 4. /設置各“串口設置”5. stringstrBaudRate=cbBaudRate.Text;6. stringstrDateBits=cbDataBits.Text;7. stringstrStopBits=cbStop.Text;8. Int32iBaudRate=Convert.ToInt32(strBaudRate);9. Int32iDateBits=Convert.ToInt32(strDateBits);10. 11. 12. Profile.G_BAUDRATE=iBaudRate+;/波特率13. Profile.G_DATA

29、BITS=iDateBits+;/數據位14. switch(cbStop.Text)/停止位15. 16. case1:17. Profile.G_STOP=1;18. break;19. case1.5:20. Profile.G_STOP=1.5;21. break;22. /防止過多刷屏,下面省寫了23. 24. 25. switch(cbParity.Text)/校驗位26. 27. case無:28. Profile.G_PARITY=NONE;29. break;30. 31. 32. Profile.SaveProfile();/保存設置33. 讀取ini文件主要在加載窗體時執行:INIFILE.Profile.LoadProfile();/加載所有七、控制文本輸入這里倒挺簡單,只是注意一點。當我們控制輸入非法字符時,可通過控制e.Handed的屬性值實現,注意這里的Handed屬性是“操作過”的含義,而非“執行此處操作”之

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論