AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR... |
28.01.2013, 21:31
|
|
Почётный гражданин KAZUS.RU
Регистрация: 25.05.2010
Адрес: г. Королёв
Сообщений: 8,497
Сказал спасибо: 30
Сказали Спасибо 3,072 раз(а) в 2,013 сообщении(ях)
|
Re: Помогите найти ошибку AVR asm
Сообщение от Boba_spb
|
Пора объявить конкурс на самую замысловатую работающую программу с DS18B20, и DS18S20.
|
Ой, ну несите уже приз!..
PHP код:
|
;************************************************* *********************
;Программы работы с интерфейсом 1-wire при тактировании Таймером
;************************************************* *********************
w1_Timer_Overflow:
in tempSreg,SREG ;Сохраняем SREG
subAddrGet ;Чтение адреса возврата из стека
retAddrLoad ;Загружаем адрес и делаем переход
ret ;Без включения прерывания
;****************************************
Del64:
subAddrGet ;Читаем адрес возврата
subAddrSave ;Сохранение адреса подпрграммы
Ini_TMR0_64 ;Запускаем таймер
Del64_1:
ldi indH,High(Del64_2) ;Грузим адрес возврата
ldi indL,Low(Del64_2) ;Грузим адрес возврата
rjmp w1save ;Выход из прерывания с сохранением
Del1024:
subAddrGet ;Читаем адрес возврата
subAddrSave ;Сохранение адреса подпрграммы
Ini_TMR0_1024 ;Запускаем таймер
rjmp Del64_1 ;Грузим адрес возврата
Del64_2:
rjmp w1stop ;Выход из прерывания
;****************************************
; Output : T - presence bit (поменял - теперь флаг "w1use")
;****************************************
w1Reset:
; sbr w1flag,(1‹‹w1work) ;Ставим флаг использования 1-wire
subAddrGet ;Читаем адрес возврата
subAddrSave ;Сохранение адреса подпрграммы
cbi w1Port,w1 ;Подключили порт
sbi w1Dir,w1 ; "0" в шину
ldi w1del,w1wait480us ;480 микросекунд(470)
Ini_TMR0_64 ;Запускаем таймер
ldi indH,High(w1Reset1) ;Грузим адрес возврата
ldi indL,Low(w1Reset1) ;Грузим адрес возврата
rjmp w1save ;Выход из прерывания с сохранением
w1Reset1:
cbi w1Dir,w1 ; "1" в шину (освобождаем)
ldi w1del,w1wait70us ;Загр. время - 70us
Ini_TMR0_8 ;Запускаем таймер
ldi indH,High(w1Reset2) ;Грузим адрес возврата
ldi indL,Low(w1Reset2) ;Грузим адрес возврата
rjmp w1save ;Выход из прерывания с сохранением
w1Reset2:
set ;Ставим флаг T
sbis w1Pin,w1 ;Пропускаем следующую команду, если шина "1"
clt ;Сбросили флаг T
bld w1flag,w1use ;Читаем T в регистр флагов(если "w1use" - устройства есть)
ldi w1del,w1wait240us ;240 микросекунд(240)
Ini_TMR0_64 ;Запускаем таймер
ldi indH,High(w1Reset3) ;Грузим адрес возврата
ldi indL,Low(w1Reset3) ;Грузим адрес возврата
rjmp w1save ;Выход из прерывания с сохранением
w1Reset3:
;rjmp w1stop ;Выход из прерывания
;****************************************
w1stop: Stop_TMR0 ;Останов Timer0
subAddrLoad ;Восстанавливаем адрес возврата
subAddrSet ; в стек
w1out: out SREG,tempSreg ;Восстанавливаем SREG
reti ;Выход из прерывания
;****************************************
w1save: retAddrSave ;Сохраняем адрес возврата
skipAddrLoad ;Подменяем адрес возврата
skipAddrSet ; в стек
out SREG,tempSreg ;Восстанавливаем SREG
reti ;Выход из прерывания
;****************************************
; Чтение байта из 1-wire в регистр (w1rdbuf)
;****************************************
w1readByte:
subAddrGet ;Читаем адрес возврата
subAddrSave ;Сохранение адреса подпрграммы
ldi w1cnt,8 ;Счетчик битов
w1readLoop:
; rcall w1ReadBit
;****************************************
w1ReadBit: ;Короткий (5us) импульс в шину
sbi w1Dir, w1 ;Шину выход в "0" на 5 us
ldi w1del,w1wait5us ;Загр. время - 5us
Ini_TMR0_8 ;Запускаем таймер
ldi indH,High(w1ReadBit1) ;Грузим адрес возврата
ldi indL,Low(w1ReadBit1) ;Грузим адрес возврата
rjmp w1save ;Выход из прерывания с сохранением
w1ReadBit1: ;Короткий (5us) импульс в шину
cbi w1Dir, w1 ; "1" в шину (освобождаем)
ldi w1del,w1wait5us ;Загр. время - 5us
Ini_TMR0_8 ;Запускаем таймер
ldi indH,High(w1ReadBit2) ;Грузим адрес возврата
ldi indL,Low(w1ReadBit2) ;Грузим адрес возврата
rjmp w1save ;Выход из прерывания с сохранением
w1ReadBit2:
lsr w1rdbuf ;сдвигаем влево
sbic w1Pin,w1 ;Пропустить, если шина ="0"
sbr w1rdbuf,$80 ;Прибавляем 1 (устанавливаем бит 7 в "1")
bst w1rdbuf,7 ;Сохраняем принятый бит
rcall GetCRC ;Вычисляем контрольную сумму
ldi w1del,w1wait50us ;Загр. время - 50us
Ini_TMR0_8 ;Запускаем таймер
ldi indH,High(w1ReadBit3) ;Грузим адрес возврата
ldi indL,Low(w1ReadBit3) ;Грузим адрес возврата
rjmp w1save ;Выход из прерывания с сохранением
w1ReadBit3:
;****************************************
dec w1cnt ;Следующий бит
brne w1ReadLoop ;Зациклились
rjmp w1stop ;Выход из прерывания
;****************************************
; Запись байта в 1-wire из регистра (w1rdbuf)
;****************************************
w1writeByte:
subAddrGet ;Читаем адрес возврата
subAddrSave ;Сохранение адреса подпрграммы
ldi w1cnt,8 ;Счетчик битов
w1WriteLoop:
bst w1rdbuf,0 ;Сохраняем бит к передаче
rcall GetCRC ;Вычисляем контрольную сумму
ror w1rdbuf ;Сдвигаем младший бит в флаг переноса
;****************************************
w1WriteBit:
brcs w1WriteOne ;Если флаг С установлен - переход на запись "1"
w1WriteZero: ;Длинный (60us) импульс в шину
sbi w1Dir, w1 ; "0" в шину
ldi w1del,w1wait60us ;Загр. время - 60us
Ini_TMR0_8 ;Запускаем таймер
ldi indH,High(w1WriteZero1) ;Грузим адрес возврата
ldi indL,Low(w1WriteZero1) ;Грузим адрес возврата
rjmp w1save ;Выход из прерывания с сохранением
w1WriteZero1:
cbi w1Dir, w1 ; "1" в шину (освобождаем)
rjmp w1WriteEnd
w1WriteOne: ;Короткий (5us) импульс в шину
sbi w1Dir, w1 ; "0" в шину
ldi w1del,w1wait5us ;Загр. время - 5us
Ini_TMR0_8 ;Запускаем таймер
ldi indH,High(w1WriteOne1) ;Грузим адрес возврата
ldi indL,Low(w1WriteOne1) ;Грузим адрес возврата
rjmp w1save ;Выход из прерывания с сохранением
w1WriteOne1:
cbi w1Dir, w1 ; "1" в шину (освобождаем)
w1WriteEnd:
ldi w1del,w1wait60us ;Загр. время - 60us
Ini_TMR0_8 ;Запускаем таймер
ldi indH,High(w1WriteEnd1) ;Грузим адрес возврата
ldi indL,Low(w1WriteEnd1) ;Грузим адрес возврата
rjmp w1save ;Выход из прерывания с сохранением
w1WriteEnd1:
;****************************************
dec w1cnt ;Следующий бит
brne w1WriteLoop ;Зациклились
rjmp w1stop ;Выход из прерывания
;************************************************* **************
;Подпрограмма вычисления контрольной суммы 1го бита (в флаге Т)
; в w1CRCtmp - контрольная сумма
;************************************************* **************
GetCRC:
clr w1CRCtmp1 ;Очищаем переменную для вычисления CRC
bld w1CRCtmp1,0 ;Восстанавливаем принятый бит
eor w1CRCtmp1,w1CRCtmp ;Исключающее или с принятым битом
ror w1CRCtmp1 ;Смотрим - "0" или "1"
mov w1CRCtmp1,w1CRCtmp ;Перезагружаем контрольную сумму
brcc Z0 ;Если приняли "0" - переход
ldi w1del,$18 ;Если приняли "1" - загружаем константу
eor w1CRCtmp1,w1del ;Исключающее или с константой
Z0: ror w1CRCtmp1 ;Сдвигаем контрольную сумму на бит вправо
mov w1CRCtmp,w1CRCtmp1 ;Сохраняем текущую контрольную сумму
ret
;****************************************
|
Пожалуй этого достаточно.
|
|
|
|
29.01.2013, 00:32
|
|
Почётный гражданин KAZUS.RU
Регистрация: 08.06.2008
Сообщений: 1,394
Сказал спасибо: 4
Сказали Спасибо 183 раз(а) в 167 сообщении(ях)
|
Re: Помогите найти ошибку AVR asm
Ну да, поразвлекались. Я чуть по другому переключаю прерывания.
Что то типа такого
ADDR_INTERRUPT: .BYTE 2
INTERRUPT:
push ZL
in ZL,SREG
push ZL
push ZH
lds ZL,ADDR_INTERRUPT
lds ZH,ADDR_INTERRUPT + 1
ijmp
InterruptExit:
sts ADDR_INTERRUPT,ZL
sts ADDR_INTERRUPT+1,ZH
pop ZH
pop ZL
out SREG,ZL
pop ZL
reti
//==============
INTERRUPT1:
....
....
ldi ZL,low(INTERRUPT2)
ldi ZH,HIGH(INTERRUPT2)
jmp InterruptExit
//============
INTERRUPT2:
....
....
ldi ZL,low(INTERRUPT3)
ldi ZH,HIGH(INTERRUPT3)
jmp InterruptExit
//============
INTERRUPT3:
....
....
ldi ZL,low(INTERRUPT2)
ldi ZH,HIGH(INTERRUPT2)
jmp InterruptExit
А когда не нужны прерывания, то просто
INTERRUPT10:
....
.....
ldi ZL, LOW(InterruptExit)
ldi ZH,HIGH(InterruptExit)
jmp InterruptExit
|
|
|
|
29.01.2013, 00:57
|
|
Почётный гражданин KAZUS.RU
Регистрация: 25.05.2010
Адрес: г. Королёв
Сообщений: 8,497
Сказал спасибо: 30
Сказали Спасибо 3,072 раз(а) в 2,013 сообщении(ях)
|
Re: Помогите найти ошибку AVR asm
В принципе те же помидоры, токлько у мну выделена ещё одна приоритетная задача...
Пробовал на указателях, но получилось ещё медленней.
|
|
|
|
29.01.2013, 09:23
|
|
Почётный гражданин KAZUS.RU
Регистрация: 08.06.2008
Сообщений: 1,394
Сказал спасибо: 4
Сказали Спасибо 183 раз(а) в 167 сообщении(ях)
|
Re: Помогите найти ошибку AVR asm
Так с - где борьба за приз ?
|
|
|
|
29.01.2013, 10:40
|
|
Почётный гражданин KAZUS.RU
Регистрация: 25.05.2010
Адрес: г. Королёв
Сообщений: 8,497
Сказал спасибо: 30
Сказали Спасибо 3,072 раз(а) в 2,013 сообщении(ях)
|
Re: Помогите найти ошибку AVR asm
Сообщение от Boba_spb
|
Так с - где борьба за приз ?
|
Действительно... а я ещё макросы не показал...
Кстати, а что за приз?
|
|
|
|
29.01.2013, 11:11
|
|
Почётный гражданин KAZUS.RU
Регистрация: 08.06.2008
Сообщений: 1,394
Сказал спасибо: 4
Сказали Спасибо 183 раз(а) в 167 сообщении(ях)
|
Re: Помогите найти ошибку AVR asm
Сообщение от omercury
|
Кстати, а что за приз?
|
Еще не думал. Давайте обсудим
|
|
|
|
04.02.2013, 16:58
|
|
Почётный гражданин KAZUS.RU
Регистрация: 25.05.2010
Адрес: г. Королёв
Сообщений: 8,497
Сказал спасибо: 30
Сказали Спасибо 3,072 раз(а) в 2,013 сообщении(ях)
|
Re: Помогите найти ошибку AVR asm
Кладу сюдой весь прожект...
Не доделан...
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 18:36.
|
|