PIC Timer0割り込みがされない

このQ&Aのポイント
  • 12F609でTimer0割り込みが実行されません。動作的に割り込みハンドラが呼ばれていない感じです。
  • プログラムの中で割り込みハンドラが定義されており、割り込みフラグのチェックや処理も行われていますが、GP4の出力が正しく反転されません。
  • 初期時にGP4を1に設定しているため、割り込み処理での反転が機能しない可能性があります。
回答を見る
  • ベストアンサー

PIC Timer0割り込み されない

12F609でTimer0割り込みが実行されません。 実行されないというか、動作的に割り込みハンドラが呼ばれていない感じです。 以下がプログラムです。 void main(void) //メインプログラム { T0IE = 0; GPIO = 0; T0CS = 0; PSA = 0; PS0 = 1; PS1 = 1; PS2 = 1; TMR0 = 0; TRISIO = 0x00; a = 0; GP4 = 1; T0IE = 1; GIE = 1; while(1) } void interrupt blink(void) //---割り込みハンドラ--- { if(T0IF==1) { T0IF = 0; if(a%15==0) { GP4 ^= 1; a=0; } a++; } } 以上です。 割り込み15回ごとにGP4の出力を反転させるプログラムです。 が、反転されずGP4は1のままになってしまいます。 (初期時にGP4=1としているので) 二週間粘りましたが、まったく解決できず困っています。 何がいけないのでしょうか。 ご教授お願いします。

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

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

あ、ごめん、忘れてた! PIC独特の【ページング】は? SFRによっては、ページを切り替えないとアクセスできないでしょ?

maruyama0422
質問者

お礼

やっと原因が特定できました! なんと恥ずかしいことに電源のノイズによる、マイコンの動作不良でした…。 16F84Aでプログラムを組んだ時は自作の実験ボードでテストし、その時は乾電池が電源でした。 だから問題なく動きました。 今回の回路は他回路と一緒に組み込まれたもので、電源にトランスを使っていました。 整流後の平滑が足りず50Hzの波形が大きく残っていたようで、マイコンが動作不良を起こしていたんです。 レギュレータの前に4700uFを足したところ無事動作するようになりました。 もともと680uFをつけていましたが、ほかの回路でも電流を食っているので足りなかったようです。 (素人の推測ですが) 基本的な部分ができていなくて恥ずかしいばかりです。 これほど回答していただいたのに、本当に申し訳ありませんでした。 お二人様ともありがとうございました。

その他の回答 (7)

  • kaoaru
  • ベストアンサー率33% (42/127)
回答No.8

「#include」で何を指定してますか? 肝心なことを聞きわすれていましたが、PIC Cなのでしょうか?これ。 それともPIC C Liteなのでしょうか?12F609ってサポートされてました? コンパイラのライブラリをチェックしてみましたか? 12F609の定義、多分、なかったかと・・・。

maruyama0422
質問者

お礼

回答ありがとうございます。 インクルードは #include "pic12f609.h" #include <htc.h> #include "delay.h" です。 コンパイラはHI-TECH社のCコンパイラを使っています。 (v9.82です) ライブラリを覗いてみると、12F609の定義は確かにありませんでした…。 サポートしていないのですか。 それが原因かもしれません。 12F609をサポートしているコンパイラってあるのでしょうか。

  • kaoaru
  • ベストアンサー率33% (42/127)
回答No.7

わからなくなったら「ソース丸投げ」というのはマズいです。ここでのQ&Aにありがちなパターンです。 「12F609のデータシート」は読まれていないのですね? これを読まないでプログラミングなんかできません。フリーダウンロードできるわけですから、熟読されてください。 http://ww1.microchip.com/downloads/en/DeviceDoc/41302A.pdf 原因は割込み開始の合図がない、ということです。それがわからなければ使えません! OPTION_REGにタイマ0の割込み許可をやってあげないと、割込みアドレスにジャンプしません。 せっかく「void interrupt blink(void)//---割り込みハンドラ---」ってあるのだから・・・これの意味がわかっていて書いているわけですよね? こういうのは、ほんとは先頭に「プロトタイプ宣言」しといたほうがわかりやすのですけど・・・。

maruyama0422
質問者

お礼

回答ありがとうございます。 >わからなくなったら「ソース丸投げ」というのはマズいです。 すみません。 >「12F609のデータシート」は読まれていないのですね? 読んであります。 >原因は割込み開始の合図がない あります。 >ほんとは先頭に「プロトタイプ宣言」 それは知りませんでした…。 チェックしておきます。

回答No.5

じゃあ、あとは、タイマースタートがかかっていないとしか考えられないね。一般的なマイコンでは、何らかのタイマースタート・ストップができるけどね。そうでなければ、完全にお手上げ。もしくは、レジスタの書き換えが、プロテクトされているか。もしくは、その個体が故障しているか。わたしは、PICはン年前に【捨てた】から、これ以上は関わらないよ。 あ、そうそう、一般的なマイコンのポートの入出力の設定は、1で出力、0で入力というのがほとんど。 それと、プログラムは、割り込み関数の中でフラグを立てて、main()の中でフラグをチェックするか、ステートマシンを組むのが定石だよ。割り込み関数の中は、極力処理を減らして、さっさと終わらせる方が良いからね。

maruyama0422
質問者

お礼

ページングを含めいろいろ試してみましたが、やはり状況は変わりませんでした。 タイマーストップもプロテクトもされていませんし、もしかしたら故障しているのかもしれません。 >プログラムは、割り込み関数の中でフラグを立てて、main()の中でフラグをチェックするか、ステートマシンを組むのが定石 なるほど…。 参考にさせていただきます。 取りあえずしばらくの間は、現に動作している16F84Aを使っておこうと思います。 あと時間があれば、上位機種である12F615を買ってきて試してみようと思います。 回答ありがとうございました。

回答No.4

タイマ割り込みの周期は何秒? それの15回分って何秒? 出力GP4がHighのままって何で確認したの? 周期って、クロックが8MHzでクロック分周比が1/4でプリスケーラが1/256だと約520Hzだから、19.2ミリ秒になるよね。まさか、LEDの点灯でHighと判断したの? それともテスタ? オシロスコープじゃないの?

maruyama0422
質問者

お礼

回答ありがとうございます。 >クロックが8MHzでクロック分周比が1/4でプリスケーラが1/256 8bitのTMR0レジスタをオーバーフローさせるので、さらに1/256ですよ。 クロック分周比が1/4なので1サイクルにかかる時間は0.5us 割り込みが呼ばれる周期は0.5*256*256=32768us =32.768ms それを15回分なので32.768*15=491.52 約0.5秒になります。 これは16F84Aで動作確認をしており、きちんと0.5秒周期で動作していますので、計算ミスはありません。 ちなみに目に見えないだけで、実は高速でLEDが点滅しているのかと思いまして、 GP4 ^= 1; を GP4 = 0; に置き換えた (つまり、0.5秒後にLEDが消灯して終わり) →しかしLEDは消灯しない。 メインの GP4 = 1; を GP4 = 0; に置き換えた (つまり、消灯から点滅を始める) →しかしLEDは点灯しない、消灯したまま。 もし、高速で点滅しているのなら、この場合でも点灯しっぱなしになるはず。 >まさか、LEDの点灯でHighと判断したの? それともテスタ? オシロスコープじゃないの? オシロは持っていないのでLED点灯でしか確認できません。 ちなみにさらに、GP2/INT端子の変化で割り込みを発生させるINTEbitでの割り込みを試したところ割り込みハンドラは呼ばれました。 やはりTimer0自体が動作していないように感じるのですが…

回答No.3

GP4の示すポートを出力にし忘れているとか・・・。 > TRISIO = 0x00; は、 # TRISIO=0x10; ではないの? あーあ、PICのアークテクチャ見直すなんて、ン年ぶりだわ。疲れるね。

maruyama0422
質問者

お礼

回答ありがとうございます。 TRISIO<5:0>: GPIO Tri-State Control bit 1 = GPIO pin configured as an input (tri-stated) 0 = GPIO pin configured as an output とデータシートに記載があるので大丈夫かと思われます。

回答No.2

残念ながら、 > while(1) は、C言語の文法的に誤りです。 PICの書き方とか、どうとかいうレベルではなくね。 正しくは、 # while(1); もしくは、 # while(1){ #   ; # } などとなります。わたしの言った「文」とは、プログラムのことではなく、式文すなわち「;」で終わる式のことです。

maruyama0422
質問者

お礼

そういうことでしたか(汗) そう言われれば確かにその通りです… 私のミスでした。 回答ありがとうございました。

回答No.1

PICのプログラムをC言語で書こうというのが間違いだね。 これ、エラーでないの? やっぱり、PICのC言語はモドキだわ。 1.変数aが宣言されていない。・・・変数aは、【静的変数】であるはず。 2.while(1) に文が付いていない。 3.なんらかのヘッダーファイルがインクリュードされると思うけど・・・。 4.割り込みベクトルの設定はいらないのか。   たしか、PICは4番地が割り込みベクトルになっているから、   interrupt修飾子で勝手にテーブルに貼ってくれるのかな? > if(a%15==0) > { > GP4 ^= 1; > a=0; > } は、 # if(a==15) もしくは if(a>14) # { # GP4 ^= 1; # a=0; # } とすべし。なぜか、わかるでしょ?

maruyama0422
質問者

お礼

>1,3 ごめんなさい、当たり前のことなので記載していませんでしたが、メインプログラムの前にはちゃんとインクリュードや変数aの宣言、コンフィグなど書いてあります。 >2 while(1)に文がないのは、PICの割り込みでは普通です。 調べて頂ければすぐにお分かりになります。 >4 16F84Aではこれで大丈夫でした。 ネットで調べる限り、設定はないと思います。 >if(a%15==0) 確かにその通りです。 修正しました。 (無論状況は何も変わらず) 16F84Aはこれで普通に動いていますので、12F609固有の設定があるのだと思っているのですが、データシートを見ても見つけることができず、困惑している次第です。 回答ありがとうございました。

関連するQ&A

  • PIC12F675 GPIO入出力について

     現在、PIC12F675にてA/D変換、EEP- W/R,TMR0を使ったプログラムを作成しているのですが、GPIOの入出力がおかしくTMR0、GP0~2が正常に動作しません。   ●各PINの使用状況・・・ ・GP0/出力(H/L) ・GP1/出力(H/L) ・GP2/TMR0 ・GP3/入力(S/W) ・GP4/入力(A/D変換) ・GP5/出力(H/L) ●開発環境   ・MPLAB IDE V8.40   ・デイバイス PIC KIT1 MPLAB IDEのファイルレジスタとウォッチのウインドウでデバッグしていて気づいたのですが、SFRアドレス00H~05Hまでの変化がそのままGPポートの変化へとつながっており、GP0がRestricted Memoryicted Memoryが表示され、SIMでRUNさせてみるとプログラムでは「BSF」でGP0を出力してもGPIOの0ビット目は変化しません。 GP2も変化がなくTMR0も動作していない様です。  もちろんBANK1でTRISIOの設定(B'00011000')は行っています。 自己解決を試みましたが万策尽きて投稿させていただきました。 恐れ入りますが何方かご教授いただけましですでしょうか。  

  • PIC12F615でGP5が使えません(T_T)

    お世話になりますm(_ _)m PICマイコン初心者です(^^;) MPLAB IDE v8.80で、C言語でプログラムして、 PICkit3を使ってPIC12F615に書き込んでいます。 GP2にスイッチ、GP5にLEDを接続して、スイッチを押すとLEDが点灯するプログラムです。 これだけなら、普通にGP5は利用できます。 タイトルの「GP5が使えない」というのは、 このプログラムに、 割り込みを使用するために INTE=1; を書き込むと何故か、GP5が使えなくなります。 入力も出力も出来ません。 どなたか分かる方、よろしくお願い致しますm(_ _)m ↓プログラム↓ ---------------------------------------------------------------- #include <htc.h> __CONFIG(OSC_4MHZ & UNPROTECT & MCLREN & PWRTEN & WDTDIS & INTIO & BORDIS); void main(void) { //PIC12F615仕様  CMCON0 = 0x07 ; //コンパレート無効化  ANSEL = 0x00 ; //全てデジタル  TRISIO = 0b00001100 ; //入力出力設定  WPU = 0b00000100; //プルアップビット指定  GPPU = 0; //プルアップ有効化  GPIO = 0 ; //各ピンデフォルト値  INTEDG = 0; //INT割り込み立ち下がりエッジ  INTE = 1;  GIE = 1;  while(1)   {    if(!GP2) GP5=1; else GP5=0;   } } ----------------------------------------------------------------

  • PIC12F683 TMR2の割込がうまくいきませ

    タイトルのPICを使ってTMR2の割込動作を確認しているのですが、割込が全く掛かりません。 TMR2は単独で割込を掛けないで動作することは確認できましたがエラーもあるわけでもなく あれこれやっても解決せず迷走中です。また、割込ルーチンはこれまで動作が確認できたプログラムを埋め込んで使っているので問題はないと思っています。 何方かお助け頂けませんでしょうか。宜しくお願い致します。 ;******************************************* ; PIC初期設定 ;******************************************* START_INI BCF STATUS,RP0    ;BANK【0】 MOVLW 07h MOVWF CMCON0 ;GP0-2はデジタルIO BSF STATUS,RP0    ;BANK【1】 MOVLW B'0000000' MOVWF ANSEL ;A/D変換クロックF/2 デジタルI/O BCF OPTION_REG,7 ;GPIO端子をプルアップ MOVLW B'001000' ;RESET端子有効 MOVWF TRISIO ;GP0,1,2,4,5:OUT GPO3:IN MOVLW B'1000000' ;40h MOVWF OSCCON ;クロック=1MHz ;******************************************* ; TMR2の設定 ;******************************************* BCF STATUS,RP0    ;BANK【0】 MOVLW B'000101' ;ポス=1:1 TMR2=ON プリ=1:4 MOVWF T2CON ; BCF PIR1,TMR2IF    ;Timer2 割込み検出フラグをクリア BSF STATUS,RP0    ;BANK【1】 BSF PIE1,TMR2IE    ;Timer2 有効 MOVLW H'FA' ;250 MOVWF PR2    ;TRM2カウントSET ;******************************************* BCF STATUS,RP0     ;BANK【0】 CLRF TMR2 BSF INTCON,GIE     ;割り込み全体を有効

  • PICマイコンでGIEビットが1に出来ません。(コンパイラのバグ?)

    質問は初めてです。 GIEビットが1にセット出来ません。 デバッグでは、 GIE = 1; の文が無視され飛び越えます。 デバッグのwatchで監視してもセットされないのが確認出来ます。 マイコンに書き込んで実行させても割り込みが発生してないのが分かります。 環境はMAPLAB IED v8.46 と HI-TECH PICC の無料版?です。 ↓プログラム全てを書くとやたら長いのでIOなどの設定している関数だけ表示します↓ void Ioport(){ PORTA = 0x00; //ポートA初期化 PORTB = 0x00; //ポートB初期化 PORTC = 0x00; //ポートC初期化 TMR0 = 0x00; //タイマ0初期化 OSCCON = 0x60; //外部クロック20MHz使用 OSCTUNE = 0x00; //動作クロックのチューン無し CM1CON0 = 0x00; //コンパレータ無効でデジタルIOモード可能 CM2CON0 = 0x00; ANSEL = 0x00; //デジタルIOモード ANSELH = 0x00; OPTION = 0x08; //RBプルアップ有効、TMR0を命令クロック、 //プリスケーラをTMR0に使わない T0IF = 0; //フラグ タイマ0初期化 T0IE = 1; //割り込みタイマ0可能 GIE = 1; //割り込み全体可能(ココが飛ばされます) TRISA = 0b11000000; //出力:0~4LED7セグメントのブロック用5つ WPUB = 0b11100111; //0~2プルアップ設定 3赤外線受信4赤外線送信 TRISB = 0b11101111; //0~2ボタン3つ 出力:4赤外線送信 TRISC = 0b00000000; //0~7LED7セグメントのパーツ用8つ //GIE = 1; ココに書くとコンパイラがエラーを起こします。 } void main(void){ Ioport();     //GIE = 1; ココに書くとセットしてくれて正常に動作します。 } 他に GIE = 1; を書く場所によっては、 Ioport()関数の最後に書くと、 67.23 ";" expected 71.1 undefined identifier "portBRead" 77.9 void function can't return a value 81.9 void function can't return a value 85.9 void function can't return a value 88.9 void function can't return a value 91.9 void function can't return a value と、的外れ的なコンパイルエラーが出ます。 そして、 main()関数のIoport()関数の後に書くと、 何故か正常動作し実際に書き込んでも正常に動作します。 後 書く順番によっては T0IF = 0; GIE = 1; T0IE = 1; と書くとGIEビットは1にセットされるが、T0IEビットは無視され飛び越えます。 新規projectで再度試しましたが同じでした。 これは、コンパイラのバグなのでしょうか? 解決策の回答をお願いします。

  • 割り込みのカウントの仕方

    c言語、PICともに素人です。 あるサイトのプログラムで、割り込みを使いLEDを点滅させるというものがありました。 割り込み時毎にLEDへの出力を反転させているだけです。 しかし、これだとLEDの点滅が速いのでもう少し遅くしようと、割り込み10回で出力を反転させるようなプログラムを組みました。 #include "pic.h" #include "delay.h" __CONFIG(FOSC_HS & WDTE_OFF & PWRTE_ON & CP_OFF); int a; void main(void) {  GIE = 1;  T0IE = 0;  T0CS = 0;  PSA = 0;  OPTION_REG |= 0x07;  TMR0 = 0x00;  TRISA = 0x00;  TRISB = 0x00;  a = 0;  T0IE = 1;  while(1); } void interrupt peko(void) {  if(T0IF)  {   if(a==10)   {    T0IF = 0;    PORTA ^= 0xff;    PORTB ^= 0xff;    a=0;   }   else   {    a++;   }   return;  } } aという変数をおいて、最初a=0にしておきます。 割り込みが発生するたびにaに+1していき、aが10に達した時処理をし、aを0に戻す。 これで点滅速度が1/10ぐらいになるだろうと思ったのですが、全く変わりません。 点滅はします。 一体何が違うのでしょうか。 ご教授お願いします。

  • PIC タイマー0の使い方

    PIC16F886を触り始めたのですが、タイマー割り込みで苦戦しています。 タイマー割り込みを使ったLEDの点滅の間隔が、自分の思った時間にならないのです。 下に今のプログラムを載せておきます。 私の今の考え方はこうです。 ・内部クロックは4MHzに設定してある ・TMR0のカウントはクロックの1/4らしい→1MHzなので周期は1μsec ・プリスケーラは1:128に設定→128μsecでTMR0がカウントアップ ・TMR0の初期値を61に設定→195回のカウントアップでT0IF=1 ・128μsec*195μsec=2496μsec≒0.025msec←タイマー割り込み ・40回カウントすると1秒 と、1秒ごとにLEDのON,OFFが切り替わるはずだと考えているのですが、書き込んで計測したところ、約0.8秒でon,offを繰り返しています。 私の考え方やプログラムに間違いがあるのでしょうか? もしくはPICがハード的に壊れているのでしょうか?(picに5Vをかけても動かず、mainが実行中に点灯するLED(この時点では点いていない)の端子の両端を指で触ると何故か動き出します。) 以下プログラムです。(注釈などは省いたので見難いかもしれません) #include <stdio.h> #include <stdlib.h> #include <xc.h> #include <pic.h> #pragma config FOSC = INTRC_NOCLKOUT #pragma config WDTE = OFF #pragma config PWRTE = OFF #pragma config MCLRE = OFF #pragma config CP = OFF #pragma config CPD = OFF #pragma config BOREN = ON #pragma config IESO = OFF #pragma config FCMEN = OFF #pragma config LVP = ON void interrupt tc_int(void); volatile unsigned int cnt = 0; volatile unsigned int cnt1 = 0; #define sw RB0 #define led RA0 #define led2 RA1 #define led3 RA2 #define _XTAL_FREQ 4000000 void init(void) //初期設定 { OSCCON=0b01101000; // 内部クロック設定 4MHz TRISA=0b00000000; TRISB=0b00000000; TRISC=0b00000000; ANSEL=0x00; /* 割り込み初期設定 */ GIE = 1; // すべての割り込みを許可 T0IE = 0; // タイマー割り込みを禁止 T0CS = 0; // TIMAR0モジュールをタイマーとして使用 PSA = 0; // プリスケーラをTIMER0モジュール用にセット OPTION_REG |= 0x06; // CPUクロックを128分周 TMR0 = 61; // カウンタ値をリセット T0IE = 1; // タイマー割り込みを許可 T0IF = 0; // 割り込みフラグをクリア } int main(void) { init(); sw=1; led=1; led3=0; cnt1=0; LEDflg=0; while(1) { if(cnt1>=10){ led3=~led3; cnt1=0; } } } void interrupt tc_int(void){ // 割り込みハンドラ if(T0IF == 1){ cnt++; TMR0=61; T0IF = 0; // 割り込みフラグをクリア if(cnt>=40){ cnt=0; cnt1++; led2= ~led2; } } }

  • picのタイマ1発振開始時間に関して

    マイコン Pic16F1939を使用して回路を組み、タイマ1を外部に取り付けた水晶で 動作させています(pic自体は内部オシレータで8MHzで動作させ、Timer1は正確な 1秒を取得するために使用しています) 使用している水晶は32768Hzの時計用のものです。 タイマ1が0.5秒ごとにオーバーフローするように設定し、割込みの関数で液晶の 点滅処理をおこなっています。 水晶の両端はそれぞれコンデンサが添付画像のような接続でつながっています。 また、関連部分のプログラムの抜き出しは以下のようになっています。 // 割込み処理 static void interrupt isr(void) { if (PIR1bits.TMR1IF) { // 32Khz水晶 割込み Int_Timer1(); } ~ 省略 ~ } // タイマー1割り込み(32khz水晶) : 0.5秒ごと void Int_Timer1(void) { PIR1bits.TMR1IF = 0; // 次の割り込み許可のためクリア // 0.5秒で次の割り込みが発生するように設定 TMR1H = 0b11000000; TMR1L = 0b00000000;     ~ 点滅処理 ~     ~省略~ return; } そして以下の初期設定用関数 InitTimer1()と InitInterrupt()を main()の始めに呼んでいます。 // Timer1 setting 32kHz , external crystal void InitTimer1(void) { T1CONbits.TMR1CS1 = 1; T1CONbits.TMR1CS0 = 0; T1CONbits.T1CKPS1 = 0; T1CONbits.T1CKPS0 = 0; T1CONbits.nT1SYNC = 1; T1CONbits.T1OSCEN = 1; T1CONbits.TMR1ON = 1; } // 割込み初期化 void InitInterrupt(void) { PIE1bits.TMR1IE=1; // enable timer 1 interrupt INTCONbits.PEIE=1; INTCONbits.GIE=1; } 質問なのですが、実際に液晶が点滅するまでに2秒ほどかかっています。 どこかのホームページでタイマ1の水晶の発振が安定するまでに 数msecかかるというような情報が書いてあったので、ずいぶん 遅いなと感じ2つのコンデンサの容量を10pF~200pFくらいのあいだで色々 変更して試しているのですが、2秒より早く点滅開始となることはありませんでした。 これは、上記プログラムの問題なのでしょうか? それとも2秒ほどかかって発振するのは仕方ない(Picの仕様)なのでしょうか? どなたかご存知の方いらっしゃいましたらご回答をお待ちしております。

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

  • PIC12F683を用いたCapture実験

    いま、PIC12F683を用いてCCPモジュールのCapture機能の実験をしています。一応、ビルドはできたので書き込んで動かしてみましたが、思ったとおり(スイッチを押したときにLEDを点灯させる)に動作しませんでした 動作はとしては、押しボタンスイッチを押したときにキャプチャーして LEDを点灯させるという簡単なものです。 下に使用しているプログラムを掲載しますので、どうしたらいいか教えてください。 // CaptureTest.c #include <pic.h> #include "delay.h" #include "CCP.h" __CONFIG( FCMDIS & IESODIS & BORDIS & WDTDIS & UNPROTECT & UNPROTECT & MCLRDIS & PWRTEN & INTIO); __IDLOC(0x00); unsigned char temp; ioport(); main(void) { //ポートの初期化、入出力設定など     ioport(); //Captureモード、立ち上がりエッジに設定 setCcpMode(CCP_CAPUTURE_PGE);      //フラグ(CCP1IF)を「0」にセット ResetCcpFlag();      //CCP割り込み許可 setCcpEnable(ENABLED); //TIMER1のプリスケーラを「1/8」に設定      T1CKPS1=1; T1CKPS0=1;     //外部回路を動作させない T1OSCEN=0;     //TIMER1を同期モードにセット T1SYNC=0;     //TIMER1のクロックは内部クロックを使用 TMR1CS=0;     //全割り込み、周辺割り込み許可 GIE=1; PEIE=1;      //TIMER1をリセット(0セット) ResetTMR1(); //TIMER1スタート     T1_START();      //CCP割り込みフラグが立つまでチェック while(ChkCcpFlag()==0);     //CCP割り込みフラグクリア ResetCcpFlag();     //GP3をハイレベルに設定してLEDを点灯 temp=1; GPIO3=temp; } ioport() { ANSEL=0x00; TRISIO=0x04; } //CCP.c #include <pic.h> void setCcpMode(unsigned char mode) { CCP1CON= mode; } void setPwmPeriod(unsigned char T) { PR2=(T-1); } void setPwmDuty(unsigned int duty) { DC1B0 = 0x01&duty; DC1B1 = 0x02&duty; CCPR1L = 0xFC &duty; } void setCcpEnable(unsigned char flag) { CCP1IE=flag; } void ResetCcpFlag(void) { CCP1IF=0; } unsigned char ChkCcpFlag(void) { unsigned char ret=0; if(CCP1IF==1) return ret=1; return ret; } void ResetTMR1(void) { TMR1H=0x00; TMR1L=0x00; } void T1_START(void) { TMR1ON=1; } void T1_STOP(void) { TMR1ON=0; } //CCP.h #define ENABLED 1 #define DISABLED 0 #define CCP_OFF 0x00 #define CCP_CAPUTURE_NGE 0x04 #define CCP_CAPUTURE_PGE 0x05 #define CCP_CAPUTURE_4th_PGE 0x06 #define CCP_CAPUTURE_16th_PGE 0x07 #define CCP_COMPARE_SET_ON_MATCH 0x08 #define CCP_COMPARE_CLR_ON_MATCH 0x09 #define CCP_COMPARE_INT 0x0A #define CCP_COMPARE_RESET_TIMER 0x0B #define CCP_PWM 0x0C extern void setCcpMode(unsigned char); extern void setPwmPeriod(unsigned char); extern void setPwmDuty(unsigned int); extern void setCcpEnable(unsigned char); extern void ResetCcpFlag(void); extern unsigned char ChkCcpFlag(void); extern void ResetTMR1(void); extern void T1_START(void); extern void T1_STOP(void);

  • PIC12F683 のULPW機能につきまして

    PIC12F683の機能のUltra Low-Power Wake-up の機能使おうとこちらhttp://www.picfun.com/pic26.htmlを参考にさせていただいて、GP0に抵抗と、コンデンサをR=200Ω、C=0.1μFで動かしてみました。 取りあえずは動作した(オシロできちんとのこぎりの波形を確認でました)のですが、しばらくすると、GP0がHiの状態のままになってしまいます。 このような現象を経験された方はいないでしょうか? 情報があれば助かります。 この動作を行うためのプログラムは以下のようにしてみました。 (MikroCを使っています) *****************************************************/ #define _ON 1 #define _OFF 0 #define _INPUT 1 #define _OUTPUT 0 #define SIG GPIO.F1 #define PWR GPIO.F5 void interrupt() { // 全体割り込み停止しているので、GPIO.1pin に変化があっても、ここの関数は呼び出されない if (INTCON.GPIF) { INTCON.GPIF = 0; // Port Change Interrupt Flag clear // GPIO.F1 = 1; // delay_ms(700); // 700ms LED ON // GPIO.F1 = 0; } } void opl_sleep() { INTCON.GIE = 0; //全体割り込みは停止 IOC = 0b00000001; // Interrupt pin GP0 only //1pinだけ検知する。 INTCON.GPIF = 0; // Port Change Interrupt Flag clear INTCON.GPIE = 1; //Enables the GPIO port change interrupt //ポート割り込み有効にすればsleepから復帰 TRISIO.F0 = _INPUT; // Input PCON.ULPWUE = _ON; SIG = _OFF; // Low sleep_start: asm{ nop nop nop nop sleep nop nop nop nop } INTCON.GPIE = 0; // disable GPIO port change interrupt INTCON.GPIF = 0; // Port Change Interrupt Flag clear //場合によっては、ここにチャタリング処理(wait)を入れると良い // INTCON.GIE = 1; } void _FloatValToStr( float val, char* str ) { unsigned char ch = 0x00; int val2; val2 = val * 1000; // val2 = val; ch = (val2 / 1000) % 10; // extract 1.0 volts digit str[0] = 48+ch; // write ASCII digit at cursor point str[1] = '.'; ch = (val2 / 100) % 10; // extract 0.1 volts digit str[2] = 48+ch; // write ASCII digit at cursor point ch = (val2 / 10) % 10; // extract 0.01 volts digit str[3] = 48+ch; // write ASCII digit at cursor point ch = val2 % 10; // extract 0.001 volts digit str[4] = 48+ch; // write ASCII digit at cursor point str[5] = 0x00; } void _CheckADC() { short i; double adc; double val = 0; char str[10]; //センサー信号取り込み ( Vref=3.0V : 実測値 ) adc = Adc_Read(2); val = (double)( adc * 300 ) / 1023; val = val / 100; // _FloatValToStr( val, str ); if ( val > 2.5 ) { // センサーに圧が掛かった! PWR = _ON; Delay_ms( 2000 ); PWR = _OFF; } } void main() { unsigned int co; ANSEL = 0b00100; // Configure AN pins as digital // CMCON = 7; // Turn off the comparators OSCCON = 0b01110000; // クロックを8Mhzに設定する。 CMCON0 = 0b00000111; // コンパレータ使用しない PCON = 0b00100000; // Ultra Low-Power Wake-up enabled TRISIO = 0b00000101; //GP0 pin input GPIO = 0; OPTION_REG.NOT_GPPU = 0; //GPIO pull-ups are enabled //内部弱プルアップに設定する WPU = 0b00000001; //PULL-UP REGISTER setting ,only GP0 pull-up SIG = _OFF; while( 1 ) { TRISIO.F0 = _OUTPUT; // Output GPIO.F0 = _ON; // Hi delay_ms(10); /*** for(co=0;co<10;co++){ //500ms だけLEDをピカピカッとやる GPIO.F1 = ~GPIO.F1; delay_ms(50); } **/ opl_sleep(); //SLEEPへ SIG = _ON; _CheckADC(); delay_ms(40); } }

専門家に質問してみよう