初めての店舗開業を成功させよう>>

PCとマイコンをシリアル通信を介して送受信したいのですが
どのサイトを見てもVC++やWindows上のAPIを使ったものばかりです。

開発環境はLINUXのgcc4.5を想定していますが、使える関数が異なりますよね?
どのような流れで作成すればいいのでしょうか。
単にシリアル変換のUSBで文字列を送受信するだけでいいです。

このQ&Aに関連する最新のQ&A

A 回答 (1件)

これが参考になるかもしれない。


http://linuxjf.sourceforge.jp/JFdocs/Serial-Prog …
デバイスは /dev/ttyUSB0 などになると思う。

参考URL:http://linuxjf.sourceforge.jp/JFdocs/Serial-Prog …
    • good
    • 0
この回答へのお礼

ありがとうございます。
非常に参考になりそうです。

お礼日時:2011/07/24 10:00

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qシリアル通信でのread関数の戻り値

オムロン製PLCと上位コンピュータをRS232Cで接続し、FINSコマンドを用いてシリアル通信をしようとしています。
現在作っているプログラムの流れは、

・シリアルポート"/dev/ttyS2"のオープン
  comm_fd = open("/dev/ttyS2", O_RDWR | O_NOCTTY);
・通信設定
  termios構造体を設定
・コマンドフレーム(COMMAND)を作成し、ポートに書き込む
  write(comm_fd, &COMMAND, strlen(COMMAND));
・PLCからのレスポンスを読み出す
  read(comm_fd, &RESPONSE, 256);

のようにしているのですが、read関数が実行されたままになってしまいます。(エラーコードも返ってこない状態です)
readの戻り値が-1ならポートにアクセスできていないとわかるのですが…

ためしにcomm_fdと違う値をread関数に入れてみたところ(read(6, &RESPONSE, 256)、戻り値は-1となりました。

これはどういう状態になってしまっているのでしょうか?
わかりにくい質問で申し訳ありません。

オムロン製PLCと上位コンピュータをRS232Cで接続し、FINSコマンドを用いてシリアル通信をしようとしています。
現在作っているプログラムの流れは、

・シリアルポート"/dev/ttyS2"のオープン
  comm_fd = open("/dev/ttyS2", O_RDWR | O_NOCTTY);
・通信設定
  termios構造体を設定
・コマンドフレーム(COMMAND)を作成し、ポートに書き込む
  write(comm_fd, &COMMAND, strlen(COMMAND));
・PLCからのレスポンスを読み出す
  read(comm_fd, &RESPONSE, 256);

のようにしているのです...続きを読む

Aベストアンサー

PLCはttyS2に接続されていますか?
接続が正しいのであれば、termiosの設定が気になります。
newtio.c_iflag = (IGNPAR | ICRNL); みたいになってないと
readが改行受信で戻ってこずに、256バイト読むまで待っているかもしれません。

Qシリアルの送信完了を待つ方法

AdvantechのPCM-9575ボードにRedHat9を入れてCOM2
をRS-485にして115kでシリアル通信しています。
プログラム的には"/dev/ttyS1"を使用して普通の23
2Cポートと同じように操作できますが、送信イネー
ブル信号(RTS 信号がつながっているのでioctl()
関数で制御できます)を操作してやらないと送受信
できないので、送信直前にセットし、送信完了直後
にクリアしたいと考えているのですが、write() 関
数が送信完了まで待ってくれないので、タイミング
を作るのに困っています。
シリアルの送信完了待ちの方法とかご存じでないし
ょうか?

Aベストアンサー

今回の問題はドライバレベル以下で起こっているのだと思います。SIOには例えば16バイトのFIFOがあって、ドライバはハードに書き込んだら、すぐにカーネルに戻ってしまうのでしょう(FIFOの目的を考えれば当然ですね)。だからプロセスレベルでBLOCKINGであろうとなかろうと短時間ではバッファリングが起きているのだろう ... という理解になりました。質問主さんは最初からお気づきだったのでしょう。

ドライバのソースを読んだところでは、closeをするとハードウェアFIFOが空になるのをちゃんと待っています。ですからwrite直後にcloseしたら完全に送信完了ということになります。またcloseでは
if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
serial_outp(info, UART_MCR, info->MCR);
ということをしているので、RTSも一緒にクリアされるようです。

open/closeを繰り返すのはコストが高いので避けたいですけれど、そうでないなら単にcloseすることで質問主さんの目的は達せられるのではないでしょうか?私のボスと話したところでは、OSの内部をいじりたくないのであれば質問主さんのnanosleepがベストの解決だろう、という結論になりました。

その他の解決さくとしてはNo.3で書いたハードを直接見る方法(Linux流の行儀の悪いプログラム)や、ハードウェアFIFOにバッファリングをさせないためにはサイズを1バイトにしてしまう手があります。でもこれをすると山ほど割り込みが発生するのでダメかもしれません。とにかく全体のパフォーマンスは犠牲にしてもrs_writeがFIFOが空になるのを待つようなオプションをドライバ開発者に付けてもらうのがいいと思います。すでにトランスミッタが完全に送信したかどうかをチェックする関数がありますから、ちょっとの改造でできるはずです。きっと他の人の需要もあると思います。

ところで
>出終わってなければ再実行
これは
for (nwritten = 0;nwritten < n;nwritten += rv) {
rv = write (fd, buf+nwritten, n-nwritten);
if (rv < 0) break; // Error: bail out. //
}
こうしているということですよね?

今回の問題はドライバレベル以下で起こっているのだと思います。SIOには例えば16バイトのFIFOがあって、ドライバはハードに書き込んだら、すぐにカーネルに戻ってしまうのでしょう(FIFOの目的を考えれば当然ですね)。だからプロセスレベルでBLOCKINGであろうとなかろうと短時間ではバッファリングが起きているのだろう ... という理解になりました。質問主さんは最初からお気づきだったのでしょう。

ドライバのソースを読んだところでは、closeをするとハードウェアFIFOが空になるのをちゃんと待っています。...続きを読む

QLinuxでシリアル通信(RS232C)プログラム

Linuxでパソコンから他の機器へ文字列を送るプログラムを書きたいと思っています。
termios.h というヘッダーがあると言うことは検索して分かったのですが、それ以上に詳しいことがよく分かりません。
Linuxでシリアル通信をするC言語のプログラミングを扱っている書籍や詳しいサイトがあれば教えて頂きたく思います。

また、C言語のヘッダーは自分が勉強した本に載っているものは分かるのですが、それ以外のものはどうやって調べられているのでしょうか?
自分が求めている機能のライブラリがあるかどうかは、Googleとかで調べておられるのでしょうか?
termios.hというようなヘッダーについては、どうやって情報を集められているのでしょう?

よろしくお願い致します。

Aベストアンサー

これとか参考になるかと。
古くからあるドキュメントですが、基本的に変わってないので。
もしかすると、もっとお手軽に使えるフレームワークがQtやJavaあたりにありそうですが。

参考URL:http://www.linux.or.jp/JF/JFdocs/Serial-Programming-HOWTO.html

Qシリアル通信プログラム(受信)について

現在、シリアル通信をする(受信のみ)プログラムを作成しています。
接続先は1秒ごとに10バイトのデータを自動で送信してきます。
現段階でPC側でデータを受信できることは確認できました。
しかし、受信データが文字化け(出力結果が{や■などがでています)しており、その原因がわかりません。
どこが問題なのか教えていただけないでしょうか?

また、接続先からは10バイトのうち最初の2バイトは固定の値(0x2b,0x22)がでてくるはずなのですが、それもでてきていません。これも文字化けで見えていないだけでしょうか?
文字化けしても周期的に固定の値に対応した文字がでてくるものだと思ったのですが、でてきていません。
(ソースで50バイトまでみているのはこの周期性を確認するためです)

シリアル通信を初めてさわるので、考え方自体間違っているかもしれませんが
配列pszBufに1つずつ、受信された1バイトのデータが格納されていると思っています。
個人的にはprintfでの表記(%cがいけない?)に間違いがあるかと疑っています。

ご回答よろしくお願いいたします。

(環境)
Visual C++ 2008 (C/C++)

(シリアルポート設定)
ボーレート 9600bps
パリティ   なし
ストップビット 1
データビット 8

(ソース) ※ポートの設定は省略。受信部のみ記述
HANDLE hComm;
DWORD dwErrors;
COMSTAT ComStat;
char pszBuf[1024];
DWORD dwRead;

ClearCommError(hComm, &dwErrors, &ComStat);
ReadFile(hComm, pszBuf, 50, &dwRead, NULL);  //50バイトまでデータを取得

for(int i=0;i<50;i++){
printf("%c\n",pszBuf[i]);
}

(参考URL)
http://www.geocities.jp/terukat/_geo_contents_/win/comm.html

現在、シリアル通信をする(受信のみ)プログラムを作成しています。
接続先は1秒ごとに10バイトのデータを自動で送信してきます。
現段階でPC側でデータを受信できることは確認できました。
しかし、受信データが文字化け(出力結果が{や■などがでています)しており、その原因がわかりません。
どこが問題なのか教えていただけないでしょうか?

また、接続先からは10バイトのうち最初の2バイトは固定の値(0x2b,0x22)がでてくるはずなのですが、それもでてきていません。これも文字化けで見えていない...続きを読む

Aベストアンサー

>一応、ReadFileをおわったあとにdwReadを確認したのですが、50になっていました。

であれば、ReadFile()が失敗したとかはなさそうですね。
# ReadFile()の戻り値を確認していないのであればdwReadはReadFile()コール前にクリアしておいた方がいいかと思いますが。

>なんらかの失敗といわれるとどういった失敗がありえるのでしょうか?

タイムアウトがないのであれば…基本的には失敗はない…でしょうね。
コネクタ類が接触不良でデータが化けるとか、XON/XOFFフロー制御している…とかでなければ。

>(ボーレートの設定がおかしければデータがかわることはあるでしょうが・・・)

ボーレート以外の設定が異なっていた場合も化けると思われます。

>接続先がデータを送らなくとも、ReadFileがデータを格納することがあるのでしょうか?

受信バッファに残っていた場合は読み出す…でしょうね。

CreateFile()でシリアルポートを開く処理、シリアルポートの設定を行っている部分も掲示された方がいいかも知れません。
# が、私自身はAPI叩いてシリアルポート操作したことは無かったりします。

WindowsAPIのパターンとして…構造体は0x00でクリアして必要な部分だけ設定する。
という方法を採らないと妙な挙動することもありますので、その辺りは確認された方がいいでしょう。
APIに構造体のアドレスを渡して、情報を取得(上書きされる)から…ということで、未初期化の構造体渡したらエラーで何も設定してくれなかった。
なんて場合もあります。
# 構造体のメンバに「構造体のサイズ」を格納する場合、その構造体のサイズで対応バージョンを判別する。
# なんて挙動をしている場合もありますので。

>一応、ReadFileをおわったあとにdwReadを確認したのですが、50になっていました。

であれば、ReadFile()が失敗したとかはなさそうですね。
# ReadFile()の戻り値を確認していないのであればdwReadはReadFile()コール前にクリアしておいた方がいいかと思いますが。

>なんらかの失敗といわれるとどういった失敗がありえるのでしょうか?

タイムアウトがないのであれば…基本的には失敗はない…でしょうね。
コネクタ類が接触不良でデータが化けるとか、XON/XOFFフロー制御している…とかでなければ。

>(ボーレ...続きを読む

Qシリアル通信プログラミングでのバイナリデータ送信

UNIX系環境(IRIX)でのシリアル通信プログラムを作成していて、
バイナリデータの送信方法がわからず困っています。
write関数を使い、テキストデータの送信は出来ます。
write(fd,"テキスト",byte)のように。

ただ、今回はバイナリデータ送信を考えており、
例えば1byteのデータ00000001(01H)を送りたいと思っています。
このデータを送る場合、write関数で実現出来るのでしょうか?
write(fd,0x01,1)←イメージです。
色々ネットで調べても出てきません。

開発がWindows環境ではないので、API関数が使えない状況で困っています(MsComm等が使えない)。また、fwrite関数は使用してはいけないみたいです。教えてください。宜しくお願いします。

Aベストアンサー

> write(fd,0x01,1)←イメージです。

↑では駄目です。

write(fd,"\x01",1);

または

char data[] = { 0x01 };
write(fd, data, 1);

とする必要があります。

Qlinuxのシェル上でシリアル通信したい

linuxのシェル上でシリアル通信(RS232C)したいのですが
送信するのは、
echo "msg" /dev/tty0
で、できるのですが、
受信方法がわかりません。
知っておられる方、教えて下さい。

Aベストアンサー

cat /dev/modem

詳しくは「linux」「/dev/modem」などで検索してみてください。

Qapt-get install ****** でinstallしたものをuninstallするには?

御世話になります。
vncserverだけをinstallするつもりが
誤って
apt-get install vncとうってしまいました。
これをuninstallしたいのですが
どのようにすればよろしいでしょうか?

教えて下さい。

Aベストアンサー

# apt-get remove パッケージ名
では、設定ファイルは削除されずに残ります。

完全に削除するときは、
# apt-get --purge remove パッケージ名
です。

Qシリアル通信でのデータ受信

シリアル通信にてデータを連続的に受信するプログラムを
つくりたいと思っています.

以下のプログラムを作成して,
main関数のcountを増やして,繰り返しreadを行おうとすると,

出力結果として,
時,分,秒,ID,値B,値C,値Dというフォーマットで

0, 9,30, 1,514,708,542,290

0, 9,30, 2,515,707,542,288

0, 9,30, 3,514,709,542,287

0, 9,30, 4,514,707,543,289

0, 9,30, 5,514,708,542,289

0, 9,30, 6,514,708,542,292

0, 9,30, 7,514,708,542,291

0, 9,30, 8,514,708,542,289

0, 9,30, 9,514,708,543, 0, 9,39,35,514,708,542,289

(この後フが連続)
フフフフフフフフフフフフフフフ ク 0, 9,39,36,514,708,542,290

0, 9,39,37,515,709,541,291

0, 9,39,38,514,707,542,286

0, 9,39,39,514,708,542,281

0, 9,39,40,514,708,542,284

0, 9,39,41,514,707,542,286

0, 9,39,42,514,707,542,290

0, 9,39,43,514,709,542,290

0, 9,30, 9,514,708,543, 0, 9,39,35,514,708,542,289

フフフフフフフフフ・・・再びフ

となってしまいます.
問題としては

・フがたくさんでてきてしまう.
・1サイクルの最後で改行ができていない
・1サイクルが終わって次のサイクルに入る時までの
間にデータが失われている.
・2サイクル目になぜか1サイクル目の値が残っている?

などがあります.

どなたか解決方法を教えていただけると大変助かります.
よろしくお願いします.
-------------------------------
#include "stdafx.h"
#include <stdlib.h>
#include <windows.h>
#include <string.h>
#include <stdio.h>

#define COM_PORT_NAME"COM2"
#define BAUD_RATE57600
#define BYTE_SIZE5000 //250
#define PARITYNOPARITY //EVENPARITY
#define STOP_BITTRUE
#define F_PARITYONESTOPBIT

HANDLE hComm;// シリアルポートとの通信ハンドル

bool ComInit()
{
// シリアルポートを開ける
hComm = CreateFile(
COM_PORT_NAME,/* シリアルポートの文字列 */
GENERIC_READ | GENERIC_WRITE,
/* アクセスモード:読み書き */
0,/* 共有モード:他からはアクセス不可 */
NULL,/* セキュリティ属性:ハンドル継承せず */
OPEN_EXISTING,/* 作成フラグ: */
FILE_ATTRIBUTE_NORMAL,/* 属性: */
NULL/* テンプレートのハンドル: */
);

if (hComm == INVALID_HANDLE_VALUE) {
printf("シリアルポートを開くことが出来ませんでした。\n");
return false;
}

// 通信属性を設定する
DCB dcb;
GetCommState(hComm, &dcb); /* DCB を取得 */
dcb.BaudRate = BAUD_RATE;
dcb.ByteSize = BYTE_SIZE;
dcb.Parity = PARITY;
dcb.fParity = STOP_BIT;
dcb.StopBits = F_PARITY;
SetCommState(hComm, &dcb); /* DCB を設定 */

return true;
}

void ComEnd()
{
// ハンドルを閉じる
CloseHandle(hComm);
}


bool ReadData(char *buff, unsigned int max_size)
{
DWORD dwErrors; /* エラー情報 */
COMSTAT ComStat; /* デバイスの状態 */
DWORD dwCount; /* 受信データのバイト数 */
DWORD dwRead; /* ポートから読み出したバイト数 */

ClearCommError(hComm, &dwErrors, &ComStat);
dwCount = ComStat.cbInQue;

FILE *fid;
fid=fopen("test.txt", "w");

printf("%d %d\n", dwCount, max_size);
fprintf(fid,"%d %d\n", dwCount, max_size);

fclose(fid);
if (dwCount > max_size) {
printf("バッファサイズが足りません。\n");
return false;
}

if(hComm != NULL){
ReadFile(hComm, buff, dwCount, &dwRead, NULL);

if (dwCount != dwRead) {
printf("データの受け取りに失敗しました。\n");
return false;
}
}

return dwRead;
}

int main(int argc, char* argv[])
{

char buff[BYTE_SIZE];
int count = 0;
int data_length;
FILE *fid2;
fid2=fopen("test2.txt","w");

ComInit();

while(1){
if(count == 2) break;
count++;

data_length=ReadData(buff, strlen(buff));
printf("%s ",buff);
fprintf(fid2, "%s ",buff);


}
fclose(fid2);
ComEnd();

return 0;
}

シリアル通信にてデータを連続的に受信するプログラムを
つくりたいと思っています.

以下のプログラムを作成して,
main関数のcountを増やして,繰り返しreadを行おうとすると,

出力結果として,
時,分,秒,ID,値B,値C,値Dというフォーマットで

0, 9,30, 1,514,708,542,290

0, 9,30, 2,515,707,542,288

0, 9,30, 3,514,709,542,287

0, 9,30, 4,514,707,543,289

0, 9,30, 5,514,708,542,289

0, 9,30, 6,514,708,542,292

0, 9,30, 7,514,708,542,291

0, 9,30, 8,51...続きを読む

Aベストアンサー

先ほどの訂正と追加です。
3.dcb.Bytesizeを8にして、while文を無限ループにし
(countのif~break文を削除し), strlen(buff)のところを
BYTE_SIZEにしてみてください。データが取りこぼしなく
表示されませんか。
#通信が終わらないという問題は、受信ができない問題
とは別問題なので、今は考えていません
4.3.でデータの取りこぼしがあれば、送信側・受信側とも、
BaudRateを低く(9600bpsとか)してみて改善されるかどうか、
確認してください。

データの取りこぼしが通信速度によるものなら、フロー制御など
も考えないといけませんね。ところで、今頃聞くのもなんなんですが、
送信側・受信側は、どのような環境をお使いなんでしょう?

QC# シリアル通信でデータ受信時の欠損について

Visualstudio 2013 を使用して C# で開発を行っています。

SerialPort Classを使用してデータの送受信をするプログラムを作成しているのですが、
非同期でデータを受信する際にどうしてもうまくデータを取得出来ません。

5Byteのデータは正常に取得できるのですが、
その直後にくる40Byteのデータは、真ん中あたりの10数Byteや最後の10数Byteしか取れません。


serialPort.DataReceived に登録したイベント関数の中身です。

--------------------------------------------------------------------------------------
private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
bytesRead = 0;
// Initialize a buffer to hold the received data
byte[] buffer = new byte[this.serialPort.ReadBufferSize];

try
{
bytesRead = this.serialPort.Read(buffer, 0, buffer.Length);
if (true == serialPort.IsOpen)
{
serialPort.DiscardInBuffer();//受信バッファをクリアする
}

}
catch (Exception ex)
{
DataLog.Exception(ex);
}

//派生クラス用の処理
DeviceClassEventArgs _DeviceClassEventArgs = new DeviceClassEventArgs(buffer, bytesRead);
DeviceClassEvent(this, _DeviceClassEventArgs);
}
--------------------------------------------------------------------------------------

ネットの情報を参考に、
ReceivedBytesThreshold の値を期待するデータ量に逐一変えることで
とりあえず正常に取ることが出来たのですが、これでいいのでしょうか?
期待するデータ量がわからなかった場合は使えないのかなとも思います。

データが欠損してしまう理由、
上記の対処法以外の一般的な対処法など有りましたら教えて下さい。

その他参考になるページ等ありましたら教えていただけると大変助かります。

Visualstudio 2013 を使用して C# で開発を行っています。

SerialPort Classを使用してデータの送受信をするプログラムを作成しているのですが、
非同期でデータを受信する際にどうしてもうまくデータを取得出来ません。

5Byteのデータは正常に取得できるのですが、
その直後にくる40Byteのデータは、真ん中あたりの10数Byteや最後の10数Byteしか取れません。


serialPort.DataReceived に登録したイベント関数の中身です。

-------------------------------------------------------------------------------...続きを読む

Aベストアンサー

DataReceivedイベントが発生したときでも、
シリアルポートへの受信はまだ継続している可能性があるので
不用意にバッファクリアしてはいけない。
非同期の受信処理は、何かと難しいのです。

private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
  bytesRead = 0;
  // Initialize a buffer to hold the received data
  byte[] buffer = new byte[this.serialPort.ReadBufferSize];

  try
  {
    //bytesRead = this.serialPort.Read(buffer, 0, buffer.Length);
    //if (true == serialPort.IsOpen)
    //{
    // serialPort.DiscardInBuffer();//受信バッファをクリアする
    //}

    // 受信バッファにデータがなくなるまで繰り返し読込む
    while (true)
    {
      if (0 == serialPort.BytesToRead)
      {
        break;
      }
      buffer[bytesRead] = (byte)serialPort.ReadByte();
      bytesRead++;
      System.Threading.Thread.Sleep(0);

      // シリアルポートの受信バッファには、
      // ・必要なブロックの途中から受信している。
      // ・次のブロックの先頭部分も受信されている。
      // 可能性があるので、ここで必要なブロックだけRead()できたことを確認する。
      if (必要なブロックが正常に読めたか確認する関数())
      {
        break;
      }
    }
  }
  catch (Exception ex)
  {
    DataLog.Exception(ex);
  }

  //派生クラス用の処理
  DeviceClassEventArgs _DeviceClassEventArgs = new DeviceClassEventArgs(buffer, bytesRead);
  DeviceClassEvent(this, _DeviceClassEventArgs);
}

DataReceivedイベントが発生したときでも、
シリアルポートへの受信はまだ継続している可能性があるので
不用意にバッファクリアしてはいけない。
非同期の受信処理は、何かと難しいのです。

private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
  bytesRead = 0;
  // Initialize a buffer to hold the received data
  byte[] buffer = new byte[this.serialPort.ReadBufferSize];

  try
  {
    //bytesRead = this.serialPort.Read(buffer, 0, buffer.Le...続きを読む

Qint型からchar型への変換

タイトル通り、int型からchar型への変換の仕方がわかりません!><
どうしたらいいのでしょうか?

Aベストアンサー

#include <stdio.h>


char buf[5];
int no;

no = 10;
sprintf(buf, "%d", no);


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報