Страница 1 из 1

помогите разобраться с прошивкой

Добавлено: Ср янв 15, 2014 08:54:22
nickfreem
всем привет!написал прошивку для управления шаговым двигателем...не работает,не могу найти ошибку.особо опыта в програмировании нету.может кто подскажет что не так?
контроллер атмега16а с ножек PB0-PB3 сигнал идет на драйвер L293e.PB6 PB7 подключены светодиоды для индикации режима работы (шаг\полушаг) PD5 переключатель режимов.сейчас у меня оба светодиода горят в раз независимо от положения переключателя

.include"m16def.inc"
rjmp start
.def tmp=R16
.def counter=R17
.def nulreg=R19
.org OC1Aaddr
rjmp Obrabot
.org $30

start:
ldi tmp,High(Ramend)
out SPH,tmp
ldi tmp,Low(Ramend)
out SPL,tmp
ldi tmp,0b11001111
out DDRB,tmp
ldi tmp,~(1<<PD5)
out DDRD,tmp
ldi tmp,(1<<5)
out PORTD,tmp
ldi tmp,(1<<WGM12)|(1<<CS11)|(1<<CS10)
out TCCR1B,tmp
ldi tmp,High(625)
out OCR1AH,tmp
ldi tmp,Low(625)
out OCR1AL,tmp
ldi tmp,(1<<OCIE1A)
out TIMSK,tmp
sei
ldi counter,0
end:
rjmp end

Obrabot:
cpi counter,8
brne Rezhim
ldi counter,0

Rezhim:
sbic PIND,5
Rcall Half_step
sbis PIND,5
Rcall Full_step
reti

Half_step:
ldi ZH,High(Table2)
ldi ZL,Low(Table2)
add ZL,counter
adc ZH,nulreg
lsl ZL
rol ZH
lpm tmp,Z
out PORTB,tmp
inc counter
reti

Full_step:
ldi ZH,High(Table1)
ldi ZL,Low(Table1)
add ZL,counter
adc ZH,nulreg
lsl ZL
rol ZH
lpm tmp,Z
out PORTB,tmp
inc counter
reti

.org $300
Table1:
.dw 0b10001000
.dw 0b10000100
.dw 0b10000010
.dw 0b10000001
.dw 0b10001000
.dw 0b10000100
.dw 0b10000010
.dw 0b10000001

Table2:
.dw 0b01001000
.dw 0b01001100
.dw 0b01000100
.dw 0b01000110
.dw 0b01000010
.dw 0b01000011
.dw 0b01000001
.dw 0b01001001

Re: помогите разобраться с прошивкой

Добавлено: Ср янв 15, 2014 17:28:36
ANALOG
Используйте тег

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

, если выкладываете исходники. :wink: 

По поводу самого кода - первое что бросается в глаза - нечетное число байт в строках массива. Попробуйте добавить нолики в каждую строку.
UPD: А нет, дело не в этом, я не заметил что стоит .dw

В метке Rezhim
переход по адресам Full_Step и Half_Step должен осуществляться с помощью rjmp, а не rcall. Так как rcall сохраняет в стек текущий адрес, и потом у вас из прерывания получится выход по неправильному адресу когда прога дойдет до reti
В общем, попробуйте поменять rcall на rjmp

Re: помогите разобраться с прошивкой

Добавлено: Ср янв 15, 2014 19:23:36
Alkul
nickfreem писал(а):не работает,не могу найти ошибку.особо опыта в програмировании нету.может кто подскажет что не так?
Я вообще не увидел таблицы векторов. Где команда .org 0x00 ?
Посмотрите вот эту тему, там сказано, как правильно оформлять заголовок программы
Увидел самую главную ошибку: в модели памяти ATmega16 в таблице векторов нужно использовать команды jmp, а не rjmp, потому что там под каждый вектор отводится два слова, а не одно.
Ну и согласен с предыдущим оратором насчет того, что вместо rcall нужно использовать rjmp. Причем лучше использовать jmp, а не rjmp. В связи с тем, что у команды rjmp ограничена "дальность" перехода. Не нужно надеяться, что компилятор выдаст ошибку.


Еще момент. Вот этот участок кода:

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

Obrabot:
cpi counter,8
brne Rezhim
ldi counter,0

Rezhim:
sbic PIND,5
Вам не кажется, что переход на метку Rezhim будет сделан в любом случае? К чему тогда команда brne? :) Наверное, после команды

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

ldi counter,0
должна быть какая-то еще? Возможно, reti ? Трудно гадать, не зная, какую логику работы вы держали в голове, когда писали программу.


Еще один момент.
Вы инициализируете Counter значением 8 и сравниваете его с нулем. А в теле программы после меток

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

Half_step:

Full_step:
Вы делаете инкремент Counter'а. Это правильно? Его нужно увеличивать на 1? Или, быть может, все же уменьшать? Тогда нужна команда dec counter, а не inc counter.

Re: помогите разобраться с прошивкой

Добавлено: Ср янв 15, 2014 20:44:58
ANALOG
Alkul писал(а):Где команда .org 0x00 ?
Да это можно не писать, и так ведь с нуля команды идут
Alkul писал(а):Еще момент. Вот этот участок кода:

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

Obrabot:
cpi counter,8
brne Rezhim
ldi counter,0

Rezhim:
sbic PIND,5
...
Вы инициализируете Counter значением 8 и сравниваете его с нулем.
Не, тут тоже все правильно. Obrabot - это обработчик прерывания от таймера.
При входе в него первым делом значение counter сравнивается с 8

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

cpi counter,8
и если не равно - то сразу переходим к Rezhim, а если равно - то скидываем в 0 и идем дальше в Rezhim (где потом и делается инкремент этого регистра).
Таким образом, counter все время крутится от 0 до 7.

Re: помогите разобраться с прошивкой

Добавлено: Ср янв 15, 2014 20:51:36
Alkul
ANALOG писал(а):
Alkul писал(а):Где команда .org 0x00 ?
Да это можно не писать, и так ведь с нуля команды идут
А компилятор об этом знает? :)

Re: помогите разобраться с прошивкой

Добавлено: Ср янв 15, 2014 20:59:04
ANALOG
Ну да, если после .cseg сразу код писать, он с нуля и пойдет в прошивку.
А вот, куда сам .cseg делся - вот это действительно интересно


И все-таки мне кажется, что ошибка в массивах с пустыми байтами.
ТС, попробуйте вот такой код:
Спойлер

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

.include"m16def.inc"
.cseg
rjmp start
.def tmp=R16
.def counter=R17
.def nulreg=R19
.org OC1Aaddr
rjmp Obrabot
.org $30

start:
ldi tmp,High(Ramend)
out SPH,tmp
ldi tmp,Low(Ramend)
out SPL,tmp
ldi tmp,0b11001111
out DDRB,tmp
ldi tmp, 0b00000000 ;здесь лучше записать просто 0, а не ~(1<<PD5), т.к. ~(1<<PD5) = 11011111, а лишние порты на вывод - это нехорошо
out DDRD,tmp
ldi tmp,(1<<5)
out PORTD,tmp
ldi tmp,(1<<WGM12)|(1<<CS11)|(1<<CS10)
out TCCR1B,tmp
ldi tmp,High(625)
out OCR1AH,tmp
ldi tmp,Low(625)
out OCR1AL,tmp
ldi tmp,(1<<OCIE1A)
out TIMSK,tmp
sei
ldi counter,0
end:
rjmp end

Obrabot:
cpi counter,8
brne Rezhim
ldi counter,0

Rezhim:
sbic PIND,5
rjmp Half_step
sbis PIND,5
rjmp Full_step
reti

Half_step:
ldi ZH,High(Table2*2) ;вместо lsl ZL rol ZH можно сразу вбить удвоенные адреса
ldi ZL,Low(Table2*2)
add ZL, counter ;добавляем counter 2 раза чтобы пропустить нули из массива
adc ZL, counter
adc ZH, nulreg
lpm tmp,Z
out PORTB,tmp
inc counter
reti

Full_step:
ldi ZH,High(Table1*2)
ldi ZL,Low(Table1*2)
add ZL, counter
adс ZL, counter ;здесь то же самое
adc ZH, nulreg
lpm tmp,Z
out PORTB,tmp
inc counter
reti

;.org $300
;зачем тут .org $300 - непонятно. Компилятор и так массив разместит после того кода, что написан выше
;а вот если вы, вдруг, допишете еще кода и он уже не будет влезать в $300 - то это только лишних проблем добавит
Table1:
.db 0b10001000, 0
.db 0b10000100, 0
.db 0b10000010, 0
.db 0b10000001, 0
.db 0b10001000, 0
.db 0b10000100, 0
.db 0b10000010, 0
.db 0b10000001, 0

Table2:
.db 0b01001000, 0
.db 0b01001100, 0
.db 0b01000100, 0
.db 0b01000110, 0
.db 0b01000010, 0
.db 0b01000011, 0
.db 0b01000001, 0
.db 0b01001001, 0

Re: помогите разобраться с прошивкой

Добавлено: Чт янв 16, 2014 07:28:27
Alkul
ANALOG писал(а): ТС, попробуйте вот такой код:

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

.cseg
rjmp start
.def tmp=R16
.def counter=R17
.def nulreg=R19
.org OC1Aaddr
rjmp Obrabot
Для AVR с памятью 16кБ нужно писать не rjmp, а jmp. В таблице векторов прерываний под каждый вектор отводится 2 слова памяти, а не одно. Пусть тредстартер сразу привыкает писать правильно.
И тему, на которую я дал ссылку ранее, тоже стоит изучить. Так, как оформил таблицу векторов прерываний тредстартер, а равно и так, как написали Вы, нельзя. И в той теме я писал, почему, и чем чревато иное оформление таблицы. Приводил пример того, как это нужно делать правильно.


И еще

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

ldi tmp, 0b00000000 ;здесь лучше записать просто 0, а не ~(1<<PD5), т.к. ~(1<<PD5) = 11011111, а лишние порты на вывод - это нехорошо
С точностью до наоборот.
конструкция вида

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

(1<<PD5)
установит бит 5. а не сбросит. То есть, код

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

ldi tmp, (1<<PD5)
даст в регистре tmp результат 0b00100000, а не 0b11011111. Попробуйте в симуляторе.


А тредстартеру я, пожалуй, тоже посоветую пользоваться симулятором (например, AVR Studio) для отладки "логики" программы. Там сразу будет видно, как массивы заполняются, как прерывание вызывается и так далее. На все вопросы тредстартер получит ответ самостоятельно. Это и для наработки опыта полезно.
И еще рекомендация тредстартеру - пишите комментарии. Сам в начале сталкивался с этим. Напишешь программу, вроде все в ней понятно. А потом вернешься к ней через полгодика - уже ничего не помнишь. Приходится заново вникать.
Позволю себе привести пример того, как пишу программы я. Привожу кусок обработчика прерывания по приему байта по UART, взятый из одной разработки:
Спойлер

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

;Подпрограмма обработки прерывания по получению байта по USART --------------------------------------------------------------------------
adrURXC:				;USART RX Complete Handler
	push R16			;Сохранить на стеке рег.R16
	in R16,SREG		;Сохранить на стеке
	push R16			;регистр состояния SREG
	push YL			;Сохранить на стеке
	push YH			;рег.пару Y
	push R17			;Сохранить на стеке рег.R17
	push R18			;Сохранить на стеке рег.R18

	lds R16,UDR0		;Занести принятый по USART байт в рег.R16
	lds R17,RECVBYT	;Занести в рег.R17 кол-во принятых байт пакета
	tst R17			;Кол-во принятых байт равно нулю? (это первый байт пакета?)
	brne USRXC2		;Если нет, то переход на метку USRXC2
;Принят первый байт пакета (байт адреса)
;Инициализировать таймер 2 на отсчет 5мс, за которые весь пакет должен быть принят
USRXC1:				;
;Инициализировать таймер-счетчик 2 на отсчет интервала 5 мс. По окончанию интервала - сбрасывать USART и обнулять счетчик принятых байт
	lds YL,FLAGS		;Занести в рег.YL содержимое ячейки FLAGS
	andi YL,NONSELDELAY		;Обнулить бит SELDELAY для того, чтобы переполнение таймера-счетчика 2 обрабатывалось как отсчет
				        ;времени приема пакета запроса
	sts FLAGS,YL		;Сохранить в памяти новое значение ячейки FLAGS

	ldi YL,0x9F		        ;Инициализировать таймер-счетчик
	sts TCNT2,YL		;на отсчет 5мс при тактовой частоте 20МГц и коэффициенте деления 1024
	ldi YL,0x07		        ;Запустить таймер-счетчик 2
	sts TCCR2B,YL		;с коэффициентом деления тактовой частоты 1024
	ldi YL,(1<<TOIE2)	;Разрешение прерываний
	sts TIMSK2,YL		;по переполнению таймер-счетчика 2	
	rjmp USRXC3		;Перейти на метку USRXC3 для записи принятого байта в буфер принимаемого пакета

;Принят не первый байт пакета
USRXC2:	
        cpi R17,0x02		;Принят третий байт пакета?
	brne USRXC3		;Если нет, то переход на метку USRXC3
;Принят третий байт пакета, откорректировать длину принимаемого пакета
	ldi YL,0x05		        ;В рег. YL занести кол-во служебных байт пакета (без учета длины поля данных)
	add YL,R16		;Теперь в рег.YL общая длина принимаемого пакета
	sts LONGRECV,YL	;Сохранить новое значение длины пакета в ячейке LONGRECV		

;Запись полученного по USART байта в буфер принимаемого пакета
USRXC3:	
        ldi YL,low(BUFRECV)	;Занести в рег.пару Y
	ldi YH,high(BUFRECV)	;адрес начала буфера принимаемого пакета
	add YL,R17		;Прибавить к адресу начала буфера смещение, 
	brcc USRXC4		;соответствующее адресу текущего
	inc YH			;принимаемого байта
USRXC4:	
        st Y,R16			;Сохранить текущий принятый байт в буфер принимаемого пакета
	lds R16,LONGRECV	;Занести в рег.R16 длину принимаемого пакета
	inc R17			;Инкремент кол-ва принятых байт
	cp R17,R16		;Принят весь пакет данных?
	brlo USRXC4_0		;Если кол-во принятых байт меньше длины пакета, то пакет принят не полностью,
				;переход на метку USRXC100
	rjmp USRXC4_1		;Иначе пакет принят полностью, перейти на метку USRXC4_1
USRXC4_0:	
        rjmp USRXC100		;Пакет принят не полностью, перейти на метку USRXC100

USRXC4_1:
;Иначе принят весь пакет, рассчитать CRC принятого пакета
	subi R17,0x02		;Вычислить длину пакета за вычетом двух байт CRC
	sts LENPAK,R17		;Занести уменьшенную на 2 длину пакета в ячейку LENPAK
	ldi YL,low(BUFRECV)	;Занести в рег.пару Y
	ldi YH,high(BUFRECV)	;адрес начала буфера принимаемого пакета
	call CRC			;Вызвать подпрограмму расчета CRC, результат в ячейках CRC_L и CRC_H
	ldi YL,low(BUFRECV)	;Занести в рег.пару Y
	ldi YH,high(BUFRECV)	;адрес начала буфера принимаемого пакета
	add YL,R17		;Прибавить к адресу начала буфера смещение, 
	brcc USRXC5		;соответствующее адресу текущего
	inc YH			;принимаемого байта

;Сейчас в рег.паре Y адрес младшего байта CRC принятого пакета
USRXC5:	
        ld R17,Y+			;Занести в рег.R17 ст.байт принятой CRC
	lds R16,CRC_H		;Занести в рег.R16 ст.байт рассчитанной CRC
	cp R16,R17		;Сравнить рассчитанный и принятый младшие байты CRC
	brne USRXC_BAD	;Если они не равны, перейти на метку USRXC_BAD для отмены принятия пакета
	ld R17,Y			;Занести в рег.R17 мл.байт принятой CRC
	lds R16,CRC_L		;Занести в рег.R16 мл.байт рассчитанной CRC
	cp R16,R17		;Сравнить рассчитанный и принятый старшие байты CRC
	brne USRXC_BAD	;Если они не равны, перейти на метку USRXC_BAD для отмены принятия пакета

;CRC принятого пакета верна				
	ldi YL,low(BUFRECV)	;Занести в рег.пару Y
	ldi YH,high(BUFRECV)	;адрес первого байта, хранящего адрес целевого детектора
	ld R16,Y+			;Занести в рег.R16 байт KOPLEN

;Проверка предназначения пакета
	lds R17,ADDRESS	;Занести в рег.R17 собственный адрес детектора
	cp R16,R17		;Сравнить собственный адрес с адресом целевого детектора	
	breq USRXC6		;Если адреса равны, переход на проверку кода команды
	rjmp USRXC_BAD	;Иначе пакет предназначен для другого детектора
С первого взгляда кажется, что такой стиль требует гораздо бОльшего времени для написания кода, но это не так. А уж при отладке и сопровождении программы экономит кучу времени.

Re: помогите разобраться с прошивкой

Добавлено: Чт янв 16, 2014 14:28:45
ANALOG
Alkul писал(а):
ANALOG писал(а):

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

ldi tmp, 0b00000000 ;здесь лучше записать просто 0, а не ~(1<<PD5), т.к. ~(1<<PD5) = 11011111, а лишние порты на вывод - это нехорошо
конструкция вида

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

(1<<PD5)
установит бит 5. а не сбросит.
То есть, код

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

ldi tmp, (1<<PD5)
даст в регистре tmp результат 0b00100000
Совершенно верно, но обратите внимание на символ ~ в оригинальной версии от ТС
После инверсии то, что вы написали превратится в 0b11011111 - и в итоге, PD5 настроен на вход, а все остальные порты - на выход. А зачем настраивать лишние порты на выход, если они не используются? Чтобы спалить их, случайно дотронувшись отверткой?

Насчет прерываний - это да, лучше конечно использовать jmp вместо rjmp, но при использовании одного единственного прерывания это погоды не сделает, ну а ели по-хорошему делать, то таблица прерываний для ATmega16 будет представлять собой что-то вроде этого:
Спойлер

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

.cseg
jmp RESET ; Reset Handler
jmp EXT_INT0 ; IRQ0 Handler
jmp EXT_INT1 ; IRQ1 Handler
jmp TIM2_COMP ; Timer2 Compare Handler
jmp TIM2_OVF ; Timer2 Overflow Handler
jmp TIM1_CAPT ; Timer1 Capture Handler
jmp TIM1_COMPA ; Timer1 CompareA Handler
jmp TIM1_COMPB ; Timer1 CompareB Handler
jmp TIM1_OVF ; Timer1 Overflow Handler
jmp TIM0_OVF ; Timer0 Overflow Handler
jmp SPI_STC ; SPI Transfer Complete Handler
jmp USART_RXC ; USART RX Complete Handler
jmp USART_UDRE ; UDR Empty Handler
jmp USART_TXC ; USART TX Complete Handler
jmp ADC ; ADC Conversion Complete Handler
jmp EE_RDY ; EEPROM Ready Handler
jmp ANA_COMP ; Analog Comparator Handler
jmp TWSI ; Two-wire Serial Interface Handler
jmp EXT_INT2 ; IRQ2 Handler
jmp TIM0_COMP ; Timer0 Compare Handler
jmp SPM_RDY

EXT_INT0:
EXT_INT1:
TIM2_COMP:
TIM2_OVF:
TIM1_CAPT:
;TIM1_COMPA:
TIM1_COMPB:
TIM1_OVF:
TIM0_OVF:
SPI_STC:
USART_RXC:
USART_UDRE:
USART_TXC:
ADC:
EE_RDY:
ANA_COMP:
TWSI:
EXT_INT2:
IM0_COMP:
SPM_RDY:
reti

TIM1_COMPA:
Obrabot:
...
...

RESET:
...
...
При использовании какого-либо прерывания - закомментить его в блоке "заглушек" и вынести отдельно. Кстати, ТС на заметку - обработчикам прерываний лучше не давать имена типа "Obrabot", а оставлять названия как в даташите, чтобы было понятно где какое прерывание обрабатывается. Ну это так, из области придирок к оформлению :)

Примечание: код приведен в качестве примера как делать, и возможно, нужно будет поменять имена некоторым прерываниям, если окажется, что такие имена уже заняты (например, ADC так точно уже занято - это команда сложения с флагом переноса)

Re: помогите разобраться с прошивкой

Добавлено: Чт янв 16, 2014 17:28:43
Alkul
ANALOG писал(а):ну а ели по-хорошему делать, то таблица прерываний для ATmega16 будет представлять собой что-то вроде этого
Выше я давал ссылку на тему, где сам все это подробно и расписывал :)
ANALOG писал(а):После инверсии то, что вы написали превратится в 0b11011111 - и в итоге, PD5 настроен на вход, а все остальные порты - на выход.
А инверсию-то зачем делать? Я согласен, что на выход нужно настраивать только те порты, которые задействуются как выходы.
Вы приводите исходник со строками:

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

ldi tmp, 0b00000000 ;здесь лучше записать просто 0, а не ~(1<<PD5), т.к. ~(1<<PD5) = 11011111, а лишние порты на вывод - это нехорошо
out DDRD,tmp
Я так понял, что бит PD5 у автора задействуется, как переключатель режимов. То есть, должен быть выходом. А Вы в DDRD нуль записываете.
Нужен выход на PD5 - значит, писать

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

ldi tmp,(1<<PD5)
out DDRD,tmp 
И никаких проблем. Остальные выводы порта D останутся входами.

Но что-то странное - Вы не находите? Мы тут с Вами дискутируем, а тредстартер куда-то пропал. Оно ему вообще надо? Может, мы тут зря время тратим? :)

Re: помогите разобраться с прошивкой

Добавлено: Чт янв 16, 2014 20:12:49
ANALOG
Alkul писал(а):Я так понял, что бит PD5 у автора задействуется, как переключатель режимов. То есть, должен быть выходом. А Вы в DDRD нуль записываете.
Тут мы с вами видимо, по-разному понимаем задумку автора, но мне кажется, что PD5 все-таки должен быть входом, т.к. далее в коде идет чтение из PinD:

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

Rezhim:
sbic PIND,5
rjmp Half_step
sbis PIND,5
rjmp Full_step
reti
То есть, к PD5 подключен переключатель, которым извне управляется работа МК в одном из 2-х режимов.

Alkul писал(а):А инверсию-то зачем делать?
Совершенно незачем, но у автора-то она делается (символ ~):

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

ldi tmp, ~(1<<PD5)
out DDRD,tmp
О чем я и говорю, автор настраивает PD5 на вход с помощью значения ~(1<<PD5), что эквивалентно записи 0b11011111. В общем-то, цель достигнута - в DDRD 5-й бит = нолик, соответственно PD5 = вход. Но при таком подходе все остальные биты становятся единичками, поэтому я и предлагаю в DDRD закинуть просто 0 = все порты на вход.
Но что-то странное - Вы не находите? Мы тут с Вами дискутируем, а тредстартер куда-то пропал. Оно ему вообще надо? Может, мы тут зря время тратим? :)
Крайне странно, сам хотел об этом написать.
nickfreem, отпишитесь, нам интересно ведь, исправленный код проверяли/не проверяли? Работает/не работает?

Re: помогите разобраться с прошивкой

Добавлено: Чт янв 16, 2014 20:30:30
nickfreem
прошу прощения что замолчал..много читал а вот результатов особо не было поэтому и не отписывался.издевался над кодом и вот до чего дошел

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

Half_step:
ldi tmp,01000000
out PORTB,tmp
inc counter
reti

Full_step:
ldi ZH,High(Table1)
ldi ZL,Low(Table1)
add ZL,counter
adc ZH,nulreg
lsl ZL
rol ZH
lpm tmp,Z
out PORTB,tmp
inc counter
reti

.org $300
Table1:
.dw 0b10001000
.dw 0b10000100
.dw 0b10000010
.dw 0b10000001
.dw 0b10001000
.dw 0b10000100
.dw 0b10000010
.dw 0b10000001
в одном положении переключателя горит только PB7(full step)в другом положении когда должен гореть только PB6,горят оба..

.cseg добавил в начало кода.reti d full\half менял на ret.
так же убрал процедуру и забил всё через jmp но результата никакого..как горели оба так и горят

Re: помогите разобраться с прошивкой

Добавлено: Чт янв 16, 2014 20:40:29
ANALOG

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

Half_step:
ldi tmp,01000000
out PORTB,tmp
Тут вы 0b пропустили, а 01000000 компилятор понимает как десятичное число, а оно очень большое и в регистр точно никак не влезет. Наверняка компилятор выдал warning по этому поводу :wink:

Попробуйте полностью тот код, который я выкладывал:
Спойлер

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

.include"m16def.inc"
.cseg
rjmp start
.def tmp=R16
.def counter=R17
.def nulreg=R19
.org OC1Aaddr
rjmp Obrabot
.org $30

start:
ldi tmp,High(Ramend)
out SPH,tmp
ldi tmp,Low(Ramend)
out SPL,tmp
ldi tmp,0b11001111
out DDRB,tmp
ldi tmp, 0b00000000 ;здесь лучше записать просто 0, а не ~(1<<PD5), т.к. ~(1<<PD5) = 11011111, а лишние порты на вывод - это нехорошо
out DDRD,tmp
ldi tmp,(1<<5)
out PORTD,tmp
ldi tmp,(1<<WGM12)|(1<<CS11)|(1<<CS10)
out TCCR1B,tmp
ldi tmp,High(625)
out OCR1AH,tmp
ldi tmp,Low(625)
out OCR1AL,tmp
ldi tmp,(1<<OCIE1A)
out TIMSK,tmp
sei
ldi counter,0
end:
rjmp end

Obrabot:
cpi counter,8
brne Rezhim
ldi counter,0

Rezhim:
sbic PIND,5
rjmp Half_step
sbis PIND,5
rjmp Full_step
reti

Half_step:
ldi ZH,High(Table2*2) ;вместо lsl ZL rol ZH можно сразу вбить удвоенные адреса
ldi ZL,Low(Table2*2)
add ZL, counter ;добавляем counter 2 раза чтобы пропустить нули из массива
adc ZL, counter
adc ZH, nulreg
lpm tmp,Z
out PORTB,tmp
inc counter
reti

Full_step:
ldi ZH,High(Table1*2)
ldi ZL,Low(Table1*2)
add ZL, counter
adс ZL, counter ;здесь то же самое
adc ZH, nulreg
lpm tmp,Z
out PORTB,tmp
inc counter
reti

;.org $300
;зачем тут .org $300 - непонятно. Компилятор и так массив разместит после того кода, что написан выше
;а вот если вы, вдруг, допишете еще кода и он уже не будет влезать в $300 - то это только лишних проблем добавит
Table1:
.db 0b10001000, 0
.db 0b10000100, 0
.db 0b10000010, 0
.db 0b10000001, 0
.db 0b10001000, 0
.db 0b10000100, 0
.db 0b10000010, 0
.db 0b10000001, 0

Table2:
.db 0b01001000, 0
.db 0b01001100, 0
.db 0b01000100, 0
.db 0b01000110, 0
.db 0b01000010, 0
.db 0b01000011, 0
.db 0b01000001, 0
.db 0b01001001, 0
У вас точно в таблицах с этими .dw что-то не так пошло

А вот еще версия с "правильной" таблицей прерываний:
Спойлер

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

.include"m16def.inc"
.cseg
jmp RESET ; Reset Handler
jmp EXT_INT0 ; IRQ0 Handler
jmp EXT_INT1 ; IRQ1 Handler
jmp TIM2_COMP ; Timer2 Compare Handler
jmp TIM2_OVF ; Timer2 Overflow Handler
jmp TIM1_CAPT ; Timer1 Capture Handler
jmp TIM1_COMPA ; Timer1 CompareA Handler
jmp TIM1_COMPB ; Timer1 CompareB Handler
jmp TIM1_OVF ; Timer1 Overflow Handler
jmp TIM0_OVF ; Timer0 Overflow Handler
jmp SPI_STC ; SPI Transfer Complete Handler
jmp USART_RXC ; USART RX Complete Handler
jmp USART_UDRE ; UDR Empty Handler
jmp USART_TXC ; USART TX Complete Handler
jmp ADC ; ADC Conversion Complete Handler
jmp EE_RDY ; EEPROM Ready Handler
jmp ANA_COMP ; Analog Comparator Handler
jmp TWSI ; Two-wire Serial Interface Handler
jmp EXT_INT2 ; IRQ2 Handler
jmp TIM0_COMP ; Timer0 Compare Handler
jmp SPM_RDY

EXT_INT0:
EXT_INT1:
TIM2_COMP:
TIM2_OVF:
TIM1_CAPT:
;TIM1_COMPA:
TIM1_COMPB:
TIM1_OVF:
TIM0_OVF:
SPI_STC:
USART_RXC:
USART_UDRE:
USART_TXC:
ADC:
EE_RDY:
ANA_COMP:
TWSI:
EXT_INT2:
IM0_COMP:
SPM_RDY:
reti

RESET:
ldi tmp,High(Ramend)
out SPH,tmp
ldi tmp,Low(Ramend)
out SPL,tmp
ldi tmp,0b11001111
out DDRB,tmp
ldi tmp, 0b00000000 ;здесь лучше записать просто 0, а не ~(1<<PD5), т.к. ~(1<<PD5) = 11011111, а лишние порты на вывод - это нехорошо
out DDRD,tmp
ldi tmp,(1<<5)
out PORTD,tmp
ldi tmp,(1<<WGM12)|(1<<CS11)|(1<<CS10)
out TCCR1B,tmp
ldi tmp,High(625)
out OCR1AH,tmp
ldi tmp,Low(625)
out OCR1AL,tmp
ldi tmp,(1<<OCIE1A)
out TIMSK,tmp
sei
ldi counter,0
end:
rjmp end

TIM1_COMPA:
cpi counter,8
brne Rezhim
ldi counter,0

Rezhim:
sbic PIND,5
rjmp Half_step
sbis PIND,5
rjmp Full_step
reti

Half_step:
ldi ZH,High(Table2*2) ;вместо lsl ZL rol ZH можно сразу вбить удвоенные адреса
ldi ZL,Low(Table2*2)
add ZL, counter ;добавляем counter 2 раза чтобы пропустить нули из массива
adc ZL, counter
adc ZH, nulreg
lpm tmp,Z
out PORTB,tmp
inc counter
reti

Full_step:
ldi ZH,High(Table1*2)
ldi ZL,Low(Table1*2)
add ZL, counter
adс ZL, counter ;здесь то же самое
adc ZH, nulreg
lpm tmp,Z
out PORTB,tmp
inc counter
reti

;.org $300
;зачем тут .org $300 - непонятно. Компилятор и так массив разместит после того кода, что написан выше
;а вот если вы, вдруг, допишете еще кода и он уже не будет влезать в $300 - то это только лишних проблем добавит
Table1:
.db 0b10001000, 0
.db 0b10000100, 0
.db 0b10000010, 0
.db 0b10000001, 0
.db 0b10001000, 0
.db 0b10000100, 0
.db 0b10000010, 0
.db 0b10000001, 0

Table2:
.db 0b01001000, 0
.db 0b01001100, 0
.db 0b01000100, 0
.db 0b01000110, 0
.db 0b01000010, 0
.db 0b01000011, 0
.db 0b01000001, 0
.db 0b01001001, 0

Re: помогите разобраться с прошивкой

Добавлено: Чт янв 16, 2014 20:50:39
Alkul
nickfreem писал(а):reti d full\half менял на ret.
А это зря. Метки Half_step и Full_step у Вас ведь в обработчике прерывания находятся. Команда reti в отличие от ret кроме обычных действий по выходу из подпрограммы еще и разрешает глобальные прерывания (бит I регистра SREG). Поставив после обработчика прерывания команду ret, Вы оставляете прерывания запрещенными при выходе из обработчика.
nickfreem писал(а):так же убрал процедуру и забил всё через jmp но результата никакого..как горели оба так и горят
Хотелось бы увидеть Ваш код целиком.
Скажите, Вы пробовали по моему совету "прогнать" его в симуляторе? Там ведь все будет видно - разрешены ли прерывания, вызывается ли обработчик, устанавливаются ли биты в регистрах портов.