;------------------------------------------------------------------------------ ;; ステッピングモータ駆動,液晶シャッタ同期プログラム ;; PIC16F84A 使用 ;; ver.20010409 ;; ver.20010515 ;; whashimo@intron.kz.tsukuba.ac.jp Processor 16F84 Radix DEC EXPAND include "p16f84.inc" __config 0x3ff2 _ResetVector set 0x00 _IntVector set 0x04 #define SCLK PORTB,1 ; ステッピングモータ パルス #define LEFT PORTB,4 ; 液晶シャッター右眼 #define RIGHT PORTB,5 ; 液晶シャッター左眼 #define SWINPUT PORTA,2 ; スイッチ入力 #define STEPNUM 48 ; モータのステップ数 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 汎用レジスタ設定 cblock 0x0d ; delay_l ; delay lower byte delay_h ; delay higher byte dly_tmp ; delay temporary _count1 ; 汎用カウンタ1 _count2 ; 汎用カウンタ2 _count3 ; 汎用カウンタ3 gendly_l ; パルス発生させたい遅延 lower byte gendly_h ; パルス発生させたい遅延 higher byte gendly_m ; パルス発生させたい遅延の繰り返し数 gentime ; パルス持続時間 loopnum ; 同一クロックでパルス発生させる回数 countdown ; パルス速度の増減調整 Stepcount ; ステッピングモータカウント(位相保存用) endc ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ORG _ResetVector goto Start ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Start: call InitPort ; ポート初期化 movlw STEPNUM ; モータの位相セット movwf Stepcount ; 48 からdecrementする ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; スイッチが押されるまで待つ Restart: movlw 0xFE ; movwf _count1 ; Start_1: movlw 0xFE ; movwf _count2 ; Start_2: decfsz _count2,F ; 1/2CL goto Start_2 ; 2CL decfsz _count1,F ; goto Start_1 ; btfss SWINPUT ; L(1/2)CL スイッチが押されたか goto Start_1 ; L(2/0)CL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MainLoop: bsf LEFT ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 加速処理 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 約4Hz開始 movlw 0x09 ; 9回減算 movwf gentime ; movlw 0x12 ; gendly_m=18 movwf gendly_m ; movlw 0x02 ; gendly_m-=2 movwf countdown ; movlw 0x80 ; movwf gendly_l ; movlw 0x3E ; movwf gendly_h ; 0x3E80 = 16000CL call StartnHZ ; ; ここでのパルスレート 約16000*4CL (25.6ms,39.06Hz) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 次のパルスレート 40Hz開始,62500CL相当 movlw 0x14 ; 20回減算 movwf gentime ; movlw 0x04 ; 毎回0x04ずつdelay_h減算(2560CL) movwf countdown ; movlw 0x09 ; movwf gendly_l ; movlw 0x7A ; 0x7A09 = 31241CL movwf gendly_h ; 31241.5 CL = (62500-17)/2 movlw 0x64 ; movwf loopnum ; call IdlenHZ ; ; ここでのパルスレート 約10761*2CL (8.609ms,116Hz) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 次のパルスレート 120Hz開始, 20833CL相当 ; 目標パルスレート 150Hz 16666CL相当 movlw 0x08 ; 8回減算 movwf gentime ; movlw 0x01 ; 毎回0x01ずつdelay_h減算(256CL) movwf countdown ; movlw 0xA8 ; movwf gendly_l ; movlw 0x28 ; 0x28A8 = 10408CL movwf gendly_h ; 10408 CL = (20833-17)/2 movlw 0xFE ; movwf loopnum ; call IdlenHZ ; ; ここでのパルスレート 約8360*2CL (6.688ms,149.52Hz) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 次のパルスレート 151Hz開始, 16556CL相当 ; 目標パルスレート 180Hz 13888CL相当 movlw 0x65 ; 101回減算 movwf gentime ; movlw 0x0D ; 毎回0x0Dずつdelay_l減算 movwf countdown ; movlw 0x4D ; movwf gendly_l ; movlw 0x20 ; 0x204D = 8269CL movwf gendly_h ; 8269.5 CL = (16556-17)/2 movlw 0xFE ; movwf loopnum ; call IdleSnHZ ; ; ここでのパルスレート 約6943*2CL (5.5648ms,179.7Hz) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; call Loop180HZ ; (180Hzの矩形波,13888.8CL相当) bcf LEFT ; bcf RIGHT ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 減速処理 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 現在パルスレート 180Hz 13888CL相当 ; 目標パルスレート 151Hz, 16556CL相当 movlw 0x64 ; 100回加算 movwf gentime ; movlw 0x0D ; 毎回0x0Dずつdelay_l減算 movwf countdown ; movlw 0x17 ; movwf gendly_l ; movlw 0x1B ; 0x1B17 = 6935CL movwf gendly_h ; 6936 CL = (13888-17)/2 movlw 0x64 ; movwf loopnum ; call DownSnHZ ; ; ここでのパルスレート 約8248*2CL (6.5984ms,151.5Hz) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 現在パルスレート 151Hz 16556CL相当 ; 目標パルスレート 120Hz, 20833CL相当 movlw 0x08 ; 8回加算 movwf gentime ; movlw 0x01 ; 毎回0x01ずつdelay_h加算(256CL) movwf countdown ; movlw 0x4D ; movwf gendly_l ; movlw 0x20 ; 0x204D = 8269CL movwf gendly_h ; 8269.5 CL = (16556-17)/2 movlw 0x32 ; movwf loopnum ; call DownnHZ ; ; ここでのパルスレート 約10317*2CL (8.25ms,121.2Hz) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 現在パルスレート 120Hz 20833CL相当 ; 目標パルスレート 40Hz, 62500CL相当 movlw 0x14 ; 20回加算 movwf gentime ; movlw 0x04 ; 毎回0x04ずつdelay_h加算 movwf countdown ; movlw 0xA8 ; movwf gendly_l ; movlw 0x28 ; 0x28A8 = 10408CL movwf gendly_h ; 10408 CL = (20833-17)/2 movlw 0x32 ; movwf loopnum ; call DownnHZ ; ; ここでのパルスレート 約30888*2CL (24.7ms,40.47Hz) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; movlw 0x04 ; 4回加算 movwf gentime ; movlw 0x02 ; gendly_m=2 movwf gendly_m ; movlw 0x02 ; gendly_m+=2 movwf countdown ; movlw 0x80 ; movwf gendly_l ; movlw 0x3E ; movwf gendly_h ; 0x3E80 = 16000CL call StopnHZ ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; goto Restart ; ;StartnHZ needs variables of gendly_l,gendly_h. StartnHZ: movf gentime,W ; 減算繰り返し回数 movwf _count1 ; StartnHZ_1: movlw 0x05 ; L 内部で同じパルスを繰り返す回数 movwf _count2 ; L StartnHZ_2: bsf SCLK ; H ;立ち上がり駆動,位相の保存をする movlw STEPNUM ; H decfsz Stepcount,F ; H movf Stepcount,W ; H movwf Stepcount ; H ;液晶シャッター切り替え movf PORTB,W ; H1CL xorlw B'00110000' ; H1CL 位相反転 btfsc Stepcount,0 ; H(1/2) Stepcountが2の倍数ならスキップ movwf PORTB ; H(1/0) movf gendly_m,W ; H movwf _count3 ; H StartnHZ_HI: movf gendly_l,W ; H movwf delay_l ; H movf gendly_h,W ; H movwf delay_h ; H call delay ; H decfsz _count3,F ; H(1/2) goto StartnHZ_HI ; H(2/0) bcf SCLK ; L movf gendly_m,W ; L movwf _count3 ; L StartnHZ_LO: movf gendly_l,W ; L movwf delay_l ; L movf gendly_h,W ; L movwf delay_h ; L call delay ; L decfsz _count3,F ; L(1/2) goto StartnHZ_LO ; L(2/0) decfsz _count2,F ; L(1/2) goto StartnHZ_2 ; L(2/0) movf countdown,W ; L subwf gendly_m,F ; L decfsz _count1,F ; goto StartnHZ_1 ;大ループ return ; ;IdlenHZ needs variables of gendly_l,gendly_h. ;所要時間 gentime*(508*gen(l,h)+4319) CL IdlenHZ: movf gentime,W ; movwf _count1 ; IdlenHZ_1: movf loopnum,W ; L movwf _count2 ; L ; 計6CL IdlenHZ_2: bsf SCLK ; H(1) movf gendly_l,W ; H(1) movwf delay_l ; H(1) movf gendly_h,W ; H(1) movwf delay_h ; H(1) call delay ; H(gen) ;立ち上がり駆動,位相の保存をする movlw STEPNUM ; H(1) decfsz Stepcount,F ; H(1/2) movf Stepcount,W ; H(1/0) movwf Stepcount ; H(1) ;液晶シャッター切り替え movf PORTB,W ; H1CL xorlw B'00110000' ; H1CL 位相反転 btfsc Stepcount,0 ; H(1/2) Stepcountが2の倍数ならスキップ movwf PORTB ; H(1/0) bcf SCLK ; L(1) movf gendly_l,W ; L(1) movwf delay_l ; L(1) movf gendly_h,W ; L(1) movwf delay_h ; L(1) call delay ; L(gen) decfsz _count2,F ; L(1/2) goto IdlenHZ_2 ; L(2/0) ;小ループ,Lの時間:(gen+8)CL, Hの時間:(gen+9)CL ;小ループ計508gen+4319CL= ; [253*(2*gen+17)+(2*gen+18)] movf countdown,W ; L subwf gendly_h,F ; L decfsz _count1,F ; goto IdlenHZ_1 ;大ループ return ; ;------------------------------------------------------------------------------ IdleSnHZ: movf gentime,W ; movwf _count1 ; IdleSnHZ_1: movf loopnum,W ; L movwf _count2 ; L ; 計6CL IdleSnHZ_2: bsf SCLK ; H(1) movf gendly_l,W ; H(1) movwf delay_l ; H(1) movf gendly_h,W ; H(1) movwf delay_h ; H(1) call delay ; H(gen) movlw STEPNUM ; H(1) decfsz Stepcount,F ; H(1/2) movf Stepcount,W ; H(1/0) movwf Stepcount ; H(1) movf PORTB,W ; H1CL xorlw B'00110000' ; H1CL 位相反転 btfsc Stepcount,0 ; H(1/2) Stepcountが2の倍数ならスキップ movwf PORTB ; H(1/0) bcf SCLK ; L(1) movf gendly_l,W ; L(1) movwf delay_l ; L(1) movf gendly_h,W ; L(1) movwf delay_h ; L(1) call delay ; L(gen) decfsz _count2,F ; L(1/2) goto IdleSnHZ_2 ; L(2/0) ;小ループ,Lの時間:(gen+8)CL, Hの時間:(gen+9)CL ;小ループ計508gen+4319CL= ; [253*(2*gen+17)+(2*gen+18)] movf countdown,W ; L subwf gendly_l,F ; L btfss STATUS,C ; L decf gendly_h,F ; L decfsz _count1,F ; goto IdleSnHZ_1 ;大ループ return ; ;------------------------------------------------------------------------------ Loop180HZ: ;(13888CL周期) movlw 0xFE ; movwf _count1 ; Loop180HZ_1: bsf SCLK ; H1CL movlw 0x16 ; H1CL movwf delay_l ; H1CL movlw 0x1B ; H1CL movwf delay_h ; H1CL call delay ; HdelayCL ; H計 delay+ 13 CL movlw STEPNUM ; H1CL decfsz Stepcount,F ; H1CL movf Stepcount,W ; H1CL movwf Stepcount ; H1CL movf PORTB,W ; H1CL xorlw B'00110000' ; H1CL 位相反転 btfsc Stepcount,0 ; H(1/2) Stepcountが2の倍数ならスキップ movwf PORTB ; H(1/0) bcf SCLK ; L1CL movlw 0x16 ; L1CL movwf delay_l ; L1CL movlw 0x1B ; L1CL movwf delay_h ; L1CL call delay ; LdelayCL decfsz _count1,F ; L(1/2)CL goto Loop180HZ_1 ; L(2/0)CL btfss SWINPUT ; L(1/2)CL スイッチが押されたか goto Loop180HZ ; L(2/0)CL ; L計 delay+ 8 CL ; L=delay+8 ; H=delay+13 ; delay=6934 return ; ;------------------------------------------------------------------------------ DownSnHZ: movf gentime,W ; movwf _count1 ; DownSnHZ_1: movf loopnum,W ; L movwf _count2 ; L ; 計6CL DownSnHZ_2: bsf SCLK ; H(1) movlw STEPNUM ; H(1) decfsz Stepcount,F ; H(1/2) movf Stepcount,W ; H(1/0) movwf Stepcount ; H(1) movf gendly_l,W ; H(1) movwf delay_l ; H(1) movf gendly_h,W ; H(1) movwf delay_h ; H(1) call delay ; H(gen) bcf SCLK ; L(1) movf gendly_l,W ; L(1) movwf delay_l ; L(1) movf gendly_h,W ; L(1) movwf delay_h ; L(1) call delay ; L(gen) decfsz _count2,F ; L(1/2) goto DownSnHZ_2 ; L(2/0) ;小ループ,Lの時間:(gen+8)CL, Hの時間:(gen+9)CL ;小ループ計508gen+4319CL= ; [253*(2*gen+17)+(2*gen+18)] movf countdown,W ; L addwf gendly_l,F ; L btfsc STATUS,C ; L incf gendly_h,F ; L decfsz _count1,F ; goto DownSnHZ_1 ;大ループ return ; ;------------------------------------------------------------------------------ DownnHZ: movf gentime,W ; movwf _count1 ; DownnHZ_1: movf loopnum,W ; L movwf _count2 ; L ; 計6CL DownnHZ_2: bsf SCLK ; H(1) movlw STEPNUM ; H(1) decfsz Stepcount,F ; H(1/2) movf Stepcount,W ; H(1/0) movwf Stepcount ; H(1) movf gendly_l,W ; H(1) movwf delay_l ; H(1) movf gendly_h,W ; H(1) movwf delay_h ; H(1) call delay ; H(gen) bcf SCLK ; L(1) movf gendly_l,W ; L(1) movwf delay_l ; L(1) movf gendly_h,W ; L(1) movwf delay_h ; L(1) call delay ; L(gen) decfsz _count2,F ; L(1/2) goto DownnHZ_2 ; L(2/0) ;小ループ,Lの時間:(gen+8)CL, Hの時間:(gen+9)CL ;小ループ計508gen+4319CL= ; [253*(2*gen+17)+(2*gen+18)] movf countdown,W ; L addwf gendly_h,F ; L decfsz _count1,F ; goto DownnHZ_1 ;大ループ return ; ;------------------------------------------------------------------------------ StopnHZ: movf gentime,W ; 減算繰り返し回数 movwf _count1 ; StopnHZ_1: movlw 0x05 ; L 内部で同じパルスを繰り返す回数 movwf _count2 ; L StopnHZ_2: bsf SCLK ; H ;立ち上がり駆動,位相の保存をする movlw STEPNUM ; H decfsz Stepcount,F ; H movf Stepcount,W ; H movwf Stepcount ; H movf gendly_m,W ; H movwf _count3 ; H StopnHZ_HI: movf gendly_l,W ; H movwf delay_l ; H movf gendly_h,W ; H movwf delay_h ; H call delay ; H decfsz _count3,F ; H(1/2) goto StopnHZ_HI ; H(2/0) bcf SCLK ; L movf gendly_m,W ; L movwf _count3 ; L StopnHZ_LO: movf gendly_l,W ; L movwf delay_l ; L movf gendly_h,W ; L movwf delay_h ; L call delay ; L decfsz _count3,F ; L(1/2) goto StopnHZ_LO ; L(2/0) decfsz _count2,F ; L(1/2) goto StopnHZ_2 ; L(2/0) movf countdown,W ; L addwf gendly_m,F ; L decfsz _count1,F ; goto StopnHZ_1 ;大ループ StopLastpulse: ; 最後っ屁(位相を整える) bsf SCLK ; movf gendly_m,W ; movwf _count3 ; StopLastpulse_H: movf gendly_l,W ; movwf delay_l ; movf gendly_h,W ; movwf delay_h ; call delay ; decfsz _count3,F ; goto StopLastpulse_H ; bcf SCLK ; movf gendly_m,W ; movwf _count3 ; StopLastpulse_L: movf gendly_l,W ; movwf delay_l ; movf gendly_h,W ; movwf delay_h ; call delay ; decfsz _count3,F ; goto StopLastpulse_L ; decfsz Stepcount,F ; 位相が戻るまでパルスを出しつづける goto StopLastpulse ; return ; ;------------------------------------------------------------------------------ InitPort: ; ポートの初期化 bcf STATUS,RP0 ; Page0 clrf PORTA ; ポートA 全出力L clrf PORTB ; ポートB 全出力L clrf INTCON ; bsf STATUS,RP0 ; Page1 clrf PORTA ; ポートA 全ビット出力モード bsf SWINPUT ; ポートA 2ビット目だけ入力モード clrf PORTB ; ポートB 全ビット出力モード movlw b'00000110' ; プリスケーラ x128(51us) 設定, movwf OPTION_REG ; ポートB内部プルアップ使用しない ; 立ち下がり割り込み設定 bcf STATUS,RP0 ; page0 clrf PORTB ; ポートB 全出力L bcf LEFT ; bcf RIGHT ; return ;------------------------------------------------------------------------------ ;*************************************************** ;* Routine for generating a programmable delay ;* (routine written by Philip Doucet - obtained ;* from Electronics Design - August 8, 1994, ;* page 26ES) ;*************************************************** ;; needs value of delay_l,delay_h, ;; dly_tmp delay movlw 0x14 ;subtract minimum # of instructions to subwf delay_l,F ; execute this routine from requested delay btfss STATUS,C ;check for borrow decf delay_h,F ; and decrement high byte if there was one bcf STATUS,C ;devide by 4 rrf delay_l,F ; to determine how many times to bcf STATUS,C ; execute rrf delay_l,F ; delay_loop movf delay_h,F ;check to see if btfsc STATUS,Z ; delay_h = 0 and goto dly_30 ; skip delay_h loop if it is nop ;nop equalizes timing between paths ;delay_h setup and loop dly_10 movlw 0x3e ;since each delay_h loop needs 256 cycle, or movwf dly_tmp ; 40h times thru inner loop of cycles, minus nop ; cycle setup, so 40h - 2 = 3Eh goto dly_20 ;add a 2 cycle delay dly_20 nop ;inner decfsz dly_tmp,F ; loop goto dly_20 ; for nop ; delay_h decfsz delay_h,F ;outer loop goto dly_10 ; for nop ; delay_h ;delay_l setup and loop dly_30 movf delay_l,F ;if delay_l btfsc STATUS,Z ; =0, goto dly_end ; skip loop nop ; dly_40 nop ;loop for decfsz delay_l,F ; delay_l goto dly_40 ; nop ; dly_end retlw 0 ;return from subroutine ;end delay ;*************************************************** end ;