;--------------------------------------------------------------------- ; クリスマスツリー ; ; 2014.11.01 naka ; 1. I/Oポート ; ; (1). 出力ポート ; GP0-2,5: LEDに繋ぐ ; (2). 入力ポート ; GP4/AN3: CDS ; (3). 入力ポート ; GP3: タクトスイッチ ; ; 2. 光り方 ; 4段階(フル,1/2,1/4,消灯)でランダムに点灯する。 ; ; 3. 暗くなると自動点灯 ; 点灯させたい明るさ(暗さ)のときにタクトスイッチを押すと、 ; その明るさを点灯の閾値として記憶し、自動点灯する。 ; 閾値はEEPROMに記憶するので電源を切っても保持される。 ;--------------------------------------------------------------------- LIST P=PIC12F675 INCLUDE "P12F675.INC" __CONFIG _CPD_OFF & _CP_OFF & _BODEN_ON & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT ERRORLEVEL -302 ;アセンブル時のバンク警告メッセージ抑制 ;--------------------------------------------------------------------- ; マクロ定義 ;--------------------------------------------------------------------- BANK0 MACRO BCF STATUS,RP0 ;BANK0に切り替える ENDM BANK1 MACRO BSF STATUS,RP0 ;BANK1に切り替える ENDM ;--------------------------------------------------------------------- ; 変数レジスタの定義 ;--------------------------------------------------------------------- CNT EQU 20H ; カウンタ CNT1 EQU 21H ; WAIT用カウンタ CNT2 EQU 22H ; WAIT用カウンタ LED_NO EQU 23H ; 点灯するLED番号(0〜9) LEDBUF EQU 24H ; LED表示バッファ(24-26H) LEDCNT EQU 27H ; 割り込みで表示するLED番号カウンタ PATADDR EQU 28H ; 表示パターンのアドレスカウンタ PATCNT EQU 29H ; 表示パターンの表示繰り返しカウンタ TMP EQU 2AH ; 一時作業用(割り込み内) FLWAIT EQU 2BH ; FLASHウエイト時間 PWMCNT EQU 2CH ; 疑似PWMのためのカウンタ(0〜3で変化) ; EE_ADDR EQU 2DH ; EEPROMアドレス EE_DATA EQU 2EH ; EEPROMデータ SWFLG EQU 2FH ; スイッチフラグ bit:0 TMP2 EQU 30H ; 一時作業(割り込み外) RNDVAL EQU 31H ; 乱数生成用 WK1 EQU 32H ; 乱数生成用 ADDATH EQU 33H ; A/D変換の測定結果(上位8ビットのみ) THREDAT EQU 34H ; 点灯の閾値(上位8ビットのみ) BLNKCNT EQU 35H ; 高速点滅までのカウンタ WCNT EQU 36H ; 高速点滅回数カウンタ ; BKUPW EQU 40H ; 割り込み待避用 BKUPS EQU 41H ; 割り込み待避用 BKUPFR EQU 42H ; 割り込み待避用 BKUPPCL EQU 43H ; 割り込み待避用 ; ;--------------------------------------------------------------------- ; リセット・割り込み ;--------------------------------------------------------------------- ORG 00H ; リセット時の飛び込み先 RESET GOTO START ; 初期設定へ ; ;--------------------------------------------------------------------- ; 割り込み処理でダイナミック表示を行う。 ; (4回の割り込みで1LED分 ; 4段階PWM) ;--------------------------------------------------------------------- ORG 04H ; 割り込み時の飛び込み先 INTRUPT ;レジスタ待避 MOVWF BKUPW ;バックアップ(Wレジ) SWAPF STATUS,W ;バックアップ(STATUSレジ) MOVWF BKUPS MOVF FSR,W ;バックアップ(FSRレジ) MOVWF BKUPFR MOVF PCLATH,W ;バックアップ(PCLATHレジ) MOVWF BKUPPCL ; BCF INTCON,T0IF ;割り込みフラグリセット ; ; 点灯するLEDの明るさを確認 ; MOVF LEDCNT,W ; LED番号 CALL LEDBRT ; 0,1,2,4が返る SUBWF PWMCNT,W ; PWMCNT - 明るさ > 0 なら点灯 BTFSS STATUS,C GOTO DISP GOTO UNDISP ; DISP MOVF LEDCNT,W MOVWF LED_NO ; 表示番号をLED_NOへ ; ; LED表示 ; CLRF GPIO MOVF LED_NO,W CALL TABLE_TRIS BSF STATUS,RP0 ; bank1 切り替え MOVWF TRISIO BCF STATUS,RP0 ; bank0に戻す MOVF LED_NO,W CALL TABLE_IO MOVWF GPIO ; GOTO NEXTBIT ; UNDISP CLRF GPIO ; LED非表示 ; NEXTBIT INCF PWMCNT,W ANDLW H'03' MOVWF PWMCNT BTFSS STATUS,Z GOTO CHKSW ; INCF LEDCNT,F ; 次の割り込みに備え、カウントアップ MOVF LEDCNT,W SUBLW D'10' BTFSC STATUS,Z CLRF LEDCNT ; CHKSW BCF SWFLG,0 BTFSS GPIO,3 ; タクトスイッチ BSF SWFLG,0 ; RSTREG ;レジスタ復元 MOVF BKUPPCL,W ;復元(PCLATHレジ) MOVWF PCLATH MOVF BKUPFR,W ;復元(FSRレジ) MOVWF FSR SWAPF BKUPS,W ;復元(STATUSレジ) MOVWF STATUS SWAPF BKUPW,F ;復元(Wレジ)LED_NO SWAPF BKUPW,W ; RETFIE ;割り込みから復帰 ; ;--------------------------------------------------------------------- ; 初期設定 ;--------------------------------------------------------------------- START BCF INTCON,GIE ; 全割込み禁止 ; CLRF GPIO MOVLW B'00000111' ; GP0-2をデジタルI/Oに設定 MOVWF CMCON ; デフォルトはコンパレータ BANK1 CALL 3FFH ; 内部OSCのキャリブレーションデータ MOVWF OSCCAL ; OSCCALレジスタにセット MOVLW B'00111000' ; 内部osc(ADCS2-0:011), MOVWF ANSEL ; AN3をアナログ,GP0-2をデジタルI/O MOVLW H'FF' MOVWF TRISIO ; ポートをひとまず全て入力設定 ;割り込みタイマーセット MOVLW H'88' ; プリスケーラを使わない MOVWF OPTION_REG ; clock4MHz -> 1Mcycle ; 1Mcycle/256/2=3,906Hz(=256usec毎) ; 割り込み4回でひとつのLEDを点灯 ; 明るい :割り込み4回とも点灯 ; 少し暗い:割り込み4回のうち2回のみ点灯 ; 暗い :割り込み4回のうち1回のみ点灯 ; LED 10個x4回なので3,906/40=98Hzとなりチラチラしない BANK0 ; MOVLW B'00001100' ; ADFM:left/0, VCFG:VDD/0, CHS:ch3/11 MOVWF ADCON0 ; CLRF LEDCNT ; LEDカウンタクリア CLRF LEDBUF ; LEDバッファクリア CLRF LEDBUF+1 ; LEDバッファクリア CLRF LEDBUF+2 ; LEDバッファクリア ; CLRF PWMCNT CLRF SWFLG CLRF BLNKCNT ; EEPROMに格納された閾値取り出し MOVLW H'00' MOVWF EE_ADDR CALL REDEEP ; 読み出し MOVWF THREDAT ; ;--------------------------------------------------------------------- ; メイン ;--------------------------------------------------------------------- MAIN BSF INTCON,T0IE ; タイマー0割り込みイネーブル BSF INTCON,GIE ; 割り込み許可 ; CALL DIAG ; 電源投入の動作確認のために全LED点灯 CALL RANDINT MAINLP BTFSC SWFLG,0 ; タクトスイッチ確認 CALL SETTHRE ; 押されていたら閾値設定 ; CALL CHKCDS ; 明るさ測定 CALL CMPTHRE ; 閾値と比較 BTFSC STATUS,C GOTO LEDON CALL LEDOFF GOTO MAINLP LEDON INCF BLNKCNT,F MOVF BLNKCNT,W SUBLW D'20' BTFSS STATUS,Z GOTO LEDON1 ; CLRF BLNKCNT ; 高速点滅 MOVLW D'8' MOVWF FLWAIT MOVLW D'30' MOVWF WCNT CALL RNDPAT ; ランダム点灯 DECFSZ WCNT,F GOTO $-2 LEDON1 ; 通常点滅 MOVLW D'200' MOVWF FLWAIT CALL RNDPAT ; ランダム点灯 GOTO MAINLP ; ;--------------------------------------------------------------------- ; I/Oパターン ;--------------------------------------------------------------------- TABLE_IO CLRF PCLATH ADDWF PCL,F RETLW B'00000001' ; LED 0 RETLW B'00000010' ; LED 1 RETLW B'00000010' ; LED 2 RETLW B'00000100' ; LED 3 RETLW B'00000100' ; LED 4 RETLW B'00100000' ; LED 5 RETLW B'00000001' ; LED 6 RETLW B'00000100' ; LED 7 RETLW B'00000001' ; LED 8 RETLW B'00100000' ; LED 9 RETLW B'00000010' ; LED 10 RETLW B'00100000' ; LED 11 ; TABLE_TRIS CLRF PCLATH ADDWF PCL,F RETLW B'00111100' ; LED 0 RETLW B'00111100' ; LED 1 RETLW B'00111001' ; LED 2 RETLW B'00111001' ; LED 3 RETLW B'00011011' ; LED 4 RETLW B'00011011' ; LED 5 RETLW B'00111010' ; LED 6 RETLW B'00111010' ; LED 7 RETLW B'00011110' ; LED 8 RETLW B'00011110' ; LED 9 RETLW B'00011101' ; LED 10 RETLW B'00011101' ; LED 11 ; ;--------------------------------------------------------------------- ; Wレジ値をビット位置にデコード ;--------------------------------------------------------------------- DECBIT CLRF PCLATH ADDWF PCL,F DECBIT1 RETLW B'00000001' ;0 RETLW B'00000010' ;1 RETLW B'00000100' ;2 RETLW B'00001000' ;3 RETLW B'00010000' ;4 RETLW B'00100000' ;5 RETLW B'01000000' ;6 RETLW B'10000000' ;7 ; ;--------------------------------------------------------------------- ; LED番号からLEDBUFの値(明るさ)を取り出す(0,1,2,4) ;--------------------------------------------------------------------- LEDBRT BCF STATUS,C RLF LEDCNT,W ; LED番号を2倍しジャンプ先アドレスに変換 CLRF PCLATH ADDWF PCL,F ; CALL LEDNO_0 GOTO LEDBRT_1 CALL LEDNO_1 GOTO LEDBRT_1 CALL LEDNO_2 GOTO LEDBRT_1 CALL LEDNO_3 GOTO LEDBRT_1 CALL LEDNO_4 GOTO LEDBRT_1 CALL LEDNO_5 GOTO LEDBRT_1 CALL LEDNO_6 GOTO LEDBRT_1 CALL LEDNO_7 GOTO LEDBRT_1 CALL LEDNO_8 GOTO LEDBRT_1 CALL LEDNO_9 LEDBRT_1 MOVWF TMP SUBLW D'3' BTFSC STATUS,Z INCF TMP,F MOVF TMP,W RETURN ; LEDNO_0 MOVF LEDBUF,W ANDLW B'00000011' ; LEDNO = 0 RETURN ; LEDNO_1 MOVF LEDBUF,W ANDLW B'00001100' ; LEDNO = 1 MOVWF TMP BCF STATUS,C RRF TMP,F RRF TMP,W RETURN ; LEDNO_2 SWAPF LEDBUF,W ANDLW B'00000011' ; LEDNO = 2 RETURN ; LEDNO_3 SWAPF LEDBUF,W ANDLW B'00001100' ; LEDNO = 3 MOVWF TMP BCF STATUS,C RRF TMP,F RRF TMP,W RETURN ; LEDNO_4 MOVF LEDBUF+1,W ANDLW B'00000011' ; LEDNO = 4 RETURN ; LEDNO_5 MOVF LEDBUF+1,W ANDLW B'00001100' ; LEDNO = 5 MOVWF TMP BCF STATUS,C RRF TMP,F RRF TMP,W RETURN ; LEDNO_6 SWAPF LEDBUF+1,W ANDLW B'00000011' ; LEDNO = 6 RETURN ; LEDNO_7 SWAPF LEDBUF+1,W ANDLW B'00001100' ; LEDNO = 7 MOVWF TMP BCF STATUS,C RRF TMP,F RRF TMP,W RETURN ; LEDNO_8 MOVF LEDBUF+2,W ANDLW B'00000011' ; LEDNO = 8 RETURN ; LEDNO_9 MOVF LEDBUF+2,W ANDLW B'00001100' ; LEDNO = 9 MOVWF TMP BCF STATUS,C RRF TMP,F RRF TMP,W RETURN ; ;--------------------------------------------------------------------- ; 消灯 ;--------------------------------------------------------------------- LEDOFF CLRF LEDBUF CLRF LEDBUF+1 CLRF LEDBUF+2 RETURN ;--------------------------------------------------------------------- ; 点灯の閾値を設定 ;--------------------------------------------------------------------- SETTHRE ; 現時点の明るさを閾値に設定 CALL CHKCDS ; 明るさ測定 CALL WAIT1MS CALL WAIT1MS CALL WAIT1MS BTFSC SWFLG,0 ; タクトスイッチが離されるまで待つ GOTO $-1 ; EEPROMへ書き込み MOVLW H'00' MOVWF EE_ADDR MOVF ADDATH,W MOVWF THREDAT ; 閾値レジスタ(上位) MOVWF EE_DATA CALL WRTEEP ; EEPROMへ書き込み RETURN ;--------------------------------------------------------------------- ; 明るさの測定 ;--------------------------------------------------------------------- CHKCDS CLRF ADRESH ; A/D変換結果 ; BSF ADCON0,0 ; A/Dオン CALL W100US ; 100us待ち BSF ADCON0,1 ; A/D変換開始 BTFSC ADCON0,1 ; A/D変換が終わるまでループ GOTO $-1 ; ; MOVF ADRESH,W ; A/D変換結果を格納(上位8ビットのみ使用) MOVWF ADDATH RETURN ; ;--------------------------------------------------------------------- ; 現在の明るさと閾値の比較 ;--------------------------------------------------------------------- CMPTHRE MOVF THREDAT,W ; 閾値 <= 現在値 ? SUBWF ADDATH,W RETURN ;--------------------------------------------------------------------- ; Waitルーチン(注)割り込みが入るので下記時間にはならない ;--------------------------------------------------------------------- W100US ; 約100usec MOVLW D'32' MOVWF CNT1 W100USLP DECFSZ CNT1,F GOTO W100USLP RETURN ; WAIT1MS ;1ミリ秒(998usec) CALLと合わせて1.000ms MOVLW D'248' ;1cycle MOVWF CNT1 ;1cycle W1MSLP NOP ;1cycle*248 DECFSZ CNT1,F ;1cycle*247+2cycle GOTO W1MSLP ;2cycle*247 GOTO $+1 ;2cycle NOP ;1cycle RETURN ;2cycle ; WFLASH MOVF FLWAIT,W ;1cycle MOVWF CNT2 ;1cycle WFLASHLP CALL WAIT1MS CALL WAIT1MS CALL WAIT1MS DECFSZ CNT2,F GOTO WFLASHLP RETURN ;--------------------------------------------------------------------- ; 電源投入時、全LED点灯(点灯の明るさは1/2) ;--------------------------------------------------------------------- DIAG MOVLW B'10101010' ; MOVWF LEDBUF MOVLW B'10101010' ; MOVWF LEDBUF+1 MOVLW B'10101010' ; MOVWF LEDBUF+2 ; MOVLW D'250' ; 点灯時間 MOVWF FLWAIT CALL WFLASH RETURN ; ;--------------------------------------------------------------------- ; ランダム表示 ;--------------------------------------------------------------------- RNDPAT CALL RANDOM MOVWF LEDBUF CALL RANDOM MOVWF LEDBUF+1 CALL RANDOM MOVWF LEDBUF+2 ; CALL WFLASH RETURN ;--------------------------------------------------------------------- ; M系列乱数(1〜255) ;--------------------------------------------------------------------- RANDINT MOVLW B'00101010' XORWF TMR0,W MOVWF RNDVAL RANDOM MOVF RNDVAL,W MOVWF WK1 RRF WK1,F RRF WK1,F XORWF WK1,W RRF WK1,F RRF WK1,F XORWF WK1,W RRF WK1,F RRF WK1,F RRF WK1,F XORWF WK1,F BCF STATUS,C BTFSC WK1,0 BSF STATUS,C RLF RNDVAL,F MOVF RNDVAL,W RETURN ; ;--------------------------------------------------------------------- ; EEPROMへ書き込む(アドレス:EE_ADDR, データEE_DATA) ;--------------------------------------------------------------------- WRTEEP MOVF EE_ADDR,W ; BANK1 MOVWF EEADR ; Data Memory Address to write BANK0 MOVF EE_DATA,W ; BANK1 MOVWF EEDAT ; Data Memory Value to write BSF EECON1,WREN ; Enable writes BCF INTCON,GIE ; Disable INTs. MOVLW H'55' ; MOVWF EECON2 ; Write 55h MOVLW H'AA' ; MOVWF EECON2 ; Write AAh BSF EECON1,WR ; Set WR bit to begin write BSF INTCON,GIE ; Enable INTs. BANK0 RETURN ;--------------------------------------------------------------------- ; EEPROMから読み出す(アドレス:EE_ADDR, 結果:W) ;--------------------------------------------------------------------- REDEEP MOVF EE_ADDR,W ; BANK1 MOVWF EEADR ; Data Memory ; Address to read BSF EECON1,RD ; EE Read MOVF EEDAT,W ; W = EEDAT BANK0 RETURN ;--------------------------------------------------------------------- END ;--------------------------------------------------------------------- ; 終わり ;---------------------------------------------------------------------