• 締切済み

16F84A アセンブラに関する質問です。

使用環境はWindows10(64bit)、統合開発環境MPLAB X IDE v3.26、MPASMX v5.66,16F84Aによるアセンブルプログラムです。TIM0、TIM1、TIM2はGPRの初めのレジスタ3つ(0CH~0EH)に割り当ててあります。 ; ----- WAIT 0.1Sec WAIT_01S     ; {4x(y+1)+3}*0.4*(10/f) [uS] OSC:f=10MHz MOVLW 0FAH ; x=250(FAH) y=249(F9H) => 100001.2uSec(=0.1Sec) MOVWF TIM1 W1S_1 MOVLW 0F9H MOVWF TIM2 W1S_2 NOP DECFSZ TIM2,F GOTO W1S_2 DECFSZ TIM1,F GOTO W1S_1   RETURN 1.NOPを外して、TIM2を0FAHとすることはできないのでしょうか。 2.”DECFSZ TIM1,F" は、TIM1 を一つずつ減らしていきその結果を TIM1 に格納し、TIM1 がゼロになったら次の行の”GOTO~”を飛ばし( NOP に強制的に読み替え)、次の行の"RETURN"へ進む、という意味だと思いますが、 DECFSZ の第2パラメーターの F はファイルレジスタを示す F なのでしょうか。この F が W だとワーキングレジスタに関して同じ処理をする、という意味になるのでしょうか。検索して出てきた書式がいまいち理解できません。 3.ラベル WAIT01_S の2重ループですが、 10MHz で作動させこの逆数の周期×4の長さを1サイクルとしたとき、内側のループのTIM2に初期値249を与え、このTIM2を一つずつ減らしていく過程で249サイクル消費し、TIM2がゼロとなった時点でもう1サイクル、それとNOPが1サイクルの合わせて251サイクルを、この内側のループで消費すると考えたのですが、コメントを読む限りどうも違うようです。いったいこのルーチンで消費するサイクル数をどう数えるべきなのでしょうか。コメントも違うような気がします。 4.最後のRETURNはどの行に対応しているのでしょうか。()などと同じように階層的ネスティングを構成するとすれば、最も手前にあるラベルW1S_2に対応しそうですが、それでは無限ループに落ちいてしまうと思います。それとも一行を丸々ラベルだけ使ったWAIT01_Sに対応するとかの何らかのルールが存在するのでしょうか。 5.シミュレータを指定してデバッグモードで走らせたときストップウォッチで模擬的に測定してみたのですが、仮想の動作周波数が1MHzであるにもかかわらず、どこにブレークポイント行にしても表示サイクルが1uSの4倍の4uSの整数倍になりません。ブレークポイントを示す行頭の四角の真ん中にひびが入っているマークも理解できません。 もしよろしかったらお分かりのところだけでも結構です。どなたかお教えくださいませんでしょうか。よろしく願いします。

みんなの回答

  • MSZ006
  • ベストアンサー率38% (390/1011)
回答No.3

#2訂正です。 3. 内側のループがy(249)回、外側のループがx(250)回廻ります。 内側のループは、 NOP →1サイクル DECFSZ →1サイクル GOTO →2サイクル 3命令合計4サイクルがy回とループを抜ける最後に1サイクル余分にかかるので、 4y+1サイクル。さらに最終回はGOTO(2サイクル)は実行されないのでその分をマイナスすると、4y-1サイクルとなります。 外側のループは、 MOVLW →1サイクル MOVWF →1サイクル DECFSZ →1サイクル GOTO →2サイクル の4命令合計5サイクルがx回とループを抜ける際に1サイクルで5x+1ですが、内側ループ同様、最終回はGOTO(2サイクル)は実行されないので5x-1です。ループの中に内側ループがあるので、内側ループと外側ループを合わせると、 ((4y-1)+5)x-1ということになります。 これにこのサブルーチンの最初の、 MOVLW →1サイクル MOVWF →1サイクル と、最後の、 RETURN →2サイクル を加えると、 (4y+4)x+3 サイクル という計算になると思います。 x=250, y=249を代入して計算すると、合計250,003サイクルとなります。 1サイクル=4クロックで、1,000,012クロック。クロック周波数10MHzだと、0.1000012Secということになります。

poor_Quark
質問者

お礼

ステップバイステップでプログラムの進捗を考えてみてどうにか理解できる と思います。たびたびお手数おかけして申し訳ありません。

  • MSZ006
  • ベストアンサー率38% (390/1011)
回答No.2

1. W1S_2 NOP DECFSZ TIM2,F GOTO W1S_2 の三行で一つのループを作っています。NOPもTIM2回実行されることになるので、NOPを取ってTIM2を1増やす、というのとは意味合いが違うと思います。 2. 私の調べたところでは、DECFSZ TIM1,F のFは、1もしくは0の値で、0のときはワーキングレジスタに上書き、1のときはファイルレジスタ(このケースではTIM1)に上書きとなるようです。どこかでF=1という定義がされているのではないでしょうか。 3. 内側のループがy(249)回、外側のループがx(250)回廻ります。 内側のループは、 NOP →1サイクル DECFSZ →1サイクル GOTO →2サイクル 3命令合計4サイクルがy回とループを抜ける最後に1サイクル余分にかかるので、 4y+1サイクル。 外側のループは、 MOVLW →1サイクル MOVWF →1サイクル DECFSZ →1サイクル GOTO →2サイクル の4命令合計5サイクルがx回とループを抜ける際に1サイクルで5x+1ですが、ループの中に内側ループがあるので、内側ループと外側ループを合わせると、 ((4y+1)+5)x+1ということになります。 これにこのサブルーチンの最初の、 MOVLW →1サイクル MOVWF →1サイクル と、最後の、 RETURN →2サイクル を加えると、 (4y+6)x+5 サイクル という計算になると思います。 x=250, y=249を代入して計算すると、合計250,505サイクルとなります。 1サイクル=4クロックで、1,002,020クロック。クロック周波数10MHzだと、0.100202Secということになります。 4.最後のRETURNは、このWAIT_01Sはサブルーチンで、呼び出した元に帰るためのものだと思います。

poor_Quark
質問者

お礼

1と3に関してはいただいたご回答の内容をヒントによく考えてみます。 おかげさまで大きく理解が進んだと思います。 2と4はおおむね理解できたと思います。 ありがとうございました。

  • koujikuu
  • ベストアンサー率43% (428/992)
回答No.1

1) NOP を減らすと内側ループが、3*249-1=746 にしかなりません 4*249-1=995 TIM2レジスタ代入分を合わせて 995+2=997 が内側クロック数です 2) DECFSZ TIM2,F のFは演算結果をF=ファイルレジスタTIM2へ格納するか、W=Wレジスタへへ格納するかの違いです Wの時はTIM2は更新されません 3) 内側サイクルは、4*249-1+2=997 で外側サイクル (997+3)*250-1+2=250001 に RETURN を追加すると 250003 が正式クロックで 10MHz 時CPU実行クロックは2.5MHz 400μS なので 250003 × 0.0000004S ≒0.1S になります 4) WAIT_01S はサブルーチンとして、CALL で呼び出され RETURN で復帰します C言語の関数と同じです WAIT_01S();

poor_Quark
質問者

お礼

いただいたご回答を手がかりに一生懸命考えてやっと理解できそうです。 DECFSZ命令の使い方も説明いただいた内容でわかりました。 ご親切にご回答いただき感謝します。

関連するQ&A

  • このプログラムがどういう流れで動いてるか教えてください

    PICのプログラミングで以下の課題が学校ででました。 PB0~PB5まで1秒ごとに交互に点灯するプログラムを書くというものです。 CNT1 EQU 20H CNT2 EQU 21H main MOVLW B'00010101' MOVWF PORTB CALL TIM2 MOVLW B'00001010' MOVWF PORTB CALL TIM2 GOTO main TIM1 MOVLW 0F9H MOVWF CNT1 TIMLP1 NOP DECFSZ CNT1,F GOTO TIMLP1 RETURN TIM2 MOVLW 08H MOVWF CNT2 TIMLP2 CALL TIM1 DECFSZ CNT2,F GOTO TIMLP2 RETURN END 上記のプログラムで動きました。 だけど、このプログラムの流れがわからないため 説明できません。 誰かこのプログラムの流れをわかりやすく説明してください。 特にCALLとRETURN、DECFSZがどう動くかわかりません。

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

    このプログラムのフローチャートなんですけど・・・。 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 ; ちょっと見難いですね、ごめんなさい;; このプログラムなんだけど、自分では良く分からなくて(@@; アセンブラ?だっけこれ、これでフローチャート作ったことないんだよね・・・。 簡単なフローチャート図なら作ったことあるけど、ほんと基本的な物だったからねぇ。 どうか、教えてください!

  • PIC16F84Aから16F628Aの変換について

    以前PIC16F84Aで問題なく動作しているプログラムを 初期設定を変えて(これでいいのか?も疑問)16F628Aで動かそうとしていますが サブルーチンに入り「タイマー」のルーチンから抜け出せないみたいです。 BILD ALL ではエラーは出ません。 割込みは正常に動作します。 どこがいけないのでしょうか? よろしくお願いいたします。 プログラムはこちらです。 ;------------------------------------------------------------------------- ;     初期設定 list P=pic16f628a include "p16f628a.inc" __CONFIG _HS_OSC & _CP_OFF & _WDT_OFF & _PWRTE_ON & _BODEN_ON & _LVP_OFF & _MCLRE_OFF ORG 0 GOTO MAIN ;----------------------------------------------------------------------- ; 割り込み処理 ORG 4     ;割り込みアドレス CLRW CLRF PORTB     ;ポートBクリア GOTO MAIN ;----------------------------------------------------------------------- ; メインプログラム MAIN   BCF STATUS,RP0          MOVLW B'00000111'         MOVWF CMCON         BSF INTCON,INTE     ;割りこみ許可?          BSF STATUS,RP0     ;ポートAを全て入力に設定         MOVWF TRISA          MOVLW H'01'     ;ポートBは0(ゼロ)以外は出力に設定         MOVWF TRISB         MOVLW 90H     ;INT割り込み許可         MOVWF INTCON         BCF STATUS,RP0     ;ポートBをクリア         CLRF PORTB          CLRW ;---------------------------------------------------------------------- ; スイッチ入力チエック LOOP    BTFSS PORTA,0     ;オープンSWがONか?          GOTO OPEN      ;ONだったら OPENへ         GOTO LOOP ;----------------------------------------------------------------------- ; オープン動作 OPEN    MOVLW 010H      ;ポートB4番に5V出力(リレーON)          MOVWF PORTB        MOVLW D'250'      ;動作時間 '250'設定         MOVWF 0EH      ;アドレス0EHに250を入力          CALL LOOP3      ;サブルーチンLOOP3を呼び出す        GOTO MAIN      ;サブルーチンが終わったら MAIN に戻れ ;------------------------------------------------------------------------ ;----------------------------------------------------------------------- ; サブルーチン(タイマー) TIMER1    MOVLW D'220'           MOVWF 0CH LOOP1    NOP           DECFSZ 0CH,1           GOTO LOOP1         RETURN TIMER2     MOVLW D'100'      ;アドレス0DHに100を入力          MOVWF 0DH LOOP2    NOP           CALL TIMER1      ;TIMER1を呼び出し(行く)           DECFSZ 0DH,1      ;アドレス0DH から1を引き算する           GOTO LOOP2      ;結果が"0"でなかったら LOOP2に戻ってまた引き算          RETURN       ;引き算の結果が"0"になったら「CALL」した「次に(下)」へ戻る LOOP3    NOP      ;何もしない          CALL TIMER2      ;TIMER2を呼び出す(行く)         DECFSZ 0EH,1         GOTO LOOP3          RETURN END    END

  • picアセンブラ ビルドは完了するのに動かない

    なんとかかんとかMPLABでLEDが1秒間隔で交互に光るプログラムを 作ったんですが、全く動きません・・・ 考えてたら頭がこんがらがってきてしまいました。 PICは16F628Aです。 何処が悪いのか教えてください。 ポートBにつないだ8個のLEDが4個ずつ 1秒おきに交互に光るプログラムです。 なお、1秒の時間稼ぎですがこれまたこんがらがってきたので とりあえず適当に遅延させています。 ----------------------------- list p=pic16f628a include "p16f628a.inc" __config _boden_off & _cp_off & _pwrte_on & _wdt_off & _lvp_off & _mclre_off & _hs_osc time1 equ 020h time2 equ 021h time3 equ 022h time4 equ 023h org 0 goto start start bsf status,rp0 clrf trisb bcf status,rp0 main movlw b'00001111' movwf portb call jikan movlw b'11110000' movwf portb call jikan jikan movlw d'2' movwf time1 matu1 movlw d'10' movfw time2 matu2 movlw d'200' movfw time3 matu3 movlw d'200' movfw time4 matu4 nop nop decfsz time4,f goto matu4 decfsz time3,f goto matu3 decfsz time2,f goto matu2 decfsz time1,f goto matu1 return end

  • PIC16F84Aで入力があるとスタートするプログラム

    PIC16F84Aで、アセンブリ言語でプログラムをしています。 RA4を入力端子とし、入力があればプログラムがスタートするということをしたいんですけどうまくいきません。 私の作ったプログラムはこのようになっています。  listp=16f84A   include <p16f84A.inc>  __CONFIG _HS_OSC & _PWRTE_ON & _WDT_OFF tim1   EQU  0x20      org  0x00      NOP      GOTO start start      BSF  STATUS,RP0      MOVLW B'00010000'      MOVWF TRISA      CLRF TRISB      BCF  STATUS,RP0      MOVLW B'00010000'      MOVWF PORTA      CLRF  PORTB main      MOVLW  001h      MOVWF  tim1 timlp1  BTFSC  PORTA,5      CALL   playball      GOTO   main playball      MOVLW  B'00001111'      MOVWF  PORTA      MOVLW  B'11111111'      MOVWF  PORTB      RETURN 修正点などありましたら教えて下さい。

  • PIC、USART USART送信ができません

    下記のプログラムでUSART接続してPICマイコンからPCに送信しようとしています。 PICマイコンはP16F877 アプリにはTera Term というアプリケーションを使用しています。 このプログラムはUSARTの送信とステッピングモータを交互に動作させるプログラムです。 このプログラムを実行したところ、ステッピングモータが微小に動作したままとまってしまいました。 Tera Termにも文字は出力されませんでした。 そのため、1周目だけTXREGレジスタにデータを格納するところまでは出来ていると思います。 しかし、データ送信が行われないため、2週目以降はTSRレジスタがBUSY状態となりプログラムが進行しないのだと考えています。 以下のサイトを参考に模索しましたが、原因が分かりませんでした。 http://www.kimurass.co.jp/pic/0625p.htm http://www.picfun.com/pic19.html どのように対処したらよろしいでしょうか? 原因やアドバイスなど教えていただけたら幸いです。 ~~プログラム~~ list p=16F877 #include <p16F877.inc> __CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF& _LVP_OFF w_temp EQU 0x0C status_temp EQU 0x0D ;変数 cblock 020h CNT15mS ;15mSカウンタ CNT5mS ;5mSカウンタ CNT1mS ;1mSカウンタ CNT50uS ;50μSカウンタ USART_TEMP ;USARTのワークレジスタ POINT ;point of table BUFFER ;buffer endc ;*************************割り込み退避************************** ORG 0x000 goto MAIN ORG 0x004 movwf w_temp movf STATUS,w movwf status_temp movf status_temp,w movwf STATUS swapf w_temp,f swapf w_temp,w retfie ;************************************************************* MAIN ;-----------------------------設定---------------------------- ;BANK1 Setting bsf STATUS,RP0 clrf TRISA movlw B'11110000' clrf TRISB movlw B'01000000' movwf TRISC ;RXピンを入力に設定 movlw B'00100000' movwf TXSTA ;SET TX MODE movlw 0FH ;Set Baud Rate 19Kbps movwf SPBRG ;Set BRG ;BANK0 Setting bcf STATUS,RP0 clrf INTCON movlw 07H movwf ADCON1 ;------------------------------------------------------------ ;----------------------------初期化--------------------------- clrf PORTA clrf PORTB bcf STATUS,C bcf STATUS,Z ;------------------------------------------------------------ ;===========================MAIN_LOOP======================== MAIN_LOOP bsf STATUS,RP0 READY_CHECK btfss TXSTA,TRMT goto READY_CHECK bcf STATUS,RP0 movlw 'A' movwf TXREG call STEPPING_MOTTER goto MAIN_LOOP ;============================================================ ;================= STEPPING MOTORE ========================== STEPPING_MOTTER call wait1ms call wait1ms movlw B'00000001' movwf PORTB call wait1ms call wait1ms movlw B'00000010' movwf PORTB call wait1ms call wait1ms movlw B'00000100' movwf PORTB call wait1ms call wait1ms movlw B'00001000' movwf PORTB RETURN ;================= 15mS WAIT ================================ wait15ms MOVLW d'3' MOVWF CNT15mS wait15ms_loop CALL wait5ms DECFSZ CNT15mS,F GOTO wait15ms_loop RETURN ;================= 5mS WAIT ================================= wait5ms MOVLW d'100' MOVWF CNT5mS wait5ms_loop CALL wait50us DECFSZ CNT5mS,F GOTO wait5ms_loop RETURN ;================= 1mS WAIT ================================= wait1ms MOVLW d'20' MOVWF CNT1mS wait1ms_loop CALL wait50us DECFSZ CNT1mS,F GOTO wait1ms_loop RETURN ;================= 50μS WAIT ================================ wait50us ; 1サイクル(4クロック):0.2μS ; 50μS=0.2μS×250サイクル MOVLW d'82' ;1 MOVWF CNT50uS ;1 wait50us_loop DECFSZ CNT50uS,F ;1 GOTO wait50us_loop ;2 RETURN ;2+1 ;============================================================ ;------------------------------------------------------------ END

  • PICで1秒間の豆の数をカウントするプログラム

     PIcの初心者です。回路図を見て、基板を作れる程度、プログラムは書いてあるのを打ち込める程度で、意味はまったくわかりません。  PIC16F84のPICでカウントする公開の回路を見つけて、光りセンサ-回路でON.OFFさせるかいろも作りました。プログラムは作成者のものです。 見て書き込んで、なんとか見事にカウントしました。合計数は、わかりました。 質問は、 1,このプログラムを直して、1秒間あたり、何粒落ちるかカウントしたいと考えました。  どのように、すれば良いのか教えてください。 2,合計のカウンタ-と秒速何粒落ちているかプログラムを1つのPICに入れて、動作の最初に選択 できるようにしたいのですが、どのようにしたらよいでしょうか。  PICの回路図とプログラム(テキスト形式)を添付しています。   お願いします。私の連休中の宿題で困っています。 7セグメントLED表示4桁カウンタ ; (クロック 4MHz) ; [ ご注意 ] ;PIC プログラムには秋月電子製のライター・キットを使用しているため、アセン ;ブルにはキットに付属のアセンブラを使用しています。 ;プログラム本体は PIC の基本命令だけでの構成に書き替えていますが、ヘッ ;ダー部分などが異なる場合がありますので、他のアセンブラを使用する場合は ;適宜変更してご利用下さい。 include 16f84.h .16f84 .osc hs .pwrt on .wdt off .protect off countsw equ rb.0 ;カウント入力ポート org 0ch d1 ds 1 ;カウント用 d2 ds 1 d3 ds 1 d4 ds 1 swlc ds 1 ;swait でのループ回数 sd ds 1 ;表示データ (0~9) lc ds 1 ;汎用、ループ用 org 0 goto start org 4 goto start start ;初期設定 bsf 3h,5 ;ページ 1 movlw 10000b movwf 85h ;ポート ra の初期化 movlw 00000001b movwf 86h ;ポート rb の初期化 bcf 3h,5 ;ページ 0 clrf d1 ;カウントデータの初期化 clrf d2 clrf d3 clrf d4 ct10: btfsc countsw ;入力が 0 なら次をスキップ goto ct12 call swait btfsc countsw ;入力が 0 なら次をスキップ goto ct12 ;確かでないなら戻る incf d1,1 ;加算 movlw 10 subwf d1,0 btfss 3h,2 goto ct11 clrf d1 incf d2,1 movlw 10 subwf d2,0 btfss 3h,2 goto ct11 clrf d2 incf d3,1 movlw 10 subwf d3,0 btfss 3h,2 goto ct11 clrf d3 incf d4,1 movlw 10 subwf d4,0 btfss 3h,2 goto ct11 clrf d4 ct11: call swait btfss countsw ;入力が 1 なら次をスキップ goto ct11 ;入力が 1 になるのを待つ call swait btfss countsw ;確かに入力が 1 に戻ったかを確認 goto ct11 ct12: movlw 11111110b movwf rb movlw 01101b movwf ra ;桁4へ表示 movf d4,0 movwf sd call l7ptset call wait movlw 11111110b movwf rb movlw 01110b movwf ra ;桁 3 へ表示 movf d3,0 movwf sd call l7ptset call wait movlw 11111110b movwf rb movlw 00111b movwf ra ;桁 2 へ表示 movf d2,0 movwf sd call l7ptset call wait movlw 11111110b movwf rb movlw 01011b movwf ra ;桁 1 へ表示 movf d1,0 movwf sd call l7ptset call wait goto ct10 ;********************************************************************* l7ptset: ;sd に指定された 0~9 の数字をセットする bcf 3h,0 ;キャリフラグのクリア rlf sd,1 ;4倍 rlf sd,1 movf sd,0 ;sd の値を w にコピー addwf pc,1 ;プログラム・カウンタに加算 movlw 00000010b ;0 movwf rb goto pt10 nop movlw 11100110b ;1 movwf rb goto pt10 nop movlw 10010000b ;2 movwf rb goto pt10 nop movlw 11000000b ;3 movwf rb goto pt10 nop movlw 01100100b ;4 movwf rb goto pt10 nop movlw 01001000b ;5 movwf rb goto pt10 nop movlw 00001100b ;6 movwf rb goto pt10 nop movlw 11100010b ;7 movwf rb goto pt10 nop movlw 00000000b ;8 movwf rb goto pt10 nop movlw 01100000b ;9 movwf rb pt10: return ;********************************************************************* swait: ;カウント入力時のウェイト・ルーチン movlw 6 ;6回のループ movwf swlc swt10 movlw 11111110b movwf rb movlw 01101b movwf ra movf d4,0 movwf sd call l7ptset call wait movlw 11111110b movwf rb movlw 01110b movwf ra movf d3,0 movwf sd call l7ptset call wait movlw 11111110b movwf rb movlw 00111b movwf ra movf d2,0 movwf sd call l7ptset call wait movlw 11111110b movwf rb movlw 01011b movwf ra movf d1,0 movwf sd call l7ptset call wait decfsz swlc,1 goto swt10 return ;********************************************************************* wait: ;ウェイトルーチン(1桁の表示時間) movlw 100 movwf lc wt10 decfsz lc,1 goto wt10 return

  • 16F873AにてLEDの点灯

    16F873AにてLEDの点灯 16F873AにてLEDの点灯をさせる回路とプログラムを作っています。 PORTBとPORTCからトランジスタアレイ経由のLEDを接続。 セラロックは10MHz。5V電源を使っています。 普通に点灯は出来ているのですが、RA0からRA3にに入力があったら 点灯パターンを変化させたいです。 MAINにてRA0をチェックして、入力があったらLOOPに移動するつもりですが、 起動後いきなりLOOPに移動してしまいます。 初心者で勉強しているつもりですが、ネットの寄せ集めのコピペで 16F84Aで同じ事は出来ました。16F873Aでは上記のような状態です。 どうか解決方法を教えて下さい。 宜しくお願い致します。 ------------------------------- LIST P=PIC16F873A INCLUDE P16F873A.INC __CONFIG _HS_OSC & _PWRTE_ON & _WDT_OFF & _LVP_OFF GPR_1 EQU 020h GPR_2 EQU 021h GPR_3 EQU 022h ORG 0 INIT BSF STATUS,RP0 MOVLW 007h MOVWF ADCON1 MOVLW 00Fh MOVWF TRISA CLRF TRISB CLRF TRISC BCF STATUS,RP0 MAIN1 BTFSC PORTA,0 GOTO MAIN1 GOTO LOOP LOOP MOVLW 01h MOVWF PORTB CALL T100mS MOVLW 02h MOVWF PORTB CALL T100mS MOVLW 04h MOVWF PORTB CALL T100mS CLRF PORTB CALL T100mS BTFSC PORTA,0 GOTO MAIN1 GOTO LOOP ; << 100mS待つサブルーチン >> T100mS MOVLW 002h MOVWF GPR_3 T100LP CALL T50mS DECFSZ GPR_3,F GOTO T100LP RETURN ; << 50mS待つサブルーチン >> T50mS MOVLW 07Dh MOVWF GPR_2 T50LP CALL T04mS DECFSZ GPR_2,F GOTO T50LP RETURN ; << 0.4mS待つサブルーチン >> T04mS MOVLW 0F9h MOVWF GPR_1 T04LP NOP DECFSZ GPR_1,F GOTO T04LP RETURN END

  • PIC アセンブラ TMR0の使い方がいまいちわかりません。

    *文字数制限の為コメントや繰り返し処理プログラムの一部を省きました。解りにくくてすみません。ココに載せてくれとかあったらそっちに全部載せます。 目標としてはPICでデジタル時計を作りたいのですが、手始めに正確な1秒を作って7セグを0から9まで表示しそれを繰り返す。と言うものをやってみようと思いプログラムしましたがウンともスンとも言いません。 流れとしては 初期処理 ↓ TMR0割り込みが発生するまで無限ループ ↓ 割り込みが発生したら割り込み回数をカウントし(12,8MHzクロック、プリスケーラを256設定で1250回フラグをカウントすると1秒)1秒間分カウントが終わったら7セグの表示を切り替え無限ループに戻る どの数字まで表示したかは任意のレジスタに1を立てて判断する。PICはPIC16F628AなのでTMR1とかもあるんですが気分的にTMR0だけで時間を作ってみたかったのでTMR1とかは使ってません。で、3回くらいやり直してプログラムを作ったんですが全然動きません。 1、何処が悪いんでしょうか? 2、また、PIC16F628Aでは16番ピンがクロックの入力として使えますが その設定方法があってるかわかりません。 コンフィグ設定で OSCをHSにしてポートの設定でRA7を入力にしておけば良いんでしょうか?プログラム中の記述で合ってますでしょうか? 3,7セグをカウントアップするだけのプログラムなのに こんなに長くなる物なんですか? (プログラムが下手だから?アセンブラだから?) 4、1秒のカウント方法ですがプログラム中の記述で正確に1秒をカウントしてますか?(計算間違ってますでしょうか?) 以下、プログラムになります。 list p=pic16f628a include "p16f628a.inc" __CONFIG _LVP_OFF &_MCLRE_ON &_BODEN_OFF &_PWRTE_ON &_WDT_OFF &_HS_OSC time0 equ d'30' ;time4まで作る tcount equ d'43' count0 equ d'35' ;count7まで作る koko0 equ d'43' koko1 equ d'44' org 0 goto start org 4 goto wari start bcf intcon,gie movlw b'00000111' movwf cmcon bsf status,rp0 movlw b'00000111' movwf option_reg movlw b'10100000' movwf trisa clrf trisb bcf status,rp0 bcf status,z bcf intcon,t0if movlw b'00001000' movwf count0 ;この間に1から6の同じ処理が入ります。 movlw b'00000000' movwf count7 time movlw .30 movwf time0 bsf intcon,gie bsf intcon,t0ie clrf tmr0 roop btfsc tcount,0 call segout swapf count0,0 movwf portb swapf portb,0 movwf count0 ;この間に1から5が入ります swapf count6,0 movwf portb swapf portb,0 movwf count6 goto roop wari bcf intcon,t0ie bcf intcon,t0if incf time0,1 btfss status,z goto modori bcf status,z movlw .255 movwf time0 incf time1,1 bcf status,z goto modori bcf status,z movlw .255 movwf time0 movlw .255 movwf time1 incf time2,1 bcf status,z goto modori bcf status,z movlw .255 movwf time0 movlw .255 movwf time1 movlw .255 movwf time2 incf time3,1 bcf status,z goto modori bcf status,z movlw .255 movwf time0 movlw .255 movwf time1 movlw .255 movwf time2 movlw .255 movwf time3 incf time4,1 bcf status,z goto modori bcf status,z movlw .30 movwf time0 movlw b'00000001' movwf tcount modori bsf intcon,t0ie retfie segout clrf tcount btfss koko0,0 goto seg1 ;この中間にseg2からseg6が入ります。 btfss koko0,7 goto seg8 btfss koko1,0 goto seg9 nop goto seg0 seg1 bsfkoko0,0 movlw b'00000010' movwf count0 movlw b'00000100' movwf count1 movlw b'00000000' movwf count2 movlw b'00000000' movwf count3 movlw b'00000000' movwf count4 movlw b'00000000' movwf count5 movlw b'00000000' movwf count6 movlw b'00000000' movwf count7 nop return ;この中間にseg2からseg9が入ります seg0 clrf koko1 clf koko0 movlw b'00001000' movwf count0 movlw b'00000100' movwf count1 movlw b'00000010' movwf count2 movlw b'00000001' movwf count3 movlw b'10000000' movwf count4 movlw b'01000000' movwf count5 movlw b'00000000' movwf count6 movlw b'00000000' movwf count7 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 長くなりましたがご教授どうかお願いします。