teacup. [ 掲示板 ] [ 掲示板作成 ] [ 有料掲示板 ] [ ブログ ]

 投稿者
  題名
  内容 入力補助画像・ファイル<IMG> youtubeの<IFRAME>タグが利用可能です。(詳細)
    
 URL
[ ケータイで使う ] [ BBSティッカー ] [ 書込み通知 ] [ 検索 ]


Re: TMR0を動かすトリガーについて

 投稿者:nekosan  投稿日:2014年11月14日(金)00時32分6秒
返信・引用
  > No.665[元記事へ]

> お世話になっております・
> 下記プログラムですがおかしいところ、考え方について教えていただければ幸いです。
>
> GP0を押して割り込みを行ってGP5を変化させ、さらにTMR0をスタートさせて割り込みから復帰。
> TMR0がタイムアップしたらまた割り込みを発生してGP5を戻して割り込みから抜ける。
>
> 現状GP0をおすとGP5が変化しますが、GP0を離してもすぐにGP5がリセットされています。
> タイマーがかかっているけど思い切り短いだけなのか、そもそも間違ったプログラムなのでしょうか。
>
> タイマーで将来的には3秒待ちにする予定です。
> 2チャンネル入れたいのでTMR1も同時に使えるなら12F628、だめなら12F683あたりに書き換える予定です。
>
> あとINTCON設定でT0IEを立てると動作しないようですがこれはなぜでしょう?(以下では立ててません)
>
> お知恵をお貸しください。



プログラムを細かく追ったわけではないので、詳細は
わかりませんが、割り込みベクタが1組しかないマイコン
で、ピンチェンジ割り込みとタイマー割込みを併用すると、
多重割り込みで、色々な関連レジスタ、関連フラグが微妙
に影響しあうので、とりあえず、1ステップずつステップ実行
しながら、関連するレジスタのビット変化やブランチ文の
分岐が想定通りに動くか確認してみるのが、近道かなと思います。
(ブレークポイント仕掛けてループでもいいですが)

シミュレーションの際に、タイマー0、ピンチェンジ割り込み、
フラグレジスタ、INTCON辺り(GIEのオン/オフなど)を集中
して、変化を眺めてみれば、各命令ごとに、想定していない
動作がどこかで発生するのが拾えるのではないかと。


もしくは、別の処理方法として、タイマ割り込みの方は
フリーランにさせておいて、周期的に1ずつカウントアップ
しておいて経過時間カウントに使用し、メインルーチン側で
GPIOの変化をポーリングでチェックする、と言う形にして、
割り込み処理はタイマのみ、という風にするのもありかなと。

なにしろ、ひとつの割り込み処理ルーチンで、別の割り込み
要因の処理を振り分けすると、多重割り込みの動作が複雑に
なりがちだし、制御ビットの1個だけが狂っても全体がうまく
動かなくなるので、色々厳しいかと。

あと、この世代のPICは、1個のCPUで処理させてみて、うまく
行かないなぁと、別のCPUに切り替えてみるか…ということを
やり始めると、CPUによってハード構成やSFRのメモリマップ
や微妙な動作とかも変わってたりすると思うので、切り替えた
ほうのCPUのクセに引っかかって、新たな問題を掘り起こす的な
こともあると思うので、多分動くまで(もしくは絶対動かない
と判断されるまで)は、CPUは変えない方が良さそうに思います。

AVRだと、CPUコア周りやSFRのメモリマップは、大体同じなので、
それで困ることがないんですけどね…
 
 

補足です。

 投稿者:初心者  投稿日:2014年11月13日(木)22時30分30秒
返信・引用
  > No.665[元記事へ]

nekosan様、ほかご覧の皆さま。

わからないところ、怪しいところをQ1~Q6としてみました。
ご教授をお願いいたします。
> ; ==============================================================
> ORG 4
> ; 割込み処理(ピン変化割り込み)
> WARIKOMI_START
> MOVWF save_w ;W-regセーブ

> WARIKOMI_GP0;WARIKOMI_GP0A
>     BTFSC    GPIO,0
> BSF GP0FLG,0 ;ピン変化割り込みフラグON
>     BTFSS  GP0FLG,0  ;立っているか
>     GOTO  WARIKOMI_END ;立ってなければ終わり
>     BCF   GPIO,5       ;立っていればOFF

  Q1:ここでGP5を変化させて次にTMR0に行って平気なのでしょうか? ここが肝のような気がしています。

>     GOTO    TMR0_WARIKOMI ;タイマーを使って消す

  Q2:最初にINTR_COUNTにカウンタ値をセットしてますが問題ないでしょうか?

> TMR0_WARIKOMI;この開始トリガーは?
> MOVLW 0FFh ;0FFh=255をセット
> MOVWF INTR_COUNT
>
  Q3:ここでTMR0を呼んでいるつもりですが大丈夫でしょうか?

> TMR0_WARIKOMI_1;この開始トリガーは?
> BTFSS INTCON,T0IF ; TMR0のカウント値が 255から0まで減算したか?
> GOTO WARIKOMI_END ;まだならループへ
> BCF INTCON,T0IF ;手動でオーバーフローのクリアが必要
> DECFSZ INTR_COUNT,F ;INTR_COUNTは減算して0になったか?
> GOTO TMR0_CLR ;0なら消す
> GOTO WARIKOMI_END ;0でなければループ

  Q4:これでカウントが0以外は割り込みから抜けていると思うのですが大丈夫でしょうか?

> TMR0_CLR
> BCF GP0FLG,0 ;ピン変化割り込みフラグON
>     BSF   GPIO,5
>     BCF   PIR1,TMR1IF ;手動でオーバーフローのクリアが必要?
>
> WARIKOMI_END
> SWAPF save_st,W
> MOVWF STATUS ;STATUSレジスタロード
> SWAPF save_w,F
> SWAPF save_w,W ;W-regロード
> RETFIE ;割込み許可リターン
>
>
> ; ==============================================================
> ; PICの初期化
> INIT
>     ; GPIOをデジタルI/Oに設定
> CLRF GPIO
> MOVLW 07h
> MOVWF CMCON
> ;■バンク1
> BSF STATUS,RP0 ;■バンク1に切替え
>
>     CALL 3FFh ;OSCCAL Valueの読み込み
>     MOVWF OSCCAL ;読み込んだ校正値をOSCCALレジスタにセット
>
> MOVLW  B'00011011'   ;0と1と3と4を入力にする
> MOVWF TRISIO
>     MOVLW b'00000111' ;bit7=0内部プルアップEnable。出力時にプルアップは無効となる
>     MOVWF OPTION_REG  ;bit3=0プリスケーラ使用 bit2-0プリスケーラ分周比(111=1/256,000=1/2)
>
>   MOVLW   B'00010011' ; ピン変化割り込み設定;0と1と4
> MOVWF IOC ; GP0:ピン変化割り込み有効
>
> MOVLW   B'00000001' ; 0=TMR1E on(TMR1オーバーフローで割り込み)
> MOVWF PIE1
>
> ;■バンク0
> BCF STATUS,RP0 ;■バンク0に切替え
>

  :Q5 INTCONの⑤GPIEを「1」にすると一切動きません。 割り込みしないからでしょうか?
> MOVLW   B'10001000' ; ⑦GIE,③GPIE on  ⇒ ※③はGPIFですね。訂正します
> MOVWF INTCON      ※今気づいたんですが、GPIFに書き込んではおかしいのでしょうか
>
> CLRF GP0FLG
> CLRF ICNT
>

  :Q6 TMR0とTMR1は同時に2回路で使えるのでしょうか。

  ※とりあえず最低限のループです。
> ; ==============================================================
> ;    メイン処理
> MAIN
>     NOP
>
> GOTO MAIN
>
> ;********************************************************
  ※これ以下は今回は使っていません

> TIME_250mSEC
>         MOVLW   0FAH      ;250
>         MOVWF   CNT1      ;書き込み
> DLP1;1mS
>         MOVLW   0FAH      ;250をCNT2に書き込み
>         MOVWF   CNT2      ;
>
> DLP2
>         NOP
>         DECFSZ  CNT2,F
>         GOTO    DLP2      ;CNT2がゼロになるまで繰り返す
>         DECFSZ  CNT1,F    ;CNT1がゼロになったらDLP1へ
>         GOTO    DLP1
>
>         RETURN
>
> TIME_10mSEC
>         MOVLW   014H      ;20
>         MOVWF   CNT3      ;書き込み
> DLP1A;1mS
>         MOVLW   0FAH      ;250をCNT2に書き込み
>         MOVWF   CNT4      ;
>
> DLP2A
>         NOP
>         DECFSZ  CNT4,F
>         GOTO    DLP2A     ;CNT2Aがゼロになるまで繰り返す
>         DECFSZ  CNT3,F    ;CNT1AがゼロになったらDLP1へ
>         GOTO    DLP1A
>
>         RETURN
>
> ;********************************************************
> END
>
 

TMR0を動かすトリガーについて

 投稿者:初心者  投稿日:2014年11月13日(木)16時25分24秒
返信・引用
  お世話になっております・
下記プログラムですがおかしいところ、考え方について教えていただければ幸いです。

GP0を押して割り込みを行ってGP5を変化させ、さらにTMR0をスタートさせて割り込みから復帰。
TMR0がタイムアップしたらまた割り込みを発生してGP5を戻して割り込みから抜ける。

現状GP0をおすとGP5が変化しますが、GP0を離してもすぐにGP5がリセットされています。
タイマーがかかっているけど思い切り短いだけなのか、そもそも間違ったプログラムなのでしょうか。

タイマーで将来的には3秒待ちにする予定です。
2チャンネル入れたいのでTMR1も同時に使えるなら12F628、だめなら12F683あたりに書き換える予定です。

あとINTCON設定でT0IEを立てると動作しないようですがこれはなぜでしょう?(以下では立ててません)

お知恵をお貸しください。

; PIC12F629
; clock:INTOSCIO 4MHz
;     GP0⑦ → GP5②
;ボタン押すと変化
;INTCON定義
;⑦GIE 1=割り込み発生機能を有効にする
;⑥PEIE 0
;⑤T0IE 1ならT0IF が1のときに割り込みを発生させる
;④INTE 0
;③GPIE 1=GPIO割り込み
;②T0IF TMR0のカウント値が 255から0まで減算すると自動的に1になる
;①INTF 0
;0GPIF 0
; ==============================================================
;
; ==============================================================
LIST P=12F629
INCLUDE P12F629.INC

__CONFIG _CPD_ON & _CP_ON & _BODEN_ON & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF


save_st EQU 020h ; STATUSのセーブ領域
save_w EQU 021h ; W-regのセーブ領域

CNT1    EQU     022H
CNT2    EQU     023H
W_TEMP  EQU     024H
STATUS_TEMP EQU 025H
CNT3    EQU     026H
CNT4    EQU     027H
DELAY1  EQU     028H
DELAY2  EQU     029H

CNT2A   EQU     02AH  ;IrTx

GP0FLG  EQU   030H
ICNT    EQU   031H
START_A_FLG  EQU  032H
INTR_COUNT EQU 033h ; ピン変化割り込みカウンタ

GP1FLG  EQU   034H

ORG 0
GOTO INIT

; ==============================================================
ORG 4
; 割込み処理(ピン変化割り込み)
WARIKOMI_START
MOVWF save_w ;W-regセーブ
SWAPF STATUS,W
MOVWF save_st ;STATUSレジスタセーブ
BCF INTCON,GPIF ;ピン変化割込みフラグクリア

WARIKOMI_GP0;WARIKOMI_GP0A
    BTFSC    GPIO,0
BSF GP0FLG,0 ;ピン変化割り込みフラグON
    BTFSS  GP0FLG,0  ;立っているか
    GOTO  WARIKOMI_END ;立ってなければ終わり
    BCF   GPIO,5       ;立っていればOFF

    GOTO    TMR0_WARIKOMI ;タイマーを使って消す

TMR0_WARIKOMI;この開始トリガーは?
MOVLW 0FFh ;0FFh=255をセット
MOVWF INTR_COUNT


TMR0_WARIKOMI_1;この開始トリガーは?
BTFSS INTCON,T0IF ; TMR0のカウント値が 255から0まで減算したか?
GOTO WARIKOMI_END ;まだならループへ
BCF INTCON,T0IF ;手動でオーバーフローのクリアが必要
DECFSZ INTR_COUNT,F ;INTR_COUNTは減算して0になったか?
GOTO TMR0_CLR ;0なら消す
GOTO WARIKOMI_END ;0でなければループ

TMR0_CLR
BCF GP0FLG,0 ;ピン変化割り込みフラグON
    BSF   GPIO,5
    BCF   PIR1,TMR1IF ;手動でオーバーフローのクリアが必要?

WARIKOMI_END
SWAPF save_st,W
MOVWF STATUS ;STATUSレジスタロード
SWAPF save_w,F
SWAPF save_w,W ;W-regロード
RETFIE ;割込み許可リターン


; ==============================================================
; PICの初期化
INIT
    ; GPIOをデジタルI/Oに設定
CLRF GPIO
MOVLW 07h
MOVWF CMCON
;■バンク1
BSF STATUS,RP0 ;■バンク1に切替え

    CALL 3FFh ;OSCCAL Valueの読み込み
    MOVWF OSCCAL ;読み込んだ校正値をOSCCALレジスタにセット

MOVLW  B'00011011'   ;0と1と3と4を入力にする
MOVWF TRISIO
    MOVLW b'00000111' ;bit7=0内部プルアップEnable。出力時にプルアップは無効となる
    MOVWF OPTION_REG  ;bit3=0プリスケーラ使用 bit2-0プリスケーラ分周比(111=1/256,000=1/2)

MOVLW   B'00010011' ; ピン変化割り込み設定;0と1と4
MOVWF IOC ; GP0:ピン変化割り込み有効

MOVLW   B'00000001' ; 0=TMR1E on(TMR1オーバーフローで割り込み)
MOVWF PIE1

;■バンク0
BCF STATUS,RP0 ;■バンク0に切替え

MOVLW   B'10001000' ; ⑦GIE,③GPIE on
MOVWF INTCON

CLRF GP0FLG
CLRF ICNT

; ==============================================================
;    メイン処理
MAIN
    NOP

GOTO MAIN

;********************************************************
TIME_250mSEC
        MOVLW   0FAH      ;250
        MOVWF   CNT1      ;書き込み
DLP1;1mS
        MOVLW   0FAH      ;250をCNT2に書き込み
        MOVWF   CNT2      ;

DLP2
        NOP
        DECFSZ  CNT2,F
        GOTO    DLP2      ;CNT2がゼロになるまで繰り返す
        DECFSZ  CNT1,F    ;CNT1がゼロになったらDLP1へ
        GOTO    DLP1

        RETURN

TIME_10mSEC
        MOVLW   014H      ;20
        MOVWF   CNT3      ;書き込み
DLP1A;1mS
        MOVLW   0FAH      ;250をCNT2に書き込み
        MOVWF   CNT4      ;

DLP2A
        NOP
        DECFSZ  CNT4,F
        GOTO    DLP2A     ;CNT2Aがゼロになるまで繰り返す
        DECFSZ  CNT3,F    ;CNT1AがゼロになったらDLP1へ
        GOTO    DLP1A

        RETURN

;********************************************************
END
 

Re: ポートの隣り合うビットへの連続0書き込み

 投稿者:matsu  投稿日:2014年11月12日(水)00時44分3秒
返信・引用
  > No.662[元記事へ]

nekosanさんへのお返事です。

nekosanさん,早速のお返事ありがとうございます。
なるほど,読み出しレジスタに反映されるのが間に合わないとすると,
「なんじゃこりゃ」の2行も説明つきそうですね。
参考URLにずばり書いてありますね。
PICの癖として,覚えておきたいと思います。
これだけで4,5時間悩みました・・・。
ありがとうございました。

> この辺りの動作は、マイコンによって異なるので、
> 一律どうとはいえないのですが(PICでもシリーズ
> によって異なる)、そのため、同じポートに連続
> して読み書きするような操作を行うと、書き込んだ
> はずの情報が読み出しの際にまだ反映されていない
> という現象がおこるかと思います。
 

Re: 下記,自己解決

 投稿者:nekosan  投稿日:2014年11月12日(水)00時29分44秒
返信・引用
  > No.660[元記事へ]

> 確かに・・・,ですが別の部分で,if文の条件が間違っていました。
> (お恥ずかしい・・・)
> 今のところFosc32MHz駆動で,timer0を使ってFosc/4の8MHzをカウントさせて,
> TMR0の初期値を0にしたまま割込みがかかっても更新しない,つまり256カウント
> で割込み発生,という条件(割込み周期32us)で,割込み回数をカウントさせ,
>
>     sec=secOld=TMR0IntNum/31250;//秒の生成
>     while(1){//1秒毎にLEDをトグルさせる
>         sec=TMR0IntNum/31250;
>         if( sec-secOld){ secOld=sec; toggleLed(); }
>     }
>
> の用にして,2つのLEDを1秒周期でトグルできています。



ひとまず、解消してるようでしたら安心です。

あと、もしかしたらと思っていたのは、タイマーの
カウントがノコギリ波なのか、三角波なのかによって、
周期が2倍の違いが出るので、そっちかも…と思って
おりました。
 

Re: ポートの隣り合うビットへの連続0書き込み

 投稿者:nekosan  投稿日:2014年11月12日(水)00時26分36秒
返信・引用
  > No.661[元記事へ]

> ところが,「なんじゃこりゃ?」ってコメントの通り,ポートの各ビットを連続して
> 0を書き込むと片方しか有効になってくれません。
> PIC16F1823なんですが,隣り合うポートを連続して0にできない,ってことはあり得るんでしょうか?
>
> 上の通り,強引に一度で書き込むことで回避はできましたが,C言語に反しているようで,
> かなり気になっています。XC8のバグでしょうか?


I/Oポート関係のレジスタは、書き込んでから
シンクロナイザを通して、読み出しレジスタに
反映されるまでに、通常1~数クロックが掛かる
と思います。

この辺りの動作は、マイコンによって異なるので、
一律どうとはいえないのですが(PICでもシリーズ
によって異なる)、そのため、同じポートに連続
して読み書きするような操作を行うと、書き込んだ
はずの情報が読み出しの際にまだ反映されていない
という現象がおこるかと思います。

今回のようなビット操作は、ポート読み出しして、
ビット操作して、ポート書き込み、という操作に
なるので、各操作の間に「NOP」などで適当な間隔を
空けるか、ポート全体を一度に処理する必要があると
思います。

この辺りの仕様は、型番毎にことなるので、
ポート内部の機能構成と、各機能のクロック単位の
動作を整理してみる必要があるのかなと思います。


以下の辺りが参考になりそうです。
http://www.picfun.com/pic18/mod1801.html
http://homepage3.nifty.com/mitt/pic/pic1320_06.html
http://www.mtl.t.u-tokyo.ac.jp/~iizuka/avr/

多分そういうことなんだと思うのですが、アセンブリ
展開されたソースレベルでステップ実行してみると、
読み出し(ビット操作)に使ったレジスタの内容には
そのような値が残るかと言う気がします。

(最近PICのアセンブラを全然眺めてないので、
 ポートへのビット操作が、単独の命令なのか、
 それともポート全体の読み書き+ビット操作
 なのか忘れてしまいました。前者であれば、
 アセンブリソースでステップ実行しても
 判らないかも)

 

ポートの隣り合うビットへの連続0書き込み

 投稿者:matsu  投稿日:2014年11月11日(火)22時44分30秒
返信・引用
  別件でまた煮詰まってしまいました。これってXC8のバグでしょうか?


電源オンの直後(ポートの入出力設定だけ終わった段階)に,

-------------
#define _XTAL_FREQ 32000000
#define waitus __delay_us
#define waitms __delay_ms
-------------

typedef enum{WT, BL, ALL}ledType;
void ledOn(ledType color)
{
    switch(color){
        case WT:  PORTCbits.RC4 = 1; break;//白
        case BL:  PORTCbits.RC3 = 1; break;//青
        case ALL: PORTCbits.RC4 = 1; PORTCbits.RC3 = 1; break;//白青点灯
    }
}
void ledOff(ledType color)
{
    switch(color){
        case WT:  PORTCbits.RC4 = 0; break;//白
        case BL:  PORTCbits.RC3 = 0; break;//青
        //case ALL: PORTCbits.RC4 = 0; PORTCbits.RC3 = 0; break;//なぜかこれだと青だけが消える,なんじゃこりゃ?
        //case ALL: PORTCbits.RC4 =    PORTCbits.RC3 = 0; break;//なぜかこれだと白だけが消える,なんじゃこりゃ?
        case ALL: PORTC &= 0b11100111; break;//白青とも消える
    }
}


-------------
        for(i=0;i<2;i++){ ledOn(ALL); waitms(100); ledOff(ALL); waitms(100);}
-------------

として,200ms周期で白・青のLEDを両方同時に2回点滅させています。
ところが,「なんじゃこりゃ?」ってコメントの通り,ポートの各ビットを連続して
0を書き込むと片方しか有効になってくれません。
PIC16F1823なんですが,隣り合うポートを連続して0にできない,ってことはあり得るんでしょうか?

上の通り,強引に一度で書き込むことで回避はできましたが,C言語に反しているようで,
かなり気になっています。XC8のバグでしょうか?
 

Re: 下記,自己解決

 投稿者:matsu  投稿日:2014年11月11日(火)15時01分52秒
返信・引用
  > No.658[元記事へ]

nekosanさんへのお返事です。

丁寧に調べてくださり,ありがとうございます。
その後をご報告します。

> なんとなく、timer0に入力されるクロック回路の、
> シンクロナイザのところが原因かなと言う気が
> しました。(図語参照)
>
> データシートに詳細がかかれていなかったので、
> 詳しくは判らないのですが、2周期で分周(2分周)
> しているように読み取れるので…

確かに・・・,ですが別の部分で,if文の条件が間違っていました。
(お恥ずかしい・・・)
今のところFosc32MHz駆動で,timer0を使ってFosc/4の8MHzをカウントさせて,
TMR0の初期値を0にしたまま割込みがかかっても更新しない,つまり256カウント
で割込み発生,という条件(割込み周期32us)で,割込み回数をカウントさせ,

    sec=secOld=TMR0IntNum/31250;//秒の生成
    while(1){//1秒毎にLEDをトグルさせる
        sec=TMR0IntNum/31250;
        if( sec-secOld){ secOld=sec; toggleLed(); }
    }

の用にして,2つのLEDを1秒周期でトグルできています。
 

Re: タイマーですか。

 投稿者:nekosan  投稿日:2014年11月10日(月)23時53分4秒
返信・引用
  > No.654[元記事へ]

> その通りです! それをやりたいんです。
> 説明が足りなくて申し訳ありません。
>
> ですが、入力が入ったと同時(目標0.001秒以内・・・マイコンではかなり長そうですが)に出力信号が立ち、3秒位後に(こちらはばらつきがあっても問題なし)出力信号が消えればいいんです。
>
> 問題はそれを2回路で平行して一個のPICでやりたいんです。
>
> 前々回のプログラムだと、片方の回路の処理が終わるまでもう一方の回路は信号を受け付けないのです。



2チャンネル並行的に処理するのであれば、
やっぱりタイマー割込みで経過時間をそれぞれ
計測して、一定の間だけ入力信号を無視する
という処理が良さそうな気がしますね。

その際の、「一定時間」は、正確に「○○秒」
とかじゃなくても、計測時間の精度には影響が
ない(精度はストップウォッチ側に左右)ので、
timer0のフリーランでオーバーフロー割り込み
でも、あまり問題なさそうな気もします。
およそ1秒とか、およそ3秒とかが毎回計れれば。

あとは、どのように2チャンネル独立に経過時間
を管理したりリフレッシュするのか…ですかね。

16F84は、8ビットのタイマー0の1個しかないん
ですよね…
 

Re: 下記,自己解決

 投稿者:nekosan  投稿日:2014年11月10日(月)23時37分46秒
返信・引用
  matsuさんへのお返事です。

> 下記,なんとか自己解決できそうです。
> 糸口はつかめましたので,なんとかがんばってみます。
> ありがとうございました。
>


解決できそうですか。

なんとなく、timer0に入力されるクロック回路の、
シンクロナイザのところが原因かなと言う気が
しました。(図語参照)

データシートに詳細がかかれていなかったので、
詳しくは判らないのですが、2周期で分周(2分周)
しているように読み取れるので…
 

レンタル掲示板
/79