PIC・eepromとPIN設定について

このQ&Aのポイント
  • PICのプログラムについてとPIN設定についての質問です。
  • シリアル通信のプログラムで、eepromに書き込んだ後に書き込みの確認をする方法を知りたいです。
  • また、PICのPIN設定でRA3~5の設定方法が分からないです。外付けの振動子とリセットICがついているので、どうSETすればいいのか教えて欲しいです。
回答を見る
  • ベストアンサー

PIC・eepromとPIN設定について

目をとめて頂き、ありがとうございます。 さっそくですが、PICのプログラムについてとPIN設定について解らないところがありましたので、質問させていただきます。 1)シリアル通信のプログラムです。 eeprom内蔵のPICを使っているのですが、eepromに書き込んだ後に(画面に)「無事に書きこみましたよ」的な表示をさせたいのですが、ちゃんと書き込まれたかどうかがわからなくて… アセンブリでやると、レジスタのフラグ(?)をみて判断しているっぽいのですが、生憎とアセンブリはさっぱり分かりません。 c言語でもわかる方法はないものでしょうか? 2)PIN設定です。 RA5(OSC1)-->外付けで振動子つけてます RA4(OSC2)-->RA5と同じです RA3(MCLR/VPP)-->リセットICつけてます RA2(I/O)-->input設定 RA1(I/O)-->input設定 RA0(I/O)-->output設定 という設定のPICで、RA0~2は普通にI/OとしてSET_TRISできるのですが、RA3~5をどうSETしたらいいのかが分かりません。 普通のI/Oとしては使わないけど、外付けで振動子とICがついているので普通にI/OでSETしていいのか… 以上2点ですが、わかる方がいらっしゃいましたらよろしくお願いします。

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

  • ベストアンサー
  • rnakamra
  • ベストアンサー率59% (761/1282)
回答No.3

#2のものです。 eepromへの書込みを同時に行うことは出来なかったと思います。 CCS-Cで3回書込みを行うと(割り込み無の場合) 1回書込み→終了までwait→1回書込み→終了までwait→1回書込み→終了までwait と振舞います。書込み終了までかなり長い時間がかかりますがその間書込みの終了まで何もしません。(終了チェックのループを延々と繰り返す) これはADCを使用する場合でも同様で、はっきり言って時間の無駄です。 割り込みを使わず、EEPROMへの書込みと他の作業を同時に進めたい場合はインラインアセンブラを使用するぐらいしか方法がありません。 そのため、時間の無駄を省くには割り込みを使い処理することになりますが、この場合でも同時に複数のアドレスへの書込みは出来ないので、割り込み時の処理で対処することになります。 今回の場合、先ず書き込み先のアドレスをグローバル変数に記録し、割り込みを有効にしてから書込みを行います。 address_eeprom=0; enable_interrupts(INT_EEPROM); enable_interrupts(global); write_eeprom(address_eeprom,val[address_eeprom]); 割り込み処理で #int_eeprom void int_ee(void) { switch(address_eeprom) { 0: 1:address_eeprom++; write_eeprom(address_eeprom,val[address_eeprom]); break; 2:disable_interrupts(int_eeprom); (この後は書込みの確認と表示のプログラム) } } とでもすればよいでしょう。

B_Alice_s
質問者

お礼

再度ありがとうございます。 回答を見る前に、色々変更がありまして、今のところ関数として int Write_ee(char c1,char c2,long i){ if(c1=='A'&&c2=='I'){ WRITE_EEPROM(0,i>>8&0xFF); //上位8ビット書き込み WRITE_EEPROM(1,i&0xFF); //下位8ビット書き込み }else if(c1=='B'&&c2=='I'){ WRITE_EEPROM(2,i>>8&0xFF); //上位8ビット書き込み WRITE_EEPROM(3,i&0xFF); //下位8ビット書き込み }else if(c1=='C'&&c2=='A'){ if(i<100) WRITE_EEPROM(4,i); }else if(c1=='D'&&c2=='R'){ if(i<20) WRITE_EEPROM(5,i); }else if(c1=='E'&&c2=='W'){ if(1<10) WRITE_EEPROM(6,i); }else return 10; return 1; } という形になっています。 このWRITE_EEPROM(add,val)の後それぞれに、 書き込みが okだったら...puts("書いたよ"); ダメだったら...puts("ダメだよ"); 的なことを入れたいのですが、提示して頂いたコードでそれが出来るということでしょうか? 何を割り込むとか、割り込みがいまいちわからなくて、理解できずにいます;もうしわけありません;

その他の回答 (2)

  • rnakamra
  • ベストアンサー率59% (761/1282)
回答No.2

1)EEPROMの内蔵のものにはEEPROM書込み完了時に割り込みを発生できる機能が付いています。その割り込みの処理で内容のチェックと表示を行うようにすれば良いと思います。 2)この場合は入力にしておくのが無難だと思います。 コンフィギュレーションビットが優先されるはずですので問題は無いはずなのですが。

B_Alice_s
質問者

お礼

回答ありがとうございます。 1)enable_interrupts(INT_EEPROM);というものが割り込みと考えていいのでしょうか? WRITE_EEPROM(0,val[0]); WRITE_EEPROM(1,val[1]); WRITE_EEPROM(2,val[2]); とした場合、一回ずつで割り込みが発生するという考えでよいのでしょうか?出来れば、三回目が書き込み終わった後に「書き込んだよ」というフラグ?がほしいのですが・・・ 2)入力にしておけば大丈夫なのですね。 コンフィギュ…?わからないので調べてみます。 まだまだ理解が足りないと痛感しました。もっと勉強します。

  • bug_bug
  • ベストアンサー率78% (36/46)
回答No.1

デバイスの型番・開発環境が不明ですので、詳細を調べることができません。 以下、PICを扱う場合での概要です。 1) C言語でもアセンブラと同様に「レジスタにアサインされたフラグを監視する」ことでポーリングによる処理の完了を知ることができます。 コンパイラ(ツールチェーン)が不明ですが、提供されている該当デバイスのヘッダファイルに、ビットフィールドの定義などが記載されている場合も多く、構造体のメンバ参照として簡易に記述が可能です。 2) PICのPINの多くは複数のモジュールによって共用されていることがほとんどです。PowerOnReset後のデフォルト設定からデジタル入出力として利用する為に、不要なモジュールの首を絞める必要が多くあります。特に引っかかりやすいのがA/D入力やPSPとの共用ピンあたりでしょうか。PICのデバイスは種類が多く、PIN名を書かれても型番が分からない限り何との共用PINか調べることができません。 OSC系のPINについてはアセンブラやC言語による機能のプログラミングではなく、コンフィギュレーションを設定する為の擬似命令や開発環境からの設定が必要なのではないでしょうか? 答えはすべてMicrochip提供のデータシートに書いてありますので、熟読するのが近道だと思います。

B_Alice_s
質問者

お礼

回答ありがとうございます。 1)について、ヘッダファイルを見てみたところ、割り込みに(enable/disable_interrupts();)といものがありました。 調べてみましたがが、使い方がいまいちわかりません; 2)picは「16f687」で、ccsc社のcコンパイラを使っています。 今までは16f877aで、PINは共用してなかったので戸惑いました。 データシートもみてみたのですが、翻訳してもさっぱりでした; レジスタがどうのというのがよく理解できません; >OSC系のPIN~ これも何のことやらです… せっかく答えてくださったのに、理解が足らず申し訳ありません。

関連するQ&A

  • 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;

  • PIC のデータEEPROMに書き込みができません

    お世話になります。 PICのデータEEPROMへの初歩的な書き込みができずに悩んでいます。 ご経験のある方、私の誤りについてご教示いただければありがたく思います。 PICについてはいくつかの種類でプログラムを書いていますがEEPROMのデータ領域は初めてです。 各種のサイトでは簡単らしいのですが・・・ 当方の試験作業は次のとおりです。 対象チップ PIC16F819 パソコン Windows-XP 書き込み装置 PIC-kit3 書き込みソフト MP-LAB IDE V8.83 プログラム言語 HI-TECH C V9.83 電源 Pic-Kit3から5Vで供給 確認方法 ・MP-LAB- View- EEPROM- のFillmemoryにより、EEPROMにすべてFFH/00Hのいずれもが書き込めることを確認の上、256バイトすべてにFFH ・下記プログラムを走らせる (実行後1秒後に1回書き込み(十進15番地に十進20の例)、以降ランプの点滅。ランプの状態でひとまずの動作の正常は確認) ・MP-LAB- View- EEPROM- により確認・・(全部FFHのまま(泣)) そのほか、チップを新品に交換したり、書き込み時間をEEIFで検査するアルゴリズムにしてみたり、いろいろやってみましたが、壁にぶつかっています。 よろしくお願いいたします。 #include<htc.h> #ifndef _XTAL_FREQ #define _XTAL_FREQ 4000000 #endif __CONFIG(CP_OFF & BOREN_OFF & MCLRE_OFF & PWRTE_ON & LVP_OFF & WDTE_OFF & FOSC_INTOSCIO & DEBUG_OFF & CPD_OFF); void main() { OPTION_REG = 0b00000000; // output pullup OSCCON = 0b01100100; // internal OSC 4MHz TRISA = 0b11111110; // GP-A input RA7=output ADCON1 = 0b10000111; // No AD all digital TRISB = 0b00000000; // GP-B output INTCON = 0b00000000; // no interrupt RB1 = 0;    //Green Lamp off RB3 = 0; //Red Lamp off while (WR = 1) { __delay_ms(1000); } EEADR = 15; EEDATA = 20; EEPGD = 0; GIE = 0; WREN = 1; EECON2 = 0x55; EECON2 = 0xaa; WR = 1;      RB1 = 1; // Green Lamp __delay_ms(100);      RB1 = 0;     GIE = 1;  WREN = 0; EWWW:; // IDLE Lamp Red RB3 = 1; __delay_ms(400); RB3 = 0; __delay_ms(500); goto EWWW; }

  • PICのLVD割込中のリセット回避

    現在、PIC18F2550を使用してプログラムを組んでいます。 電源遮断前にEEPROMへ書込を行ってからシャットダウンできるように 大きめのコンデンサを使って充電し LVD機能を使用して割込を行い、アイドルモードにしたり内部クロックへの切り替え等の 省電力化をしてEEPROMへ書込を行っています。 電源を遮断して1秒程度してから電源を再投入すると 問題なく動くのですが、瞬断のようにOFF-ONを 瞬間的に行うと誤作動を起こしたように上手く作動しません。 恐らく、低電圧を検知してLVD割込に入って EEPROM書き込み等を完了する前に復電して 初期化リセットされる(初期化時にEEPROM読込エラーとなる?)ため ではないかと推測しています。 LVD割込時処理を完了するまで待機してから 初期化することが出来れば良いのですが どのように実現すれば良いか分かりません。 助言いただけますでしょうか。 出来ればプログラム書き換えだけで対応したいです。 MCLRポートはI/Oポートとして使用しているため 出来れば使用したくありません。 コンパイラはCCS社コンパイラを使用しています。 プログラムは全て書くと膨大になるのでLVD割込時のみ書きます。 要望があれば補足書き込みします。 よろしくお願いいたします。 // ==================== 電源遮断時処理 =========================== #int_lowvolt void Low_voltageDetect_isr() // low voltage detect interrupt routine { glLVDdetect = 1; while (PIR2bits.LVDIF) // check if LVDIF is set disable_interrupts(INT_EXT1); // INT1(RB1)割り込み禁止 入力信号 setup_oscillator(OSC_31KHZ | OSC_INTRC | OSC_IDLE_MODE); PIR2bits.LVDIF = 0; // set LVDIF to zero EEPROM_W(); // EEPROM書き込み }

  • PIC16F886のコンフェグ・デジタルI/O化

    PICマイコンのPIC16F887でのアセンブラ言語プログラムでの質問です。 (1)コンフェグの指定方法 現状はPIC16F877Aでプログラムした内容で設定していますが、書込み時に エラーが出ます。 (2)デジタルI/O化 このPICはI/Oが35個使用できると思います。現状はLEDを点滅し確認するということで機能確認をしていますが、RA6は常時点灯、RA7は常時消灯とプログラム指定通りに機能してくれません。他のI/Oはプログラム通りに点滅消灯の動きが出来ます。 詳しいことは知識不足のため、わかりませんがRA6・RA7はオシレータが影響しているのかな?と思います。外部で設置は考えていません。内部クロックを使用したいと検討しています。 解除?デジタルI/O化等の手段があれば教えて下さい。 (3)内部発振を使用する場合は何らかのプログラム指定が必要でしょうか? 上記(1)~(3)ですが、自分なりにネットや参考書などで調べてみましたが、887はまだあまり普及されていない?のかなかなか解決策が出ません。回答できる方、(1)~(3)の一部でもかまいませんのでよろしくお願いします。

  • C言語でプログラミングし、PICマイコンでLEDを制御する

    現在PICを使ってLEDを制御する事を勉強しています。 3つのLEDを3秒間隔で点灯させ、それを無限に繰り返すプログラムを考えてみました。LEDは一つのポートに一つのLEDを割り振るのではなく、ICを使って制御しています。 これを発展させ、待ち時間の3秒間にRA2ポートに入力があるとLEDの点灯をその場所で停止させ、もう一度RA2ポートに入力するとループが再開するといった内容にしようと考えていますが、調べてもどうすればいいのか分かりません、分かる方は教えて頂けないでしょうか # include <16f84a.h> # fuses HS, NOWDT, NOPROTECT # use delay(clock=20000000) int flag, sec, count; main() //main関数の開始宣言 { set_tris_a(0x10); set_tris_b(0x10); #use fast_io(a) //port_aの高速処理を行う設定 #use fast_io(b) //port_bの高速処理を行う設定 while(1){ //無限ループのwhile文の宣言 output_low(PIN_A0); //RA0の出力 output_low(PIN_B5); //RB5の出力 output_low(PIN_B6); //RB6の出力 output_low(PIN_B7); //RB7の出力 //LED1が点灯 delay_ms( 3000 ) ; //3秒待つ   output_high(PIN_A0); //RA0の出力 output_low(PIN_B5); //RB5の出力 output_low(PIN_B6); //RB6の出力 output_low(PIN_B7); //RB7の出力 //LED2が点灯 delat_ms( 3000 ) ; //3秒待つ        output_low(PIN_A0); //RA0の出力 output_high(PIN_B5); //RB5の出力 output_low(PIN_B6); //RB6の出力 output_low(PIN_B7); //RB7の出力 //LED3が点灯 delay_ms( 3000 ) ; //3秒待つ }

  • PICマイコン 動作せず、教えて下さい。

    PICマイコン初心者です。 PICマイコン(PIC16F877)をHI-TEC社のPICCでコンパイルして、Buildしたものを 焼き込んで電源印可しますが全然動作せず。  出力に設定しているピン(PORTB)の電圧をみると全て3.8Vぐらいになっています。(不定??)  ちなみに出力PinはVdd(5V) => 発光D => 抵抗 => PORTBと接続されています。  どこが悪いか教えて頂きたく。  *** ソース ファイル ****   #include"pic.h"   void main(void){ unsigned long i; TRISA = 0x00; TRISB = 0x00;   while(1){ PORTB = 0b11111111; //RB0をLowに設定 for(i=0;i<20000000;i++); PORTB = 0b11111110; //RB1をLowに設定 for(i=0;i<40000000;i++); PORTB = 0b11111101; //RB2をLowに設定 for(i=0;i<15000000;i++);          }        }

  • PICのピンの割り当て、この記述は正しいのでしょうか?

    現在C言語によるプログラムを勉強しているのですが、わからない箇所が出てきました。 PICのピンの入出力の割り当てをする部分の set_tris_a(0x10); //RA1,RA3を入力,RA0,RA2,RA4を出力に設定している。 という部分です。 調べたところ"0x"という部分は16進表記であるという意味で、その後の部分で格ピンの入出力を表しているようなのですが、"10"の部分は10進法表記ではないかと思うのです。 (16進なら"A"と表記するのが正しいのではないでしょうか) また"0x"は16進表記との事ですが、他に、たとえば10進や2進表記で格ピンの割り当ては可能なのでしょうか?

  • 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ヶ月ぐらいやってますがうまくいきません。 良ければご回答をお願いします。

  • PICでシリアル通信

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

  • PIC 18F2320のI/Oポート

    PIC 18F2320のI/OポートにおいてポートCの5ビット目の出力が ビットセットしてもLowのままでHighになりません。 ポートCはすべて出力設定になっているし、SPIも使用していません。 ちなみにポートCの5ビット目以外は、ビットセットでHighに変化します。 ハードの接続(回路)の問題はないと思います。 何か他に設定すべきところがあれば教えてください。

専門家に質問してみよう