USB-IO2.0(AKI)でスイッチを押している間フルカラーLEDを順番に色を変化させる

icon 項目のみ表示/展開表示の切り替え

概要

フルカラーLEDをスイッチを押している間、色(白 黄 紫 赤 水 緑 青 消灯 の順)を変える。RB4 RB5 RB6にLEDを接続する。
クロックはUSB-IOで接続済みの12MHzのセラミック振動子を使用する。USB-IO2(AKI)のプログラムを書き換えて使用する。プログラムを書き込むことにより購入時付属のサンプルプログラムでIO操作はできなくなるので注意。書込みはPICKit3を前提とする。

回路は次のとおりである。
回路図(PNG) 回路図(PDF) 回路図(DXF)

プログラムの説明

外部クロックの設定

USB2.0を動作させるには内部クロック48MHzが必要である。アセンブラソースのCONFIGで指定する。

使用するLEDと電流制限抵抗

LEDは色により順方向電圧が異なるため、色ごとに抵抗値を変えた。

IOポートの設定

使用するIOポートのピンがアナログ入力と共用(ピン配置)となっているため、ANSEL、ANSELHレジスタによりピンをデジタル入出力に設定する。ピンを出力にするためTRISA、TRISB、TRISCレジスタをクリアする。

IOポートに出力する

PORTBレジスタに書き込むことにより出力することができる。

スイッチのチャタリングを除去する(サブルーチン sw1_in)

チャタリングとはスイッチが押されたり・離されたときにスイッチの接点が振動でしばらくOn/Offする現象である。チャタリング対策をしないとスイッチを1回押したにもかかわらず数回押したような現象が発生します。
チャタリングを除去するには、1回スイッチの状態を読み込み10ms程度待ってからもう一度読み込み前回と値が同じであればチャタリングしていない、値が変化していればチャタリング中なのでもう一度10ms待って前回値が同じかどうか比較する。同じになるまで繰り返すことでチャタリングが除去できる。前回の値との比較はXORによってビット1があれば変化があったとみなせる。
SW10にスイッチの状態が返される

0.5秒を得る

3段ループにより約0.5秒の時間待ちを作るプログラムをサブルーチン化している。

10m秒を得る

2段ループにより約10m秒の時間待ちを作るプログラムをサブルーチン化している。

アセンブラソース

ソースのダウンロードsw2.zip


; RB6:Red LED,RB5:Green LED,RB4:Blue LED,RC0:SW 点灯テスト
; スイッチが押されいる間を色を変化させる 白 黄 紫 赤 水 緑 青 消灯 の順で変化
; チャタリング対策有り
; RB7の値も変化しているので注意
        #INCLUDE <p18f14k50.inc>
        CONFIG FOSC = HS,CPUDIV = NOCLKDIV,PLLEN=ON,WDTEN=OFF,LVP=OFF;not WDT

Tcount1  EQU     0
Tcount2  EQU     1
Tcount3  EQU     2

SW10     EQU     3 ; 前々回の入力値
SW11     EQU     4 ; 今回の入力値
SW12     EQU     5 ; 前回の入力値
SW1_TRG  EQU     6 ; 変化したビットが1となる

Tcount   EQU     7 ; 押されている総時間の16倍
        org 0

        goto   start
start
        movlw   0fh
        clrf    ANSEL   ; RC3-RC0,RA4をデジタル入力バッファに設定
        clrf    ANSELH  ; RB5-RB4,RC7-RC6をデジタル入力バッファに設定
        clrf    SLRCON  ; PORTA,PORTB,PORTCをスルーレートを標準に設定
        clrf    TRISA   ; PORTAを全部出力に設定
        clrf    TRISB   ; RB7-RB4を出力に設定
        movlw   01h     ; RC0のみ入力に設定
        movwf   TRISC
        clrf    Tcount
        clrf    PORTB
loop
        call    sw1_in

        btfsc   SW11,0  ; btfssを使用すると離している場合に色を変化させられる
        goto    loop    ; スイッチが離されている場合
        movf    Tcount,W ; スイッチが押されたので色を変化させる
        addlw   010h
        movwf   Tcount
        movwf   PORTB   ; LEDを点灯
        call    wait500
        goto    loop

sw1_in                  ; SW1の状態を入力しSW11に返す 0:Off 1:On
        movf    PORTC,W
        andlw   01h    ; bit0以外はクリアする
        movwf   SW12
        call    wait10
sw1_loop
        movf    PORTC,W
        andlw   01h    ; bit0以外はクリアする
        movwf   SW11
        xorwf   SW12,W ;チャタリングがあるビットは1となる
        btfsc   STATUS,Z ; Zフラグが0の場合は次の命令をスキップする
        goto    sw1_exit ; チャタリングが収まったので入力値として採用する
        movf    SW11,W
        movwf   SW12
        call    wait10   ; 10ms待機
        goto    sw1_loop
sw1_exit
        return

wait500                 ; 0.5秒Wait
        movlw   d'50'  ; 10ms*50=0.5s
        movwf   Tcount1
dloop1
        movlw   d'200'  ; 50μs*200=10ms
        movwf   Tcount2
dloop2                   ; t=(12+12*count3)/48MHz 50μs
        movlw   d'199'
        movwf   Tcount3
        nop
dloop3
        decfsz  Tcount3
        goto    dloop3
        decfsz  Tcount2
        goto    dloop2
        decfsz  Tcount1
        goto    dloop1
        return



wait10                  ; 約10ms待機
        movlw d'200'    ; 50μs*200=10ms
        movwf Tcount2
dloop21                  ; t=(12+12*count3)/48MHz 50μs
        movlw d'199'    ; 4clock
        movwf Tcount3   ; 4clock
        nop             ; 4clock
dloop31
        decfsz Tcount3  ; 4clock
        goto dloop31    ; 8clock
        decfsz Tcount2
        goto dloop21
        return

        END