Страница 37 из 400

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

Добавлено: Вт мар 30, 2010 10:29:23
MTF
Всем привет :

Почти доделал индикацию по исходнику предоставленную GP1 (все таки решил сделать 4 разряда)
вопрос: поскольку теперь 4 индикатора и у меня четыре кнопки , могу ли я подключится к 4
выводам для включения разрядов , через кнопки например на вывод portd4 ????

Загвозка теперь в том как отлавливать через pd4 какая кнопка нажата , схемы с таким подключением видел , а вот как они определяют не пойму , если не сложно обьясните как это делается ???

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

Добавлено: Вт мар 30, 2010 10:41:22
GP1
вполне.
алгоритм примерно такой:
1. выводишь цифры на индикатор
2. переводишь портВ на вход
3. на PD4 выдаешь 0/1 (если 0 то PORTB должен быть с "подтяжкой", для 1 не обязательно)
4. читаешь PINB, маскируешь лишние разряды и анализируешь.

зы: не забывай про дребезг контактов.
и я бы еще на PD4 резуюк ом так на 470 поставил, так на всякий случай.

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

Добавлено: Пт апр 02, 2010 17:47:51
vit007
Помогите разобраться с обучалкой....

.cseg
.org 0

rjmp RESET
rjmp EXT_INT0
rjmp EXT_INT1
rjmp TIM2_COMP
rjmp TIM2_OVF
rjmp TIM1_CAPT
rjmp TIM1_COMPA
rjmp TIM1_COMPB
rjmp TIM1_OVF
rjmp TIM0_OVF
rjmp SPI_STC
rjmp USART_RXC
rjmp USART_UDRE
rjmp USART_TXC
rjmp ADCC
rjmp EE_RDY
rjmp ANA_COMP
rjmp TWSI
rjmp SPM_RDY

;RESET:
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:
ADCC:
EE_RDY:
ANA_COMP:
TWSI:
SPM_RDY:
reti
;****************************************************
; ИНИЦИАЛИЗАЦИЯ
;****************************************************
Reset: ldi Temp,0b11111111 ;настройка портов
out DDRD,Temp

ldi Temp,0b00010000 ;разрешить прерывание компаратора
out TIMSK,Temp

ldi Temp,0b00000011 ;тактовый сигнал = CK/64, увилечение деление замедляет ход
out TCCR1B,Temp

ldi Temp,0x75 ;инициализация компаратора
out OCR1AH,Temp ;уменьшение имп. повышает скорость
ldi Temp,0x10
out OCR1AL,Temp

ldi Temp,high(RamEnd)
out SPH,Temp

ldi Temp,low(RamEnd)
out SPL,Temp

ldi Temp1,0b00000001 ;инициализация индикатора

ldi Temp,0 ;обнуление таймера
out TCNT1H,Temp
out TCNT1L,Temp

sei ;разрешить прерывания


;****************************************************
; ОСНОВНОЙ ЦИКЛ
;****************************************************
Inf: rjmp Inf ;бесконечный цикл


;****************************************************
; ОБРАБОТЧИК ПРЕРЫВАНИЯ КОМПАРАТОРА
;****************************************************

TIM1_COMPA:
ldi Temp,0 ;обнуление таймера
out TCNT1H,Temp
out TCNT1L,Temp

Shift: сpi Temp1,0b10000000 ;сравнить с крайним знач.
breq Init ;если равно - загрузка нач. знач.

lsl Temp1 ;иначе - сдвиг влево
rjmp Output ;перейти на вывод в порт

Init: ldi Temp1,0b00000001 ;загрузить нач. значение

Output: out PortD,Temp1 ;вывод в порт

reti ;выход из обработчика
---------------------------------------------------------------------------------------------------

Не пойму, как работает прога,

с чего начинается прога - с метки ресет?

т.к. прерывание срабатывает по какому-то внешнему воздействию - где оно "воздействие"?

reti в метке TIM1_COMPA: возвращает к др. меткам, а там тоже reti идет, куда оно то возвращает?

ИНИЦИАЛИЗАЦИЯ загружается раз в память, так как ее прога в цикле не повторяет из-за sei?

бесконечный цикл работает, как +1 и как он циклит прогу?

Почему при перестановке строк:

Init: ldi Temp1,0b00000001
Shift: cpi Temp1,0b10000000
breq Init
lsl Temp1
out PortD,Temp1

цикл запирается?

Спасибо за ответы, хоть при таком кол-ве вопросов наверно сообщение останется без ответа :(

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

Добавлено: Пт апр 02, 2010 20:25:48
Pooher
Программа выполняется с RESET.

"воздействие" - в данном случае, это момент, когда таймер досчитает до определённого значения.

reti - возвращает программу в то место, где произошло прерывание.

ИНИЦИАЛИЗАЦИЯ происходит только по внешнему сигналу RESET и при включении питания.
бесконечный цикл работает, как +1 и как он циклит прогу?
Вопроса не понял.

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

Inf:
 rjmp Inf ;безусловный переход по метке Inf
Почему при перестановке строк:

Init: ldi Temp1,0b00000001
Shift: cpi Temp1,0b10000000
breq Init
lsl Temp1
out PortD,Temp1

цикл запирается?
Вопроса не понял.

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

Добавлено: Сб апр 03, 2010 16:18:45
vit007
Pooher писал(а):
бесконечный цикл работает, как +1 и как он циклит прогу?
Вопроса не понял.

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

Inf:
 rjmp Inf ;безусловный переход по метке Inf
Все сводилось, а как образуется цикл программы....
Pooher писал(а):
Почему при перестановке строк:

Init: ldi Temp1,0b00000001
Shift: cpi Temp1,0b10000000
breq Init
lsl Temp1
out PortD,Temp1

цикл запирается?
Вопроса не понял.
В проге код обработчика такой:

Shift: cpi Temp1,0b10000000
breq Init

lsl Temp1
rjmp Output

Init: ldi Temp1,0b00000001

Output: out PortD,Temp1
------------------------------------------------------

Я решил переставить строки, как это показано выше и прога перестала выполнятся циклически, т.е. повисла на элементе инициализыциии и не туда не сюда...

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

Добавлено: Сб апр 03, 2010 16:46:51
GP1
vit007 писал(а): Все сводилось, а как образуется цикл программы....
......
......
......

В проге код обработчика такой:

Shift: cpi Temp1,0b10000000
breq Init

lsl Temp1
rjmp Output

Init: ldi Temp1,0b00000001

Output: out PortD,Temp1
------------------------------------------------------

Я решил переставить строки, как это показано выше и прога перестала выполнятся циклически, т.е. повисла на элементе инициализыциии и не туда не сюда...
1. Цикл образуется из безконечного повторения инструкции rjmp на саму себя, а в определенные моменты выполняются прерывания.
2. потому что при каждом вхождении в прерывание идет присваивание temp=0b00000001, поэтому после выполнения всего прерывания в порт будет постоянно выводиться значение temp=0b00000010, а так все работает, а в исходном коде присвоение temp=0b00000001 идет только после того как 1 "пройдет" по всем разрядам temp

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

Добавлено: Пн апр 05, 2010 11:29:02
vit007
GP1 писал(а): 2. потому что при каждом вхождении в прерывание идет присваивание temp=0b00000001, поэтому после выполнения всего прерывания в порт будет постоянно выводиться значение temp=0b00000010, а так все работает, а в исходном коде присвоение temp=0b00000001 идет только после того как 1 "пройдет" по всем разрядам temp
Не понял, пока еще сложно написано....

Хотелось обобщить, что понял...

Прога начинается с метки ресет, где происходит инициализация, раз или после кнопки сброса.
Также там ограничивается кол-во имп. для таймера, кот., в последствие, станет "воздействием" для прерывания.
После глоб. разрешения запускается таймер и считаются бесконечные циклы.
При достижении огр. таймера происходит прерывание и переходим в обработчик прерывания.

Скорее всего, я так думаю там допускается линейный алгоритм, а не ветвящийся...

происходит сброс таймера в "0" и возвращение в бесконечный цикл и по новой.

Поправьте если че не так...

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

Добавлено: Пн апр 05, 2010 20:27:13
Pooher
Вроде того...

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

Добавлено: Вт апр 06, 2010 00:49:16
ibiza11
vit007 писал(а):После глоб. разрешения запускается таймер и считаются бесконечные циклы.
таймер запускается после

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

ldi Temp,0b00000011 ;тактовый сигнал = CK/64
out TCCR1B,Temp
перед разрешением прерываний просто обнуляют таймер:

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

ldi Temp,0 ;обнуление таймера
out TCNT1H,Temp
out TCNT1L,Temp
остальное вроде верно.

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

Добавлено: Вт апр 06, 2010 12:45:40
stas00n
vit007 писал(а):Прога начинается с метки ресет
Не совсем. Исполнение программы начинается с вектора сброса (в этом МК он равен нулю), т.е. первой выполняется команда записанная после директивы В данном случае там находится команда безусловного перехода на метку RESET:

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

.org  0
   rjmp   RESET
vit007 писал(а):и считаются бесконечные циклы.
В бесконечном цикле вида

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

loop:
    rjmp   loop
ничего не считается, и если предварительно не разрешить прерывания от периферии, он будет выполняться бесконечно, для чего он собственно и предназначен. Точнее, он предназначен для того, чтобы чем-нибудь занять контроллер, пока нам от него ничего не нужно.
vit007 писал(а):При достижении огр. таймера происходит прерывание и переходим в обработчик прерывания.
Верно, только с учетом вышесказанного: таймер является периферийным устройством, работает независимо от ядра, он считает импульсы тактового генератора, а не количество выполненных инструкций.
vit007 писал(а):Скорее всего, я так думаю там допускается линейный алгоритм, а не ветвящийся...
Ветвление в обработчике есть, посмотри внимательно, там же все закомментировано. Инструкция BREQ - BRanch if EQual - "ветвление, если равно", иначе (если не равно), ветвления не происходит, а выполняется следующая инструкция.

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

Добавлено: Пт апр 16, 2010 16:15:46
Alexeus
Подскажите пожалуйста, как можно решить такую задачу:

С помощью АЦП получаю номер нажатой кнопки и кладу его в переменную буфер. (Key_buf равен от 1 до 6)
в зависимости от того, номер какой кнопки содержит буфер, нужно подставить данные соответствующих массивов в один и тот же цикл.
значения массива берутся с помощью ZH/ZL и lpm...

button_1:
.db 1,2,3,4,5
button_2:
.db 6,7,8,9,10
... и т.д.

цикл от 1 до 5.
out portb,temp <- сюда (в темп) нужно подставлять по порядку 1,2,3,4,5 если буфер кнопки содержит номер 1 и 6,7,8,9,10 если содержит номер 2
к началу цикла.

как так сделать?

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

Добавлено: Пт апр 16, 2010 17:03:40
Meteor
А почему именно АЦП за кнопками следит?
Ведь достаточно объявить входы с подтяжкой и замыкать кнопку на корпус/землю.
АЦП есть смысл применить только при плавающих потенциалах, да и то не всегда.
Код мог быть и таким:

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

ldi temp, 0x00;Начальная инициализация
ldi tmp, 0xFF
out DDRC, temp;
out PORTC, tmp;
out DDRB, tmp;
out PORTB, temp;

main:
sbis pinc, 1; Если не нажали кнопку 1 
rjmp button1;пропускаем переход
....
rjmp main;

button1:; Обработка кнопки
 ldi temp, 1;Грузим число
out portb, temp;
nop
 ldi temp, 2;Другое
out portb, temp;
nop
...
rjmp main;выходим в основной цикл

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

Добавлено: Пт апр 16, 2010 18:03:14
Alexeus
вышеописанное понятно, но у меня другая цель. как я получаю номер нажатой кнопки- вообще не нужно, вопрос в подстановке массивов. Попробую еще объяснить (может и сам заодно пойму :) )

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

короче есть массивы:

button1: .db 23,45,45,66,33,44,55,65,45,5,66,5,4,33,98
button2: .db 23,34,45,56,67,78,89,12,12,12,23,34,45,56
button3: .db 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,3,2,3,2,
button4... -//-
button5... -//- примерно то же самое, числа.
button6... -//-

вот так примерно обрабатывается:
temp=0
couter=0 и т.п.
start:
         cpi counter,15 ;цикл выполняется 15 раз. за цикл все 15 цифр массива
         breq exit
         ldi ZH,high(button3*2) ;загружаем адрес первого числа массива button3
	 ldi ZL,low(button3*2)   ;
 	 ldi temp1,0        
  	 add ZL,temp   ;загрузить адрес первого числа, второго, третьего... инкрименируем адрес в цикле
  	 adc ZH,temp1 ;
  	 lpm                ;загрузить значение по данному адресу в регистр R0
         inc temp         ;инкриминировать адрес
 	 mov R16,R0    ;переместить число из регистра памяти в регистр общего назначения

       *  тут обрабатываю регистр R16 ; в общей сумме 15 раз обрабатываю *

         inc counter ;просто счетчик сколько циклов отработано
         rjmp start
exit:
вобщем тут жестко задан массив из которого по порядку нужно брать цифры. Хочется отвязаться от конкретного массива и поставить туда переменную типа Key_buf в которая будет содержать номер кнопки =1,2,3 ... 6 и в зависимости от номера кнопки брать значения из одного или другого массива- массив не будет жестко задан, а будет определяться переменной.

что то вроде того:

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

  ldi ZH,high(Key_buf*2) ;загружаем адрес первого числа не массива button3, а смотря какое число в key_buf
	 ldi ZL,low(Key_buf*2)   ;  если число 3, то из массива button3, если там число 5, то из массива button5
       ......
вобщем очень надеюсь что понятно, а то писал, писал... ) сам пока не понял.

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

Добавлено: Пт апр 16, 2010 19:00:02
Meteor
А команда LPM Вас устраивает? Например так:

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

ldi Zl, low(Key_buf*2);Загружаем адрес данных в памяти
ldi Zh, high(Key_buf*2); программ
ldi count, 0x05;Счетчик на некоторое число (тут 5)
cycle:
lpm tmp, Z+;считываем
out portx, tmp;отсылаем
dec count;
cpi count, 0;сравниваем с 0
brne cycle;Если не 0 - циклимся
....
Или я опять не допонял? Вполне возможно что малость надо подправить...

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

Добавлено: Пт апр 16, 2010 19:01:27
GP1
Alexeus писал(а): что то вроде того:

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

  ldi ZH,high(Key_buf*2) ;загружаем адрес первого числа не массива button3, а смотря какое число в key_buf
	 ldi ZL,low(Key_buf*2)   ;  если число 3, то из массива button3, если там число 5, то из массива button5
       ......
1. при таком способе ты не получишь нужного значения.
2. я бы сделал так:
-организовал 6 массивов по 16 байт, потеря 6 байт думаю не смертельна
-затем вычисляем смещение (key-1)*16 (просто после вычитания 4 раза сдвигаем значение влево)
-загружаем в Z адрес начальной таблицы и прибавляем смещение (оно у нас кратно № кнопки)
-в цикле последовательно перебираем все значения.

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

Добавлено: Пт апр 16, 2010 19:51:18
Alexeus
Meteor писал(а):Например так:

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

ldi Zl, low(Key_buf*2);Загружаем адрес данных в памяти
ldi Zh, high(Key_buf*2); программ
ldi count, 0x05;Счетчик на некоторое число (тут 5)
cycle:
lpm tmp, Z+;считываем
out portx, tmp;отсылаем
dec count;
cpi count, 0;сравниваем с 0
brne cycle;Если не 0 - циклимся
....
вы снова привязались к конкретному массиву -key_buf и из него тянете 5 чисел... а подразумевается, что Key_buf это переменная, а не массив, в которой находится число от 1 до 6, показывающее, какая кнопка нажата. Цикл с Zрегистром всегда считывает одно и то же количество цифр- пятнадцать штук, а вот ОТКУДА, из какого массива он их будет брать, должна определять переменная Key_buf. То есть если в переменной кейбуф будет число 4, то берем из массива button_4, если в кейбуф число 2, то берем все так же 15 цифр, но уже из массива button_2.

идея в том, что цикл один. в нем последовательно из массива считывается 15 цифр, а сами массивы, откуда считывать задаются значением переменной (1й массив, 2й массив... 6й массив). :)

вот это не корректно, это не работает с переменной:

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

ldi Zl, low(Key_buf*2);Загружаем адрес данных в памяти
ldi Zh, high(Key_buf*2); программ
просто я не знаю как выразить такую операцию, вот хоть что то начеркал для примерного понятия.

GP1 по-моему ближе к тому что я хочу, я правда не совсем понял что он написал, могли бы вы, GP1 по-подробнее, может на примере показать...

массивы даны, вот они, их 6 штук:

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

button1: .db 23,45,45,66,33,44,55,65,45,5,66,5,4,33,98
button2: .db 23,34,45,56,67,78,89,12,12,12,23,34,45,56
button3: .db 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,3,2,3,2,
button4... -//-
button5... -//- примерно то же самое, числа.
button6... -//-
вот как связать значения в переменной Key_buf (например там число 3) с тем, что нужно считать 15 цифр из массива button3, а если в переменной Key_buf было бы число 5, то нужно было бы считать все в том же цикле, все то же количество цифр -15 (это не минус пятнадцать, а дефис), НО из массива button5.

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

Добавлено: Пт апр 16, 2010 20:53:21
GP1
Alexeus писал(а): вот как связать значения в переменной Key_buf (например там число 3) с тем, что нужно считать 15 цифр из массива button3, а если в переменной Key_buf было бы число 5, то нужно было бы считать все в том же цикле, все то же количество цифр -15, НО из массива button5.
так как ты организовал цикл это не получится, а будет примерно так:
читаются данные из массива-3, предположим прочиталось 7 значений, и тут мы меняем массив-3 на массив-5, а до конца цикла осталось всего 8 повторов. :roll:
с примером конечно можно, но ....
может сам попробуешь? :wink:
для затравки:

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

       dec  key  ;уменьшаем значение клавиши на 1, я так понимаю 0 - клавиша не нажата
                     ;и умножаем на 16, как я говорил, иначе придется умножать на 15, а не все АВРки умеют это делать аппаратно
       lsl  key
       lsl  key
       lsl  key
       lsl  key
                     ;и вуаля в key у нас смещение адреса для выбора массива
       ldi  ZL,low(button1*2)    ;грузим в Z адрес первого массива
       ldi  ZH.high(button1*2)
                      ;складываем адрес и смещение
       add  ZL,key
       adc  ZH,tmp   ;tmp=0
;естественно при key=1 мы получим смещение 0, и получится адрес первого массива.

;дальше цикл

ну что-то типа такого.

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

Добавлено: Пт апр 16, 2010 21:01:15
Alexeus
не, ничего менять не нужно, наверное (-15) вас смутило. это не минус, а дефис.

просто в переменной Key_buf всегда находиться значение кнопки. Если никакая кнопка не нажата, то там "0", а если нажимаются кнопки от 1 до 6, то там будет значение нажатой в данный момент кнопки. Mне нужно вызвать функцию в которой есть цикл обработки массива. А массив туда нужно будет подставить в зависимости от того, какая цифра в переменной Key_buf.

Можно наверное было бы сделать типа "если в кейбуф цифра "1", то идем на цикл, где жестко прописана обработка массива баттон1, в противном случае, если в кейбуф цифра два, то идем в другой цикл, где обрабатываем только массив баттон2..." все это будет работать, но хотелось бы оптимизировать до одного цикла, в который подставляется нужный массив в зависимости от числа в переменной keybuf.

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

Добавлено: Пт апр 16, 2010 21:11:55
GP1
пока писал ты уже напостил :)))
см.выше :tea:

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

Добавлено: Пт апр 16, 2010 21:38:23
Alexeus
О! :) Спасибо большое. Поизучаю. Вроде то что нужно.