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

Обсуждаем контроллеры компании Atmel.
Ответить
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

ПТУ-шник писал(а):...
О какой избыточности вы говорите? В студии есть все, что требуется. И ничего лишнего. И редактор и симулятор. Ну и так далее. Никакого квеста. Необходимый набор инструментов. Вы хотите в один файлик? Это только если светодиодиком поморгать. Как только пойдут более-менее серьезные проекты, вам придется научиться модульности программ.
Не надо ничего усложнять. AVR-Studio 4.19 проста как рубанок.
Последний раз редактировалось Demiurg Чт ноя 26, 2015 21:18:07, всего редактировалось 1 раз.
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 6347
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

ПТУ-шник писал(а): На AVR Studio программировать не хочу, слишком много лишнего.
Никто и не заставляет использовать "лишнее" - ни Студиевский редактор, ни замечательный его симулятор . Написал в своем любимом редакторе исходник, парой кликов мышью создал проект - и вы уже в Хопре :) - компилируй, получай и hex, и obj, и lst - в зависимости от настроек. Создать файл данных для записи в EEPROM - да сколько угодно. А если прога чуть сложнее 'помигать диодами' - отладка в Студии - прямо сказка. И Про Те Усы можно не вспоминать.
В общем, не надо бояться человека с ружьем АВР-Студии - она очень хорошая и доброжелательная даже к новичкам :)
Изображение
Реклама
Мучитель микросхем
Сообщения: 469
Зарегистрирован: Вс авг 30, 2015 03:52:59

Сообщение Pnjom-Penb »

Есть еще один аргумент против ASM Editor'а - как видно из последних постов, количество пользователей этого редактора намного меньше, чем той же студии, или IAR'а, а значит и подсказку получить труднее.
Нашел транзистор. Понюхал.
Сообщения: 167
Зарегистрирован: Чт янв 01, 2015 16:34:55

Сообщение ПТУ-шник »

Проблему ASM Editora решил, там в батнике не тот параметр стоял. Поправил и всё заработало.

Возникли вопросы про работу программы на ассемблере. Вот код:

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

.include "C:\avrtools\Appnotes\tn13def.inc" ; Библиотека для Тини13
SBI DDRB, 1 ; Настройка порта
SBIC PINB, 0 ; Если пин 0 порта В в лог. единице, то выполняем следующую команду. Если лог. нуле то пропускаем. 
SBI PORTB, 1 ; пин 1 установка
SBIS PINB, 0 ; если на пине 0 нет сигнала то пин 1 в ноль
CBI PORTB,1
Программа гасит и зажигает светодиод по кнопке. Всё прекрасно работает.

Вопросы:
1) Почему она зациклина? Получается когда счётчик команд в мк доходит до конца помяти то он прыгает в начало т.е. аппаратно находится в цикле? Думал что программа дойдёт до последней команды и остановится, а не прыгнет обратно на первую.
2) Почему этот код вообще работает? :)) Тут нет векторов прерываний в начале, не установлен начальный адрес. Просто сразу идёт код.
3) Что за дериктива .device? Что именно она делает? А то в inc файлах уже покапался, а с device непонятно.
Реклама
Эиком - электронные компоненты и радиодетали
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

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

"Прекрасно" работает в протеусе или железе?
Станислав
Реклама
Нашел транзистор. Понюхал.
Сообщения: 167
Зарегистрирован: Чт янв 01, 2015 16:34:55

Сообщение ПТУ-шник »

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

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

DEVICE - Определить устройство для которого компилируется программа
Директива DEVICE позволяет указать для какого устройства компилируется программа. При использовании данной директивы компилятор выдаст предупреждение, если будет найдена инструкция, которую не поддерживает данный микроконтроллер. Также будет выдано предупреждение, если программный сегмент, либо сегмент EEPROM превысят размер допускаемый устройством. Если же директива не используется то все инструкции считаются допустимыми, и отсутствуют ограничения на размер сегментов.

Если прерывания не используются, то допустимо их не указывать.

По первому вопросу не могу ниче вразумительного сказать. Вообще-то так не принято. Все делают бесконечный цикл. Может ваш компилятор посчитал, что его надо вставить и сделал это сам. Может так и есть, если дошел до конца памяти, то прыгает на начало (или сбрасывается, что скорее всего). Однако, это сильно криво, так делать. :dont_know:

Да и в железе, если даже по умолчанию стоит у МК 1 МГц тактовая, все равно на кнопку реагировать должна как попало.
Станислав
Нашел транзистор. Понюхал.
Сообщения: 167
Зарегистрирован: Чт янв 01, 2015 16:34:55

Сообщение ПТУ-шник »

СКАЗОЧНИК писал(а):
По первому вопросу не могу ниче вразумительного сказать. Вообще-то так не принято. Все делают бесконечный цикл. Может ваш компилятор посчитал, что его надо вставить и сделал это сам. Может так и есть, если дошел до конца памяти, то прыгает на начало (или сбрасывается, что скорее всего). Однако, это сильно криво, так делать. :dont_know:
Компилятор из AVR Studio 4. Кодил в ней, результат тот же.


На кнопку реагирует нормально. Хоть как жмякай. У меня attiny13 работает от встроенного генератора по умолчанию, во фьюзы пока не лазию.
Родился
Сообщения: 6
Зарегистрирован: Сб дек 05, 2015 23:21:05

Сообщение Shark-vc »

Народ, помогите пожалуйста, пытаюсь подключить ЖКИ HD44780 к ATmega8535 , вроде собрал правильно, но все равно не работает, мб в коде ошибка? Вроде делаю все по инструкции

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

   #define RS 2							
   #define e  3

;НАСТРОЙКА И ВЫВОД НА ЖКИ----------------------------------------------------------------------
   ser temp
   out DDRA,temp        ;порт РА на вывод
   ldi temp,$0C        ;PC0-PC1,PD4 на ввод
   out PORTC,temp
   rcall delay2ms
   ldi acc,$38      ;8-битовый режим вывода,
   rcall lcdcom      ;2 строки, шрифт 5х7
   ldi acc,$06      ;Направление сдвига курсора вправо, без сдвига дисплея
   rcall lcdcom
   ldi acc,$0C      ;включить дисплей
   rcall lcdcom      ;погасить курсор
   ldi acc,$01      ;Очистить дисплей и установить курсор в нулевую позицию
   rcall lcdcom
   rcall delay2ms
   ldi     acc,0x31   ; загрузить цифру "1" в регистр lcd
   rcall lcddat
 rjmp Loop
 
     ;Подпрограмма вывода на дисплей байта данных
lcddat:
   out PORTA,acc      ;вывод символа
   ldi temp,0x04      ;установка режима записи данных E=1
   out PORTC,temp
   cbi PORTC,e      ;фронт 1/0 строба
   rcall delay40us
   ret
 
     ;Подпрограмма вывода на дисплей байта команды
lcdcom:
   out PORTA,acc      ;вывод команды
   ldi temp,0x08      ;установка режима записи команд 
   out PORTC,temp
   ldi temp,0x04      ;установка режима записи команд E=1
   out PORTC,temp
   cbi PORTC,e      ;фронт 1/0 строба
   rcall delay40us
   ret
Вложения
Безымянный.png
СХЕМА
(84.68 КБ) 448 скачиваний
akl
Друг Кота
Сообщения: 4473
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Поправил. Не хотел писать пп DELAY, поэтому закомментировал их.
Спойлер

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

	.include "m8535def.inc"

.equ	RS=2                     
.equ	E=3
;   #define RS 2                     
;   #define E  3
.def	TEMP=R16
.def	ACC=R17

	LDI	ZH,HIGH(RAMEND)
	LDI	ZL,LOW(RAMEND)
	OUT	SPH,ZH
	OUT	SPL,ZL



;НАСТРОЙКА И ВЫВОД НА ЖКИ----------------------------------------------------------------------
   ser temp
   out DDRA,temp        ;порт РА на вывод
   LDI	R22,1<<RS|1<<E
   OUT	DDRC,R22

;   ldi temp,$0C        ;PC0-PC1,PD4 на ввод???
;   out PORTC,temp ;PC0-PC1,PD4 на вЫвод???

;   rcall delay2ms
   ldi acc,$38      ;8-битовый режим вывода,
   rcall lcdcom      ;2 строки, шрифт 5х7
   ldi acc,$06      ;Направление сдвига курсора вправо, без сдвига дисплея
   rcall lcdcom
   ldi acc,$0C      ;включить дисплей
   rcall lcdcom      ;погасить курсор
   ldi acc,$01      ;Очистить дисплей и установить курсор в нулевую позицию
   rcall lcdcom
;   rcall delay2ms
   ldi     acc,0x31   ; загрузить цифру "1" в регистр lcd
   rcall lcddat
LOOP:
 rjmp Loop
 
     ;Подпрограмма вывода на дисплей байта команды
lcdcom:
	CBI	PORTC,RS      ;установка режима записи команд
	RJMP	LCDDAT+1

     ;Подпрограмма вывода на дисплей байта данных
lcddat:
	SBI	PORTC,RS      ;установка режима записи данных
	RCALL	PAUSE_RET
	SBI	PORTC,E
	RCALL	PAUSE_RET
	out PORTA,acc      ;вывод символа
	RCALL	PAUSE_RET
	CBI	PORTC,E
;   ldi temp,0x04      ;установка режима записи данных E=1
;   out PORTC,temp
;   cbi PORTC,e      ;фронт 1/0 строба
;   rcall delay40us
PAUSE_RET:
	ret
 
Инициировать дисплей желательно без отступлений от DS
Держит паяльник хвостом
Аватара пользователя
Сообщения: 965
Зарегистрирован: Сб апр 12, 2014 23:46:03
Откуда: Киев

Сообщение Flash.#13 »

Здравствуйте товарищи, возникла накладка с АЦП. Настроил ADCSRA, настроил ADMUX, Ref прописал питание +5В, замер делается нормально. Затем следующий замер Ref прописываю внутренний 2.56В, делаю два замера с задержкой для отсева переключения, а на выходе бяка. Щупаю тестером ножку Aref а там и близко не пахнет 2.56В, как быть?

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

...
ldi R16, 0b01000000	;РС0, +5VCC
out ADMUX, R16
sbi ADCSRA,6		;старт замера АЦП
rcall delay40mks
rcall delay40mks
rcall delay40mks
rcall delay40mks
sbi ADCSRA,6		;старт замера АЦП, х2 для точности, все ок
...
ldi R16, 0b11000000	;РС0, +2.56V internal source
out ADMUX, R16
sbi ADCSRA,6		;старт замера АЦП
rcall delay40mks
rcall delay40mks
rcall delay40mks
rcall delay40mks
sbi ADCSRA,6		;старт замера АЦП, х2
//и ничего, нету 2.56 на ноге Aref, и замер чего-попало
Немного файлов по зажиганию: ФУОЗ 2.2 + программа правки таблиц 0.987, монтажка
Нашел транзистор. Понюхал.
Сообщения: 167
Зарегистрирован: Чт янв 01, 2015 16:34:55

Сообщение ПТУ-шник »

Как настроить таймер в Attiny13 в ассемблере? Я пытаюсь сделать так:

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

LDI temp, 0b00000001
OUT TIMSK, temp ;  Разрешение прерывания от таймер TIM0
LDI temp, 0b00000101
OUT TCCR0, temp ; установка пред. делителя
temp это переменная R16 в РОН.

Такая программа даже не компилируется. Примерно понял почему она не работает - регистр TIMSK однобитный, остальные 7 бит к шине не подключены поэтому туда никакие значения запихнуть нельзя. И как быть?

Видел такой пример:

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

ldi temp,(1<<TOIE0) ;разр. прерывания Timer0
out TIMSK,temp
Но не очень понимаю как это работает. Вроде тоже самое что и у меня. Вот эту скобку (1<<TOIE0) я вообще не понимаю. Зачем то сдвиг числа сюда запихнули. Я знаю что TOIE0 это тот бит который нужно установить в «1» но как тут к нему обратились?
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Такая программа даже не компилируется.
На что ругается?
Примерно понял почему она не работает - регистр TIMSK однобитный
Не угадали, в AVR все регистры 8-битные. Может, кроме совсем уж внутренних, к которым нет прямого доступа.
Вот эту скобку (1<<TOIE0) я вообще не понимаю.
Это хороший тон форматирования - не использовать магических чисел, а использовать именованные константы. Совсем хорошо, когда константы поименованы разработчиком системы, как здесь. Суть всего лишь в установке бита номер TOIE0, то есть с точки зрения компилятора не отличается от вашей записи.
Друг Кота
Аватара пользователя
Сообщения: 6347
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

ПТУ-шник писал(а):Видел такой пример:

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

ldi temp,(1<<TOIE0) ;разр. прерывания Timer0
out TIMSK,temp
Но не очень понимаю как это работает. Вроде тоже самое что и у меня. Вот эту скобку (1<<TOIE0) я вообще не понимаю. Зачем то сдвиг числа сюда запихнули. Я знаю что TOIE0 это тот бит который нужно установить в «1» но как тут к нему обратились?
TOIE0 - это просто номер бита в регистре. Ничего там на самом деле не двигается, просто такая запись говорит компилятору : " Установи в temp бит номер такой-то в 1" . А не компилироваться может вот почему: в разных поколениях АВРок регистры могут быть в разных диапазонах адресов, что, конечно, нехорошо. Поэтому то, что в одном МК проходит как OUT, в другом выглядие как STS, потому что не входит в диапазон адресов, к которым допустима команда OUT. Конкретно мы ничего не знаем о типе обсуждаемого тут МК, да и по ДШ шарить - мне лениво. Но это одна из версий.
Изображение
akl
Друг Кота
Сообщения: 4473
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

ПТУ-шник писал(а):Как настроить таймер в Attiny13 в ассемблере? Я пытаюсь сделать так:

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

LDI temp, 0b00000001
OUT TIMSK, temp ;  Разрешение прерывания от таймер TIM0
LDI temp, 0b00000101
OUT TCCR0, temp ; установка пред. делителя
Такая программа даже не компилируется.
Естественно, не должна, т.к. TOIE0 у ATtiny13 стоит в другом месте. А когда командуете (1<<TOIE0), то ассемблер сам определяет положение этого бита.
Нашел транзистор. Понюхал.
Сообщения: 167
Зарегистрирован: Чт янв 01, 2015 16:34:55

Сообщение ПТУ-шник »

akl писал(а):
ПТУ-шник писал(а):Как настроить таймер в Attiny13 в ассемблере? Я пытаюсь сделать так:

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

LDI temp, 0b00000001
OUT TIMSK, temp ;  Разрешение прерывания от таймер TIM0
LDI temp, 0b00000101
OUT TCCR0, temp ; установка пред. делителя
Такая программа даже не компилируется.
Естественно, не должна, т.к. TOIE0 у ATtiny13 стоит в другом месте. А когда командуете (1<<TOIE0), то ассемблер сам определяет положение этого бита.
Хм. Именно в этом случае ему оказывается без разницы. Ошибка: TIMSK это неверное название, надо TIMSK0. Пробывал устанавливать нулевой бит, компилятор молчит.

А вот с TCCR0 всё равно ругаеться, пишет что и раньше: Undefined variable referenced. Тобишь недопустимый адрес как я понял.

По совету поставил за место out, sts и ошибок вылезло ещё больше :o

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

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

Как-то так работал с таймером на ТИНИ13... Не помню уже чего там понакалякал... :))) Но что-то даже работало.
Спойлер

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

; ******************************************************
; * Автор: СКАЗОЧНИК 								   *                           
; * Дата: 10.10.2014                                   *                                              
; * Версия: 140831                                     *                                            
; * Имя файла: ИК управление    					   *                                      
; * Для AVR: ATTiny13                                  *                                                    
; * Тактовая частота: 9,6 MHz	            		   *
; * Среда разработки: AVR Studio 4.12				   *
; *													   *
; * Выполняемые функции: 					           *
; *    											       *
; * 									               *
; ******************************************************

; ================
; ПОДКЛЮЧАЕМЫЕ БИБЛИОТЕКИ (.include)
; ================

	.include "tn13def.inc"	

; ============
; ТИП МИКРОКОНТРОЛЛЕРА (.device)
; ============

	.device ATtiny13
 
; =================
; ОБЪЯВЛЕНИЯ И КОНСТАНТЫ (.def, .equ)
; =================
 
	.def	temp = R16
	.def	TIME = R17	
	.def	FLAG = R18
	.def	LADR = R19
	.def	HADR = R20
	.def	LCMD = R21
	.def	HCMD = R22
	.def	CNT = R23
	.def 	RUN = R24
	.def	SCREEN = R25
	.def 	YYY	= R26
			
; ====
; МАССИВЫ И Т.Д. (.eseg) EEPROM (.db, .dw)
; ====
	
	.eseg

; =================
; МАКРОСЫ (.MACRO)
; =================

	.MACRO PUSHF	; Положить СРЕГ в стек
		push r16
		in r16, SREG
		push r16
	.ENDM

	.MACRO POPF		; Достать СРЕГ из стека
		pop r16
		out SREG, r16
		pop r16
	.ENDM

; ******************************
; НАЧАЛО ПРОГРАММЫ (.cseg) FLASH
; ******************************
	
	.cseg

; ------------------
; ВЕКТОРЫ ПРЕРЫВАНИЙ
; ------------------
	
	rjmp RESET 			; Reset Handler
 	rjmp INT0add 		; External Interrupt0 Handler
 	rjmp PCI0add 		
 	rjmp OVF0add 	
 	rjmp ERDYadd 	
	rjmp ACIadd		
	rjmp OC0Aadd 	
	rjmp OC0Badd 	
	rjmp WDTadd	
	rjmp ADCCadd 	
	
		;RESET: 		; Reset Handler
		;INT0add: 		; External Interrupt0 Handler
		PCI0add: 		
		OVF0add: 	
		ERDYadd: 	
		ACIadd: 		
		OC0Aadd: 	
		OC0Badd: 	
		WDTadd: 	
		ADCCadd: 	
	
	reti			; Выход из прерываний, которые не используются

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

		PUSHF
			
			in TIME, TCNT0		; Закидываем в Тайм значение счетчика, будем использовать его позже
			clr temp
			out TCNT0, temp		; Первоначально очищаем счетный регистр раймера 
			inc CNT	
			ldi YYY, 1
		
		POPF
		
	reti						; Выходим из прерывания

;	OVF0add:

;		inc CNT

;	reti

; **************************************************************************************************
; ИНИЦИАЛИЗАЦИЯ МК (логическое начало основной программы) ******************************************
; **************************************************************************************************

;           --------- конфигурация портов -----------------------------------------------           

	Reset:	ldi temp, (1<<PB4)|(1<<PB3)|(0<<PB2)|(0<<PB1)|(0<<PB0)			; Конфигурация порта
			out DDRB, temp	

			ldi temp, (0<<PB4)|(0<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0)
			out PORTB, temp

			ldi temp, (1<<INT0)		; Разрешить прерывание 
			out GIMSK, temp

			ldi temp, (1<<ISC01)|(0<<ISC00)			; Настраиваем прерывание по низкому уровню (на ИНТ0)
			out MCUCR, temp
			
			ldi temp, low(RAMEND)	; Загрузка указателя стека
			out SPL, temp
			
			ldi temp, 0x00			; Конфигурация таймера
			out TCCR0A, temp
			ldi temp, (1<<CS02)|(0<<CS01)|(1<<CS00)	; Тактовый сигнал = CK/1024 (ЗАПУСКАЕМ ТАЙМЕР)
        	out TCCR0B, temp

			clr FLAG				; Просто очищаем 
			clr TIME
			clr CNT
			clr RUN
			clr SCREEN
			clr YYY
		 	
;           ---------- разрешение прерываний --------------------------------------------			

			sei						; Разрешаем прерывания	

; *******************************************************************************************************************
; ОСНОВНАЯ ПРОГРАММА (основной цикл) ********************************************************************************
; *******************************************************************************************************************

	Start:	
		
		cpi YYY, 1
		brbs SREG_Z, KOD
		rjmp Start

		KOD: rcall NULONE

		cpi RUN, 1
		brbs SREG_Z, KOD1

		rjmp Start

		KOD1: rcall DRIWER

	rjmp	Start	; Конец программы, переход на начало

; *******************************************************************************************************************
; ПОДПРОГРАММЫ ******************************************************************************************************
; *******************************************************************************************************************

	NULONE:					; Заполнение 4 переменных нулями и единицами с послыл
		
			cpi FLAG, 0
			brbc SREG_Z, A1	; 
			inc FLAG
			clr YYY
			ret

	A1:		cpi FLAG, 1
			brbc SREG_Z, A2
		
				cpi TIME, 120		; Проверка 122 < T < 130
				brlo END
				cpi TIME, 132
				brsh END

						N:	ldi temp, (0<<PB4)|(0<<PB3)|(1<<PB2)|(0<<PB1)|(1<<PB0)	; Стоп мотор
							out PORTB, temp	
							rjmp N


			inc FLAG
			clr CNT
			clr YYY
			ret

	A2: 	cpi FLAG, 2
			brbc SREG_Z, END

				cpi TIME, 8			; Проверка 8 < T < 12
				brbs SREG_C, END
				cpi TIME, 12
				brbc SREG_C, ONE
			
					clc				; Убираем флаг С
					rol LCMD		; Задвигаем ноль в самый правый разряд
					rol HCMD		; и по очереди сдвигаем все байты влево
					rol LADR		; В итогде, вся цепочка переместилась влево на один бит, а старший вывалился... 
					rol HADR
					rjmp TT			; Все, вышли .

		ONE: 	cpi TIME, 18		; Проверка 18 < T < 22
				brbs SREG_C, END
				cpi TIME, 22
				brbc SREG_C, END
		
					sec				; 
					rol LCMD		; 
					rol HCMD		; 
					rol LADR		; 
					rol HADR
									
		TT: 	cpi CNT, 32
				brbs SREG_Z, PROVERKA

					clr YYY
					ret

		PROVERKA: 	cpi HADR, 0b00010000
					brbc SREG_Z, END
					cpi LADR, 0b11001000
					brbc SREG_Z, END
					cpi HCMD, 0b11100001
					brbc SREG_Z, END
					cpi LCMD, 0b00011110
					brbc SREG_Z, END

					clr FLAG
					clr CNT
					clr YYY
					ldi RUN, 1

					ret
		
		END:
			
			clr FLAG
			clr CNT
			clr YYY
			clr RUN
		
	ret

; =============

	DRIWER:

		clr temp	; Запретить прерывание 
		out GIMSK, temp

		cpi SCREEN, 0b00000000		; Проверяем флаг, опущен экран или поднят
		brbc SREG_Z, UP

			ldi temp, (0<<PB4)|(1<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0)	; Запускаем мотор вниз, а на остальных оставляем поддтяжку
			out PORTB, temp

		TUDA:	ldi temp, (1<<TOIE0) ; Разрешить прерывание по переполнению таймера
				out TIMSK0, temp
				clr temp
				out TCNT0, temp							; счетный регистр раймера
			;	ldi temp, (1<<CS02)|(0<<CS01)|(1<<CS00)	; Тактовый сигнал = CK/1024 (ЗАПУСКАЕМ ТАЙМЕР)
        	;	out TCCR0B, temp

		NEXT:	cpi CNT, 2			; ждем, пока таймер проткает 3 раза примерно 100 мсек
				brbc SREG_Z, NEXT	; Тупо задержка по таймеру

				clr temp 			;Запретить прерывание по переполнению таймера
				out TIMSK0, temp				
	    		out TCCR0B, temp
				
		NEXT1:	sbic PINB, 0		; Пропускаем следующую, если бит очищен (датчик сработал, прижал вывод к земле)
				rjmp NEXT1			; а если не очищен, то продолажем крутиться и ждать, пока датчик не сработает

				ldi temp, (0<<PB4)|(0<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0)	; Стоп мотор
				out PORTB, temp

				com SCREEN			; переворачиваем флаг положения экрана

				rjmp EX 			; Выходим

		UP: 	ldi temp, (1<<PB4)|(0<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0)	; Запускаем мотор вверх
				out PORTB, temp

				rjmp TUDA

	EX:		
			clr FLAG				; Просто очищаем 
			clr TIME
			clr CNT
			clr RUN
			clr YYY
				
		ldi temp, (1<<INT0)		; Разрешить прерывание 
		out GIMSK, temp
		ldi temp, (1<<ISC01)|(0<<ISC00)			; Настраиваем прерывание по низкому уровню (на ИНТ0)
		out MCUCR, temp

	ret

							
Всё равно не понял эту (1<<TOIE0) команду. Можете объяснить по подробней? Хочу более глубинно понять что происходит внутри, а то этот << арифметический сдвиг меня смущает. И почему эта команда в скобках? Это макрос какой то? Хочу видеть исходник если это макрос.
Для начала надо разобраться, подключена ли у вас библиотека с определениями всех этих названий????

.include "tn13def.inc"

А потом все просто. Запись (1<<TOIE0) говорит запихать единицу в бит ТОIE0 в регистре. А бит TOIE0 определен в подключенной библиотеке (см. выше), если ее открыть, то можно его там найти и понять что ему присвоено. Сделано это для "удобочитаемости", как вам уже и ответили выше. В скобках, потому что так и читать удобнее. А по поводу вообще команды <<, читайте инструкции к ассемблеру. В гугле их очень много.
Можно было вместо (1<<TOIE0) написать (1<<3), что означало бы, задвинуть (сделать так, чтобы было) единицу в позицию третьего бита.

Вот пример:

ldi temp, (1<<INT0) ; Разрешить прерывание
out GIMSK, temp

Запихиваем единицу в бит INT0 регистра temp, т.е. бит INT0 у нас объявлен в подключенной библиотеке (без нее работать не будет), а там он может записан быть непосредственно для этого микроконтроллера как 0. Т.е. INT0=0. Значит,
ldi temp, (1<<0)

что означает запихать единицу в нулевой бит регистра temp, а по сути, сделать это:

ldi temp,0b00000001

но читается верхнее лучше.

После этого мы просто копируем темп в нужный нам регистр.
Последний раз редактировалось СКАЗОЧНИК Чт дек 17, 2015 18:34:05, всего редактировалось 1 раз.
Станислав
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

ПТУ-шник писал(а):...
Вложения
jhytfcyf.jpg
(64.53 КБ) 460 скачиваний
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

ПТУ-шник писал(а):эту (1<<TOIE0) команду
Это не команда. TOIE0 - это константа и ее значение может быть разным. И еще зависит от среды программирования. В AVR STUDIO надо было в исходник включать специальный файл, в котором были прописаны константы именного того контроллера, для которого пишется код. Другая среда может сама подключить все файлы для нужного контроллера.
Во включаемом файле может быть, например, такая строка:

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

TOIE0 equ 0x03
Это означает что компилятор встретив TOIE0 заменит ее на 0x03.

Запись (1<<TOIE0) скажет компилятору, что надо 1 сдвинуть влево 0x03 раз. И компилятор заменит (1<<TOIE0) на 0b00001000 (0x08).
Следующие две команды будут скомпилированы в один и тот же код.

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

ldi R16,(1<<TOIE0)
ldi R16,0x08
Последний раз редактировалось Z_h_e Чт дек 17, 2015 19:41:45, всего редактировалось 1 раз.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

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

Да. ))) Выше дорисовал тоже самое, может и не так понятно..
Станислав
Ответить

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