現在電子工作をしており、それに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ヶ月ぐらいやってますがうまくいきません。
良ければご回答をお願いします。

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

A 回答 (2件)

>消えている状態でRA1に入力を入れたときなぜか5秒後に点灯してしまいます。


点灯するでしょうね。そういうプログラムになってますから。

>・RA1に入力があったときLEDが点灯しているなら5秒後にLEDを消灯。
>・RA0に入力があったときRB0につないであるLEDが消灯しているならLEDを点灯。
RA1に入力があり、5秒後にLEDを消灯した次の瞬間に、RA0に入力があったら「LEDが消灯しているのでLEDを点灯」する事になります。

こういう場合には、普通
・入力ポートに変化があったら割り込みがかかる
・タイマーにより割り込みがかかる
と言うハード構成にします。

セオリーは「メインでポートを監視する為の無限ループを組まない事」です。

つまり
>どれもすべて動作を終えて、あとはwhile(1)で割り込みを待つだけ
というプログラムにするのが常道なのです。

なので、ネットでさがすと、そういうプログラムばかり見付かる筈です。

以下のような作り方をしましょう。

グローバル変数は「直前のRA0の状態」と「秒カウンタ」と「LEDの状態」を用意します。

int 直前のRA0の状態;
int 秒カウンタ;
int LEDの状態;

main()
{
 ハードの初期化;
 直前のRA0の状態=0;
 秒カウンタ=0;
 LEDの状態=0;
 割り込み許可;
 while(1) {;}
}

void interrupt isr(void)
{
 if (直前のRA0の状態 != 今のRA0) {
  直前のRA0の状態 = 今のRA0;
  if (RA0==1) {
   LED点灯;
   LEDの状態=1;
   秒カウンタ=0;//RA1の入力後の5秒間にRA0が変化したらチャラにする
  } else {
   LED消灯;
   LEDの状態=0;
   秒カウンタ=0;//RA1の入力後の5秒間にRA0が変化したらチャラにする
 }
 if (秒カウンタ==0) {//通常時
  if ((LEDの状態==0) && (RA1==1)) {//消灯時はRA1は無視
   秒カウンタ++;//5秒待ち状態に入る
  }  
 } else {//5秒待ち状態に入っている時
  秒カウンタ++;
  if (秒カウンタ>=500) {//1ミリ秒×500=5秒
   LED消灯;
   LEDの状態=0;//LEDを消す
   秒カウンタ=0;//5秒待ち状態から通常状態に戻る
  }
 }
 割り込みを再許可する
}

割り込み間隔を1ミリ秒にしているのは、チャタリング防止の意味も兼ねていて、エッジノイズやパルスなど、1ミリ秒より短い変化は拾いません。

この回答への補足

お早いご回答ありがとうございます。

>セオリーは「メインでポートを監視する為の無限ループを組まない事」です。

>つまり
>>どれもすべて動作を終えて、あとはwhile(1)で割り込みを待つだけ
>というプログラムにするのが常道なのです。
そーだったんですか・・・・。

とりあえず、このプログラムの通りやってみました、が、
なかなかうまくいきません(汗
最初にRA0につながれているスイッチを押したらそのままLEDがつきっぱなしになっちゃって・・・。
スイッチを押している間消えています。
あと割り込みもうまくいかなかったです・・・。
なかなか消えてくれません。

とりあえずプログラムは
#include "pic.h"

int a; //直前のRA0の状態
int cnt; //秒カウンタ
int LED; //LEDの状態

main()
{
/*初期化始まり
 TRISA=0xFF;
 TRISB=0x00;
 PORTA=0x00;
 PORTB=0x00;

 a=0;
 cnt=0;
 LED=0;
*/初期化終わり

 OPTION=0x87; //割り込みの設定
 TMR0=0x00;
 T0IF=0;
 T0IE=1; //割り込み許可
 GIE=1; //全体割り込み許可
 while(1) {;}
}

void interrupt isr(void)
{
 if (a != RA0) {
  a = RA0;
  if (RA0==1) {
   RB0=0;
   LED=1;
   cnt=0; //RA1の入力後の5秒間にRA0が変化したらチャラにする
  } else {
   RB0=1;
   LED=0;
   cnt=0; //RA1の入力後の5秒間にRA0が変化したらチャラにする
  }
 } //※1
 if (cnt==0) { //通常時
  if ((LED==1) && (RA1==1)) { //消灯時はRA1は無視
   cnt++; //5秒待ち状態に入る
  }
 } else { //5秒待ち状態に入っている時
  cnt++;
  if (cnt>=500) { //1ミリ秒×500=5秒
   RB0=1;
   LED=0; //LEDを消す
   cnt=0; //5秒待ち状態から通常状態に戻る
  }
 }
 T0IE=1; //割り込みを再許可する
 GIE=1;
}

※1…カッコが1つ足りなかったのでおそらくここだと思います。

という感じになっています。

補足日時:2008/01/07 20:54
    • good
    • 0

訂正



  if ((LEDの状態==0) && (RA1==1)) {//消灯時はRA1は無視

  if ((LEDの状態==1) && (RA1==1)) {//消灯時はRA1は無視
の間違い
    • good
    • 0

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

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

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

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

QAVRマイコンの割り込みについて

AVRマイコンの割り込みについて

初心者です。
・AVRマイコンの割り込みの優先順位ですが、割込みベクターのアドレスが小さい順に優先度が高いでよろしいでしょうか?
・優先低の割り込みルーチンを処理している時に、優先高の割り込みが入った場合、
 (1)優先低の割り込みルーチン処理中断→優先高の割り込みルーチンの処理、完了→優先低の割り込みルーチン処理再開(中断ヶ所から)
 (2)優先低の割り込みルーチン処理、完了→優先高の割り込みルーチンの処理、完了
 (3)その他
(1)、(2)、(3)のどの処理が行われますか?
・優先高の割り込みルーチンを処理している時に、優先高の割り込みを禁止し、ルーチン内で優先低の割り込みが入った場合、優先高の割り込みルーチンから優先低の割り込みルーチンにとばすことは可能でしょうか?

以上、よろしくお願い致します。

Aベストアンサー

AVRは使用経験がないのでマイコン一般的な回答ですが、
・優先度は割り込みごとに設定できるものが多いです。同優先度の割り込みが複数入った場合にどうなるかはハンドラ次第です。

・多重割り込みをサポートしていない、あるいは有効にしていない場合は(2)です。多重割り込みが有効の場合は(1)ですね。

・多重割り込みで可能なのはより高優先の割り込みのみです。ISR実行中にその割り込みを禁止したとしても、ISR自体が終了する訳ではない上に優先度は有効のままですから、ISR中に低優先度割り込みが入ることはできません。

QPIC16F84AのデバイスでC言語を用いて音を出したい

PIC16F84AデバイスでCCS社のCコンパイラーを用いて音を出したいのですが、C言語の記述が分かりません。
音は、圧電ブザーで、Bポートの1つを使います。
Aポートの1つにスイッチを取り付け、スイッチが入ったら、音を鳴らしたいのですが、C言語で音階が記述できるんでしょうか?
簡単で良いので、C言語で、音を鳴らす記述を教えていただけないでしょうか?

Aベストアンサー

圧電ブザーは他励式だと仮定して書かせてもらいます。
音は、圧電ブザーのON/OFFで出すことが可能ですが、周波数(音階)は1秒間に何回ON/OFFを繰り返せるかで周波数が決まります。例えば、周波数800Hzは、1秒にONとOFFを1組として800組繰り返します。
ようは、ONとOFFの時間が可変長な関数を作ってやれば色々な周波数を出すことができます。

[参考関数]
void sound( int time, int count )
{
int loop;
// 残り時間だけループを繰り返す。
for( ; time>0 ; time-=(count*2) ) {
// 圧電ブザーをONにする。ON時間はcountで決まる。
for( loop=0 ; loop<count ; loop++ ) {
圧電ブサーのポートをONに。
}
// 圧電ブザーをOFFにする。OFF時間はcountで決まる。
for( loop=0 ; loop<count ; loop++ ) {
圧電ブサーのポートをOFFに。
}
}
}

[説明]
timeでなり続ける時間を指定します。
countでON/OFFの周期を指定します。大きな数字ほど周波数が低くなります。0は音が鳴りません。
C言語だとアセンブラほど高速にON/OFFを繰り返せないので、アセンブラに比べると出せる周波数は低めになるかと思います。いろんな値を入れて実際にどんな音するか試してみてください。

それとこのプログラムはCPUを占有しますので、音を鳴らしながら平行して処理をしたい場合は、タイマー割り込みでブザーをON/OFFする方式に変更しないと実用性が低いかもしれません。

圧電ブザーは他励式だと仮定して書かせてもらいます。
音は、圧電ブザーのON/OFFで出すことが可能ですが、周波数(音階)は1秒間に何回ON/OFFを繰り返せるかで周波数が決まります。例えば、周波数800Hzは、1秒にONとOFFを1組として800組繰り返します。
ようは、ONとOFFの時間が可変長な関数を作ってやれば色々な周波数を出すことができます。

[参考関数]
void sound( int time, int count )
{
int loop;
// 残り時間だけループを繰り返す。
for( ; time>0 ; time-=(count*2) ) {
// 圧電ブザーをO...続きを読む

Q割り込み処理について

割り込み処理について

初心者です。
AVRマイコンの割り込み処理について質問させて頂きます。
INT0割り込みの割り込みが入ったら、割り込みルーチン中の他の割り込みを許可し、かつINT0の割り込みを禁止したいのですが、下記ソースで問題はありませんか?
INT0割り込みが終了して、メインルーチンに復帰した直後にINT0割り込みを許可したいのですが、下記ソース(1)で問題はありませんか(メインルーチンに復帰した直後に許可したいのですが、方法がわかりません)?

ISR(INT0_vect,ISR_NOBLOCK)
{
    int0割り込み禁止
     ・
     ・
     ・
     ・
   (int0割り込み要求フラグクリア) ・・・・(1)    
   (int0割り込み許可)         ・・・・(1)  
}

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

Aベストアンサー

初心者なら、マイコンのマニュアルを見てプログラムできるようになる練習をすることです。

URLに個別の割込みマスクとretiでの動作等書かれています。

・SREG ($3F) : Status Register
bit7-I : Global Interrupt Enable
すべての割り込みを可能にするにはこのビットを1にする必要があります。割り込みがかかるとクリアされ、割り込みルーチンの終わりでRETI命令がかかると同時に再びセットされます。CEI,SEI命令でクリア,セットできます。

にあるように、基本的にはAVRの割込みモデルは多重割込みでない対応としているようです。
これを
>割り込みルーチン中の他の割り込みを許可し
ということなので、多重割込みの対応をしたいようですが、多重割込みについての問題点等
検討されているでしょうか。たとえば、多重割込みでは何重の多重割込みを想定して、それに必要なスタックサイズは検討されていますか?

されているとして、以下のようになると思います。

ISR(INT0_vect,ISR_NOBLOCK)
{
    int0割り込み禁止
    ・SREG ($3F) : Status Register bit7-I : Global Interrupt Enableを1にする。
     (これで割込み許可になる。もともと他の割込みは許可されているものと考えています。)
     ・
     ・このへんは他の割込みが許可状態。
     ・
     ・
    ・SREG ($3F) : Status Register bit7-I : Global Interrupt Enableを0にする。
   (int0割り込み要求フラグクリア) ・・・・(1) これは不要と思います。(理由)   
   (int0割り込み許可)         ・・・・(1)  
}

理由:
・割り込みフラグは割り込みが起こったときにセットされ、割り込みハンドリング時に自動でクリアされます。割り込みをマスクしていた場合にはフラグは立ったままとなります。

参考URL:http://ww2.tiki.ne.jp/~maro/AVR/programing/index.html

初心者なら、マイコンのマニュアルを見てプログラムできるようになる練習をすることです。

URLに個別の割込みマスクとretiでの動作等書かれています。

・SREG ($3F) : Status Register
bit7-I : Global Interrupt Enable
すべての割り込みを可能にするにはこのビットを1にする必要があります。割り込みがかかるとクリアされ、割り込みルーチンの終わりでRETI命令がかかると同時に再びセットされます。CEI,SEI命令でクリア,セットできます。

にあるように、基本的にはAVRの割込みモデルは多重割込みでない対応と...続きを読む

QPIC16F84A PWM制御でトラブル。・゜・(ノД`)・゜・

PIC16F84Aでサーボを動かすためにDelay関数を用いたPWMのプログラムを組んだのですが、picの電源を安定化電源にすると問題なく動作するのですが、乾電池(4本直列)につなぐと動作が不安定になってしまいます・・。

安定化電源、乾電池共に電圧は5.6V程度で、電流の問題かと思い、乾電池(4本直列パック)を並列に繋いで見たのですが改善されませんでした。

また、サーボ自体には問題はなく、picからのパルス出力そのものが不安定になっていることは確認出来ました。

リモコンカーに搭載するため、安定化電源ではなく、乾電池で動作させたいのですが、どうしたらいいのかお手上げ状態です・・
今週末に動かしたいので、どなたかお助け願います。・゜・(ノД`)・゜・

Aベストアンサー

状況から推測するとソフトが原因とは思えません。ハード側に何らかの問題があると思われます。
回路図見てないので何とも言えませんが、乾電池で動作しているときに、電圧が不安定になっている事が一番考えれる原因です。
サーボの電源とPICの電源は共通なのでしょうか?
ちゃんと乾電池→安定化電源回路→PICになってますか?
サーボ動作時にクロックは安定していますか?サーボのノイズの影響を受けていませんか?

Qシステムの割り込みについて システムの割り込みで調べてもよく分からないのですが遅延など調べましたが、

システムの割り込みについて
システムの割り込みで調べてもよく分からないのですが遅延など調べましたが、主にシステムの割り込みとはどんなのでしょうか?
先程cpuが1%(何もしてない時1〜0%)でしたがシステムの割り込みというはじめて聞いた単語がありましたので質問されていただきました。
システムの割り込みが0〜0.3%になっていて何か動いているのかなと思い数分ほど放置しましたが常に0〜0.3%だったのでシャットダウンしましたが割り込みと書いてましたのでもしかしたらシャットダウンとかしない方が良かったのでしょうか?

Aベストアンサー

ある処理の途中に、その処理以外の事象発生により、処理を中断(これが割り込みです)して別のことを行う様なことを言います。
例えば、円周率πの計算プロセスが稼働中はほぼCPU100%で動作しますが、この計算中にDVDメディアが装填されて自動再生が動き出すケースです。これは円周率πの計算中にDVDデバイスからシステムに割り込みが入り、システムが計算を一旦中断して自動再生プログラムを起動(CPUをこの処理に回す)したらかなる状態なのです。
割り込み要件には、上記のデバイスの割り込みの他にタイマーの割り込み(特定の時間が経過したらある処理を実行する等)や他のプロセスが終了したことによる割り込み等多種多様なものがあります。

QPIC16F88のA/D変換の時間設定について質問です。最近PICを始

PIC16F88のA/D変換の時間設定について質問です。最近PICを始めたばかりの素人です、色々な書籍を読みあさりC言語でプログラミングしていますが、PIC16F88のA/D変換を利用しステッピングモータの回転数を制御するプログラムを作りました。そこでアナログからデジタルに変換する待ち時間が必要とわかりとりあえず仕様書に19.72μSの待ち時間らしき時間がありましたので使用しましたがこれが正しいのかわかりません。どうぞアドバイスお願いします。
以下プログラムの抜粋です。コンパイラはCCS社のPCMを使用しています。

#include<16f88.h>
#fuses HS,NOWDT,PUT,NOPROTECT,NOLVP,NOBROWNOUT,
#device ADC=10
#usedelay(clock=10000000)
途中省略
void DEGVR()
{
///////////////////////VR→デジタル計算///////////////////////
set_adc_channel(2);//A/D変換チャンネル設定
delay_us(20);//変換にかかる時間19.72μs
vr = read_adc();//A/D変換レジスタリードしvrへ
途中省略
main()
{
////////////////////////vr設定///////////////////
setup_adc_ports(sAN2); //アナログポート設定
setup_adc(ADC_CLOCK_DIV_32);//アナログ変換クロック設定
途中省略

PIC16F88のA/D変換の時間設定について質問です。最近PICを始めたばかりの素人です、色々な書籍を読みあさりC言語でプログラミングしていますが、PIC16F88のA/D変換を利用しステッピングモータの回転数を制御するプログラムを作りました。そこでアナログからデジタルに変換する待ち時間が必要とわかりとりあえず仕様書に19.72μSの待ち時間らしき時間がありましたので使用しましたがこれが正しいのかわかりません。どうぞアドバイスお願いします。
以下プログラムの抜粋です。コンパイラはCCS社のPCMを使用していま...続きを読む

Aベストアンサー

こんにちは。
一言でA/D変換時間と言いましても、PICの場合は、サンプルホールドコンデンサの充電待ち時間と、A/D変換待ち時間の2つの待ちが必要です。

A/Dコンバートの流れとしましては、以下のような感じになるかと思います。

 A/Dコンバータのチャネル選択
   ↓
 コンデンサの充電待ち(固定時間)
   ↓
 A/Dコンバートスタート(ADCON0レジスタのGOビットに1をライト)
   ↓
 A/Dコンバートの終了を待つ(先ほどのビットが0になれば終了)
   ↓
 結果を取りだす
   ↓
 最初に戻る

このうち、後半のA/Dコンバートの終了待ちは、レジスタの監視で事足りるので問題ないのですが、前半の「コンデンサの充電待ち時間」の方が、今ひとつハッキリしなくて、何というか面倒くさい感じです。

データシートに載っている、何やらややこしい計算式は、この充電待ち時間を計算するものです
なお、そこで示されている、19.72μsというのは、インピーダンスが推奨値になるよう組まれたアナログ回路を、周囲温度が50℃の状況下で使用する場合の計算例です。

頑張って計算して求めるのが理想と言えば理想ですが・・・。
実はこれは最小値でして、これ以上の長さであれば、ええ加減で大丈夫です。
よほどパフォーマンスを追及するとかでもなければ、50μsとかテキトーに決めていいんじゃないでしょうか・・・。

こんにちは。
一言でA/D変換時間と言いましても、PICの場合は、サンプルホールドコンデンサの充電待ち時間と、A/D変換待ち時間の2つの待ちが必要です。

A/Dコンバートの流れとしましては、以下のような感じになるかと思います。

 A/Dコンバータのチャネル選択
   ↓
 コンデンサの充電待ち(固定時間)
   ↓
 A/Dコンバートスタート(ADCON0レジスタのGOビットに1をライト)
   ↓
 A/Dコンバートの終了を待つ(先ほどのビットが0になれば終了)
   ↓
 結果を取りだす
   ↓
 最初に戻る

こ...続きを読む

Qpicタイマ0割り込みについて

タイマ0割り込みについて教えて下さい。
解説書などに、割り込みルーチンの最初の部分で

(1)割り込みフラグ(TMR0IF)を消す
(2)TMR0を再設定する

と書かれていますが、なぜ(2)を割り込みルーチンの最初で行うのでしょう?
これでは、
・1秒ごとに割り込みを発生させたい
・割り込みルーチンの作業時間は0.5秒
だとすると、結果的に割り込み発生は0.5秒ごとになってしまいます。

TMR0再設定は割り込みを抜ける時(retfie の直前)に行えば、ほぼ希望通りの間隔で、割り込みを発生させられると思うのですが、それはルール違反なのでしょうか?

Aベストアンサー

N0.2です。
普通の処理だったら問題無いのですが、
たとえば、割り込みが発生してもすぐに
割り込みルーチンに入れない様な場合、
気を付けないと次の割り込みが発生してしまいます。
で、マニュアルでは割り込み原因となる
TMR0を再設定するように指示をしているのですが、
たしかに割り込み後に一定時間間隔でまた割り込みたい
場合には、抜ける前にまた再設定するしかありません。

ただ、通常の場合、一定時間の割り込みというのは
割り込みそのものを一定時間毎に発生させたい筈
なんです。
たとえば、割り込みは10mSおき、処理は1mSだとすると
スタート(0mS)から数えて
10mS 割り込み発生 TMR0再設定
11mS 割り込み処理終了
20mS 割り込み発生 TMR0再設定
21mS 割り込み処理終了
30mS 割り込み発生 TMR0再設定
と言うぐらいに、きれいに
10mSおきに割り込みが発生します。
しかも、割り込み処理が長くなっても短くなっても
間隔は変わりません。

QPIC16F819

PIC16F819のADコンバータを使用しています。
RA0からアナログ信号を入力して、PORTBのそれぞれのピンから1bitずつ(計8bit)のデジタル信号を出力させるためのプログラムを書いてみましたが、まったく動作しません。レジスタの設定なども変えてみましたが動作しませんでした。特にPORTBを全てHighにした場合、なぜかRB6とRB7からの出力を確認することができませんでした。
動作しない原因がまったく分からないので困っています。原因が分かる方がおられましたらご教授お願いします。

#include <pic.h>
__CONFIG(DEBUGEN&WDTDIS&LVPDIS&HS&PWRTEN);

void init_a2d(void){
 ADCON0=0x40;
 ADCON1=0x40;
 ADON=1;
}

unsigned char read_a2d(unsigned char channel){
 channel&=0x07;
 ADCON0&=0xC5; ADCON0|=(channel<<3);
 GODONE=1;
 while(GODONE)continue;
 return(ADRESH);
}

void main(void){
 unsigned char x1;
 init_a2d();//initialise the A2D module
 GIE=0;// we don't want interrupts
 TRISB=0x00;    // PORTB will be used in output mode
 PORTB=0x00;
 x1=read_a2d(1);// sample the analog value on RA0
 PORTB=x1;
}

PIC16F819のADコンバータを使用しています。
RA0からアナログ信号を入力して、PORTBのそれぞれのピンから1bitずつ(計8bit)のデジタル信号を出力させるためのプログラムを書いてみましたが、まったく動作しません。レジスタの設定なども変えてみましたが動作しませんでした。特にPORTBを全てHighにした場合、なぜかRB6とRB7からの出力を確認することができませんでした。
動作しない原因がまったく分からないので困っています。原因が分かる方がおられましたらご教授お願いします。

#include <pic.h>
__CON...続きを読む

Aベストアンサー

> x1=read_a2d(1); // sample the analog value on RA0

RA0 だとchannel は0ではないですか?

QマイコンSH-2の割り込みを用いたシリアル通信

SH7144Fで割り込みを用いたシリアル通信を行っていますが,
途中で割り込みがかからなくなる症状に悩んでいます.

開発環境はHEW上でツールチェインにRenesas SuparH StandardとKPIT GNUSH [ELF]を
組み込んでおり,適宜選んで使っています.
以下,Renesas SuparH Standardで,受信割り込みの場合に限って書かせて頂きます.

少々長くなりますが状況をご説明致します.

最初にSCI1回りの設定を適切に行い,割り込みレベルを15とした後,
set_imask(0)で割り込みレベルを0として割り込みがかかるようにしています.
受信割り込みがかかるとINT_SCI1_RXI1に飛び,
_UBYTE c = SCI1.RDR;
SCI1.SSR.BIT.RDRF = 0;
と直ちにした後,cの内容をバッファに入れ,戻っていますが,一文字受信しただけで
割り込みがかからなくなります.(_UBYTEはtypedefine.hでunsigned charとしています.)

相当悩んだ挙句,INT_SCI1_RXI1の末尾に,
set_imask(0);
を入れてやると連続して割り込みがかかり,うまく受信できるようになっています.

ハードウェアマニュアルを読めば,割り込みがかかるとSRレジスタは退避され,
SCI1の割り込みレベル15の内容がSRレジスタのI0~I3に書き込まれる,とあります.
当然,割り込みが終われば,退避された内容がSRレジスタに戻るので割り込みマスクは
0に戻るもの・・・と解釈していますが,余りにも当たり前なのかハードウェアマニュアルには
明記はされていません.もしかしたら元に戻っていないのでは・・・と,上記のようにいちいちに
割り込みマスクを0にする手続きを追記すると動いている,と言う状況です.

因みに上記の状況はKPIT GNUSH [ELF]を選んだときにも同じです.
更には,送信割り込みのときも上記と同じくset_imask(0)を入れてやると動きます.

そこで質問ですが,
1.SRレジスタは割り込みが終われば元の内容に戻ると解釈していますが,
  これで合っているでしょうか.
2.上記1で元に戻るのだとしたら,なぜいちいちset_imask(0)をしてやらないといけない
  状況になっているのか・・・考えられる原因をお教えください.

雑多な説明で申し訳ございませんが,どうぞ宜しくお願い致します.<(__)>

SH7144Fで割り込みを用いたシリアル通信を行っていますが,
途中で割り込みがかからなくなる症状に悩んでいます.

開発環境はHEW上でツールチェインにRenesas SuparH StandardとKPIT GNUSH [ELF]を
組み込んでおり,適宜選んで使っています.
以下,Renesas SuparH Standardで,受信割り込みの場合に限って書かせて頂きます.

少々長くなりますが状況をご説明致します.

最初にSCI1回りの設定を適切に行い,割り込みレベルを15とした後,
set_imask(0)で割り込みレベルを0として割り込みがかかるようにしてい...続きを読む

Aベストアンサー

ハードウエアマニュアルをよく読めば書いてあるのですが、SHのSSR.RDRFビットをクリアするのは、一度1を読み込んでから0を書く必要があります。
質問文からは、1を読む作業が抜けているように思われます。

set_imask()は、関数呼び出しではなく、インライン展開されるようですが、展開されたものを読んでみても、結果的にLDC命令を使ってSRのIMASK部を書き換えるだけの処理です。
ですから、set_imask(0)を実行した時点で、再びsci割り込みがかかると思いますが、それは新たな受信データを得た訳ではないので、読み出したデータは以前と同じになっているのではないでしょうか。

一方、割り込みからの復帰に使用するRTE命令は、セーブされたSRとPCの値をレジスタに戻すものです。
アセンブラで書いていると、間違ってRTSで戻してしまうことがありますが、この場合はSRの内容うんぬんという以前に、PCの値が変になって暴走するので、すぐにわかります。
Cで書いていればそのような間違いは起きないので、SRの復帰について心配する必要はありません。

ただ、LDCでSRのIMASK部を変えるのと、RTEで変えることに違いが生じているようですが、これは内部割込みのエッジ検出フラグのリセット回路の働きに、なにか違いがあるのかも知れません。

ハードウエアマニュアルをよく読めば書いてあるのですが、SHのSSR.RDRFビットをクリアするのは、一度1を読み込んでから0を書く必要があります。
質問文からは、1を読む作業が抜けているように思われます。

set_imask()は、関数呼び出しではなく、インライン展開されるようですが、展開されたものを読んでみても、結果的にLDC命令を使ってSRのIMASK部を書き換えるだけの処理です。
ですから、set_imask(0)を実行した時点で、再びsci割り込みがかかると思いますが、それは新たな受信データを得た訳ではないので...続きを読む

QPIC16F877AとC-552SRDとOSL40562-LRとC言語でマイコン時計を作っています

回路図を添付しました。動作確認しましたが全く動きません。コードの間違いをご指摘下さい。
#include<xc.h>
#pragma config PWRTE=ON,WDTE=OFF,FOSC=LP,CP=OFF,LVP=OFF
void init_port();
void init_timer();
void segment_set_data(short seg1,short seg2,short seg3,short seg4,short dot);
void segment_set_data_ss(short seg1,short seg2,short dot);
void interrupt intr();
void segment_disp();
void segment_disp_ss();
long clock_msec;
short lock;
#define LOCK 1
#define UNLOCK 0
void main(void){
short hh,mm,ss;long temp;init_port();init_timer();
INTCONbits.PEIE = 1;INTCONbits.GIE = 1;
while (1) {
temp=clock_msec /1000;
hh=temp/3600;
mm=(temp%3600)/60;
ss=temp%60;
segment_set_data(hh/10,hh%10,mm/10,mm%10,2);
segment_set_data_ss(ss/10,ss%10,1);
if (RE0==0) {
hh++;ss=0;
if(hh==24){hh=0;}
lock=LOCK;
clock_msec=(((long)hh*3600)+((long)mm*60)+(long)ss)*1000;
lock=UNLOCK;
}
if (RE1==0){
mm++;ss=0;
if(mm==60){mm=0;}
lock=LOCK;
clock_msec=(((long)hh*3600)+((long)mm*60)+(long)ss)*1000;
lock=UNLOCK;
}
_delay(8192);
}
}
void init_port(){
TRISA=0b000000;PORTA=0b000000;TRISB=0b00000000;PORTB=0b00000000;
TRISC=0b00000000;PORTC=0b00000000;TRISD=0b00000000;
PORTD=0b00000000;TRISE=0b011;PORTE=0b000;
}
void init_timer(){
T2CONbits.T2CKPS0 = 0;T2CONbits.T2CKPS1 = 0;T2CONbits.TOUTPS3 = 1;
T2CONbits.TOUTPS2 = 1;T2CONbits.TOUTPS1 = 1;T2CONbits.TOUTPS0 = 1;
TMR2 = 0;PIE1bits.TMR2IE = 1;PIR1bits.TMR2IF = 0;PR2 = 0.512;
T2CONbits.TMR2ON = 1;
}
short seg_dat[4] = {0, 0, 0, 0};short dot_point = 0;
void segment_set_data(short seg1, short seg2, short seg3, short seg4, short dot){
seg_dat[0] = seg1;seg_dat[1] = seg2;seg_dat[2] = seg3;seg_dat[3] = seg4;
dot_point = dot;
}
short seg_dat_ss[2] = {0, 0};short dot_point_ss = 0;
void segment_set_data_ss(short seg1, short seg2, short dot){
seg_dat_ss[0] = seg1;seg_dat_ss[1] = seg2;dot_point_ss = dot;
}
long clock_msec = 0;short lock = UNLOCK;
void interrupt intr(){
if(PIR1bits.TMR2IF == 1){
PIR1bits.TMR2IF = 0;
segment_disp();
segment_disp_ss();
if(lock == UNLOCK){
clock_msec++;
if(clock_msec == 86400000){clock_msec = 0;}
}
}
}
short seg_tbl[10] = {0b00111111,0b00000110,0b01011011,0b01001111,0b01100110, 0b01101101,0b01111101,0b00100111,0b01111111,0b01101111};
short seg_cnt = 0;
void segment_disp(void){
switch(seg_cnt){
case 0:
RA3=1;
PORTC=seg_tbl[seg_dat[0]];
if(dot_point==1){RC7=1;}
RA0=0;seg_cnt=1;break;
case 1:
RA0=1;
PORTC=seg_tbl[seg_dat[1]];
if(dot_point == 2){RC7=1;}
RA1=0;seg_cnt=2;break;
case 2:
RA1=1;
PORTC=seg_tbl[seg_dat[2]];
if(dot_point==3){RC7=1;}
RA2=0;seg_cnt=3;break;
case 3:
RA2=1;
PORTC=seg_tbl[seg_dat[3]];
if(dot_point==4){RC7=1;}
RA3=0;seg_cnt=0;break;
}
}
void segment_disp_ss(void){
switch(seg_cnt){
case 0:
PORTB=seg_tbl[seg_dat_ss[0]];
if(dot_point_ss==1){RB7=1;}
seg_cnt=1;break;
case 1:
PORTD=seg_tbl[seg_dat_ss[1]];
if(dot_point_ss==2){RB7=1;}
seg_cnt=0;break;
}
}

回路図を添付しました。動作確認しましたが全く動きません。コードの間違いをご指摘下さい。
#include<xc.h>
#pragma config PWRTE=ON,WDTE=OFF,FOSC=LP,CP=OFF,LVP=OFF
void init_port();
void init_timer();
void segment_set_data(short seg1,short seg2,short seg3,short seg4,short dot);
void segment_set_data_ss(short seg1,short seg2,short dot);
void interrupt intr();
void segment_disp();
void segment_disp_ss();
long clock_msec;
short lock;
#define LOCK 1
#define UNLOCK 0
vo...続きを読む

Aベストアンサー

デバッグ方法を勉強しようと言うなら答えは来るでしょうが、
丸投げじゃ無視されるだけですよ。
http://so-zou.jp/robot/tech/microcomputer/pic/development-environment/mplab-ide/debug/


人気Q&Aランキング

おすすめ情報