全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:20610
推到 Plurk!
推到 Facebook!

在Win32[BCB]下用Serial Port通訊的範例

 
jackkcg
站務副站長


發表:891
回覆:1050
積分:848
註冊:2002-03-23

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-02-08 23:37:49 IP:61.64.xxx.xxx 未訂閱
此為轉貼資料    http://netcity3.web.hinet.net/userdata/k1228341/art/bcb232.txt    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Subject: 在Win32[BCB]下用Serial Port通訊的範例    發信人: vega6385.bbs@cszone.twbbs.org (simayi), 信區: programming 標  題: 在Win32[BCB]下用Serial Port通訊的範例 發信站: 程式設計樂園(CSZone) (Thu Jul 27 21:16:13 2000) 轉信站: cis_nctu!news.cis.nctu!freebsd.ntu!news.ntu!CSZone 來  源: octa2.ee.ntu.edu.tw    在Win32[BCB]下用Serial Port通訊的範例 /////////////////////////////////////////////// 下列的程式示範了如何在Win32下 用console mode做Serial Port通訊 關於與之通訊的硬體,請參考松崗 出版的"單晶片8051實務<增修版>" 一書,作者:吳一農,ISBN:957-22-3242-8 硬體線路及8051ASM CODE.請參照 書中第16章的部份.本程式能完全取代 16-19頁中的Qbasic程式,達到雙向傳輸的功用. 本程式在BCB5中能順利編譯執行!!    #include #include #include int main(int argc, char* argv[]) { HANDLE com2_handle ; //RS-232的Com2的handle DCB dcb ; //設定傳輸參數所需之結構 char buffer[10]; //讀取資料所需的緩衝區 DWORD read_bytes = 1 ; //每次讀取的byte數 com2_handle = CreateFile( "COM2" ,GENERIC_READ|GENERIC_WRITE , 0, NULL ,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); //開啟com2,設為一般讀取寫入,一般屬性,不使用非同步IO BuildCommDCB( "baud=4800 parity=N data=8 stop=2", &dcb ); //設定傳輸參數結構的內含值:鮑率:4800,無同位檢查,資料位元8,停止位元2 SetCommState( com2_handle , &dcb ); //設定傳輸參數 COMMTIMEOUTS time_out ; //設定讀寫逾時參數的結構 time_out.ReadIntervalTimeout = MAXDWORD ; //設為MAXDWORD:如果沒有資料供讀取,ReadFile函式將立即返回 time_out.ReadTotalTimeoutMultiplier = 0 ; time_out.ReadTotalTimeoutConstant = 0 ; //不使用讀取總和時間來判斷是否讀取逾時 time_out.WriteTotalTimeoutMultiplier = 5 ; time_out.WriteTotalTimeoutConstant = 50 ; //使用寫入總和時間來判斷是否寫入逾時,逾時WriteFile函式將立即返回 SetCommTimeouts( com2_handle , &time_out ) ; //設定com2讀寫逾時返回 printf("請撥動switch然後接收 或 按數字鍵0~9傳輸 或 可以按X結束\n"); while( 1 ) { ReadFile( com2_handle , buffer , read_bytes ,&read_bytes ,NULL); //由com2讀取1byte //因為ReadFile函式逾時的時候,不僅沒讀到資料(所以buffer[0]沒變動)就返回, //還會把read_bytes內含值改為0,因此read_bytes!= 0時表示有讀到資料 if(read_bytes!= 0) { //下面這一段顯示四個switch的狀態,用1與0表示ON/OFF //方法是有點拙,我也知道用<<和>>很快,可是實作時出了點狀況,所以用這個拙方法 int sw1,sw2,sw3,sw4 ; sw1 = (0-buffer[0]-113) / 8 ; sw2 = ((0-buffer[0]-113)- (sw1 * 8)) / 4 ; sw3 = ((0-buffer[0]-113)-(sw1*8)-(sw2*4)) / 2 ; sw4 = ((0-buffer[0]-113)-(sw1*8)-(sw2*4)-(sw3*2)) / 1 ; printf("由COM2得到Switch狀態 %d%d%d%d \n", sw1,sw2,sw3,sw4); printf("可以按X結束\n"); } else { read_bytes = 1 ; //因為ReadFile函式逾時的時候,不僅沒讀到資料(所以buffer[0]沒變動)就返回, //還會把read_bytes內含值改為0,所以我們要設回初值,不然下一輪會讀不到資料 //(因為內函值為0,表示要讀取0byte,所以讀不到資料) } if( kbhit() != 0 ) //如果鍵盤有被按到,kbhit函式傳回值不等於0 { int key ; //存放被按的鍵的鍵值 key = getch() ; //把被鍵值讀出來 if( key == 'x' ) { break ; //按下小寫x結束本程式 } else { switch( key ) //如果輸入數字鍵0~9,將之傳給8051實習板顯示出來 { case '0' : WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); printf("傳送%c到UART的另一端\n",key); printf("可以按X結束\n"); break ; case '1' : WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); printf("傳送%c到UART的另一端\n",key); printf("可以按X結束\n"); break ; case '2' : WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); printf("傳送%c到UART的另一端\n",key); printf("可以按X結束\n"); break ; case '3' : WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); printf("傳送%c到UART的另一端\n",key); printf("可以按X結束\n"); break ; case '4' : WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); printf("傳送%c到UART的另一端\n",key); printf("可以按X結束\n"); break ; case '5' : WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); printf("傳送%c到UART的另一端\n",key); printf("可以按X結束\n"); break ; case '6' : WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); printf("傳送%c到UART的另一端\n",key); printf("可以按X結束\n"); break ; case '7' : WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); printf("傳送%c到UART的另一端\n",key); printf("可以按X結束\n"); break ; case '8' : WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); printf("傳送%c到UART的另一端\n",key); printf("可以按X結束\n"); break ; case '9' : WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); printf("傳送%c到UART的另一端\n",key); printf("可以按X結束\n"); break ; default: break ; } } } } CloseHandle( com2_handle ); //關閉com2 return 0; } /////////////////////////////////// 改寫成BCB的版本如下 /////////////////////////////////// //--------------------------------------------------------------------------- #include #pragma hdrstop #include "uart_GUI_cpp.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" #include TForm1 *Form1; HANDLE com2_handle ; //RS-232的Com2的handle DCB dcb ; //設定傳輸參數所需之結構 char buffer[10]; //讀取資料所需的緩衝區 DWORD read_bytes = 1 ; //每次讀取的byte數 COMMTIMEOUTS time_out ; //設定讀寫逾時參數的結構 int key ; //存放被按的鍵的鍵值 char temp_string[256]; char temp_string2[256]; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::FormResize(TObject *Sender) { Width = 435 ; Height = 300 ; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button11Click(TObject *Sender) { Form1->Close(); } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { com2_handle = CreateFile( "COM2" ,GENERIC_READ|GENERIC_WRITE , 0, NULL ,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); //開啟com2,設為一般讀取寫入,一般屬性,不使用非同步IO BuildCommDCB( "baud=4800 parity=N data=8 stop=2", &dcb ); //設定傳輸參數結構的內含值:鮑率:4800,無同位檢查,資料位元8,停止位元2 SetCommState( com2_handle , &dcb ); //設定傳輸參數 time_out.ReadIntervalTimeout = MAXDWORD ; //設為MAXDWORD:如果沒有資料供讀取,ReadFile函式將立即返回 time_out.ReadTotalTimeoutMultiplier = 0 ; time_out.ReadTotalTimeoutConstant = 0 ; //不使用讀取總和時間來判斷是否讀取逾時 time_out.WriteTotalTimeoutMultiplier = 5 ; time_out.WriteTotalTimeoutConstant = 50 ; //使用寫入總和時間來判斷是否寫入逾時,逾時WriteFile函式將立即返回 SetCommTimeouts( com2_handle , &time_out ) ; //設定com2讀寫逾時返回 Memo1->Clear(); Memo2->Clear(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { key = '1'; sprintf(temp_string,"%c",key); Memo1->Clear(); Memo1->SetSelTextBuf(temp_string); WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { key = '2'; sprintf(temp_string,"%c",key); Memo1->Clear(); Memo1->SetSelTextBuf(temp_string); WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button10Click(TObject *Sender) { key = '0'; sprintf(temp_string,"%c",key); Memo1->Clear(); Memo1->SetSelTextBuf(temp_string); WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button3Click(TObject *Sender) { key = '3'; sprintf(temp_string,"%c",key); Memo1->Clear(); Memo1->SetSelTextBuf(temp_string); WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button4Click(TObject *Sender) { key = '4'; sprintf(temp_string,"%c",key); Memo1->Clear(); Memo1->SetSelTextBuf(temp_string); WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button5Click(TObject *Sender) { key = '5'; sprintf(temp_string,"%c",key); Memo1->Clear(); Memo1->SetSelTextBuf(temp_string); WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button6Click(TObject *Sender) { key = '6'; sprintf(temp_string,"%c",key); Memo1->Clear(); Memo1->SetSelTextBuf(temp_string); WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button7Click(TObject *Sender) { key = '7'; sprintf(temp_string,"%c",key); Memo1->Clear(); Memo1->SetSelTextBuf(temp_string); WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button8Click(TObject *Sender) { key = '8'; sprintf(temp_string,"%c",key); Memo1->Clear(); Memo1->SetSelTextBuf(temp_string); WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button9Click(TObject *Sender) { key = '9'; sprintf(temp_string,"%c",key); Memo1->Clear(); Memo1->SetSelTextBuf(temp_string); WriteFile( com2_handle , &key , read_bytes , &read_bytes ,NULL ); } //--------------------------------------------------------------------------- void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action) { CloseHandle( com2_handle ); } //--------------------------------------------------------------------------- void __fastcall TForm1::Timer1Timer(TObject *Sender) { Timer1->Enabled = false; ReadFile( com2_handle , buffer , read_bytes ,&read_bytes ,NULL); //由com2讀取1byte if(read_bytes!= 0) { //下面這一段顯示四個switch的狀態,用1與0表示ON/OFF //方法是有點拙,我也知道用<<和>>很快,可是實作時出了點狀況,所以用這個拙方法 int sw1,sw2,sw3,sw4 ; sw1 = ((0-buffer[0]-113) & 8)/8 ; sw2 = ((0-buffer[0]-113) & 4)/4 ; sw3 = ((0-buffer[0]-113) & 2)/2 ; sw4 = ((0-buffer[0]-113) & 1)/1 ; sprintf(temp_string2,"由COM2得到Switch狀態 %d%d%d%d \n", sw1,sw2,sw3,sw4); Memo2->Clear(); Memo2->SetSelTextBuf(temp_string2); while(read_bytes!= 0)//把緩衝區資料全讀完才跳出 { ReadFile( com2_handle , buffer , read_bytes ,&read_bytes ,NULL); //由com2讀取1byte sw1 = ((0-buffer[0]-113) & 8)/8 ; sw2 = ((0-buffer[0]-113) & 4)/4 ; sw3 = ((0-buffer[0]-113) & 2)/2 ; sw4 = ((0-buffer[0]-113) & 1)/1 ; sprintf(temp_string2,"由COM2得到Switch狀態 %d%d%d%d \n", sw1,sw2,sw3,sw4); Memo2->Clear(); Memo2->SetSelTextBuf(temp_string2); } read_bytes = 1 ; //因為ReadFile函式逾時的時候,不僅沒讀到資料(所以buffer[]沒變動)就返回, //還會把read_bytes內含值改為0,所以我們要設回初值,不然下一輪會讀不到資料 //(因為內函值為0,表示要讀取0byte,所以讀不到資料) } else { read_bytes = 1 ; //因為ReadFile函式逾時的時候,不僅沒讀到資料(所以buffer[]沒變動)就返回, //還會把read_bytes內含值改為0,所以我們要設回初值,不然下一輪會讀不到資料 //(因為內函值為0,表示要讀取0byte,所以讀不到資料) } Timer1->Enabled = true; } //--------------------------------------------------------------------------- -- ********************************************* * Simayi司馬仲達 simayi@kimo.com.tw ? * * CICQ : 663287 ICQ : 49827636 * * 歡迎大家一起討論程式設計的問題 * * C/C OWL ASM QB都可以討論喔!! * ********************************************* -- ※ Origin: 程式設計樂園 ◆ From: h117.s170.ts32.hinet.net ********************************************************* 哈哈&兵燹 最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好 Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知 K.表Knowlege 知識,就是本站的標語:Open our mind to make knowledge together! 希望能大家敞開心胸,將知識寶庫結合一起
------
**********************************************************
哈哈&兵燹
最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好

Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知
K.表Knowlege 知識,就是本站的標語:Open our mind
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2010-04-05 08:05:03 IP:111.250.xxx.xxx 訂閱
 另一篇有提到的Simple Serial Communication with Borland Turbo C Explorer

Create the Application

Test the ApplicationWith the form created and code written in the Turbo C Explorer IDE, press F9 (Run) and your simple serial communications program is running. Press the Start button to open the COM port. Incoming serial text data will appear in Memo1 and anything you type into Memo1 will be transmitted. If you don't have a connected serial device suitable for testing the program, use a loopback connector. Make one by simply jumpering pins 2 and 3 of a serial cable or DB9F connector. With a loopback connector, anything you type in Memo1 will be echoed back through the port and displayed in Memo1.
If the program doesn't work, carefully review your code and serial connections. The COM port designated in CreateFile() must be the one your are connected to and actually exist on your computer. COM1 is most common but you might be connected to COM2, COM3, etc. If the port is connected to an external serial device, the comm parameters (baud rate, etc.) of the device and your program must agree. Change parameters in the BuildCommDCB() function if needed.

"COM1", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if (hComm == INVALID_HANDLE_VALUE) { Memo1->Lines->Add(return; } The next group of functions configure the serial Device Control Block (DCB) which controls baud rate, parity, data bits, and stop bits among other things. We call the WIN32 API GetCommDCB() function to load existing DCB parameters into our dcbCommPort structure. We next call BuildCommDCB() with a string describing baud rate, parity, data bits, and stop bits. Although the DCB has many parameters, in our example we're keeping it simple by using the BuildCommDCB() function to populate the dcbCommPort structure for us. Finally, calling SetCommState() loads our parameters into the DCB for our open port. If it's successful, we move on, otherwise we close the port, print an error message, and return.
  dcbCommPort.DCBlength = if(!BuildCommDCB("Cannot build comm DCB.");
    if(!SetCommState(hComm, &dcbCommPort)) {
    CloseHandle(hComm);
    hComm = NULL;
    Memo1->Lines->Add(return;
  }    
We next set the CommTimeouts. These settings control delays when trying to read from or write to the comm port. The values used in this example cause no delays when reading the port and a maximum delay of 250 ms when writing (Actually, the write delay will never occur in our example because we transmit characters individually without calling WriteFile().) We load our timeout values by calling SetCommTimeouts(). If no errors are returned, the comm port is now configured the way we want it.
  CommTimeouts.ReadIntervalTimeout = MAXDWORD;
  CommTimeouts.ReadTotalTimeoutConstant = 0;
  CommTimeouts.WriteTotalTimeoutConstant = 1;      "Cannot set timeouts.");
    true;
  ButtonStart->Enabled = true;
  Memo1->ReadOnly = Process any events that occur elsewhere in the program.
  • If bytes were read, display them in Memo1.
  • Calling ProcessMessages() inside the loop allows the application to handle other events like typing in Memo1 or clicking the Stop button. Sleep() prevents our loop from consuming all available CPU cycles which would far exceed our requirements. Because the serial device driver within the Windows OS has its own internal buffer, we won't miss any incoming characters while still allowing CPU time for other applications. It's the polite thing to do.
    The ReadFile() function tries to read 100 bytes into our global array InBuffer. Because of our CommTimeout settings, ReadFile() will return immediately with whatever is available from the Windows internal serial receive buffer even if it's empty. If ReadFile() received any characters, we null-terminate the string and display it in Memo1. Pretty simple.
      1)
        ReadFile(hComm, InBuffer, if(BytesRead) {
          InBuffer[BytesRead] = if(hComm) TransmitCommChar(hComm, Key);
      Key = Final Thoughts

    For the sake of clarity and simplicity, our example application omits a few things.
    • Memo1 holds a lot of characters but will eventually run out of memory and just stop displaying anything new that arrives. You can limit the number of characters it will display by setting the Memo1 MaxLength property but then it will just run out of space sooner. A better approach is to limit the number of lines without affecting the display.
    • LinksSimpleSerial.zip Download Turbo C Explorer Simple Serial Project.
      Microsoft MSDN Serial Communication Resources WIN32 API serial communication reference.
      www.turboexplorer.com/cpp Borland's FREE Turbo C Explorer

      //--------------------------------------------------------------------------- #include #pragma hdrstop #include "Main.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; // Add these global variables HANDLE hComm = NULL; char InBuffer[//--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Add these local variables. DCB dcbCommPort; COMMTIMEOUTS CommTimeouts; DWORD BytesRead; // Open the port using WIN32 API CreateFile(). // Change COM1 for different port. // Leave the remaining parameters alone for simple // non-overlapped serial I/O. hComm = CreateFile( // If port cannot open, print error message and return. if (hComm == INVALID_HANDLE_VALUE) { Memo1->Lines->Add(return; } // Get the existing DCB parameters dcbCommPort.DCBlength = // Use the WIN32 API BuildCommDCB() to load simple comm parameters // into DCB. If it fails, print error message and return. "baud=9600 parity=N data=8 stop=1", &dcbCommPort)) { hComm = NULL; Memo1->Lines->Add(return; } // Use the WIN32 API SetCommState() to set parameters from DCB. // If it fails, close hComm, print error message, and return. "Cannot set comm state."); // Set CommTimeouts parameters. // See ReadFile() function later for details. CommTimeouts.ReadIntervalTimeout = MAXDWORD; CommTimeouts.ReadTotalTimeoutConstant = 0; CommTimeouts.WriteTotalTimeoutConstant = 1; // Use the WIN32 API SetCommTimeouts() to set parameters from DCB. // If it fails, close hComm, print error message, and return. "Cannot set comm timeouts."); // Set CommFlag and Button states. Allow typing in Memo1. CommFlag = false; ButtonStop->Enabled = false; Memo1->SetFocus(); // Constantly loop while CommFlag is true. // ProcessMessages() allows other other events within the program // to be serviced. ReadFile() tries to read 100 bytes into InBuffer. // Because of the timeouts we used earlier, ReadFile() will return // immediately with whatever characters it has (up to 100). The // BytesRead variable will contain the number of characters loaded // into InBuffer. // If BytesRead > 0, make the last charater in the received string = 0. // This terminates the string. Notice that we dimensioned InBuffer[101] // to accomodate the terminating 0 if necessary. Use SetSelTextBuff() // to append the contents of InBuffer onto the end of text in Memo1. // Pressing either the Stop button or Window close button will // set CommFlag = false. That will end the loop. 1) ReadFile(hComm, InBuffer, if(BytesRead) { InBuffer[BytesRead] = // Close the comm port and set hComm to NULL. CloseHandle(hComm); hComm = NULL; //Set button enables back to original state. Make Memo1 read-only. ButtonStart->Enabled = false; Memo1->ReadOnly = //--------------------------------------------------------------------------- // If Stop button pressed... CommFlag = false; } //--------------------------------------------------------------------------- // If attempting to close the window... CommFlag = //--------------------------------------------------------------------------- // If a Memo1 key is pressed, transmit it. // TransmitCommChar() returns 0 if the previous character has not // finished sending. Keep trying until non-zero is returned. while(TransmitCommChar(hComm, Key) == // Set Key=0 so it will not echo in Memo1. // Omit this line if you want local echo. Key = //---------------------------------------------------------------------------

    系統時間:2024-12-04 1:23:14
    聯絡我們 | Delphi K.Top討論版
    本站聲明
    1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
    2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
    3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!