PICシリアル通信での入出力送信方法

このQ&Aのポイント
  • PIC16F877Aを2台使用し、シリアル通信で相互間に入力12点を出力12点に送信する方法について教えてください。
  • 現在1点の入力を1点の出力に送ることはできているが、12点の入力をまとめて送信し、展開して出力する方法がわかりません。
  • 入力はRA,RE,RC,RDを使用し、出力はRB,RC,RDを使用します。2進数でまとめて送信する方法があれば教えてください。
回答を見る
  • ベストアンサー

PICシリアル通信での入出力送信方法

現在PIC勉強中の初心者です。 教えて頂きたいのですが、 現在PIC16F877Aを2台使用して相互間をシリアル通信で結び、 一台のPICからの入力12点を二台目のPICの出力12点に出力するプログラムを作成中です。 現在は通信で1点の入力をうけ1点の出力にだすところまでは何とかできました。 そこで調べても合理的で良いやりかたが見つからなかったのでよく御存じの方に教えて頂きたいのですが、 12点の入力をどのようなやり方でまとめ、シリアル通信で送り、どのようなやり方で展開し12点の出力を出すのか良いやり方がありましたら教えて下さい。 (入力はRA,RE,RC,RDを使い、出力はRB,RC,RDを使用してます) (自分としては2進数でまとめて2つ送ったらわかりやすいのではないかと思っているのですが..)

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

PICも含めて、いかなる組込みマイコンでシリアル通信を行う場合でも、その内蔵のシリアル通信機能を使えば、比較的簡単に「送信」する事は誰でも可能です。 問題は、シリアルデーターの2バイト以上の受信です。 (1)その内蔵のシリアル通信機能で、いつ来るか判らない「受信データー」を絶えず環視している必要が有る。->つまり割込処理とするか、あるいは絶えず受信のプログラムを優先的に動かしている必要があるという事です。 (2)内蔵機能であろうが、プログラムでのシリアル受信であろうが、1バイト以上連続して何バイトもデーターが送られて来る様な場合には、その間髪入れずに送られてくるバイトデーターを、取りこぼす事無く、次々と記憶する領域(バッファー)が必要となります。 PICの内蔵シリアル受信機能には、バイトバッファを2個持っています。つまり、2個までは連続したバイトデーターを取りこぼしする事無く自動で受信できますが、それ以上連続したバイトを受信すると、取りこぼしを起こすという事です。 今回は、2バイトで済むので、特に問題なく受信が可能と思いますが、あまりにも、通信のノイズに対する防御が無くて、今後のためにも、そのままの受信はお薦めできません。 詳しくは、下記サイトにPICでのシリアル通信で、割込型ソフトウエアFIFOバッファについて、やさしく詳しく教えています。 ご参照ください。これを知らないと、2バイト以上の受信が全てのマイコンで出来ません。 「パレットソフト」 http://www.palettesoft.co.jp/index.htm HOME > 技術談話 > PIC microcontroller > シリアル通信 頑張って下さいね。

seventozero
質問者

お礼

回答頂きありがとうございます。 読ませて頂き、いろいろ調べて理解できました。 今後のためにもソフトでバッファをもたせ1バイト以上の通信をするプログラムを作ろうと思います。 丁寧な説明を頂きありがとうございました。

その他の回答 (1)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

結局のところ 12個のデータを送受信するしかないわけだから, ある意味どうにもならないとはいえる. 「送信側では 12個のデータをシリアライズして何らかの方法で送り, 受信側で受け取ったデータをデシリアライズする」しかないよね. そもそも, データの流れは 何らかのデバイスからのデータを 1台目の PIC が受け取り, それを 2台目の PIC に送る でいい? もしそうだとすると, 「入力はRA,RE,RC,RDを使い、出力はRB,RC,RDを使用してます」 の「入力」とか「出力」ってなに? 「出力」が「1台目の PIC が 2台目の PIC にデータを送るための信号線」, 「入力」が「2台目の PIC が 1台目の PIC からデータを受け取るための信号線」の意味だとしたら, この 2つの本数が異なるのは明らかに異常でしょ? あと「2進数でまとめて2つ送る」は何をしているのかさっぱり分からん.

seventozero
質問者

お礼

ありがとうございました。

seventozero
質問者

補足

失礼しました、正確には 「ボタン入力はPIC1の12点を使い、LED出力はPIC2の12点を使用してます」ということです。 ↑ 質問の説明が悪すぎましたすいません。 あと「2進数でまとめて2つ送る」なんですが、例えば ボタン入力12点をPIC1でまとめて data1=0b00000001;data2=0b00000000; という形でPIC2におくれるかな みたいになるかなと思ったのですが、素人考えなのですいません。 至らない質問でご迷惑おかけしますが、宜しくお願いします。

関連するQ&A

  • PIC同士のシリアル通信について

    PIC初心者なのですが 現在↓サイトでPIC-PIC間のシリアル通信を勉強中です。 http://kuri6005.sakura.ne.jp/pic/index.php?PIC-PIC%A4%CE%C4%CC%BF%AE(USART) その中で通信設定の   Usart_Init(2400); //通信速度を2400 band rateに設定   do {     if(PORTA.F0 == 1) {       Usart_Write('A'); //RA0=1なら'A'を送信     } else {       Usart_Write(0); //RA0=0なら 0 を送信     } の部分でコンパイルエラーがでます。 たぶんヘッダーファイルのようなものが必要で指定されてないからエラーが出るのだとは思いますが、 どこからとってきて?またはどこにあるものなのかがわかりません。 わかる方教えて下さい。 ※テストで使っているPICの種類が違ってPIC16F877Aです

  • PIC間通信

    http://kuri6005.sakura.ne.jp/pic/pukiwiki.php?PIC-PIC%A4%CE%C4%CC%BF%AE%28USART%29 現在上記のサイトを利用してPICの勉強中です。 上記サイトでは、'A'という文字を転送していますが、数字や'AA'など複数文字ではうまく動作しません。 なにか良い方法があるのでしょうか? 下記 Usart_Write(1); の1の部分を'A'にするとうまく動作します。 (もちろん、送信・受信両方のPICは書き換えています。) できれば、変数にして受信側に送りたいのですが、可能でしょうか? よきアドバイスをお願い致します。 void main() { Kmode=0; PORTA=0b00000000; //PORTAの中身をきれいにする PORTB=0b00000000; //PORTBの中身をきれいにする CMCON=0b00000111; //PORTAをデジタル入出力使用に設定 TRISA=0b00000001; //RA0を1:入力に、他を0:出力に設定 TRISB=0b00000010; //PORTB RB1:入力、他7ヶは出力設定 Usart_Init(2400); //通信速度を2400 band rateに設定 do { if(Button(&PORTA, 0, 1, 0)) { //スイッチONの場合 Usart_Write(1); }else{ Usart_Write(0) } while(1); }

  • 離れたPIC同士のシリアル通信の回路でのPICの…

    離れたPIC同士のシリアル通信の回路でのPICの破損について 5m離れた2つのPIC間でシリアル通信(9600bps)をする回路を作りました。 単にそれぞれのPICの内蔵モジュールのTXとRXをたすきがけしただけの回路です。 また、メインの電源は12Vで、それぞれのPICの近くにそれぞれ専用の7805を配置してPICに5Vを供給しています。 また、2つのPIC間のケーブルはコネクターで取り外せるようになっており、同ケーブルにはシリアル通信(送信、受信)、+12V、GNDの計4本の線で構成されています。 この状態で特に問題無く通信はできているのですが、ふとしたことでPICの内蔵モジュールが破損することがあります。 同じ回路を2セット作りましたが、同様に破損してしまいました。 多分、コネクタを抜き差しするか、或は電源を投入、切断のタイミングではないかと予測しています。 (詳しくは、参考URLの図をご覧ください。  図には電源のコンデンサなどは記載していませんが、それぞれ適宜、配置してあります。) 尚、2つのPIC付近の7805には、PIC以外にそれぞれ違う消費電流の負荷が接続されています。 そのため、5Vに安定するまでの時間に違いが出てしまい、結果、内蔵モジュールの規格外の電圧がかかってしまうのかと予測しています。 ここで質問です。 ・このような状況の場合、PICが破損する原因はどのようなことが考えられるでしょうか? ・解決策はどうしたら宜しいでしょうか? まだ試していませんが、MIDIのようにフォトカプラを使用するか、RS-232Cトランシーバを使用するか等を考えておりますが、なるべく簡易で確実な方法をとりたいです。 宜しくお願いいたします。 http://box.c.yimg.jp/res/box-s-vboqi4x6dy2zfrx7fyns5aqghq-1001?uid=5c9c0a84-d898-45e4-8d4b-df319ca25f24&etag=5c2f1b99137520886935391

  • PICのシリアル通信について

    現在PICで電子工作を勉強中です。 PIC16f628Aを使ってパソコンとのシリアル通信をしようと思っています。 しかし、PICから"Hit some key for test"という文字列をおくったところ、 文字化けして"ソ3!・ソ)5"といった感じで出力されてしまいました。 文字化けが起きる原因としては何が考えられるのでしょうか? なお、パソコン側の端末にはTera Termを使用しています。 どなたかご教授お願いします。 以下にソースコードを示します。 #include <pic.h> __CONFIG(MCLRDIS & PWRTEN & BORDIS & UNPROTECT & WDTDIS & LVPDIS & HS); __IDLOC(628A); unsigned char getchr(void) { while(RCIF == 0); return (RCREG); } void putchr(unsigned char c) { while(TXIF == 0); TXREG = c; } void puts(const unsigned char *s) { while(*s) putchr(*s++); } void main(void) { PORTB = 0; TRISB = 0b00000010; SPBRG = 129; TXSTA = 0b00100100; RCSTA = 0b10010000; puts("Hit some key for test\n"); puts("\n"); while(1) putchr(getchr()); }

  • シリアル通信の通信・検証方法とは?

    Visual C++ 6.0(MFC)でプログラミングを行っています. VB 6.0でPCから値を入力し,PICへRS232Cケーブルを用いて値を送り,モータコントロールするプログラムは既に存在しており,現在はVBで書かれていた部分(インターフェイス部)をVC++に書き換えようとしています. サンプルプログラムを参考にシリアル通信に関するVC++のプログラムは完成し,PCからモータの制御を行おうと思ったのですが,うまくいきません. こういった際,どこに問題があるのかを検証したいのですがどうすればいいでしょうか? 現状, 1,シリアル通信ができていない 2,シリアル通信はできているが,PICへ値がうまく格納されていない 3,それ以外 問題があるのは分かるのですが,プログラマーのほうに原因がフィードバックされないため困っています. 明確な答えでなくても,アドバイスのようなものがいただけたら幸いです.

  • PICによるLED制御について

    大学の講義でPICのLED制御の課題がよくわかりません。 どなたか教えていただけないでしょうか? [問]  PIC16F84Aにおいて、動作を実現するプログラムを示せ。  メインルーチンでLED出力の点燈箇所を1秒ごとに巡回させる。   RA3=Low(OFF)のとき、左向きに巡回シフト(RLF命令)させる。   RA3=High(ON)のとき、右向きに巡回シフト(RRF命令)させる。  また割り込みルーチンによって、RA0~RA2の3ビットの値に応じて  点灯速度を変化させる(値が大きいほど速く)  ただし、ポートAは全て入力モード、ポートBはRB0以外を出力モードとし(RB0は割り込み用)、ポートBの初期出力を0000100*(LED出力の初期点燈位置は第3ビットのみ)とせよ。

  • PICでシリアル通信

    温度センサーLM35DZからの情報をPIC、ADM232,を経てシリアル通信でパソコンに表示するというのがあって、本で読んだとうりに、組んでみましたらうまくいきました。これは外付けオシレータ10MHzで動いています。 今度はこれを内蔵オシレータ4MHzで動かしたいんですが、その場合、どのような設定にしたらいいんでしょうか。 現在は OSC 10MHz 9600bps 非同期 高速モード SPBRG  D’64’ TXSTA  B’00100100’ で動いてます。 とりあえずは、SPBRGの数をかえてためしてみたんですが、一応情報は送っているみたいなんですが、文字化けしてうまくいきませんでした。

  • PICの出力できる電圧について

    PIC(16F88)のキャプチャモジュールを使い、対象物の周波数を得て、それをLCDに表示する工作をしています。SIMやstimulusでプログラムにはとくに問題がないことを確認しました。 つぎに、別なPIC(16F84A)で100Hzの実験用信号を先の16F88のCCP1(RB3)に入れて、16F88のプログラムの確認をしようと思ったのですが、うまくいきません。LCDには、ただ0Hzとだけ表示されます。なお、ここでもSIM等を使って、プログラム上での100Hzの出力は確認しました。 16F84Aからは、RB0とRB1から100Hzの出力をし、RB0を16F88のCCP1に直接入力し、RB1にはLEDにて出力の視覚での確認をしようとしています。 ここで使用する両PICには、それぞれ別々にTA4805Sで5Vをかけ、アースは共通にしました。 手持ちのアナログ電圧計で、16F84AのRB0とRB1の出力電圧を測ってみると、RB0はほとんど0Vであり、RB1はおおよそ4.5Vあり、LEDはちゃんと光ります。また、RB1のLEDをそのままに、RB0を開放すると、RB0は4.5Vありました。16F88側のCCP1(RB3)は入力に設定してあります。 PICの出力する電圧は、5Vくらいだとおもっていたのですが、どうしてこのようなことになるのでしょうか?どうすれば、CCP1に100Hzの実験用信号を送れるようにできるのでしょうか?電気にはまったく疎いので現在勉強中なのですが、どなたかよろしくおねがいいたします。

  • PICの割り込み機能

    現在電子工作をしており、それにPIC16F84Aを使っています。 正直アセンブリはよくわからないので、C言語でプログラムを作っています。 コンパイラはPICCLITEで、LEDの点灯・消灯に関するプログラムです。 機能としては ・RA0に入力があったときRB0につないであるLEDが消灯しているならLEDを点灯。 ・RA0に入力があったときRB0につないであるLEDが点灯しているならLEDを消灯。 ・RA1に入力があったときLEDが点灯しているなら5秒後にLEDを消灯。 というものを目指しています。 1つ目、2つ目の項目はif文で簡単に実現できましたが、割り込みがうまくいかず、 消えている状態でRA1に入力を入れたときなぜか5秒後に点灯してしまいます。 だからRB0の出力を逆にしてみたんですがうまくいかず・・・。 ハード的には、RB0には反対側から5Vをかけ、 RB0=0の時は点灯 RB0=1の時は消灯 としています。 またセラロックは10MHzのものを使用しています。 現在のプログラムとしては #include "pic.h" #define XTAL_FREQ 10MHZ #define MHZ*1000 void DelayUs(unsigned char cnt){ //時間待ち関数  unsigned char i;  i=(cnt)/(12MHZ/(XTAL_FREQ))|1;  while(--i!=0) continue; } void DelayMs(unsigned int cnt){ //時間待ち関数  unsigned char i;  do{   i=4;   do{    DelayUs(250);   }while(--i);  }while(--cnt); } int cnt,SW; //SWが0なら消灯 //SWが1なら点灯 void interrupt isr(void){ //割り込み関数  if(T0IF==1){   T0IF=0;   cnt--;  }  if(cnt==0){   RB0=1; //消灯   SW=0;   cnt=190;   T0IE=0;   GIE=0;  } } main() {  TRISA=0xFF; //入出力設定  TRISB=0x00;  PORTA=0x00;  PORTB=0x00;  SW=0;  OPTION=0x87; //プリスケーラの設定  TMR0=0x00;  T0IF=0;  T0IE=1;  cnt=190;  while(1){   if(RA0==1){    DelayMs(60); //チャタリング防止    if(RA0==1){     if(SW==0){      RB0=0;      SW=1;     }    else{     RB0=1;     SW=0;    }   }  }  if(RA1==1){   DelayMs(60); //チャタリング防止    if(RA1==1 && SW==1){     TMR0=0;     T0IF=0;     T0IE=1; //割り込み許可     GIE=1; //全体割り込み許可    }   }  } } インターネット上での割り込みのプログラムをいくつか見てみたのですが、 どれもすべて動作を終えて、あとはwhile(1)で割り込みを待つだけ というプログラムばかりでした。 僕のは基本的にRA0の入力によってLEDを点灯・消灯させつつ RA1の入力で割り込みを開始。 5秒後に消えたら割り込みを禁止する。 という仕様にしたいのですが・・・・・・。 1ヶ月ぐらいやってますがうまくいきません。 良ければご回答をお願いします。

  • PIC16F1827のEEPROMへの書込み

    PCM V5.0(PIC用CCS社コンパイラ)を Mplab8.92に組込み、PICkit3を使ってプログラムしています。 PIC16F1827のEEPROMへの書込みがうまくいきません。 RAは入力ポートで固定してあります。 RBは出力ポートでLEDが接続してあります。 テストプログラムは一回のみの動作です。 実機で動作させると RAは固定してあるので当然(4)でLEDが点灯しますが、 実機からCPUを抜き取りMplab上でReadすると EEPROMのアドレス0,1,2は異なるデータであり 動作させるたびに違うデータが書込まれています。 しかし (1) a0=35h (2) a1=a6h (3) a2=93h と定数にすると EEPROMのアドレス0,1,2は正しいデータが 書込まれています。 Q1. a0,a1,a2をポート入力とする場合は CPU自体に何か設定する必要があるのでしょうか? それともプログラムに工夫が必要なのでしょうか? いままで使っていたPIC16F88では このようなことはなかったと思うのですが・・・。 ----- テストプログラム ----- a0 = RA; //(1) write_eeprom (0,a0); a1 = RA; //(2) write_eeprom (1,a1); a2 = RA; //(3) write_eeprom (2,a2); if (a0 == a1 && a1==a2) //(4) RB =255; else RB =0;