線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2161
推到 Plurk!
推到 Facebook!

有關8051->RS232讀取空值會停住的問題

缺席
cyjhs90146
一般會員


發表:11
回覆:7
積分:3
註冊:2009-02-01

發送簡訊給我
#1 引用回覆 回覆 發表時間:2009-09-22 22:35:38 IP:218.162.xxx.xxx 訂閱
就是我打的測試程式阿
我要在8051上案數字鍵盤
然後案完他會傳到BUFFER裡面
會在一個一個讀取出來
可是
如果我的BUFFER是空值沒有東西
他就會停在
ReadFile(hComm, &rxBuf, 1, &dwRead, NULL);
這一串程式上都不動= =
我想問是我打的程式有問題還是設定上的問題
//---------------------------------------------------------------------------

#include
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
HANDLE hComm = NULL;
COMMTIMEOUTS ctmoNew = {0}, ctmoOld;
char buffer[10];
DWORD dwbytesread = 1 ;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
DCB dcbCommPort;
hComm = CreateFile("COM1",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
0);
BuildCommDCB("1200,N,8,1", &dcbCommPort);
//CloseHandle(hComm);
}
//---------------------------------------------------------------------------




void __fastcall TForm1::Button1Click(TObject *Sender)
{
Edit1->Text="";
}
//---------------------------------------------------------------------------


void __fastcall TForm1::Button3Click(TObject *Sender)
{
char txBuf[10],rxBuf[10];
DWORD dwRead;
ReadFile(hComm, &rxBuf, 1, &dwRead, NULL);
Edit1->Text=rxBuf;
/*if(Edit1->Text=="#")
{
Edit3->Text="hjhj";
} */
}
//---------------------------------------------------------------------------

編輯記錄
cyjhs90146 重新編輯於 2009-09-22 22:36:21, 註解 無‧
cyjhs90146
一般會員


發表:11
回覆:7
積分:3
註冊:2009-02-01

發送簡訊給我
#2 引用回覆 回覆 發表時間:2009-09-23 00:08:43 IP:218.162.xxx.xxx 訂閱
哈哈~~~
我已經找到資料了
原來是
ReadFile的本身設定
所以遇到問題就要找資料^^



win32api所提供的serial port寫方式有分兩種
同步方式: 夠了指定的字元才會返回(執行緒不會先返回去做其他工作)
非同步方式: ReadFile/WriteFile函式被呼叫之後,執行緒會先返回,win32api自動幫你新增一個執行緒在背景做IO工作,你必須去檢查OVERLAPPED結構的hEvent物件是否已被觸發,才知道背景IO工作是否已經結束

標準做法是先用WaitForSingleObject去檢查hEvent物件,如果觸發了,才使用GetOverlappedResult去檢查執行的結果(IO工作結束後有很多種結果,到的字元可能介於0~N個你指定的字元,可能是順利完之後返回或是因為timeout被迫先返回而實際字元=0或是


win32做IO的方式(serial port/檔案寫/和其他IO都適用)會受到timeout的影響,否則同步方式很容易會鎖死,如果是在XP系統,逾時機制的預設值應該都是0,也就是不使用timeout機制
你在開啟通訊埠使用CreateFile函式的時候並沒有指定要用overlapped非同步方式去執行,我也沒看到你有去設定timeout值,所以你的IO執行緒是以同步方式在跑,overlapped結構和設定等等動作是白做的,因為ReadFile根本不會去使用

因此你的程式應該是會鎖死住,一直等到ReadFile夠了256個bytes才會返回...,我建議你要把一些事情做好,比較容易debug

1. 開啟通訊埠之後,把UART晶片的緩衝區一律清除掉,否則程式上一次執行所傳送的資料仍然會在緩衝區裡面等著被(至系統記憶體內),事實上一般白牌的UART晶片的接收緩衝區大約是16到256個bytes,很容易就被塞暴,因此windows事實上在背後幫你提早接收了這些資料,並自行保管,等到你去serial port的時候,它就直接把資料給你(系統記憶體的複製動作),所以你會發現寫入serial port返回的時間跟baudrate以及字數有相關,但是serial port卻是""瞬間""完成,即使你的baudrate很低...我把這個稱之為windows所提供的""軟體緩衝區"",實測結果是這個軟體緩衝區 可以放超過1MB以上的資料(雖然被灌暴的時候,win32API函式有檢查overrun的事件和機制,也可以警告你,但是資料仍然被存放入軟體緩衝區 裡面,一個byte都沒少也不會被丟掉),所以開啟/關閉通訊埠的動作要確實,該清空/reset的動作都要做,不然改過的新程式碼去軟體緩衝區裡面的舊資料,改對了還是可能產生錯誤結果

2. 因為win32api提供了timeout返回的機制,所以你可以沒事就去看看,大不了就是沒資料可而已,這種方式特別適合資料固定在流動,但是資料量不定的情況(而且最新資料可以取代舊資料),另一種方式是先檢查接收緩衝區之後,知道了有無字元和實際數量,然後才去做動作,這種方式如果出了問題比較好debug
系統時間:2017-12-14 4:30:55
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!