BTFSC 分岐命令の不思議

このQ&Aのポイント
  • PIC16F886でスイッチフラグ変数を制御する際に、BTFSC命令が上手く動作しない現象についての疑問
  • シミュレーションでステップごとに確認したところ、フラグの状態によってジャンプが正常に行われないことが判明
  • 解決策として、BTFSC命令の後にGOTO命令を挿入することで正常な動作が確認できた
回答を見る
  • ベストアンサー

BTFSC 分岐命令の不思議

PIC アセンブラを勉強し始めたばかりの者です。今あるモノを PIC16F886 で作っています。 PORTB 変化割り込み機能を使い、スイッチ RB7 が H→L で割り込みが掛かるようにしました。 そのルーチンの中で、スイッチフラグ変数 F_SW を MOVLW 1 XORWF F_SW,F のように押されるたびに反転します。 次に BTFSC F_SW,0 BSF PORTC,3 BCF PORTC,3 のようにしてフラグの状態によって RC3 を H にしたり L にしたいんですが、これが上手く動作しないのです。 試しにシミュレーションで 1 ステップづつ確かめてみると、F_SW = 1 だと BTFSC の次の行、0 だと 1 つ先にジャンプします。 ここまでは良いのです。 ところが、F_SW = 1 の場合、 BSF PORTC,3 に行って RC3 が H になったあと、次のステップでなぜか L に戻るのです。 これを発見するまで 3 日ほど悩みました。 ふと思い、以下のようにすると思い通りの動作をしてくれるようになりました。 BTFSC F_SW,0 GOTO HANDAN_ON GOTO HANDAN_OFF HANDAN_ON BSF PORTC,3 ; 制御 ON GOTO INTR_END HANDAN_OFF BCF PORTC,3 ; 制御 OFF ; 割り込み終了 INTR_END なぜなんでしょう?

  • Lucus
  • お礼率86% (212/244)

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

  • ベストアンサー
noname#159916
noname#159916
回答No.1

詳しくないですが。 (1)BTFSCF_SW,0 (2)BSFPORTC,3 (3)BCFPORTC,3 F_SWのbit0が0 の 時は (2)をスキップする。つまり(1)→(3) F_SWのbit0が1 の 時は (2)をスキップしない。つまり(1)→(2)→(3) つまり、どっちの場合も(3)によりクリアされる。 という事だと思いますが。 >RC3 が H になったあと、次のステップでなぜか L に戻るのです。 次のステップは Low にする命令だから、でしょう。

Lucus
質問者

お礼

まったくお恥ずかしい限りです。 umamimiさんの回答を見て「そりゃそーだ!」と顔が赤くなりました。 F_SW が 1 の場合、 (2) のあと (3) が実行されますね。 これを (2) のあと (3) を飛び越える物だと思いこんでしまっていました(笑) 本当にありがとうございました!

関連するQ&A

  • PIC16F84Aで出力が反転してしまう

    PIC16F84Aを用いて、矩形波を出そうとしています。 下記のようなプログラムを動かそうとしているのですが、 PORTA,1をONした時、出力がすべて反転してしまいます。 原因はどのような事が考えられますでしょうか? PORTA,0:矩形波の波長 PORTA,1:入力トリガが立ち上がりか立ち下がりか? PORTA,2:矩形波を立ち上がりにするか、立ち下がりにするか? PORTA,3:LED用出力 PORTA,4:手動トリガスイッチ PORTB,4~7:出力 で行っています。 ラベルL_Hの所で、出力はBCFで0になっているはずですが、 すべて1出力になります。 トリガを入れた時の出力も反転された状態になります。 ----------------------- LIST P=PIC16F84A ; LIST宣言で使用するPICを16F84Aと定義する。 INCLUDE P16F84A.INC ; 設定ファイルp16f84a.incを読み込む。 __CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF ; ;変数の設定(タイマ用カウンタ)********************* CNT1 EQU 0CH CNT2 EQU 0DH CNT3 EQU 0EH CNT4 EQU 0FH CNT5 EQU 10H CNT6 EQU 11H ;リセット************** ORG 0 ;リセット ;初期設定************* CLRF PORTB ;PORT-Bをオール0 BSF STATUS,RP0 ;バンク1へ MOVLW B'00001111' ;00001111 MOVWF TRISB ;PORT Bを0-3を入力、4-7を出力として設定 MOVLW B'10111' ;00010111 MOVWF TRISA ;PORT Aを0-3を入力、4を出力として設定 NOP BCF PORTB,4 ;PORTB,4~7をオール0 BCF PORTB,5 ;PORTB,4~7をオール0 BCF PORTB,6 ;PORTB,4~7をオール0 BCF PORTB,7 ;PORTB,4~7をオール0 BSF PORTA,3 ;PORTA,3を1 CLRF CNT1 CLRF CNT2 CLRF CNT3 CLRF CNT4 CLRF CNT5 CLRF CNT6 ;入力が1か0か?************************ Trig_Direc NOP BTFSS PORTA,1 ;入力判定が立ち上がりの時 GOTO Diec_Hight GOTO Direc_Low ;入力立ち上がり、出力判定******************* Diec_Hight BTFSS PORTB,2 ;連続波出力の時 GOTO H_Comti BTFSS PORTA,2 ;出力判定が立ち上がりの時 GOTO H_H ;入力立ち上がり、出力立ち上がり GOTO H_L ;入力立ち上がり、出力立ち下がり ;入力立ち下がり、出力判定***************************************** Direc_Low BTFSS PORTB,2 ;連続波出力の時 GOTO L_Comti BTFSS PORTA,2 ;出力判定が立ち上がりの時 GOTO L_H ;入力立ち下がり、出力立ち上がり GOTO L_L ;入力立ち下がり、出力立ち下がり ;入力立ち上下がり、出力立ち上がり トリガ入力判定と出力************ H_H BCF PORTB,4 ;Trig出力1 OFF BCF PORTB,5 ;Trig出力2 OFF BCF PORTB,6 ;Trig出力3 OFF BCF PORTB,7 ;Trig出力4 OFF BSF PORTA,4 ;LED点灯 off ~正常出力 ・ ・ ・ ;入力立ち上下がり、出力立ち上がり トリガ入力判定と出力*************** L_H BCF PORTB,4 ;Trig出力1 OFF BCF PORTB,5 ;Trig出力2 OFF BCF PORTB,6 ;Trig出力3 OFF BCF PORTB,7 ;Trig出力4 OFF BSF PORTA,3 ;LED点灯 off L_H_ON BTFSS PORTB,0 ;トリガ入力1に入力があった場合 GOTO L_H_Time BTFSS PORTB,1 ;トリガ入力2に入力があった場合 GOTO L_H_Time BTFSS PORTA,4 ;手動トリガ入力に入力があった場合 GOTO L_H_Time GOTO Trig_Direc ;トリガ入力がなかった場合、初期判定に戻る L_H_Time BCF PORTA,3 ;トリガ判定LED点灯 BTFSS PORTA,0 ;パルス幅が50ms指定の場合」 GOTO L_H_50 GOTO L_H_200 L_H_50 BSF PORTB,4 ;Trig出力1 ON BSF PORTB,5 ;Trig出力2 ON BSF PORTB,6 ;Trig出力3 ON BSF PORTB,7 ;Trig出力4 ON CALL Timer_50ms BCF PORTB,4 ;Trig出力1 OFF BCF PORTB,5 ;Trig出力2 OFF BCF PORTB,6 ;Trig出力3 OFF BCF PORTB,7 ;Trig出力4 OFF CALL Timer_50ms GOTO L_H_Loop L_H_200 BSF PORTB,4 ;Trig出力1 ON BSF PORTB,5 ;Trig出力2 ON BSF PORTB,6 ;Trig出力3 ON BSF PORTB,7 ;Trig出力4 ON CALL Timer_200ms BCF PORTB,4 ;Trig出力1 OFF BCF PORTB,5 ;Trig出力2 OFF BCF PORTB,6 ;Trig出力3 OFF BCF PORTB,7 ;Trig出力4 OFF CALL Timer_200ms GOTO L_H_Loop L_H_Loop BTFSC PORTB,0 ;トリガ入力1が出力状態だった場合 GOTO L_H_Loop BTFSC PORTB,1 ;トリガ入力2が出力状態だった場合 GOTO L_H_Loop BTFSS PORTA,4 ;手動トリガ入力に入力があった場合 GOTO L_H_Loop BSF PORTA,3 ;トリガ判定LED消灯 GOTO Trig_Direc ;初期へ戻る ・ ・ ・ 以下略

  • PICの条件分岐について

    お世話になります。PICについて質問があります。ボタンを押せば、PORTBのLEDに対する出力が変わるという物ですが、意図したようになりません。PORTに対する設定は間違っていないと思うのですが、チャタリングを考慮したプログラムになっており、上手く条件分岐してくれません。条件というのは、PORTAに入力があれば、25ms待機して再度PORTAを見に行きます。そのときにもPORTAに入力があれば、変数に格納した数値を一つずつ減らしていき、そのときに0であればPORTBを設定したとおりに出力するというものです。以下がソースですが、ここがおかしいということだけでも教えてくださると助かります。よろしくお願いします。 list p=16f628a #include<p16f628a.inc> __CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _LVP_OFF SWI equ 0x21 SWI2 equ 0x22 CNT1 EQU 0x20 CNT2 EQU 0x21 ORG 0x000 goto main ORG 0x004 main bcf STATUS,RP0 bcf STATUS,RP1 clrf INTCON clrf PORTA movlw 0x07 movwf CMCON bsf STATUS,RP0 bsf PCON,OSCF clrf TRISB movlw 0x03 movwf TRISA bcf STATUS,RP0 clrf PORTA clrf PORTB clrf SWI main_loop btfss PORTA,1 goto flase_wait_routine goto trues_wait_routine flase_wait_routine goto main_loop trues_wait_routine call DLY_25 btfss PORTA,1 goto main_loop incf SWI,f movf SWI,W movwf SWI2 decfsz SWI2,f goto a_loop_1 bsf PORTB,0 bcf PORTB,1 bcf PORTB,2 bcf PORTB,3 goto main_loop a_loop_1 decfsz SWI2,f goto a_loop_2 bcf PORTB,0 bsf PORTB,1 bcf PORTB,2 bcf PORTB,3 goto main_loop a_loop_2 decfsz SWI2,f goto a_loop_3 bcf PORTB,0 bcf PORTB,1 bsf PORTB,2 bcf PORTB,3 goto main_loop a_loop_3 decfsz SWI2,f goto a_loop_4 bcf PORTB,0 bcf PORTB,1 bcf PORTB,2 bsf PORTB,3 clrf SWI goto main_loop a_loop_4 goto main_loop ;Delay Routine DLY_25 ; 25ms movlw d'25' movwf CNT1 DLP1;1ms movlw d'20' movwf CNT2 DLP2 nop nop decfsz CNT2,f goto DLP2 decfsz CNT1,f goto DLP1 return END

  • PIC16F819とMAX232Cについて困っています。

    まだ駆け出しでわからないことだらけで、以下のプログラムをふまえてPIC16F819とMAX232C(RS232C?)を接続したいのですが、どうプログラム(アセンブラ)を追加したら、また回路的にどうしたらいいのかわからないので教えてください。以下のプログラム(コメント省略)は、電圧変化により出力(LEDの点灯数の変化)を行ったものです。 LIST p=PIC16F819 #include <P16F819.inc> __CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _LVP_OFF AD_DATA_H EQU 20h AD_DATA_L EQU 21h WAITCOUNT EQU 22h ORG H'00' GOTO START ORG H'04' GOTO START ;------------------------------ ; 初期設定 ;------------------------------ START BSF STATUS, RP0 BCF ADCON1, ADFM BCF ADCON1, ADCS2 BSF ADCON1, PCFG3 BSF ADCON1, PCFG2 BSF ADCON1, PCFG1 BCF ADCON1, PCFG0 MOVLW B'00000001' MOVWF TRISA MOVLW B'00000000' MOVWF TRISB BCF STATUS, RP0 CLRF ADCON0 CLRF PORTA CLRF PORTB ;------------------------------- ; メインルーチン ;------------------------------- MAIN CALL AD_CONVERT MOVLW b'10000000' SUBWF AD_DATA_H, W BTFSC STATUS, C GOTO V_UPPER_HALF GOTO V_LOWER_HALF V_UPPER_HALF MOVLW b'11000000' SUBWF AD_DATA_H, W BTFSC STATUS, C GOTO V_3_4 GOTO V_1_2 V_LOWER_HALF MOVLW b'01000000' SUBWF AD_DATA_H, W BTFSC STATUS, C GOTO V_1_4 GOTO V_ZERO V_3_4 MOVLW b'00000111' MOVWF PORTB GOTO MAIN V_1_2 MOVLW b'00000011' MOVWF PORTB GOTO MAIN V_1_4 MOVLW b'00000001' MOVWF PORTB GOTO MAIN V_ZERO MOVLW b'00000000' MOVWF PORTB GOTO MAIN ;--------------------------------- ; A/D 変換サブルーチン ;--------------------------------- AD_CONVERT MOVLW B'10000001' MOVWF ADCON0 CALL WAIT_100U BSF ADCON0, GO BTFSC ADCON0, GO GOTO ADLOOP MOVF ADRESH, W MOVWF AD_DATA_H MOVF ADRESL, W MOVWF AD_DATA_L RETURN ;------------------------------------------------------------ ; 100usec ( 100usec = 0.2u/Cycle at 20MHz x 500 ) ;------------------------------------------------------------ WAIT_100U MOVLW D'165' MOVWF WAITCOUNT WAIT_100UL DECFSZ WAITCOUNT,F GOTO WAIT_100UL RETURN END 長くなりましたがご教授どうかお願いします。

  • PICのスイッチのプログラムについて

    基本的な事なのですが、よろしくお願いします。 以下のアセンブラのソースでPICを作ってみました。プログラムを変えてみたり、回路を変えてみたりしましたが、改善されませんでした。回路の構成は、LED(仮に、A・Bとします)2個、スイッチ1個、PIC、抵抗器など・・・これを交互にスイッチのオンオフで切り替える。としています。現状の問題点は、スイッチ入力で、LEDAは光るときは綺麗に光りますし、消えるときは綺麗に消えます。問題は、LEDBのほうで、光るときに高速で点滅します。理由と対策が解りません。どなたか教えてください。よろしくお願いします。 list p=16f628a #include<p16f628a.inc> __CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _LVP_OFF ORG 0x000 goto main ORG 0x004 main bcf STATUS,RP0 bcf STATUS,RP1 clrf INTCON clrf PORTA movlw 0x07 movwf CMCON bsf STATUS,RP0 bsf PCON,OSCF clrf TRISB movlw 0x03 movwf TRISA bcf STATUS,RP0 clrf PORTA clrf PORTB main_loop btfsc PORTA,0;この辺りがよくわかりません。 goto loop2 bsf PORTB,0 bcf PORTB,1 goto main_loop loop2 bcf PORTB,0 bsf PORTB,1 goto main_loop END

  • PIC16F88の使い方?に関する質問(アセンブラ)

    現在PICの16F88に書きこむプログラムをアセンブラで書いてます。4番ピンのMCLRをRA5として使いたいのですが、MPLABのWATCHの機能を使って、ポートAの動きを見てみると、ポートAが出力になっているはずなのに、何をしてもポートAの0~4がHにならず、ポートAのRA5はBSF,BCFの命令が利きません。コンフィグの設定が怪しいと思うのですが、自分には理由が分からないので、誰か教えてください。お願いします。(下に書いたプログラムはテスト用に書いたプログラムなので特に目的はありません) ;外部発振,セラロック20MHz使用 LIST P=PIC16F88 INCLUDE P16F88.INC __CONFIG _CONFIG1, _CP_OFF & _DEBUG_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF BSF STATUS,RP0 MOVLW B'000000' MOVWF TRISA MOVLW B'00000000' MOVWF TRISB BCF STATUS,RP0 MAIN CLRF PORTA MOVLW B'11111111' MOVWF PORTA MOVWF PORTB BSF PORTA,0 BCF PORTA,0 BSF PORTA,1 BCF PORTA,1 BSF PORTA,2 BCF PORTA,2 BSF PORTA,3 BCF PORTA,3 BSF PORTA,4 BCF PORTA,4 BSF PORTA,5 BCF PORTA,5 GOTO MAIN END

  • PIC 初歩プログラムについて

    PICの初めてのプログラムを書いたのですがテキストのように動きません。 ORG 0 ; MAIN  BSF STATUS,RP0 MOVLW B'00000000' ;ポートB 出力 MOVWF TRISB ; MOVLW B'00001111' ;ポートA 0,1,2,3入力 MOVWF TRISA ; BCF STATUS,RP0 SW BTFSS PORTA,0 GOTO  LED1 BTFSS PORTA,1 GOTO LED2 GOTO SW LED1 MOVLW B'00000010' MOVWF PORTB GOTO SW LED2 MOVLW B'00000001' MOVWF PORTB GOTO SW END 入力SWを押していないときがHIです。したがって何もしなければSWのループになると思うのですが、LED2に行ってしまいます。BTFSC POARTA,1とすればSWループ状態ですがテキストとは違います。 何かおかしいのでしょうか?

  • PICの誤動作についての質問です

    現在PIC18F24K20というPICを使用していて、2つの入力信号に対して、1ビットずつ判定を行いその2つの信号が間違っていればPORTBを+1してカウントしていくというプログラムを作っています。 RC0、RC2から信号を入力しています。Receive0でまずタイミングを合わせて、Receiveで間違っているかの判定を行うというプログラムです。 Receive0 BTFSS PORTC,0 ;RC0がHighなら次の命令をスキップ GOTO Receive0 NOP NOP NOP NOP NOP ;*** 入力信号の解析 Receive BTFSS PORTC,0 ;RC0がHighなら次の命令をスキップ GOTO ZERO BTFSS PORTC,2 ;RC2がHighなら次の命令をスキップ INCF PORTB,F ;PORTBを+1 NOP GOTO Receive ZERO BTFSC PORTC,2 ;RC2がLowなら次の命令をスキップ INCF PORTB,F ;PORTBを+1 NOP GOTO Receive (PORTの設定は省かせてもらっています) プログラムにおかしい点があれば指摘していただければうれしいです。 回路は入力をFPGAから直接RC0、RC2に入力して、PORTBも開放してロジアナで波形を観測しています。 ロジアナで見ると思っているような動作ではなく、PORTBが勝手にHighやLowになってしまっています。どのようなことが問題になっているのでしょうか?

  • フローチャート、教えて!

    このプログラムのフローチャートなんですけど・・・。 list P=PIC16F84A INCLUDE "P16F84A.INC" __CONFIG _HS_OSC&_WDT_OFF&_PWRTE_ON ; WCNT EQU 018H ; ORG 0 GOTO START ; ORG 05H ; START BSF STATUS,RP0 MOVLW 03H MOVWF TRISA BCF STATUS,RP0 ; st CALL SPEAKER goto st ; SPEAKER BCF PORTA,2 CALL WAIT2 BSF PORTA,2 CALL WAIT2 RETURN ; WAIT2 MOVLW D'249' ; MOVWF WCNT ; WAIT3 NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; DECFSZ WCNT,F ; GOTO WAIT3 ; RETURN ; ; WAIT4 NOP ; DECFSZ WCNT,F ; GOTO WAIT3 ; RETURN ; END ; ちょっと見難いですね、ごめんなさい;; このプログラムなんだけど、自分では良く分からなくて(@@; アセンブラ?だっけこれ、これでフローチャート作ったことないんだよね・・・。 簡単なフローチャート図なら作ったことあるけど、ほんと基本的な物だったからねぇ。 どうか、教えてください!

  • PICでLEDを点滅させる

    16F628Aを使ってLEDが点滅するプログラム作ることはできたのですが、それを16F873A用に組み替えてみたのですが点滅せずに点灯したままになります。ハード的な問題なのかそれともプログラム問題なのかがわかりません。マイコンの勉強をはじめたばかりなのでお教えいただければたすかります。 ちなみにプログラムは以下のようになっています。クロックは10MHzです。 開発環境はMPLABをつかっていて秋月のキットを使って書き込んでいます。 ; ; ; list p=pic16f873a #include <P16F873A.INC> __CONFIG _WDT_OFF & _HS_OSC & _CP_OFF & _PWRTE_ON & _LVP_OFF COUNT EQU 20H COUNT1 EQU 21H ORG 0 MAIN BSF STATUS,RP0 CLRF TRISA CLRF TRISB CLRF TRISC BCF STATUS,RP0 MOVLW B'11111111' MOVWF PORTC CALL LA CLRF PORTC CALL LA GOTO MAIN LA MOVLW B'11111111' MOVWF COUNT LOOP2 MOVLW B'11111111' MOVWF COUNT1 LOOP NOP NOP NOP NOP NOP NOP NOP DECFSZ COUNT1,1 GOTO LOOP DECFSZ COUNT,1 GOTO LOOP2 RETURN END

  • PIC初心者です。 PIC16F88のLED制御で以下のプログラムを実

    PIC初心者です。 PIC16F88のLED制御で以下のプログラムを実行すると点滅を繰り返します。 意図としては1度だけ光って消えてほしいのですが… CONFIG部分がおかしいのでしょうか? 環境として、PCはVista、MPLABとPICkit2を使用しています お分かりになる方、お願いいたします。 以下ソースです LIST P=PIC16F88 INCLUDE "P16F88.INC" __CONFIG _CONFIG1, _INTRC_IO & _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_OFF & _PWRTE_ON & _WDT_OFF __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_ON BSF STATUS,RP0 CLRF TRISB BCF STATUS,RP0 BCF STATUS,0 CLRF PORTB MAIN BSF PORTB,0 NOP NOP NOP (以下、NOPが100個ほど) NOP BCF PORTB,0 END