Инициализация стека в Attiny26

Обсуждаем контроллеры компании Atmel.
Ответить
Открыл глаза
Сообщения: 49
Зарегистрирован: Ср апр 16, 2014 18:46:46

Сообщение Родион@22 »

Люди выручите пожалуйста новичка! Возникла проблема инициализации стека в Attiny26.
[img][img]http://img.radiokot.ru/files/96849/thumbnail/blyvtzk9b.jpg[/img][/img]
Что нужно дописать в коде, чтобы инициализировать стек?
Запуск производил в AVR Simulator пошагово, а ошибка возникла в строчке:

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

; опрос уровня заряда конденсатора
rcall	adcn
Сама программа:

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

.include "tn26def.inc"

; Микроконтроллер: AVR tiny26
; Тактовая частота: 8 МГц
; Питание: нестабилизированное 3,8 В
.list
.def tmp  = r16
.def tmp2 = r17
.def tmp3 = r18
.def tempo = r19
.def pir = r22
.def pur = r23
.def par = r20
.def Xa = r21
.def adr = r0
.def prg1 = r24
.def prg2 = r25


.cseg
.org 0
	rjmp RESET
	nop  ;rjmp EXT_INT0 - прерывание по входному сигналу
	nop  ;rjmp EXT_PIN - прерывание не используется
	nop  ;rjmp TIME_CMPA - прерывание от таймера
	nop  ;rjmp TIME_CMPB - прерывание от таймера
	nop  ;rjmp TIME_OVF1 - прерывание от таймера
	nop  ;rjmp TIME_OVF0 - прерывание от таймера
	nop  ;rjmp USI_STRT - прерывание от USI
	nop  ;rjmp USI_OVR - прерывание от USI
	nop  ;rjmp EE_RDY - прерывание от таймера
	nop  ;rjmp ANA_COMP - прерывание от компаратора
	nop  ;rjmp ADC - прерывание от АЦП

.org 20
; настройка портов

RESET:   nop
	clr  tmp
	out DDRA, tmp
	out PORTA, tmp ; обнулить порт А
	clr tmp
	ldi tmp, $FC       ; РА0, РА1, - входы
	out DDRA, tmp
	clr tmp
	out DDRB, tmp
	out PORTB, tmp ; обнулить порт В
	clr tmp
	ldi tmp, $BF ; РВ6-вход
	out DDRB, tmp
;Начало программы
nStart:	nop
;сброс всех значений
	clr	pir
	clr	pur
	clr	prg1
	clr	prg2
	clr	adr
;вход в подпрограмму опроса АЦП1
	nop
	ldi	tmp3, $80	;источник питания, ADC2, ADMUX
	ldi	tmp2, $C6	; одиночное, запуск, 1/64, ADCSR
; опрос уровня заряда конденсатора
	rcall	adcn
	mov	r30, tmp2		;загрузка младшего разряда
	mov	r31, tmp3		;загрузка старшего разряда
	nop
	ldi	tmp2, $B5	;значение младшего разряда порога
	ldi	tmp3, $01	;значение старшего разряда порога
;вычитание значения АЦП и порога
	sub	r30, tmp2
;проверка на ноль старшего байта
	clr	tmp
	rol	tmp
	sub	r31, tmp3		;вычитание старшего байта с заемом
	sub	r31, tmp		;вычитание заема
loki:	nop
	brmi	nStart		;переход, если результат < 0
	nop
;опрос DIP1
DIP:	nop
	in	tmp, PORTA
	nop
	sbis PINA, 1		;пропустить если не нажат DIP1.1
	rjmp qq0
s1:	nop
	sbis	PINB, 6		;пропустить если не нажат DIP1.2
	rjmp	qq1
	nop
	rjmp qq2
; DIP1.1
qq0:	nop
	sbis	PINB,6		;пропустить если не нажат DIP1.2		
	rjmp qq3
	nop
	rjmp nStart
qq3:	nop
	clr pir
cvb:	nop
	inc	pir
	rcall	zader
	nop
	rcall	opros
	nop
	cls
	cpi	pir, $0B
	brlt	cvb
	nop
	rjmp	nStart
; DIP1.2
qq1:	nop
	sbis	PINB, 1		;пропустить если не нажат DIP1.1
	rjmp	qq4
	nop
	rjmp	nStart
qq4:	nop
	clr	pir
cvbn:	nop
	inc	pir
	rcall	zader
	nop
	rcall	opron
	nop
	cls
	cpi	pir, $0B
	brlt	cvbn
	nop
	rjmp	nStart
; DIP1
qq2:	nop
	nop
cvbm:	nop
	inc	pir
	rcall	zader
	nop
	rcall	oprom
	nop
	cls
	cpi	pir, $14
	brlt	cvbn
	nop
	rjmp	nStart

;Настройка АЦП
adcn:	nop
	nop
	nop
	nop
	nop
	nop
	nop
	clr	tmp
awe:	nop
	cpi	tmp, $04
	brsh	ass
	clr	tmp3
	ldi	tmp3, $83		;внутренний источник, вход ADC3
	out	ADMUX, tmp3		;коммутация входов АЦП
	clr	tmp2
	clr	tmp3
	ldi	tmp2, $C4		;одиночное, запуск, 1/16
	out	ADCSR, tmp2		;запуск АЦП на преобразование
;Сохранение данных АЦП
	in	tmp2, ADCL
	in	tmp3, ADCH
	mov	r2, tmp2
	mov	r3, tmp3
	mov	r4, r2
	mov	r5, r3
	mov	r6, r4
	mov	r7, r5
	inc	tmp
	rjmp	awe
;среднее арифметическое действие
ass:	nop
	clr	r8
	clc
	add	tmp2, r2
	adc	r9, r8
	add	tmp2, r6
	adc	r9, r8
	add	tmp2, r6
	adc	r9, r8
	clc
	lsr	r9
	ror	tmp2
	lsr	r9
	ror	tmp2
	clr	r9
	clc
	add	tmp3, r3
	adc	r9, r8
	add	tmp3, r5
	adc	r9, r8
	add	tmp3, r7
	adc	r9, r8
	clc
	lsr	r9
	ror	tmp3
	lsr	r9
	ror	tmp3
	lsr	r9
	ror	tmp3
	nop
	ret

; Подпрограмма задержки включения светодиодов
zader:	nop
	wdr
	clr	r26
	clr	r29
	ldi	r29, $AF
	cpi	tmp3, $00
	brne	goo
	ldi	r26, $01
	add	r26, tmp3
	nop
goo:	nop
	mov	r26, tmp3
dm:	nop
	cpi	tmp2, $00
	brne	goq
	ldi	Xa, $01
	add	Xa, tmp2
	nop
goq:	nop
	mov	Xa, tmp2
dv:	nop
	wdr
	nop
dx:	dec	r29
	brpl	dx
	cln
	dec	Xa
	brpl	dv
	cln
	dec	r26
	brne	dm
	ret

;Подпрограмма опроса светодиодов программа1
opros:	nop
	ldi	ZH, high(2*prog1A)
	ldi	ZL, Low(2*prog1A)
	Add	ZL, pir
	LPM
	mov	prg1, adr
	out	PORTB, prg1
	nop
	ldi	ZH, high(2*prog1B)
	ldi	ZL, Low(2*prog1B)
	Add	ZL, pir
	LPM
	mov	prg2, adr
	out	PORTB, prg2
	ret
;Подпрограмма опроса светодиодов программа2
opron:	nop
	ldi	ZH, high(2*prog2A)
	ldi	ZL, Low(2*prog2A)
	Add	ZL, pir
	LPM
	mov	prg1, adr
	out	PORTB, prg1
	nop
	ldi	ZH, high(2*prog2B)
	ldi	ZL, Low(2*prog2B)
	Add	ZL, pir
	LPM
	mov	prg2, adr
	out	PORTB, prg2
	ret
;Подпрограмма опроса светодиодов программа3
oprom:	nop
	ldi	ZH, high(2*prog3A)
	ldi	ZL, Low(2*prog3A)
	Add	ZL, pir
	LPM
	mov	prg1, adr
	out	PORTB, prg1
	nop
	ldi	ZH, high(2*prog3B)
	ldi	ZL, Low(2*prog3B)
	Add	ZL, pir
	LPM
	mov	prg2, adr
	out	PORTB, prg2
	ret

.org $200

prog1A:
.DB $00, $00, $00, $00, $80, $40, $20, $10
.DB $08, $04
prog1B:
.DB $08, $04, $02, $01, $00, $00, $00, $00
.DB $00, $00

prog2A:
.DB $00, $00, $00, $00, $80, $C0, $E0, $F0
.DB $F8, $FC

prog2B:
.DB $08, $0C, $0E, $0F, $0F, $0F, $0F, $0F
.DB $0F, $0F

prog3A:
.DB $0C, $18, $30, $60, $C0, $80, $00, $00
.DB $0C, $08

prog3B:
.DB $00, $00, $00, $00, $00, $01, $03, $06
.DB $0C, $08

.EXIT
Реклама
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Сообщение Alkul »

Родион@22 писал(а):Что нужно дописать в коде, чтобы инициализировать стек?
Сразу после метки RESET вместо команды nop напишите:

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

ldi tmp,RAMEND
out SP,tmp
Коль скоро у Вас подключен файл "tn26def.inc", то константа RAMEND должна корректно распознаться ассемблером, поскольку она определена в этом файле.
Вам понятно, что это за константа, чему она равна и откуда вообще взялась?
Если нет, то скажите, и я объясню.

И настоятельно рекомендую оформлять программу вот так:

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

.cseg
.org 0x00
rjmp RESET ; Reset handler
rjmp EXT_INT0 ; IRQ0 handler
rjmp PIN_CHANGE ; Pin change handler
rjmp TIM1_CMP1A ; Timer1 compare match 1A
rjmp TIM1_CMP1B ; Timer1 compare match 1B
rjmp TIM1_OVF ; Timer1 overflow handler
rjmp TIM0_OVF ; Timer0 overflow handler
rjmp USI_STRT ; USI Start handler
rjmp USI_OVF ; USI Overflow handler
rjmp EE_RDY ; EEPROM Ready handler
rjmp ANA_COMP ; Analog Comparator handler
rjmp ADC ; ADC Conversion Handler

;"Заглушки" обработчиков неиспользуемых прерываний
EXT_INT0: ; IRQ0 handler
PIN_CHANGE: ; Pin change handler
TIM1_CMP1A: ; Timer1 compare match 1A
TIM1_CMP1B: ; Timer1 compare match 1B
TIM1_OVF: ; Timer1 overflow handler
TIM0_OVF: ; Timer0 overflow handler
USI_STRT: ; USI Start handler
USI_OVF: ; USI Overflow handler
EE_RDY: ; EEPROM Ready handler
ANA_COMP: ; Analog Comparator handler
ADC: ; ADC Conversion Handler
reti

RESET:   
ldi tmp,RAMEND
out SP,tmp

clr  tmp

;ну и дальше Ваша программа
Не надо вместо векторов переходов ставить nop'ы, Вы этим ничего не сэкономите и не выиграете.
При создании нового проекта открываете даташит на контроллер и там в разделе Interrupt полностью приведена таблица векторов прерываний, копируете её оттуда, удаляете адреса перед каждый rjmp'ом - вуаля - готова таблица векторов. А потом также делаете блок "заглушек" обработчиков.
Если какое-то прерывание используете, то соответствующий вектор в таблице "закомментировать" точкой с запятой, скопировать метку и в теле программы писать обработчик.
Последний раз редактировалось Alkul Вт апр 22, 2014 21:20:08, всего редактировалось 2 раза.
Реклама
Открыл глаза
Сообщения: 49
Зарегистрирован: Ср апр 16, 2014 18:46:46

Сообщение Родион@22 »

Огромное спасибо Вам! :)
Думаю будет интересно узнать)
У меня возник еще вопрос: "Будет ли большим отличие программ для Tiny26 от Tiny261?"
P.S. Узнал только, что регистр ADCSR - в 261 его нет, он называется ADCSRA и ADCSRB
Открыл глаза
Сообщения: 49
Зарегистрирован: Ср апр 16, 2014 18:46:46

Сообщение Родион@22 »

А не знаете почему АВР студио ругается на строчку:

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

ADC: ; ADC Conversion Handler
[img][img]http://img.radiokot.ru/files/96849/thumbnail/bm0yr5235.jpg[/img][/img]
Реклама
Эиком - электронные компоненты и радиодетали
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Сообщение Alkul »

Родион@22 писал(а):Думаю будет интересно узнать)
Адресное пространство ОЗУ разбито на 3 блока:
1. Блок регистрового файла (регистры R0... R31), занимающий адреса от 0x0000 до 0x001F
2. Блок регистров ввода-вывода (порты и все служебные регистры), занимающий адреса от 0x0020 до 0x005F
3. Собственно ОЗУ, начинающееся с адреса 0x0060. Так как объем ОЗУ равен 128 байтам (0x7F), то последний байт ОЗУ будет иметь адрес 0x60 + 0x7F = 0xDF.
Для контроллера ATtiny26 константа RAMEND равна 0xDF. RAMEND - это адрес последнего байта ОЗУ. Так как стек у авр'ок "растет" сверху вниз (при помещении числа на стек указатель стека декрементируется), то логично присваивать вершине стека адрес самого последнего байта в ОЗУ.

А вообще-то, все это описано в даташите на контроллер :) Иногда невредно почитать, прежде чем начинать разработку :))

Родион@22 писал(а):У меня возник еще вопрос: "Будет ли большим отличие программ для Tiny26 от Tiny261?"
Радикально отличаться не будет, но нужно обязательно открыть даташиты на оба контроллера и тщательно сравнить все служебные регистры. Насчет регистров управления АЦП Вы совершенно правы. Соответственно, программа должна быть скорректирована, исходя из логики работы с АЦП.
Родион@22 писал(а):А не знаете почему АВР студио ругается на строчку:

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

ADC: ; ADC Conversion Handler
Знаю. В ассемблере AVR есть команда adc (сложение с учетом переноса), а имена меток не могут совпадать с командами.
Это общая "болезнь" всех даташитов на авр'ки - указывать в качестве названия обработчика прерывания АЦП метку ADC, которая не принимается компилятором :)
Лечится очень просто. Замените метку ADC на метку ADC_ (как в векторе перехода, так и в обработчике, естественно).
И сразу настанут мир и гармония :))
Последний раз редактировалось Alkul Вт апр 22, 2014 21:48:00, всего редактировалось 3 раза.
Реклама
Открыл глаза
Сообщения: 49
Зарегистрирован: Ср апр 16, 2014 18:46:46

Сообщение Родион@22 »

А вообще-то, все это описано в даташите на контроллер :) Иногда невредно почитать, прежде чем начинать разработку :))
А существует ли даташит на русском)))
Реклама
Открыл глаза
Сообщения: 49
Зарегистрирован: Ср апр 16, 2014 18:46:46

Сообщение Родион@22 »

И сразу настанут мир и гармония :))
Оказывается все гениальное - просто)
Спасибо Вам еще раз большое :)))
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Сообщение Alkul »

Родион@22 писал(а):А существует ли даташит на русском)))
Конечно, поищите в инете.
Вот тут можете попробовать книги скачать.
Родион@22 писал(а):Спасибо Вам еще раз большое :)))
Пожалуйста :) Обращайтесь :))
Открыл глаза
Сообщения: 49
Зарегистрирован: Ср апр 16, 2014 18:46:46

Сообщение Родион@22 »

Позвольте спросить Вас, я хочу протестировать схему в Протеусе, а в Протеусе тини261 мне нужно менять программу под тини261?
P.S. данная программа под тини26 не симулируется(можно судить об отсутствии индикации светодиодов :) )
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Сообщение Alkul »

Родион@22 писал(а):Позвольте спросить Вас, я хочу протестировать схему в Протеусе, а в Протеусе тини261
Скорее всего, да. Если есть отличие в регистрах, то эмуляция может идти некорректно. Это теоретически. А практически я Протеусом не пользуюсь и почти ничего о нем не знаю.
Ответить

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