疑似的なPWM(Pulse Width Modulation)を使って、LEDによる蛍もどきを作ってみました。
10mSをデューティー比100%として、最大値10mS-50uSから徐々に デューティー比 を変化させ、最小値50uSとして、200分割しています。明るい→暗いを200*10mS=2S、暗い→明るいを200*10mS=2Sとして4S周期で明暗を繰り返します。
Cdsを使用して、暗くなったら明暗を繰り返すようにしました。
回路図は下記ののとおりです。

明るさ検出には、Cdsセンサーを使用して、アナログ比較器AIN1(PB1)に10Kでプルアップして入力されています。 アナログ比較器AIN0(PB0)には、10Kで分割した、基準電圧(約2.5V)か入力されています。
リセット後、スタックポインターを設定したのち、PB2のみ出力設定します。
PB0、PB1は、高インピーダンスモードにします、(DDB0/1,PORTB0/1とも0に設定)
明るさ判定のループ内は、ACSR(Analog Comparator Control and Status Register)のACO(Analog Comparator Output)を直接見に行きます(今回は割り込みは使用していません)
ACOが1の場合、PORTBのPB2に0を書き込みLEDが消灯します(Cdsセンサーの受光が明るいとき)
ACOが0の場合、サブルーチンhotaruをコールします。
reset:
ldi r16, RAMEND ;Stack pointer setting
out SPL, r16
ldi r16, 0b00000100 ;PB2 output setting
out DDRB, r16
ldi r16, 0b00000000
out PORTB, r16
ldi r16, 0b00000011 ;Analog Comparator setting
out ACSR, r16
loop:
ldi r16, 0b00000000
sbic ACSR, 5 ;ACSR(ACO(5))=0 skip
out PORTB, r16
sbis ACSR, 5 ;ACSR(ACO(5))=1 skip
rcall hotaru
rjmp loop
サブルーチンhotaruでは、明→暗をwait_hotaru1、暗→明をwait_hotaru2をそれぞれコールしています。
wait_hotaru1 / wait_hotaru2はそれぞれ200分割され、1周期が10mSに設定されています。
r16は当初200に設定されていますが、 wait_hotaru1を呼びごとに r16を1だけ減算します。0になれば
r16を200に設定したのち wait_hotaru2を呼び出します。wait_hotaru2も呼び出されるごとにr16を1だけ減算します。0になれば、サブルーチンをリターンします。
hotaru: ldi r16, 0d200
loop1:
rcall wait_hotaru1
dec r16
brne loop1
ldi r16, 0d200
loop2:
rcall wait_hotaru2
dec r16
brne loop2
ret
wait_hotaru1では、r16およびr17は最初は200に設定されていますが呼ばれるごとに1ごとに減算されていきます
wait50usのwaitを行ったのち、r17を1だけ減算します。r17が0になるまで繰り返します。
0になったらPB2を0にします。パルス立下りになります。
200*50=10000us、199*50=9950、9900・・・100、50のようにhigh側の出力され、立下りパルスになります
r16には201-r16の値が入ります。
wait50usのwaitを行ったのち、r17を1だけ減算します。r17が0になるまで繰り返します。
0になったらPB2を0にします。パルス立ち上がりになります。
1*50=50us、2*50=100、150・・・9950、10000のようにlow側の出力され、立上がりパルスになります。
これにより、初期10000usの highの出力され、立下りパルス 後、50usの low側の出力され、立上がりパルスになります。 続いて9950 usのhigh、100usのlowと デューティー比 を変えていきます。
wait_hotaru2:はlow→highと逆のパルスになります
wait_hotaru1:
mov r17, r16
wait_hotaru01:
rcall wait50us
dec r17
brne wait_hotaru01
ldi r18, 0b00000000
out PORTB, r18
ldi r17, 0d201
sub r17, r16
wait_hotaru02:
rcall wait50us
dec r17
brne wait_hotaru02
ldi r18, 0b00000100 ;PB2 high level outpit
out PORTB, r18
ret
wait_hotaru2:
ldi r17, 0d201
sub r17, r16
wait_hotaru04:
rcall wait50us
dec r17
brne wait_hotaru04
ldi r18, 0b00000000 ;PB2 low level outpit
out PORTB, r18
mov r17, r16
wait_hotaru03:
rcall wait50us
dec r17
brne wait_hotaru03
ldi r18, 0b00000100
out PORTB, r18
ret
ソースは下記のようになります
;AT90S2313 LED hotaru
;
;; AT90S2313 cpu
;; rom 0000h -- 03ffh
;; ram 0000h -- 00dfh
;; eeprom 0000h -- 007fh
;; External clock 8MHz
;;
;;
;; assemblers ASxxxx and ASlink V5.40
;; file name 2313_led_pulse_hotaru.asm
;; $ asavr -l -s -o 2313_led_pulse_hotaru.asm
;; $ aslink -i 2313_led_pulse_hotaru
;; $ (sudo) avrdude -v -p 2313 -c usbasp -P usb -F -e -U flash:w:2313_led_pulse_hotaru.ihx
;I/O regster
SREG .equ 0x3f ;Status Register
SPL .equ 0x3d ;Stack Pointer Low
GIMSK .equ 0x3b ;General Interrupt MaSK register
GIFR .equ 0x3a ;General Interrupt Flag register
TIMSK .equ 0x39 ;Timer/Counter Interrupt MaSK register
TIFR .equ 0x38 ;Timer/Counter Interrupt Flag register
MCUCR .equ 0x35 ;MCU general Control Register
TCCR0 .equ 0x33 ;Timer/Counter 0 Control Register
TCNT0 .equ 0x32 ;Timer/CouNTer 0
TCCR1A .equ 0x2f ;Timer/Counter 1 Control Register A
TCCR1B .equ 0x2e ;Timer/Counter 1 Control Register B
TCNT1H .equ 0x2d ;Timer/CouNTer 1 High byte
TCNT1L .equ 0x2c ;Timer/CouNTer 1 Low byte
OCR1AH .equ 0x2b ;Output Compare Register 1 High byte
OCR1AL .equ 0x2a ;Output Compare Register 1 Low byte
ICR1H .equ 0x25 ;T/C Input Capture Register High byte
ICR1L .equ 0x24 ;T/C Input Capture Register Low byte
WDTCR .equ 0x21 ;WatchDog Timer Control Register
EEAR .equ 0x1e ;EEPROM Address Register
EEDR .equ 0x1d ;EEPROM Data Register
EECR .equ 0x1c ;EEPROM Control Register
PORTB .equ 0x18 ;Data Register, Port B
DDRB .equ 0x17 ;Data Direction Register, Port B
PINB .equ 0x16 ;Input Pins, Port B
PORTD .equ 0x12 ;Data Register, Port D
DDRD .equ 0x11 ;Data Direction Register, Port D
PIND .equ 0x10 ;Input Pins, Port D
UDR .equ 0x0c ;UART Data Register
USR .equ 0x0b ;UART Status Register
UCR .equ 0x0a ;UART Control Register
UBRR .equ 0x09 ;UART Baud Rate Register
ACSR .equ 0x08 ;Analog Comparator Control and Status Register
RAM .equ 0x60
RAMEND .equ 0xdf
.AT90S2313
start :
rjmp reset ;reset
reti ;INT0
reti ;INT1
reti ;Timer/Counter1 CAPT1
reti ;Timer/Counter1 COMP1
reti ;Timer/Counter1 OVF1
reti ;Timer/Counter0 OVF0
reti ;UART RX
reti ;UART UDRE
reti ;UART TX
reti ;Analog Comparator ANA_COMP
reset:
ldi r16, RAMEND ;Stack pointer setting
out SPL, r16
ldi r16, 0b00000100 ;PB2 output setting
out DDRB, r16
ldi r16, 0b00000000
out PORTB, r16
ldi r16, 0b00000011 ;Analog Comparator setting
out ACSR, r16
loop:
ldi r16, 0b00000000
sbic ACSR, 5 ;ACSR(ACO(5))=0 skip
out PORTB, r16
sbis ACSR, 5 ;ACSR(ACO(5))=1 skip
rcall hotaru
rjmp loop
hotaru: ldi r16, 0d200
loop1:
rcall wait_hotaru1
dec r16
brne loop1
ldi r16, 0d200
loop2:
rcall wait_hotaru2
dec r16
brne loop2
ret
wait_hotaru1:
mov r17, r16
wait_hotaru01:
rcall wait50us
dec r17
brne wait_hotaru01
ldi r18, 0b00000000
out PORTB, r18
ldi r17, 0d201
sub r17, r16
wait_hotaru02:
rcall wait50us
dec r17
brne wait_hotaru02
ldi r18, 0b00000100 ;PB2 high level outpit
out PORTB, r18
ret
wait_hotaru2:
ldi r17, 0d201
sub r17, r16
wait_hotaru04:
rcall wait50us
dec r17
brne wait_hotaru04
ldi r18, 0b00000000 ;PB2 low level outpit
out PORTB, r18
mov r17, r16
wait_hotaru03:
rcall wait50us
dec r17
brne wait_hotaru03
ldi r18, 0b00000100
out PORTB, r18
ret
wait50us: push r17
ldi r17,0d79
wait_loop:
nop
nop
dec r17
brne wait_loop
pop r17
ret
.end