ある機器をシリアル通信で制御しようと思っています。
指令を出力し、300ms間応答が無ければ、04Hを出力し100ms待って、
再度、指令を出力・・・これを3回繰り返し駄目なら通信異常と判断します。
この部分をforループで繰り返し、300ms、100msのSleepを入れました。
一方、シリアル通信の部分は、ActivXのMS_Commを使いました。
MS_Commでは、受信するとハード割り込みで受信イベントの処理を実行できるようです。
送信前に、フラグを0にして3回のforループに入り、フラグが1になるとループを
抜けるようにしました。
一方、受信するとフラグを1に変更するようにしました。
送受信の履歴を記録したところ
送信1
受信
送信2
送信3
となって、1度目の送信の後に受信されていますが、フラグの方はforループを抜けるまで
変更されていません。
UpdateData(TRUE)をいれてみても駄目でした。
このような状態で変数を更新するには、どうしたら良いでしょうか?
よろしく、お願いいたします。
UpdateData(TRUE)ってCWnd::UpdateData(BOOL)(ダイヤログのコントロールからメンバ変数へ値を取り込むための関数)ですよね?
それとフラグがどうして関係があるんですか?
int nTry = 3;
BOOL bRecieved = FALSE;
while (nTry-- && !bRecieved)
{
if (<受信>)
bRecieved = TRUE;
Sleep(300);
}
とか云うことでは?
ゴンさま
UpdateDataは関係なかったですね
おっしゃる通り、ループの中で受信処理を書ければ問題ないなくできるのですが
MS_Commを使ってしまったので、受信関数がまったく別の関数になってしまい
こちらの関数はハード割り込みで呼ばれるようなのです。
Sleep(300)の間に実行されているようです。
フラグはpublic変数にしていますが、やはり、ループを抜けるまで関数の
更新はできないでしょうか?
開発環境や設定の情報は?
”フラグ”とやらがどんな変数でどう宣言されてるのか?
for文のところでどう使われてるのか?
”フラグ”によって、どのようにループを抜けるようにプログラムしたのか?
ループ内でフラグ更新してないから最適化で省かれたに一票
該当箇所のソースを提示した方が話は早いかも。。
少し長いのですが、ソース抜粋です。
①送信後 Sleep(300)の間に
③受信 ④フラグ更新しているようですが?
②に入りません
OnOnCommMscomm1はMSCommアイコンをダブルクリックで自動つかされた関数で、
呼ばれるタイミングも、こちらでは操作していません。
void CServoCntrlView::OnButton3() //送信処理
{
char SOH = 0x01;
char STX = 0x02;
char ETX = 0x03;
char EOT = 0x04;
char TAB = 0x09;
・
・
CString sendtxt;
char chr;
char ctimes;
m_HandsF = 0; //0:送信済み 1:受信あり 2:応答チェック済み
for(int times = 0; times<3; times++)
{
//--------------------------------------- 送信
for(int i=0; i<nn+2; i++)
{
chr = sendtxt.GetAt( i );
SendBinary( &chr ); //①送信
}
//--------------------------------------- 履歴追加
itoa( times+1, &ctimes, 10);
m_RichEdit1 = m_RichEdit1 + "<Send>" + "(" + ctimes + ")" + TAB + m_Edit1 + TAB
+ m_Edit2 + TAB + m_Edit3 + TAB + m_Edit4 + '\r' + '\n';
UpdateData(FALSE);
Sleep(300);
if(m_HandsF == 1) //受信ありの場合
{
times = 9; //②ここに入らない
}
else if(m_HandsF == 0 && times<3) //受信が無い場合
{
chr = EOT;
SendBinary( &chr );
Sleep( 100 );
m_RichEdit1 = m_RichEdit1 + "<Send> EOT" + '\r' + '\n';
UpdateData(FALSE);
}
}
}
void CServoCntrlView::OnOnCommMscomm1() //OnCommイベント
{
char TAB = 0x09;
COleSafeArray aRecvData; //Byte要素の1次元配列
LPBYTE pRecvByte;
int i = 0;
int j;
i = m_comm.GetCommEvent(); //イベントの種類を取得
int nn = 0;
CString EvnMsg;
switch( i )
{ //----------------------------イベントメッセージ
case 1: //comEvSend
break;
case 2: //comEvReceive //受信イベント
aRecvData = m_comm.GetInput();
aRecvData.AccessData((void**)&pRecvByte);
nn = aRecvData.GetOneDimSize();
if( nn )
{
m_RichEdit1 = m_RichEdit1 + "<Rece>" + TAB; //③受信履歴追加
}
・
内容をm_RichEdit1へ追加
・
m_RichEdit1 = m_RichEdit1 + " " + '\r' + '\n';
UpdateData( FALSE );
aRecvData.UnaccessData();
m_HandsF = 1; //④フラグ更新
break;
case 3: //comEvCTS
break;
case 4: //comEvDSR
break;
case 5: //comEvCD
break;
case 6: //comEvRing
break;
case 7: //comEvEOF
break;
・
・
・
最適化で省かれたとは?
RThresholdの設定してる?
MSCOMMって使ったことないんだけど、イベントは多分メッセージドリブンだよね?
本当にハード割り込みなら、m_HandsFに排他処理とRichEdit1の設定をPostMessageでやらないとぶつかりそう。
if(m_HandsF == 1) //受信ありの場合
{
break; // ループから抜ける //②ここに入らない
}
else
{
chr = EOT;
SendBinary( &chr );
Sleep( 100 );
m_RichEdit1 = m_RichEdit1 + "<Send> EOT" + '\r' + '\n';
UpdateData(FALSE);
}
これで抜けなければ、"m_HandsF"を1にする方が間違ってる。
> ループ内でフラグ更新してないから最適化で省かれたに一票
私も一票。
m_HandsFの宣言にvolatileキーワードが付いていますか?
volatileを付けて2度目のループで抜けるようになりました。
ありがとうございまいした。
ツイート | ![]() |