⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ltc.asm

📁 Source code for line followe Robot... aslo going to upload Schametic
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;----------------------------------------------------------------------------;
; Line following robot embedded program (Int.RC 8MHz)
;----------------------------------------------------------------------------;

.include "m8def.inc"	; Device definition file included in "AVR Family Assembler".
.include "avr.inc"

.def	_0	= r15	;Zero reg.

.def	_Flags	= r25	;b0: Senor capture completed
			;b1: Enable motor

.def	_Err	= r14	;Number of sensing error continue...


;-----------------------------------------------------------------------------;
; SRAM椞堟掕媊

.dseg
	.org	RAMTOP
ScanCh:	.byte	2	;Current channel and phase (for background process)

SensReg:.byte	12	;Processing registers (Value)
	.byte	12	;Processing registers (Sensor #)
	.byte	12	;Background scan register
ComVal:	.byte	12	;Inter-channel compensation value

Parms:	.byte	3	;Control parameters (PWM base, P-gain, D-gain)

Pwm:	.byte	3	;PWM control variables (Left, Right, Phase)

LineBuf:.byte	32	;Online command line buffer




;-----------------------------------------------------------------------------;
; EEPROM initial value

.eseg

eeParms:.db	0x18, 0x20, 0xF0	; PWM base, P gain, D gain
eeComVal:.byte	12			; Sensor compensation values



;-----------------------------------------------------------------------------;
; Vector table

.cseg
	rjmp	reset		; RESET
	rjmp	0		; INT0
	rjmp	0		; INT1
	rjmp	0		; TC2 COMP
	rjmp	0		; TC2 OVF
	rjmp	0		; TC1 CAPT
	rjmp	0		; TC1 COMPA
	rjmp	0		; TC1 COMPB
	rjmp	0		; TC1 OVF
;	rjmp	tc0_ovf		; TC0 OVF (Enter tc0_ovf directly)
;	rjmp	0		; SPI
;	rjmp	0		; USART RXC
;	rjmp	0		; USART UDRE
;	rjmp	0		; USART TXC
;	rjmp	0		; ADC
;	rjmp	0		; EE_RDY
;	rjmp	0		; ANA_COMP
;	rjmp	0		; TWI
;	rjmp	0		; SPM_RDY


;-----------------------------------------------------------------------------;
; TC0 overflow interrupt isr (9.6kHz)

tc0_ovf:
	push	AL
	outi	TCNT0, -12
	in	AL, SREG
	pushw	A
	pushw	Y
	pushw	Z

	 rcall	drive_pwm
	 rcall	scan_sens

	popw	Z
	popw	Y
	popw	A
	out	SREG, AL
	pop	AL
	reti


drive_pwm:
	in	AH, PORTB
	cbr	AH, bit1+bit2
	sbrc	_Flags, 1	;Exit if PWM disable
	rjmp	PC+3		;
	out	PORTB, AH	;
	ret			;/
	ldsw	Z, Pwm		;Load PWM values
	lds	AL, Pwm+2	;/
	cp	AL, ZL		;Left drive
	brcc	PC+2		;
	sbr	AH, bit1	;/
	cp	AL, ZH		;Right drive
	brcc	PC+2		;
	sbr	AH, bit2	;/
	out	PORTB, AH	;Set output
	subi	AL, 1		;PWM counter --;
	brcc	PC+2		;
	ldi	AL, 23		;
	sts	Pwm+2, AL	;/
	ret


scan_sens:
	ldsw	Y, ScanCh	;Get current channel pointer
	mov	ZL, YL		;
	lsl	ZL		;
	clr	ZH		;
	addiw	Z, SensReg+24	;/
	cpi	YH, 0		;Branch by channel phase
	breq	rs_0		;
	cpi	YH, 1		;
	breq	rs_1		;
	cpi	YH, 2		;
	breq	rs_2		;
	rjmp	rs_3		;/

rs_0:	inw	A, ADC		;Store base value
	stdw	Z+0, A		;/
rs_1:	inc	YH		;Next phase
	rjmp	rs_exit

rs_2:	sbi	ADCSR, ADSC	;Capture peak value
	ldi	AL, 33		;
	dec	AL		;
	brne	PC-1		;/
	outi	PORTD, 0x7f	;LED off
	inc	YH		;Next phase
	rjmp	rs_exit

rs_3:	ldd	AH, Z+0		;Store peak value - base value
	in	AL, ADCL	;
	sub	AL, AH		;
	std	Z+0, AL		;
	ldd	AH, Z+1		;
	in	AL, ADCH	;
	sbc	AL, AH		;
	std	Z+1, AL		;
	brcc	PC+3		; If result is minus, it is zero.
	std	Z+0, _0		;
	std	Z+1, _0		;/
	clr	YH		;Next cannel (0 -> 2 -> 4 -> 1 -> 3 -> 5)
	addi	YL, 2		;
	cpi	YL, 6		;
	brne	PC+3		;
	ldi	YL, 1		;
	rjmp	PC+13		;/
	brcs	PC+12		;When all channels are completed,
	sbrc	_Flags, 0	; update working regs
	rjmp	PC+9		;
	ldiw	Z, SensReg	;
	ldi	AL, 12		;
	ldd	AH, Z+24	;
	st	Z+, AH		;
	dec	AL		;
	brne	PC-3		;
	sbr	_Flags, bit0	;
	clr	YL		;/
	 rcall	sel_adch	;Capture base value
	sbi	ADCSR, ADSC	;
	ldi	AL, 33		;
	dec	AL		;
	brne	PC-1		;/
	 rcall	sel_led		;LED on
rs_exit:
	stsw	ScanCh, Y
	ret


sel_led: ;Select sensor LED specified by YL (0..5)
	mov	ZL, YL
	clr	ZH
	addiw	Z, led_pat*2
	lpm	ZL, Z
	out	PORTD, ZL
	ret

sel_adch: ;Select sensor A/D channel specified by YL (0..5)
	mov	ZL, YL
	clr	ZH
	addiw	Z, adch_pat*2
	lpm	ZL, Z
	out	ADMUX, ZL
	ret

led_pat:.db	0x7e, 0x7d, 0x7b, 0x6f, 0x5f, 0x3f
adch_pat:.db	0xc0, 0xc1, 0xc2, 0xc3, 0xc6, 0xc7




;-----------------------------------------------------------------------------;
; Power ON / Reset button released

reset:
	ldiw	A, RAMEND		;Initialize SP
	outw	SP,A			;/
	clr	_0			;Permanent zero

	ldiw	Z, RAMTOP		;Clear RAM
	clr	AL			;
	st	Z+, _0			;
	st	Z+, _0			;
	st	Z+, _0			;
	st	Z+, _0			;
	dec	AL			;
	brne	PC-5			;/

	outi	PORTB,0b11101001	;Initialize Port B
	outi	DDRB, 0b00010110	;/
	outi	PORTD, -1		;Initialize Port D
	outi	DDRD, 0b11110111	;/
	outi	PORTC, 0b00110000	;Initialize Port C

	outi	TCCR0, 0b011		;TC0.ck = 115kHz

	clr	_Flags

	sei

	ldiw	Z,m_start*2		;Start up message
	 rcall	dp_str			;/
	 rcall	load_allparms		;Load working parameters
	sbis	PINB, MOSI		;Enter online mode if cable is attached
	rjmp	monitor			;/
	rjne	enter_sleep		;Enter sleep mode if parameter is broken

;-----------------------------------------------------------------------------;
; Self Running Mode


start:
	outi	ADCSR, 0b11000101	;Enable ADC
	outi	TIMSK, (1<<TOIE0)	;Start background process

	ldiw	X, 400			;Wait for 1 sec
	 rcall	read_sens		;
	sbiw	XL, 1			;
	brne	PC-2			;/
	 rcall	read_sens		;Abort if in line sensing error
	rjne	enter_sleep		;/


; 400Hz servo processing loop

running:
	 rcall	read_sens	;Read sensor value
	breq	PC+4		; Stop if error continues for 120 times (0.3s)
	dec	_Err		;
	breq	enter_sleep	;
	rjmp	running		; /
	ldi	BL, 120		;
	mov	_Err, BL	;/

	subi	AL, low(640)	;Remove offset, 640 as center(0)
	sbci	AH, high(640)	;/
	movw	T6L, AL		;Save current value
	lds	BL, Parms+1	;--- P term
	clr	BH		;
	 rcall	muls1616	;
	movw	CL, T2L		;
	movw	DL, T4L		;/
	movw	AL, T6L		;--- D term
	sub	AL, r10		; Get difference between current and 2 times
	sbc	AH, r11		; before into AH:AL
	movw	r10, T8L	; 
	movw	T8L, T6L	; /
	ldiw	X, -127		; Clip difference between +127 and -127
	cpw	A, X		;
	brge	PC+2		;
	movw	AL, XL		;
	ldiw	X, 127		;
	cpw	A, X		;
	brlt	PC+2		;
	movw	AL, XL		; /
	lds	BL, Parms+2	;
	clr	BH		;
	 rcall	muls1616	;/
	addw	C, T2		;DL:CH = (D + P) / 512;
	adc	DL, T4L		;
	asr	DL		;
	ror	CH		;/

	lds	XH, Parms+0	;Set motor output
	mov	XL, XH		;
	sbrc	CH, 7		;
	rjmp	PC+5		;
	sub	XL, CH		;
	brcc	PC+2		;
	clr	XL		;
	rjmp	PC+5		;
	neg	CH		;
	sub	XH, CH		;
	brcc	PC+2		;
	clr	XH		;
	stsw	Pwm, X		;/
	sbr	_Flags, bit1	;Enable motor

	rjmp	running



enter_sleep:
	out	ADCSR, _0		;Disable ADC
	out	TIMSK, _0		;Stop background process
	outi	PORTB, 0b00001000	;
	outi	PORTD, -1		;
	clr	_Flags			;/
	sbis	PINB, MOSI		;Enter online mode if cable is attached
	rjmp	monitor			;/
	outi	MCUCR, 0b10100000	;Enter power-down mode
	sleep				;
	rjmp	PC-3			;/


read_sens:
	cbr	_Flags, bit0	;Wait for a scan completed
	sbrs	_Flags, 0	;
	rjmp	PC-1		;/
	 rcall	comp_sens	;Gain error compensation
	 rcall	sort_value	;Sort by strength
	 rcall	flip_value	;Flip ceiling and floor
	rjmp	get_peak	;Get peak position




;-----------------------------------------------------------------------------;
; Online Mode
; 僆儞儔僀儞儌乕僪

monitor:
	ldiw	Z,m_crlf*2	; Display command prompt
	 rcall	dp_str		; 
	ldi	AL,'%'		; 
	 rcall	xmit		; /
	 rcall	get_line	; Get command line
	ldiw	X,LineBuf	; X -> command line
	ld	BH,X+		; BH = command char
	 rcall	caps		; /
	cpi	BH,0x0d		; Null line ?
	breq	monitor		;  yes, returen
	cpi	BH,'O'		; Output port ?
	breq	do_output	;  yes, do
	cpi	BH,'I'		; Input port ?
	breq	do_input	;  yes, do
	cpi	BH,'E'		; Edit memory ?
	rjeq	do_edit		;  yes, do
	cpi	BH,'S'		; Test motors/sensors ?
	rjeq	do_test		;  yes, do
	cpi	BH,'R'		; Run ?
	rjeq	start		;  yes, do


cmd_err:ldiw	Z,m_error*2	; Syntax error
	 rcall	dp_str		; /
	rjmp	monitor



;--------------------------------------;
; I/O儗僕僗僞偵彂偒崬傒
; Write into I/O register

do_output:
	 rcall	get_valh	; Get I/O address (0-3F)
	breq	cmd_err		; /
	andi	AL,0x3f	; I/O address in memory space (+0x20)
	mov	ZL,AL		; 
	ldi	ZH,0		; 
	adiw	ZL,0x20		; /
	 rcall	get_valh	; Get data value to be written
	breq	cmd_err		; /
	st	Z,AL		; Output data
	rjmp	monitor


;--------------------------------------;
; I/O儗僕僗僞偐傜撉傒崬傒
; Read from I/O register

do_input:
	ld	BH,X		; Get sub command
	 rcall	caps		; 
	mov	CL,BH		; 
	cpi	BH,'R'		; 
	brne	PC+2		; 
	inc	XL		; /

	 rcall	get_valh	; Get I/O address (0-3F)
	breq	cmd_err		; /
	andi	AL,0x3f		; I/O address on memory area (+0x20)
	mov	ZL,AL		; 
	ldi	ZH,0		; 
	adiw	ZL,0x20		; /
	ldi	AL,0x0a		; LF
	 rcall	xmit		; /
	ld	CH,Z		; 1st data
	com	CH		; /
	sbic	PINB,MOSI	; If break, exit loop
	rjmp	monitor		; /
	ld	AH,Z		; Wait data change
	cp	AH,CH		; 
	breq	PC-4		; /
	mov	CH,AH		; Display data
	 rcall	di_disp		; /
	cpi	CL,'R'
	breq	PC-8
	rjmp	monitor

di_disp:
	ldi	AL,0x0d		; CR
	 rcall	xmit		; /
	mov	AL,AH		; Hex
	 rcall	dp_byte		; /
	 rcall	space		; SP
	ldi	BH,8		; Bin
	ldi	AL,'0'
	lsl	AH
	adc	AL,ZH
	 rcall	xmit
	dec	BH
	brne	PC-5
	rcall	space		; SP
	ret


;--------------------------------------;
; 儊儌儕偵彂偒崬傒
; Write into memory

do_edit:
	ld	BH,X+		; BH = command char
	 rcall	caps		; /
	cpi	BH, 'M'		;Get destination
	breq	PC+4		;
	cpi	BH, 'E'		;
	breq	PC+2		;
	rjmp	cmd_err		;
	mov	EH, BH		;/
	 rcall	get_valh	;Get memory address
	rjeq	cmd_err		;
	movw	ZL,AL		;/
	 rcall	get_valh	;Get data value to be written
	rjcs	cmd_err		;/
	breq	de_lp		;Is interactive mode?
	 rcall	wr_mem		; no, store directly and exit
	rjmp	monitor		;/

de_lp:	ldi	AL, 0x0a	; Display data prompt
	 rcall	xmit		; 
	mov	AL,ZH		; 
	 rcall	dp_byte		; 
	mov	AL,ZL		; 
	 rcall	dp_byte		; 
	 rcall	space		; 
	 rcall	rd_mem		; 
	 rcall	dp_byte		; 
	ldi	AL, '-'		; 
	 rcall	xmit		; /
	 rcall	get_line	; Input data value to be written
	ldiw	X,LineBuf	; 
	ld	AL,X		; /
	cpi	AL,'.'		; End of edit?
	rjeq	monitor		;  yes, exit.
	 rcall	get_valh	; Get data value
	rjcs	cmd_err		; /
	breq	PC+2		; Skip if blank.
	 rcall	wr_mem		; Store data into memory
	adiw	ZL,1		; Next location
	rjmp	de_lp		; Continue

rd_mem:	cpi	EH, 'E'
	brne	PC+2
	rjmp	read_eep
	ld	AL, Z
	ret
wr_mem:	cpi	EH, 'E'
	brne	PC+2
	rjmp	write_eep
	st	Z, AL
	ret


;--------------------------------------;
; Test motors and sensors

do_test:
	outi	ADCSR, 0b11000101 ;Enable ADC
	 rcall	get_valh	;secondary command (1-3)
	rjeq	cmd_err
	cpi	AL, 1		;s1 <left> <right> (Output moror PWM)
	breq	ds_1
	cpi	AL, 2		;s2 (dislpay sensor status)
	breq	ds_2
	cpi	AL, 3		;s3 (calibrate sensor)
	rjeq	do_cal
	rjmp	cmd_err

ds_1:
	 rcall	get_valh	;Left motor
	rjeq	cmd_err		;
	sts	Pwm+0, AL
	 rcall	get_valh	;Right motor
	rjeq	cmd_err		;
	sts	Pwm+1, AL

	sbr	_Flags, bit1	;Enable motor
	outi	TIMSK, (1<<TOIE0) ;Start PWM
	sbis	PINB, MOSI	;Break if any key is pressed
	rjmp	PC-1		;/
	out	TIMSK, _0	;Stop PWM
	out	PORTB, _0	;/

	rjmp	monitor


ds_2:
	cbr	_Flags, bit1	;Disable motor
	ldi	ZL, 120		;Scan 120 times
	 rcall	scan_test	;/
	sbic	PINB, MOSI	;Exit when break is detected,
	rjmp	monitor		;/
	ldi	AL, 12		;CLS
	 rcall	xmit		;/
	 rcall	comp_sens	;Compensation
	 rcall	disp_sens_regs
	 rcall	sort_value
	 rcall	flip_value
	 rcall	get_peak
	 rcall	disp_peak
	rjmp	ds_2


sort_value:
	ldiw	Y, SensReg+12	;Put sensor # to each value
	clr	AL		;
	st	Y+, AL		;
	st	Y+, _0		;
	inc	AL		;
	cpi	AL, 6		;
	brcs	PC-4		;/
	ldiw	Y, SensReg	;Sort sensor values in small order
sv_l1:	movw	ZL, YL		; (bubble sort)
sv_l2:	adiw	ZL, 2		;
	lddw	A, Y+0		;
	ldd	BL, Y+12	;
	ldd	BH, Z+0		;
	ldd	CL, Z+1		;
	ldd	CH, Z+12	;
	cp	BH, AL		;
	cpc	CL, AH		;
	brcc	PC+7		;
	std	Y+0, BH		;
	std	Y+1, CL		;
	std	Y+12, CH	;
	stdw	Z+0, A		;
	std	Z+12, BL	;
	cpi	ZL, SensReg+12-2;
	brne	sv_l2		;
	adiw	YL, 2		;
	cpi	YL, SensReg+12-2;
	brne	sv_l1		;/
	ret

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -