質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

3217閲覧

PIC16F USART割り込み

raspypy

総合スコア247

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2019/04/16 07:12

編集2019/04/17 04:23

##USARTの割り込みプログラムについて

受信割り込みでLEDを点灯させるプログラムを作成しています。
'X'を受信すると、割り込みが発生し、LEDが5回点滅するというプログラムです。

##困っていること
割り込みは発生するのですが、一度しか発生しません。
電源ON後、1回目の'X'受信では、確かにLEDが5回点滅しますが、
2回目の'X'受信では、割り込みプログラム(LED点滅)へ移行しません。

##プログラムコード

html

1#include <xc.h> 2 3// CONFIG1 4//(省略) 5 6// CONFIG2 7//(省略) 8 9#define LED1 LATCbits.LATC0 10#define _XTAL_FREQ 8000000 11#define __delay(X) _delay((unsigned long)((X))) 12#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0))) //msec delay 13 14unsigned char rx_data; 15int rx_flg = 0; 16int i=1; 17 18void main(void) { 19 OSCCON=0x72; 20 ANSELA=0x04; 21 ANSELC=0x00; 22 TRISA=0x04; 23 TRISC=0x28; 24 LATC=0x00; 25 26 RXDTSEL = 0; 27 TXCKSEL = 0; 28 TXSTA = 0x24; 29 RCSTA = 0x90; 30 BAUDCON = 0x00; 31 SPBRGH = 0x00; 32 SPBRGL = 0x33; 33 34 RCIF = 0; 35 RCIE = 1; 36 PEIE = 1; 37 GIE = 1; 38 39 while(1){ 40LED1=1; 41 } 42} 43 44void interrupt Rx( void ) 45{ 46 if (RCIF == 1) { 47 RCIF = 0 ; 48 rx_data = RCREG ; 49 rx_flg = 1 ; 50 if(rx_data == 'X'){ 51 while(i<=5){ 52 LED1=1; 53 __delay_ms(100); 54 LED1=0; 55 __delay_ms(100); 56 i=i+1; 57 } 58 } 59 } 60}

##修正後(割り込みプログラム部)

html

1void interrupt Rx( void ) 2{ 3int i; 4GIE = 0; 5 if (RCIF == 1) { 6 RCIF = 0 ; 7 rx_data = RCREG ; 8 rx_flg = 1 ; 9 if(rx_data == 'X'){ 10 for(i=0;i<5;i++){ 11 LED1=1; 12 __delay_ms(100); 13 LED1=0; 14 __delay_ms(100); 15 i=i+1; 16 } 17 } 18 } 19GIE = 1; 20}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

i がグローバル変数になってますが、これはローカル変数にしときましょう

int i=1;

は削除しといて、

C

1void interrupt Rx( void ) 2{ 3int i; 4 // なんやかや 5 for(i=0;i<5;i++){ 6 // なんやかや 7 } 8 // なんやかや 9}

ってのが模範解答、なんだけど、

基本的に割り込み関数というのは時間のかかる処理をしたらダメです。

#こういう実験的な動作をさせるのはべつにいいけどねっ

投稿2019/04/16 07:56

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2019/04/16 08:50

あとは、割り込み処理中に割り込み禁止になっていないので、短い間隔で割り込みあったら再入してしまうかも。割り込みハンドラの冒頭でGIE=0で割り込み禁止にして、return前にGIE=1で再度、割り込み許可した方が良いように思いました。 ※y_waiwaiさんが書かれているように、実験で、かつ分かった上でのことなら良いですけど。
raspypy

2019/04/17 00:02

回答ありがとうございます。 一度しか割り込みが発生しない理由がよく理解できました。 質問にUpした割り込みプログラムで確認してみました。 しかし、割り込み内で5回LEDを点滅させる記述をしているのですが、実際の動作では、3回の点滅しか行われません。 この理由がよくわからないのですが、 "基本的に割り込み関数というのは時間のかかる処理をしたらダメ"というコメントの通りの結果なのでしょうか。 今回は、割り込み動作の確認のために、このような処理(LED5回点滅)を入れていますが、この処理がいけないのでしょうか。
y_waiwai

2019/04/17 03:22

なぜ3回かってのは、 > i=i+1; これが余計だからです。コードの意味を考えましょう。 コードがどういう動作をするのか、あなたの頭の中で追いかけてみましょう。 なぜ割り込みで時間のかかる処理をしたらダメかってのは、割り込み処理中に次の文字の受信したらどうなるかを考えてみればわかるかと思います 一般的に割り込み処理中には同じ割り込みはかからないようになってますが、そうなるとその受信文字は失われることになりますね
raspypy

2019/04/17 05:08

i=i+1のご指摘ありがとうございました。 現象にばかり追われて、コードを見直すことを怠っていました。 意図した割り込み動作ができるようになりました。ありがとうございました。 dodox86さまから指摘の”短い間隔で割り込みあったら再入してしまうかも。”について。 割り込みハンドラの冒頭でGIE=0で割り込み禁止にして、return前にGIE=1で再度、割り込み許可するように記述しましたが、 この記述にしてしまうと、割り込み中に割り込みがあった場合、通常動作(無限ループ)に戻ってくれません。 この記述をなくして、void main()の中でGIE = 1;と設定するだけでは、割り込み中に割り込みがあった場合でも、通常動作に戻ってくれます。
dodox86

2019/04/17 05:14

>GIE=1で再度、割り込み許可するように記述しましたが、この記述にしてしまうと、割り込み中に割り込みがあった場合、通常動作(無限ループ)に戻ってくれません。 そうでしたか。今現在検証環境が無く、確認できないのですが、私が以前試したときの状況とは様々な点で違うようです。お手間を取らせてすみませんでした。
raspypy

2019/04/17 06:44

dodox86さま いえいえ。ご指摘の通り、割り込み処理中に割り込みがあった場合…を考えると、 "割り込みハンドラの冒頭でGIE=0で割り込み禁止にして、return前にGIE=1で再度、割り込み許可"するのが正解だと私も思ったのですが、実動作は逆の結果となってしまいました。
y_waiwai

2019/04/17 06:49

こうするとこうなった、で思考停止するのではダメです CPUのデータシートをよく読んで、割り込み時にどういう振る舞いをするのかを調べましょう。そこから、なぜそういう動作になるのかはわかるはずです CPUはデータシート通りにしか動きません
ikadzuchi

2019/04/17 11:13

PIC16Fは割込み時にGIEがクリアされ、割込みから復帰するRETIE命令でGIEがセットされます。ですので普通に割込みをすれば割込み処理中は割込み禁止状態になり、多重割込みは起こりません。 一方割込み処理の終了前に割込み許可すると、その時点でペンディング状態の割り込みがあれば2重に割込みが起こり、想定していなければ問題が起こります。 dodox86さんがどのような環境で試したのか分かりませんが、割込み処理終了前に割込み許可して多重割込みが起こらないような環境はあまり無いと思います。
dodox86

2019/04/17 12:16

ikadzuchiさん、フォローありがとうございます。 > 一方割込み処理の終了前に割込み許可すると、その時点でペンディング状態の割り込みがあれば2重に割込みが起こり、想定していなければ問題が起こります 確かにそうでした。microchipのPICのニーモニックのリファレンスを確認すると、 http://ww1.microchip.com/downloads/jp/DeviceDoc/31029a.pdf Section 29. Instruction Set RETFIE > The Global Interrupt Enable bit, GIE (INTCON<7>), is automatically set, enabling Interrupts. とあり、少なくとも割り込みハンドラー内でGIEを操作した方が良い旨の私の指摘は不適切です。(注意無くGIEを操作すべきではない、のが正しい) 当時試したコードや環境が正確には思い出せないのですが、チップの型番も正確には思い出せないのと、アセンブラとCで色々やっていたのに加え、あるいは割り込みハンドラー内の話ではなかったかもしれません。混乱させてしまったこと、重ねてお詫びいたします。 (本件について、今後は私の指摘事項はとりあえず脇においてください)
raspypy

2019/04/17 23:44

みなさん、ありがとうございました。
guest

0

while(i<=5){ LED1=1; __delay_ms(100); LED1=0; __delay_ms(100); i=i+1; }

だけではi>5のまま。
なので

while(i<=5){ LED1=1; __delay_ms(100); LED1=0; __delay_ms(100); i=i+1; } i = 1;

にしてみる。

投稿2019/04/16 07:41

MasahikoHirata

総合スコア3747

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問