Ассемблер (ASM) для AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
dr.doc
Это не хвост, это антенна
Сообщения: 1368
Зарегистрирован: Вс мар 28, 2010 12:52:22
Откуда: Беларусь

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение dr.doc »

Мой аналитический склад ума дошел до того, что это либо импульсы на тахометр идут не ровно, а у меня замеряет между двух импульсов период...
Скорее всего идут от датчика положения коленвала. А на нем, как правило, несколько "зубов" отсутствуют. Поэтому без фильтрации и гистерезиса и будет "дергать". Фильтр позволит уменьшить гистерезис.
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Я же скорость считываю, а не обороты... :roll:
Возможно и там может быть тот факт, что где-то импульсы пропускает. Спидометр на это не реагирует, т.к. там инерционность большая, конденсаторы стоят какие-нибудь.
А у меня реагирует на каждый чих.
Станислав
Аватара пользователя
dr.doc
Это не хвост, это антенна
Сообщения: 1368
Зарегистрирован: Вс мар 28, 2010 12:52:22
Откуда: Беларусь

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение dr.doc »

Точно. Попутал. просто недавно знакомый про своего американца данные искал и у него получалось 4000 имп/миля. Но последовательность была неравномерной. Возможно мозг выдавал пачки, использую что-либо вроде ABS.
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Вот. Уже ближе к делу! У меня Тойота, на ней, как мне удалось найти, 2548 импульсов на километр. Схемку хочу сделать универсальную. На Тойотах самые меделнные импульсы (их меньше всего). На других автопромах их больше.
Чтобы измерить такие медленные импульсы я и сделал две переменные, т.к. у ТИНИ13 нет 16 разрядного таймера. Как и посоветовали, при каждом переполнении таймера делаю инкремент переменной. Получился таймер 16 разрядный. ))) По сохраненным значениям в памяти МК видно, что их достаточно, да и в ручную я посчитал, что при 4,8 МГц и делителе таймера на 256, один тик таймера будет 0,000213 секунды.
Станислав
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Demiurg »

Я асм почти окончательно забросил. Делюсь некоторыми советами для тех кто еще верен асму животворящему :)))
Шаблон. Главный файл. pattern.asm:
Спойлер

Код: Выделить всё

//==================
.nolist
.include	"m32def.inc"
.list
//==================

//=============== Функции и глобальные определения проекта ===============
//------------------------------------------------------------------------
#define NO	0
#define YES 1
//------------------------------------------------------------------------

//------------------------------------------------------------------------
#define TINY 0
#define MEGA 1
//------------------------------------------------------------------------

//------------------------------------------------------------------------
#define NO_CHANGE 0
#define CHANGE 1
//------------------------------------------------------------------------

//------------------------------------------------------------------------
#define tab_h(x) HIGH(x), LOW(x)
#define tab_l(x) LOW(x), HIGH(x)
//------------------------------------------------------------------------

//------------------------------------------------------------------------
#define WORK	0
#define DEBUG	1
//==================

//==================
#define PROJECT			DEBUG // WORK // 

#define CPU_TYPE		MEGA

#define WATCH_DOG		NO_CHANGE

#define EEPROM			YES
//==================

//==================
.equ	XTAL	= 8000000
//==================

//==================
//----------- List used register -----------------------------------------
//									n/u - Not Used
//							= r0	result multiply
//							= r1	result multiply
.def	RCLR				= r2
.def	RSER				= r3
.def	RSREG				= r4
.def	EEDREG				= r5
.def	KEYS_PREV			= r6
.def	KEYS_CURRENT		= r7
.def	ADC_PUMP_SPEED		= r8
//							= r9
//							= r10
//							= r11
//							= r12
//							= r13	n/u
//							= r14	Used.
//							= r15	Used.
//------------------------------------------------------------------------
.def	TEMP				= r16 // Used. Everywhere
//							= r17	Used. Everywhere
//							= r18	Used. Everywhere
//							= r19	Used. Everywhere
.def	FSM_STATE			= r20
.def	FSM_FLAGS			= r21
.def	CNT					= r22
.def	FLAGS				= r23
.def	POINT_ENTRY_L		= r24 // adiw/sbiw
.def	POINT_ENTRY_H		= r25 // adiw/sbiw
//							= r26	XL
//							= r27	XH
//							= r28	YL
//							= r29	YH
//							= r30	ZL
//							= r31	ZH
//==================

//==================
.set	NUM_FLG = -1

.macro Def_Flag
.set NUM_FLG = (NUM_FLG+1)
.set @0 = NUM_FLG
.if	(NUM_FLG<=7)
.message "Flag Defined!"
.else
.error "Flag Not Defined"
.endif
.endmacro

.set	NUM_ERR = 0

.macro Def_Err_ID
.set NUM_ERR = (NUM_ERR+1)
.set @0 = NUM_ERR
.message "Number Error Defined!"
.endmacro

.macro	End_Table
.db		0xFF, 0xFF
.endmacro
//==================

#if (PROJECT==DEBUG)

//==================
.equ	TEST_LED_PORT	= PORTD
.equ	TEST_LED_DDR	= DDRD
.equ	TEST_LED_PIN	= PIND

.equ	TEST_LED		= PD7
//------------------------------------------------------------------------

//------------------------------------------------------------------------
.macro	test_led_on
	in			r16, TEST_LED_DDR
	setb		r16, TEST_LED
	out			TEST_LED_DDR, r16
.endmacro

.macro	test_led_off
	in			r16, TEST_LED_DDR
	clrb		r16, TEST_LED
	out			TEST_LED_DDR, r16
.endmacro
//==================

#endif

//==================
.include	"vectors_m32.inc"

.include	"library.inc"

.include	"proc_errors.inc"

.include	"system_timer.inc"

.include	"fsm.inc"

.include	"prototreads.inc"

.include	"in_out_def.inc"

.include	"in_out_lib.inc"

.include	"val_def.inc"

.include	"kbd_drv_def.inc"

.include	"kbd_drv.inc"

.include	"proc_menu.inc"
//************************************************************************

.dseg
.org 0x200

rdata:
.byte 6

.cseg

//************************************************************************
Reset:
//------------------------------------------------------------------------
	Clear_Registers
//------------------------------------------------------------------------

//------------------------------------------------------------------------
	clr		RCLR
	ser		r16
	mov		RSER, r16
	clr		FLAGS
//------------------------------------------------------------------------

//------------------------------------------------------------------------
	Init_Stack // Инициализация стека.
//------------------------------------------------------------------------

//------------------------------------------------------------------------
	Clear_SRAM // Очистка ОЗУ.
//------------------------------------------------------------------------

//------------------------------------------------------------------------
	Init_System_Timer // Инициализация системного таймера.
//------------------------------------------------------------------------

//------------------------------------------------------------------------
	Init_WDT
//------------------------------------------------------------------------

//------------------------------------------------------------------------
	Init_Sleep_Mode
//------------------------------------------------------------------------

//----------------------------- Отладка ----------------------------------
#if (PROJECT==DEBUG)

#endif
//==================

	sei

//==================
Main:
	wdr
	rcall	Service_Timers
	rcall	KBD_DRV
	rcall	Proc_Menu
	rjmp	Main
//==================

В конце заголовочный файлов на конкретные МК есть таблицы векторов. Для каждого используемого МК делаем отдельный файл по этому примеру. vectors_m32.inc:
Спойлер

Код: Выделить всё

.cseg

.org	0x0000
		rjmp	Reset

; ***** INTERRUPT VECTORS ************************************************
.org	INT0addr				; External Interrupt Request 0
		reti

.org	INT1addr				; External Interrupt Request 1
		reti

.org	INT2addr				; External Interrupt Request 2
		reti

.org	OC2addr					; Timer/Counter2 Compare Match
		reti

.org	OVF2addr				; Timer/Counter2 Overflow
		reti

.org	ICP1addr				; Timer/Counter1 Capture Event
		reti

.org	OC1Aaddr				; Timer/Counter1 Compare Match A
		reti

.org	OC1Baddr				; Timer/Counter1 Compare Match B
		reti

.org	OVF1addr				; Timer/Counter1 Overflow
		reti

.org	OC0addr					; Timer/Counter0 Compare Match
		rjmp	Sys_Timer_Comp

.org	OVF0addr				; Timer/Counter0 Overflow
		reti

.org	SPIaddr					; Serial Transfer Complete
		reti

.org	URXCaddr				; USART, Rx Complete
		reti

.org	UDREaddr				; USART Data Register Empty
		reti

.org	UTXCaddr				; USART, Tx Complete
		reti

.org	ADCCaddr				; ADC Conversion Complete
		reti

.org	ERDYaddr				; EEPROM Ready
		reti

.org	ACIaddr					; Analog Comparator
		reti

.org	TWIaddr					; 2-wire Serial Interface
		reti

.org	SPMRaddr				; Store Program Memory Ready
		reti
;-------------------------------------------------------------------------

;-------------------------------------------------------------------------
.org	INT_VECTORS_SIZE		; size in words
;===================

Шаблон конечного автомата (этакое ядро конечного автомата) с переходом по индексу-состоянию.
Спойлер

Код: Выделить всё

.cseg

//==================
.macro Proc_FSM
	ldz		@0*2
	rjmp	_Proc_FSM
.endmacro

_Proc_FSM:
	lpm		XH, Z+ ; Считывание старшего байта адреса состояния автомата.
	lpm		XL, Z+ ; Считывание младшего байта адреса состояния автомата.
	ld		r16, X ; Считывание состояния автомата.
	lpm		r17, Z+ ; Считывание количества состояний автомата.
	cp		r16, r17
	brsh	Process_Errors_FSM
	lpm		XH, Z+
	lpm		XL, Z
	movw	ZH:ZL, XH:XL
	add		ZL, r16
	adc		ZH, RCLR
	shiftlwz
	lpm		r17, Z+
	lpm		r16, Z
	movw	ZH:ZL, r17:r16
	ijmp
Process_Errors_FSM:
	cli
	adiw	ZL, 2
	lpm		r16, Z
	rjmp	Proc_Errors
//==================

//==================
Set_FSM_State:
	st			Y, FSM_STATE
	ret
//==================

//==================
//Proc_FSM_Exit:
//	st			Y, FSM_FLAGS
//	std			Y+1, FSM_STATE
//	ret
//==================
Пример использования шаблона конечного автомата:
Спойлер

Код: Выделить всё

KBD_DRV:
	pushiwl		Kbd_Drv_Save_Val // Эти две строки - манипуляция со стеком. В стек загоняется эта подпрограмма. 
                                                            // После выхода из конечного автомата прыгаем сюда, сохраняем данные,
                                                            // после этого возвращаемся в место, откуда вызвали конечный автомат.
                                                            // если толком не знаете как работает стек, и как им манипулировать,
                                                            // не используйте этот прием.
	pushiwl		Define_Keys          // 

	ldy			_KEYS
	ldd			FSM_STATE, Y+DISP_KEYS
	ldd			FSM_FLAGS, Y+DISP_KEYS_FLAGS

	Scan_Keys // Макрос сканирование кнопок. Дефайнами подставляются нужные функции. Порт\Матрица\Несколько портов.
	Proc_FSM	Tab_FSM_KBD_DRV

//==================
Kbd_Drv_Save_Val:
	std		Y+DISP_KEYS, FSM_STATE
	std		Y+DISP_KEYS_FLAGS, FSM_FLAGS
	ret
//==================

Keys_Init:
	ser			r16
	mov			KEYS_PREV, r16
	mov			KEYS_CURRENT, r16
	std			Y+DISP_KEYS_BUF, r16
	Set_State	_KEYS_NONE
	ret

Tab_FSM_KBD_DRV:
.db		tab_h(_KEYS), MAX_FSM_KBD_DRV_STATES, tab_h(Tab_Jmp_KBD_DRV), ERR_ID_KBD_DRV

Tab_Jmp_KBD_DRV:
.equ	MAX_FSM_KBD_DRV_STATES	= 5 // Количество состояний автомата.

.equ	_KEYS_INIT				= 0
.db		tab_h(Keys_Init)

.equ	_KEYS_NONE				= 1
.db		tab_h(Keys_None)

.equ	_KEYS_DOWN				= 2
.db		tab_h(Keys_Down)

.equ	_KEYS_WAIT_UP			= 3
.db		tab_h(Keys_Wait_Up)

.equ	_KEYS_UP				= 4
.db		tab_h(Keys_Up)
До кучи набор макросов, подпрограмм.
Спойлер

Код: Выделить всё

.macro	clrb
	cbr		@0,1<<@1
.endmacro

.macro	setb
	sbr		@0,1<<@1
.endmacro

.macro sfbs
	lds		r16,@0
	sbrs	r16,@1
.endmacro

.macro sfbc
	lds		r16,@0
	sbrc	r16,@1
.endmacro

.macro stfb
	lds		r16,@0
	sbr		r16,@1
	sts		@0,r16
.endmacro

.macro clfb
	lds		r16,@0
	cbr		r16,@1
	sts		@0,r16
.endmacro

.macro	ldiw
	ldi		@0,High(@2)
	ldi		@1,Low(@2)
.endmacro

.macro	ldx
	ldi		XH,High(@0)
	ldi		XL,Low(@0)
.endmacro

.macro	ldy
	ldi		YH,High(@0)
	ldi		YL,Low(@0)
.endmacro

.macro	ldz
	ldi		ZH,High(@0)
	ldi		ZL,Low(@0)
.endmacro

.macro	pushx
	push	XL
	push	XH
.endmacro

.macro	pushy
	push	YL
	push	YH
.endmacro

.macro	pushz
	push	ZL
	push	ZH
.endmacro

.macro	popx
	pop		XH
	pop		XL
.endmacro

.macro	popy
	pop		YH
	pop		YL
.endmacro

.macro	popz
	pop		ZH
	pop		ZL
.endmacro

.macro	stsi
	ldi		r16,@1
	sts		@0,r16
.endmacro

.macro	stsiw
	ldi		r16,high(@1)
	sts		@0+1,r16
	ldi		r16,low(@1)
	sts		@0,r16
.endmacro

.macro	outi
	ldi		r16,@1
	out		@0,r16
.endmacro

.macro outiw
	ldi		r16,high(@1)
	out		@0H,r16
	ldi		r16,low(@1)
	out		@0L,r16
.endmacro

.macro adi
	subi	@0,-@1
.endmacro

.macro adci
	sbci	@0,-@1
.endmacro

.macro addiw
	subi	@0L,LOW(-@1)
	sbci	@0H,HIGH(-@1)
.endmacro

.macro cpw
	cp		@0,@1
	cpc		@2,@3
.endmacro

.macro subiw
	subi	@0L,LOW(@1)
	sbci	@0H,HIGH(@1)
.endmacro

.macro addw
	add		@0L,@1
	adc		@0H,@2
.endmacro

.macro shiftlwz
	lsl		ZL
	rol		ZH
.endmacro

.macro shiftrw
	lsr		@0H
	ror		@0L
.endmacro

.macro			INIT_STACK
.ifdef	SPH
	outi	SPH,HIGH(RAMEND)
.endif
	outi	SPL,LOW(RAMEND)
.endmacro

.macro	INIT_WATCH_DOG
	outi	WDTCR,1<<WDTOE | 1<<WDE ;  | 1<<WDP2 | 1<<WDP1 | 1<<WDP0
.endmacro

.macro	INIT_SLEEP_MODE
	in		r16,MCUCR
	sbr		r16,1<<SE
	out		MCUCR,Temp
.endmacro

.macro	INIT_EXT_INT0
	in		r16,MCUCR
	sbr		r16,1<<ISC00 | 1<<ISC01
	out		MCUCR,Temp
	in		r16,GICR
	sbr		r16,1<<INT0
	out		GICR,r16
.endmacro

.macro	INIT_EXT_INT1
	in		r16,MCUCR
	sbr		r16,1<<ISC10 | 1<<ISC11
	out		MCUCR,Temp
	in		r16,GICR
	sbr		r16,1<<INT1
	out		GICR,r16
.endmacro

.macro	INIT_EXT_INT2
	in		r16,MCUCR
	sbr		r16,1<<SE
	out		MCUCR,Temp
	in		r16,MCUCSR
	sbr		r16,1<<ISC2
	out		MCUCSR,Temp
	in		r16,GICR
	sbr		r16,1<<INT2
	out		GICR,r16
.endmacro

.macro	INIT_TIMER0
	out		TCNT0,RCLR
	in		r16,TIMSK
	sbr		r16,1<<OCIE0
	out		TIMSK,r16
	outi	OCR0,(XTAL/64/1000)
	outi	TCCR0,1<<CS00 | 1<<CS01
.endmacro

.macro	INIT_TIMER1
	in		r16,TIMSK
	sbr		r16,1<<OCIE1A
	out		TIMSK,r16
	out		TCNT1H,Zero
	out		TCNT1L,Zero

	ldi		r16,High(36)
	out		OCR1AH,r16
	ldi		r16,Low(36)
	out		OCR1AL,r16 ; При частоте кварца 7,3728 Мгц число 72=10 мс.

	ldi		r16,0x05
	out		TCCR1B,r16
.endmacro

.macro	INIT_TIMER2
	out		TCNT2,RCLR
	in		r16,TIMSK
	sbr		r16,1<<OCIE2
	out		TIMSK,r16
	outi	OCR2,(XTAL/64/1000)
	outi	TCCR2,4
.endmacro

.macro	Case
	cpi		STREG,@0
	brne	Exit_Case
	rjmp	@1
Exit_Case:
.endmacro

.macro	Case_Not_Equal
	cpi		STREG,@0
	breq	Exit_Case
	rjmp	@1
Exit_Case:
.endmacro

.macro	Read_State
	lds		r16,@0
.endmacro

.macro	Set_State
	ldi		r16,@1
	sts		@0,r16
.endmacro

.macro	Set_Mode
	ldi		r16,@1
	sts		@0,r16
.endmacro

.macro	Check_States
	cpi		r16,@0
	brlo	Check_States_Exit
	rjmp	@1
Check_States_Exit:
.endmacro

.macro	Read_Last_State
	lds		r17,@0
.endmacro

.macro	ClearRegisters
	clr		r0
	clr		r1
	clr		r2
	clr		r3
	clr		r4
	clr		r5
	clr		r6
	clr		r7
	clr		r8
	clr		r9
	clr		r10
	clr		r11
	clr		r12
	clr		r13
	clr		r14
	clr		r15

	clr		r16
	clr		r17
	clr		r18
	clr		r19
	clr		r20
	clr		r21
	clr		r22
	clr		r23
	clr		r24
	clr		r25
	clr		r26
	clr		r27
	clr		r28
	clr		r29
	clr		r30
	clr		r31
.endmacro

.macro	Set_State
	ldi		FSM_STATE, @0
.endmacro

.macro Clear_Registers
	clr		ZH
	ldi		ZL, 30
Clear_Register_Cycle:
	dec		ZL
	st		Z, ZH
	brne	Clear_Register_Cycle
.endmacro

;*************************************************************************
;=========== SRAM ====================
;*************************************************************************

.macro	OUT_SRAM
	ldi		XH,HIGH(@0)
	ldi		XL,LOW(@0)
	ldi		Data_H,HIGH(@1)
	ldi		Data_L,LOW(@1)
	rcall	_OUT_SRAM
.endmacro

.macro	OUTI_SRAM
	ldi		XH,HIGH(@0)
	ldi		XL,LOW(@0)
	ldi		r17,@1
	ldi		r16,@2
	rcall	_OUT_SRAM
.endmacro

_OUT_SRAM:
	st		X+,r16
	dec		r17
	brne	_OUT_SRAM
	ret

.macro	Copy_SRAM
.if @3==YES
	push	YH
	push	YL
.endif
	ldi		XH,HIGH(@0)
	ldi		XL,LOW(@0)
	ldi		YH,HIGH(@1)
	ldi		YL,LOW(@1)
	ldi		r17,@2
	rcall	_Copy_SRAM
.if @3==YES
	pop		YL
	pop		YH
.endif
.endmacro

_Copy_SRAM:
	ld		r16,X+
	st		Y+,r16
	dec		r17
	brne	_Copy_SRAM
	ret

.macro	Clear_SRAM
	ldx		SRAM_START
Clear_SRAM_Cycle:
	st		X+,RCLR
	cpi		XL,LOW(SRAM_START+SRAM_SIZE)
	brne	Clear_SRAM_Cycle
	cpi		XH,HIGH(SRAM_START+SRAM_SIZE)
	brne	Clear_SRAM_Cycle
.endmacro
;*************************************************************************

;*************************************************************************
;========== EEPROM ===================
;*************************************************************************

;Так как возможна случайная запись в EEPROM в случае сбоя питания, то:
;1 - В микроконтроллере включить контроль снижения напряжения питания. 
;2 - Первый (0x00) байт никогда не используется. 
;3 - После ресета обнулить указатель адреса EEPROM. 
;Решения для увеличения ресурса EEPROM:
;4 - Перед записью считывается байт, предназначенный для записи,
;проверяется на равенство с записываемым, если байты равны, то переход
;к записи следующего байта. 
;5 - В конце работы с EEPROM обнулить указатель адреса. 

#if (EEPROM==YES)

.macro Read_EEPROM
	ldix	@0 ; Указатель адреса EEPROM.
	ldiy	@1 ; Указатель адреса SRAM.
	ldi		r17,@2
	rcall	_Read_EEPROM
.endmacro

_Read_EEPROM:
	sbic	EECR,EEWE
	rjmp	_Read_EEPROM
.ifdef EEARH
	out		EEARH,XH
.endif
	out		EEARL,XL
	sbi		EECR,EERE
	sbi		EECR,EERE
	in		EEDREG,EEDR
	st		Y+,EEDREG
	adiw	XL,1
	dec		r17
	brne	_Read_EEPROM
_Read_EEPROM_0:
	sbic	EECR,EEWE
	rjmp	_Read_EEPROM_0
.ifdef EEARH
	out		EEARH,RCLR
.endif
	out		EEARL,RCLR
	ret

EERead:
	sbic	EECR,EEWE
	rjmp	EERead
.ifdef EEARH
	out		EEARH,XH
.endif
	out		EEARL,XL
	sbi		EECR,EERE
	sbi		EECR,EERE
	in		EEDREG,EEDR
EERead_1:
	sbic	EECR,EEWE
	rjmp	EERead_1
.ifdef EEARH
	out		EEARH,RCLR
.endif
	out		EEARL,RCLR
	ret

EEWrite:
	sbic	EECR,EEWE
	rjmp	EEWrite
.ifdef EEARH
	out		EEARH,XH
.endif
	out		EEARL,XL
	out		EEDR,EEDREG
	sbi		EECR,EEMWE
	sbi		EECR,EEWE
EEWrite_1:
	sbic	EECR,EEWE
	rjmp	EEWrite_1
.ifdef EEARH
	out		EEARH,RCLR
.endif
	out		EEARL,RCLR
	ret

.macro Write_EEPROM
	ldiy	@0 ; Указатель адреса SRAM.
	ldix	@1 ; Указатель адреса EEPROM.
	ldi		r17,@2
	rcall	_Write_EEPROM
.endmacro

_Write_EEPROM:
	sbic	EECR,EEWE
	rjmp	_Write_EEPROM
.ifdef EEARH
	out		EEARH,XH
.endif
	out		EEARL,XL
	ld		EEDREG,Y+
	out		EEDR,EEDREG
	sbi		EECR,EEMWE
	sbi		EECR,EEWE
	adiw	XL,1
	dec		r17
	brne	_Write_EEPROM
_Write_EEPROM_0:
	sbic	EECR,EEWE
	rjmp	_Write_EEPROM_0
.ifdef EEARH
	out		EEARH,RCLR
.endif
	out		EEARL,RCLR
	ret

.macro	Clear_EEPROM
	ldx		@0
	ldy		@1
	rcall	_Clear_EEPROM
.endmacro

_Clear_EEPROM:
	sbic	EECR,EEWE
	rjmp	_Clear_EEPROM
.ifdef EEARH
	out		EEARH,XH
.endif
	out		EEARL,XL
	out		EEDR,RCLR
	sbi		EECR,EEMWE
	sbi		EECR,EEWE
	adiw	XL,1
	sbiw	YL,1
	brne	_Clear_EEPROM
_Clear_EEPROM_0:
	sbic	EECR,EEWE
	rjmp	_Clear_EEPROM_0
.ifdef EEARH
	out		EEARH,RCLR
.endif
	out		EEARL,RCLR
	ret

#endif
;*************************************************************************

/************************************************************************/
#if (BCD==YES)

.dseg

HEX_DEC_BUFFER:
.equ	HEX_DEC_BUFFER_LENGHT = 5
.byte	HEX_DEC_BUFFER_LENGHT


.cseg

Hex_Dec:
	ldx		HEX_DEC_BUFFER
	ldi		r17,HIGH(10000)
	ldi		r16,LOW(10000)
	rcall	Digit
	st		X+,r18
	ldi		r17,HIGH(1000)
	ldi		r16,LOW(1000)
	rcall	Digit
	st		X+,r18
	ldi		r17,HIGH(100)
	ldi		r16,LOW(100)
	rcall	Digit
	st		X+,r18
	ldi		r17,HIGH(10)
	ldi		r16,LOW(10)
	rcall	Digit
	st		X+,r18
	mov		r16,r14
	ori		r16,0x30
	st		X+,r16
Hex_Dec_End:
	ret

Digit:
	ldi		r18,-1
Digit_Cycle:
	inc		r18
	sub		r14,r16
	sbc		r15,r17
	brsh	Digit_Cycle
	add		r14,r16
	adc		r15,r17
	ori		r18,0x30
	ret
#endif
/************************************************************************/

/************************************************************************/
Empty_Action:
	ret
/************************************************************************/

/************************************************************************/
Table_Bits:
.db 0b00000001, 0b00000010, 0b00000100, 0b00001000
.db 0b00010000, 0b00100000, 0b01000000, 0b10000000
/************************************************************************/

/************************************************************************/
.macro end_array
.db 0xFF,0xFF
.endmacro
/************************************************************************/

Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Вот устроили из темы срач холиварный. :facepalm: Эту часть надо вырезать и отнести в МЯЯЯУ.
А у меня тем временем глюки с моей программулиной даже в Протеусе. Не могу понять в чем дело. Возможно и прерывания гонят. Хотя, не должны. В эмуляторе же крутил много раз программу, там тупо крутится в главном цикле и выполняет условия. Однако, почему-то умудряется погасить один светодиод не тогда, когда надо, должен гасить оба сразу. А даже команды во всем тексте такой нет, где он гасит один светодиод... :facepalm:
Не пойму, как он умудряется это сделать.
и когда совсем импульсов нет, соответственно нет и прерываний. Почему тогда он не выключает их иной раз? :facepalm:

Код: Выделить всё

Start:	

		cp  ONBlL, PERIODL 
		cpc  ONBlH, PERIODH
		brsh ONB

		 rjmp T
		
	ONB: sbi PORTB, 2
 
	T:	cp  ONTumL, PERIODL 	; Если 
		cpc  ONTumH, PERIODH 
		brsh ONT

		 rjmp O

	ONT: sbi PORTB, 0

	O:	cp  OFFL, PERIODL  	; Сравниваем с настоящим значением накопленного
		cpc  OFFH, PERIODH	; Если начисленное больше, то выключаем (скорость сильно маленькая)
		brlo OFF

		rjmp Start		

	OFF: cbi PORTB, 0
		 cbi PORTB, 2

	rjmp	Start	; Конец программы, переход на начало
Станислав
Аватара пользователя
Z_h_e
Собутыльник Кота
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Z_h_e »

Когда все работает, но иногда глючит причиной зачастую является ошибка сохранения флагов в обработчике прерывания или регистров. Поверьте ка что там у Вас.
Сказочник писал(а):Вот устроили из темы срач холиварный. :facepalm:
Жирный плюс Вам за остановку этого беспредела.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Demiurg »

СКАЗОЧНИК писал(а):...
Программа не вся. У вас там строка есть, если начисленное больше, то выключаем, а команда стоит brlo. Или считается что если PERIOD больше?

Если происходит что-то необъяснимое, то локализуем ошибку. В вашем случае гаснет один светодиод. Значит, предполагаемые причины: в прерывании не сохраняется-восстанавливается SREG, какой-нибудь регистр. Работа с портом в прерывании и в основном цикле.

Какие функции еще выполняет пин? Может вы режим какой включаете, из-за чего гаснет светодиод.

Также следует не исключать ошибку самого протеуса. Для отладки программ лучше AVR-Studio 4.19 ничего нет. Так как это продукт самого ATMEL, то симулятор симулирует максимально приближенно к правде. Если же у студии и есть какие косяки с симулированием, то они известны.

Лично я пользуюсь всегда только студией, если нужно проверить программу. Протеусом пользовался для проверки пару раз максимум. Когда нужно было быстро проверить работоспособность связки. символьный дисплей, семисегментный дисплей.
Аватара пользователя
Starichok51
Модератор
Сообщения: 19046
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Starichok51 »

СКАЗОЧНИК писал(а):Вот устроили из темы срач холиварный.
на правах модератора удалил весь устроенный срач холиварный...
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Z_h_e писал(а):ошибка сохранения флагов в обработчике прерывания или регистров
:dont_know: А там я делал по вашему совету. :) Т.е. использовал флаг прерывания таймера, т.к. он меньше по приоритету, чем внешнее прерывание по фронту/спаду.
Ой! Точно, в таймере флаги то используются! Сейчас исправлю! :beer:
Спойлер

Код: Выделить всё

; ----------------------
; ОБРАБОТЧИКИ ПРЕРЫВАНИЙ
; ----------------------

	INT0add:

		push temp						; Закидываем в стек темп
		in temp, SREG					; Закидываем в стек СРЕГ
		push temp

			in temp, TIFR0				; Проверка флага переполнения таймера
			andi temp, (1<<1)			; Накладываем маску, если 1 бит был единицей, то он и останется, все остальные будут 0. Если он 0, то будет флаг Z
			breq NOFLAG					; Нет флага (стоит Z), значит уходим, иначе обрабатываем флаг
				out TIFR0, temp			; В темп уже есть этот флаг, как 1, снова его запихиваем и тем самым скинем флаг
				inc OVF					; Добавляем еще одно переполнение к таймеру
				
				
		NOFLAG: in PERIODL, TCNT0		; Считываем значение младшего
				mov PERIODH, OVF		; Считываем занчение старшего
				
				clr OVF					; Чистим все для очередного замера
				out TCNT0, OVF
		
		pop temp						; Вытаскиваем из стека СРЕГ
		out SREG, temp		
		pop temp						; Вытаскиваем из стека темп		    

	reti

;----------------------------------------------------------------------------------------

	OVF0add:

		inc OVF

		cpi OVF, 251
		brsh OVER
		reti

		OVER: ldi OVF, 250

	reti
Demiurg писал(а):а команда стоит brlo. Или считается что если PERIOD больше?
Да, именно так. Если период больше всего всего, то значит импульс слишком длинный и давно пора выключить все нагрузки. ))) Даже алгоритм пришлось рисовать для этого на листочке. Вообще все конспектирую и стараюсь рисовать. Так понятнее разбираться.
Demiurg писал(а):в прерывании не сохраняется-восстанавливается SREG, какой-нибудь регистр. Работа с портом в прерывании и в основном цикле.
Demiurg писал(а):Может вы режим какой включаете, из-за чего гаснет светодиод.
Вот. В прерывании сохраняю регистры. Во втором прерывании с ними не работаю, поэтому и не трогаю. С портами не работаю в прерывании, Тини13, там альтернативных функций не так много, поэтому использую порт как есть и всего один INT0. Все... :dont_know:
Demiurg писал(а):Для отладки программ лучше AVR-Studio 4.19 ничего нет.
Тоже так думаю. Но сама студия в отладке показывает = все прекрасно. Даже с эмуляцией прерываний и т.д. и т.п. Все значения обрабатывает идеально.
Глючить начинает Протеус и Железо. Причем, как-то одинаково почти. В Протеусе я подаю импульсы с генератора, а в реальной жизни от спидометра на Тойота Спасио. И там и там моргает... А когда частота спидометра/генератора снижается, то выключается ближний свет, в то время, когда выключиться должны только вместе при самой маленькой скорости. Даже в программе нет такой строчки, где отдельное выключение порта... Только одновременно. :dont_know:

В Протеусе начал проверять, просто от безысходности. Дома нет возможности реальное железо тестировать, т.к. нет датчика скорости (или его эмулятора). Обычно Протеусом вообще не пользуюсь...

Не знаю. Буду сидеть и думать до конца. Хочу доделать это устройство. Результатами обязательно всеми поделюсь. Может кто полезное для себя возьмет или найдет.
Если кому будет интересно, выложу проект Протеуса и Прошивку.

Благодарю всех за проявленный интерес!
Starichok51 писал(а):на правах модератора
:) :beer:

З.Ы. В верху неправильный подсчет написал по времени периода таймера.
Вот правильный:
СпойлерЧастота МК 4,8 МГц. Тмк = 0,000000208 с.
Частота таймера 4,8 МГц/256 = 18750 Гц. Ттайм = 0,000053333 с.
Полный счет таймера 256 TCNT0 и еще 250 переполнений (так ограничивает прерывание), получается за примерно 3,4 с.
Минимальный период импульса указан выше = 0,0000533333 с.
Т.е. таймер может считать от f = 0.294 Гц, до f = 18750 Гц.
Мои подсчеты по замерам на реальном автомобиле при скорости в районе 5 км/ч fимп. = 8,75 Гц или Тимп. = 0,1143 с.
А при скорости 200 км/ч fимп. = 141,844 Гц или Тимп. = 0,007 с.
Запас есть, как не крути. :roll:
Думаю, надо считать несколько импульсов за период времени... или несколько импульсов измерять период, а потом вычислять среднее арифметическое, как и раньше говорил(и).
Станислав
Аватара пользователя
Z_h_e
Собутыльник Кота
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Z_h_e »

СКАЗОЧНИК писал(а):В Протеусе начал проверять, просто от безысходности.
Протеус отлично средство отладки, просто надо понимать что это всего лишь эмулятор, но Вашу задачу он легко съест.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

У меня еще комп его плохо тянет. и иной раз виснет. :)
Станислав
Аватара пользователя
Z_h_e
Собутыльник Кота
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Z_h_e »

Виснет часто тоже. Тут приходится играться, бывает добавляешь резистор не в тему, просто не подключенный и опять все заработало. А по скорости, если убрать аналоговую часть, то работает в реальном режиме времени.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Все. Тема моя походу умерла сама собой. )))) Я только что осознал, что в городе есть светофоры и пешеходные переходы... И каждое снижение скорости или остановка будут гасить туманки и второй ближний свет. Лампам придет писец еще быстрее... :facepalm: Вот блин.

У кого есть предложения, куда еще можно применять эту плату? Может использовать ее как отсечку для Жигулей? А то у меня просили. :)))
Станислав
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Demiurg »

СКАЗОЧНИК писал(а):...
Смириться, успокоив себя тем, что получил бесценный опыт. Отрицательный результат - тоже результат.
А наработки когда-нибудь пригодятся в другом устройстве.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение WiseLord »

А ввести два режима - город и трасса? В одном ничего такого не делать (или делать иначе), в другом - переключать фары как задумано.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Хороший вариант. ))) Все равно решили эту схему доделывать, но изменили немного критерии и включили в работу задержки, т.е. если стоим более 10 секунд, то выключить свет. А город-трасса - тоже есть, можно включить в ручную все. А можно в автоматическом режиме через эту конструкцию.
Сейчас буду додумывать.
Спасибо.
Станислав
Аватара пользователя
ILYAUL
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср мар 28, 2012 21:45:24
Откуда: ВО

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение ILYAUL »

Код: Выделить всё

;----------------------------------------------------------------------------------------

   OVF0add:

      inc OVF

      cpi OVF, 251
      brsh OVER
      reti


   reti
Команда CPI меняет регистр SREG. Когда Вы научитесь сохранять этот регистр , если применяете команды его изменяющие?
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

В прерываниях у меня сохраняется этот регистр. Уже )))) :dont_know:
Станислав
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение akl »

СКАЗОЧНИК писал(а): ...Мои подсчеты по замерам на реальном автомобиле при скорости в районе 5 км/ч fимп. = 8,75 Гц или Тимп. = 0,1143 с. А при скорости 200 км/ч fимп. = 141,844 Гц или Тимп. = 0,007 с.
Уточню. Если при скорости 200 км/3600сек измерено 141,844 имп./сек, то датчик выдает 2553 имп/км. В общем, ожидаемо. Чего нельзя сказать про скорость 5км/час. Должно получиться 3,54 имп./сек.
Ответить

Вернуться в «AVR»