私のtermios設定は、read()を使用してシリアルポートから読み取った最初の文字を変更しています。私は、Linuxのボックスに話しているマイクロコントローラがあります。マイクロコントローラは、Linuxマシンから送信されたコマンドに応答します。次のようにセットアップは次のとおりです。シリアルポート読み込み後に最初の文字を変更するLinux termios
- マイクロコントローラ(PIC24F)RS485ポート< - > UbuntuのPC - USBコンバータ<へ> RS485。
私がCutecomなどの端末プログラムを実行すると、すべてが計画どおりに動作します。私はPICにコマンドキャラクターを送りますが、私はコマンドラインプログラムを使うと最初のキャラクターが修正されていますが、応答があります。ここに私のコードです:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#define DEVICE "/dev/ttyUSB0"
#define SPEED B38400
int main()
{
struct termios tio; //to hold serial port settings
struct termios stdio; //so we can accept user input
struct termios old_stdio; //save the current port settings
int tty_fd; //file descriptor for serial port
int res, n, res2, read1, wri;
char buf[255];
char buf2[255];
//save the current port settings
tcgetattr(STDOUT_FILENO,&old_stdio);
//setup serial port settings
bzero(&tio, sizeof(tio));
tio.c_iflag = 0;
tio.c_iflag = IGNPAR | IGNBRK | IXOFF;
tio.c_oflag = 0;
tio.c_cflag = CS8 | CREAD | CLOCAL; //8n1 see termios.h
tio.c_lflag = ICANON;
//open the serial port
tty_fd=open(DEVICE, O_RDWR | O_NOCTTY);
//set the serial port speed to SPEED
cfsetospeed(&tio,SPEED);
//apply to the serial port the settings made above
tcsetattr(tty_fd,TCSANOW,&tio);
for(n = 5; n > 0; n--)
{
printf("Please enter a command: ");
(void)fgets(buf2, 255, stdin);
(void)write(tty_fd, buf2, strlen(buf2));
printf("Ok. Waiting for reply.");
res = read(tty_fd, buf, 255);
printf("Read:%d START%d %d %d %d %dFINISH\n",res,buf[0],buf[1],buf[2],buf[3],
buf[4]);
}
//close the serial port
close(tty_fd);
//restore the original port settings
tcsetattr(STDOUT_FILENO,TCSANOW,&old_stdio);
return EXIT_SUCCESS;
}
ここに私が得ている結果の例です。
- PICは "00000 \をn" は送信出力は次のとおりです。PICは "23456 \をn" は送信出力されると6 START-16 48 48 48 48FINISH
- :読む:6 [スタート] - 読みます51 52 53 54FINISH
- PICは送信14 "34567 \ n" は出力され:読む6 START-14 52 53 54 55FINISH
- PIC "は45678は、n \" が出力される送信:読む:6 START-12 53 54 55 56FINISH
- PICが「56789 \ n」を送信すると、出力は次のようになります。読み取り:6 START-12 54 55 56 57FINISH
何らかの理由で、最初の文字がいくつかのtermios設定によって混乱しています。 Cutexを実行すると、上記のテスト入力が正確に返されるので、termios設定でなければなりません。マニュアルページを何度も読んで、入力コントロールのすべての設定を試してみましたが、私が何をしてもこの問題を揺さぶってはいけません。
簡単な修正のために、データを1文字にシフトすることはできますが、これを避けたいと考えています。
誰もこのような問題を経験したことがありますか、それについて何か考えていますか?
多くのありがとうございます。
28/3/13 オースティン。
まず私のプログラム
スピード38400ボーでのtermios設定がされています。:ここに興味がある人のために2つの出力があります行0;列0;ライン= 0; intr =;終了する。消去=;殺す=; eof =; eol =; eol2 =; swtch =;開始=;ストップ=; susp =; rprnt =; werase =; lnext =; flush =; min = 0;時間= 0; -parenb -parodd CS8 -hupcl -cstopb CREAD CLOCAL -crtscts IGNBRK -brkint IGNPAR -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon IXOFF -iuclc -ixany -imaxbel -iutf8 -opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel NL0 CR0 TAB0のBS0 VT0 FF0 -isig ICANON -iexten -echo -echoe -echok -echonl -noflsh -Xcase -tostop -echoprt -echoctl -echoke
そして、 cutecomが使用する設定
速度38400ボー;行0;列0;ライン= 0; intr =^C; quit =^\;消去= ^?;殺す=^U; eof =^D; eol =; eol2 =; swtch =; start =^Q;ストップ=^S; susp =^Z; rprnt =^R; werase =^W; lnext =^V; flush =^O; min = 60;時間= 1; -parenb -parodd CS8 HUPCL -cstopb CREAD CLOCAL -crtscts IGNBRK -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 -opost -olcuc - ocrnl -onlcr -onocr -onlret -ofill -ofdel NL0 CR0 TAB0のBS0 VT0 FF0 -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -Xcase -tostop -echoprt -echoctl -echoke
私はまだすべてを進めており、進歩すると投稿を更新します。
29/3/13 まだ同じ問題があります。私はCutecomのソースコードを見つけて、彼らが使用するtermios設定に従っていました。それでも問題は存在します。その最初の文字が壊れている!!!!
私のプログラムのTermios設定は以下の通りです。何らかの理由でフラッシュすることができません。
速度38400ボー;行0;列0;ライン= 0; intr = ^?; quit =^\;消去=^H;殺す=^U; eof =^D; eol =; eol2 =; swtch =; start =^Q;ストップ=^S; susp =^Z; rprnt =^R; werase =^W; lnext =^V;フラッシュ=; min = 60;時間= 1; -parenb -parodd CS8 HUPCL -cstopb CREAD CLOCAL -crtscts IGNBRK -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 -opost -olcuc - ocrnl -onlcr -onocr -onlret -ofill -ofdel NL0 CR0 TAB0のBS0 VT0 FF0 -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -Xcase -tostop -echoprt -echoctl -echoke
そして、私の新しいコード:
#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <termios.h> #include <sys/ioctl.h> #define DEVICE "/dev/ttyUSB0" #define SPEED B38400 int main() { struct termios tio; //to hold serial port settings struct termios stdio; //so we can accept user input struct termios old_stdio; //save the current port settings int tty_fd; //file descriptor for serial port int retval, res, n, res2, read1, wri; char buf[255]; char buf2[255]; tty_fd = open(DEVICE, O_RDWR | O_NDELAY); if(tty_fd < 0) { perror(DEVICE); exit(-1); } printf("Init 1 complete.\n"); tcflush(tty_fd, TCIOFLUSH); int f = fcntl(tty_fd, F_GETFL, 0); fcntl(tty_fd, F_SETFL, f & ~O_NDELAY); retval = tcgetattr(tty_fd, &old_stdio); if(retval != 0) { perror(DEVICE); exit(-1); } printf("Init 2 complete.\n"); struct termios newtio; retval = tcgetattr(tty_fd, &newtio); if(retval != 0) { perror(DEVICE); exit(-1); } printf("Init 3 complete.\n"); cfsetospeed(&newtio, SPEED); cfsetispeed(&newtio, SPEED); newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS8; newtio.c_cflag |= CLOCAL | CREAD; newtio.c_cflag &= ~(PARENB | PARODD); newtio.c_cflag &= ~CRTSCTS; newtio.c_cflag &= ~CSTOPB; newtio.c_iflag = IGNBRK; newtio.c_iflag &= ~(IXON | IXOFF | IXANY); newtio.c_lflag = 0; newtio.c_oflag = 0; newtio.c_cc[VTIME] = 1; newtio.c_cc[VMIN] = 60; newtio.c_cc[VINTR] = 127; newtio.c_cc[VQUIT] = 28; newtio.c_cc[VERASE] = 8; newtio.c_cc[VKILL] = 21; newtio.c_cc[VEOF] = 4; newtio.c_cc[VSTOP] = 19; newtio.c_cc[VSTART] = 17; newtio.c_cc[VSUSP] = 26; newtio.c_cc[VREPRINT] = 18; newtio.c_cc[VFLSH] = 15; newtio.c_cc[VWERASE] = 23; newtio.c_cc[VLNEXT] = 22; retval = tcsetattr(tty_fd, TCSANOW, &newtio); if(retval != 0) { perror(DEVICE); exit(-1); } printf("Init 4 complete.\n"); int mcs = 0; ioctl(tty_fd, TIOCMGET, &mcs); mcs |= TIOCM_RTS; ioctl(tty_fd, TIOCMSET, &mcs); retval = tcgetattr(tty_fd, &newtio); if(retval != 0) { perror(DEVICE); exit(-1); } printf("Init 5 complete.\n"); newtio.c_cflag &= ~CRTSCTS; retval = tcsetattr(tty_fd, TCSANOW, &newtio); if(retval != 0) { perror(DEVICE); exit(-1); } printf("Init 6 complete.\n"); for(n = 5; n > 0; n--) { printf("Please enter a command: "); (void)fgets(buf2, 255, stdin); (void)write(tty_fd, buf2, strlen(buf2)); printf("Ok. Waiting for reply\n"); res = read(tty_fd, buf, 255); printf("Read:%d START%d %d %d %d %dFINISH\n",res,buf[0],buf[1],buf[2], buf[3], buf[4]); } //restore the original port settings tcsetattr(tty_fd, TCSANOW, &old_stdio); close(tty_fd); return EXIT_SUCCESS; //return all good }
I私は何ができるのか、どこから取り除かなければならないのか全く分かりません。
読み込みで6が読み込まれたと表示されたときに最初の5バイトだけを報告する理由はありますか? RS-482とUSBの組み合わせを介して送信されるものを監視して、マイクロコントローラが実際にあなたが期待するバイトを送信しているかどうか、または情報が変更されているかどうかを調べる手段がありますか?私はRS-482で作業していませんでした(ただし、私はRS-232を覚えています)。しかし、制御文字やメッセージフレーミングがありますか?読んだ最初のバイトが 'expected&0xEE'によって修正されたようです... –
こんにちはジョナサン、私は6番目のバイトを報告していない理由は、\ nです。 termiosに標準モードを使用しているので、読み込みは\ nになると戻ります。同じLinuxマシンで動作しているCutecomを使用してセットアップを正常に実行できなかった場合、私はtermiosの反対側を見ています。私は仮定が危険であることを知っていますが、この状況では私のPIC、485-to-USBコンバータはCutecom内部で動作するので正常に動作していると考えることは安全だと思います。あなたはどこから来ているのかわからないので、 "expected&0xEE"について詳しく説明してください。よろしく。 –
私が一貫して実行した他のテストでは、最初の文字から64が減算されていました。 read()がbuf [0]に格納される結果に64を追加すると、正しいASCII値が得られます。これに関する混乱していたことは、正しい値のASCII値が6番目のビットが設定されていないことでした。だから、どこかで&0x1011111が実行されたと思っても、そのアイデアはサポートされませんでした。私は値についていくつかの操作を試みましたが、どんな種類のパターンも識別できませんでした。 –