疑似的な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			
おすすめの記事