-

Осваиваем AVR!

новости  | с чего начать? | ссылки | учебник | примеры | программатор | отладчики | осциллограф | давно это было | download | сотрудничество | пишите мне

пример отладки  | бегущие огни | МигалкаЭкономим ресурс ПЗУ | Работаем с USART | 555

На этой страничке вам предлагается достаточно простой пример, идею которого мне предложил kuznecov_s@bru3.uralkaly.ru. Надеюсь, пример удачный - во первых, программа (и само устройство) достаточно просты, во вторых - результат весьма нагляден. Это простейшая программа для реализации эффекта "бегущие огни", которую при желании легко модифицировать и развивать дальше.

Схема простейших бегущих огней для AT90s8535. Кварц 8 МГц, светодиоды любые (например АЛ307Б) 

Итак, задача - достаточно простая. Есть AVR, к нему подключены 8 светодиодов и 2 кнопки. При нажатии на одну из кнопок горящий светодиод бежит в одну сторону, и наоборот. Пусть мы используем горячо мною любимый AT90s8535, светодиоды подключены к порту PORTC, а кнопки - на первые два пина порта PORTA. Ну, естественно, не забыто про питание и кварц...

А программа будет такая:

 

;            +--------------------+
;------------|(c)nml, 22-oct-2002 |-----------------------------
;            +--------------------+
; ну, в общем, прикинем простейшие световые эффекты длЯ AVR
; пусть будет так (длЯ начала): на PORTC подключены 8 светодиодов,
; на PORTA.0 и PORTA.1 подключены кнопки, замыкание на землю.
; При нажатии на кнопки - пусть "вертитсЯ" один горЯший, в разных
; направлениЯх. Скорость (пока) фиксирована.
; Светодиоды подкл. так, чтобы горели при подаче "0"
;---------------------------------------------------------------
; Ну че, приступим? :-) без умничаньЯ (прерываний и прочего)
;---------------------------------------------------------------
	.include "8535def.inc"	; тут определЯютсЯ имена регистров
				; спец функций и прочее символьное
	; длЯ удобства определим символьные имена регстров
	; ведь COUNTER при чтении программы гораздо понЯтнее,
	; чем R22 :-)
.def	TMP	= R16	; используем рег начинаЯ с 16, так как нам
.def	VERT	= R17	; много не надо, а младшие не могут исп в
.def	COUNT1	= R18	; операциЯх с непосредственным операндом
.def	COUNT2	= R19	; что иногда неудобно
.def	COUNT3	= R20	;
;.def		= R21	;
;.def		= R22	;
;.def		= R23	;
;.def		= R24	;
;.def		= R25	; все, дальше пошли пары указателей X,Y,Z
			; впрочем, при необходимости можно и их
			; использовать, это обычные регистры
	.org	0	; по вкл пит-Я или сбросу программа стартует с 0
	rjmp	START	;\
	.org	0x50	; суть подобного "старта" описана у менЯ на сайте,
START:			;/сохранение ресурса
	; инициализируемсЯ. Ну, во первых, надо установить указатель
	; стека, прерываниЯ и подпрограммы без этого работать не будут
	; Он устанавливаетсЯ на конец ОЗУ (стек растет вниз)
	ldi	TMP,low(RAMEND)	; ramend определено в .inc так как
	out	SPL,TMP		; длЯ разных процессоров разные
	ldi	TMP,high(RAMEND)
	out	SPH,TMP
	; готово. TMP использовали как перевалочную базу, вывод
	; возможен только из регистра.
	; теперь надо определить как будет работать порт. ДлЯ этого
	; есть регистр DDRx - записываЯ в соответствующий разрЯд "1",
	; определЯем тот же разрЯд PORTx как выходной. Если "0" - то
	; входной, при этом запись "1" в PORTx подключит подтЯгивающий
	; резистор на +
	ser	TMP		; =FF
	out	DDRC,TMP	; PORTC-все выходные
	out	PORTA,TMP	; PORTA по умолчанию на ввод, запись "1"
				; нужна длЯ подтЯгивающих резисторов
	ldi	VERT,0xFE	; это то, что вертетьсЯ будет
				; впрочем, можно и другое число....
				; например,0x0F - будут 4 горЯщих.
	; ну вот и всЯ, наверное, инициализациЯ.
	; прерываниЯ все после старта запрещены, ничего переопределЯть
	; не надо.
	; теперь нам длЯ получениЯ эффекта "бегущего огнЯ" надо, в общем-то,
	; сделать паузу (если вертеть с частотой в 1 кгц - не увидишь ничего),
	; потом в зависимости от нажатой кнопки сдвинуть вправо или влево,
	; не забыть вывести в порт и опЯть на паузу. Итак:
LOOP:
	out	PORTC,VERT	; собственно вывод в порт. сюда придем после
				; каждого сдвига!
	ldi	COUNT3,16	; см. на формирование задержки
WAIT:
	dec	COUNT1
	brne	WAIT		; это даст 256*3 такта = 96 мкс паузу. маловато!
	dec	COUNT2
	brne	WAIT		; грубо это умножит на 256, 25 мс - тоже мало...
				; нам бы 0,4сек=100 мс - еще на 16 умножить.
	dec	COUNT3
	brne	WAIT
	; все, пауза кончилась. теперь смотрим на кнопки
	; кчтати, времЯ считалось исходЯ из 8мГц тактовой
	in	TMP,PINA	; ввод не из PORTx, а PINx!
	; тут если кн нажата, то соотв бит будет =0
	sbrs	TMP,0	; эта команда пропустит следующую, если бит TMP.0=1
	rjmp	vlevo	; то есть если перваЯ кнопка не нажата
	sbrs	TMP,1
	rjmp	vpravo	; -//- втораЯ
	rjmp	LOOP		; если ничего не нажато, то и не делать ничего
;-----------------------------------------------------------------------------
; а вот тут собственно осуществлЯем сдвиги. Тут надо иметь в виду, что у AVR
; есть только сдвиг через "C" разрЯд, а нам бы надо сразу из 7 в 0 и наоборот!
;-----------------------------------------------------------------------------
vlevo:
	mov	TMP,VERT	; во временный
	rol	TMP		; результат по барабану, главное C бит
	rol	VERT		; тут в 0 вдвинетсЯ старший!
	rjmp	LOOP		; выведетсЯ там!
;--------------
vpravo:
	mov	TMP,VERT	;
	ror	TMP		;
	ror	VERT		;
	rjmp	LOOP		; тут, в общем-то, все аналогично
;------------
	.exit		
; все, после этого уже не транслируетсЯ!
----------------------------------------------------------
 вот и все... по идее, должно работать.
 паЯть это длЯ проверки как-то лениво.
----------------------------------------------------------
Да, при нажатии на обе кнопки работать будет как при нажатой первой,
тут получаетсЯ приоритет. А можно было бы после ввода с PINA сделать
	andi	TMP,3		; оставить 2 мл бита
	breq	oba_nazaty	; если ОБА нули, то на отдельную ветвь
				; например, зажечь все светодиоды...
Вообще тут громаднейший простор длЯ фантазии.
- сделать не на 8, а 16 и более (31 мах) светодиодов
- подключить потенциометр на вход АЦП и плавно изменЯть скорость вращениЯ
- крутить не "1", а хренову тучу разных комбинаций, эффектов придумать
  можно много... (например 2 последних по искл ИЛИ на первый)
- сделать плавное зажигание/гашение (типа звездного неба в Нортоне)
- управлЯть всей этой хренью с компа по RS232 (нужна схема согласованиЯ
  уровней, на компе +-12V) впрочем, схема несложнаЯ.

 

Вот, собственно, и вся программа. Даже проверено (не поленился таки) - работает :-) Желаю успеха!

 
Rekl:Хотите насладиться распрекрасным массажем? Только соблазнительные массажистки способны служить для вас в любое время дня и ночи, не оплошайте первокласную возможность побаловать себя красивым приятностью. | Продукты adem cad CAM. | Технические условия Двигатель серии АИР.

(с)nml 11-Jul-2009