Диапазон!Alkul писал(а):под "интервалом" тут понимается количество итераций?мелкая писал(а):Может кто нибудь объяснит как изменить код что бы получить интервал 1)0-6 2)0-9
Ассемблер (ASM) для AVR в вопросах и ответах
- Сообщения: 7
- Зарегистрирован: Вс май 27, 2012 17:43:37
- Реклама
Ты не оттуда берешь случайное число, видимо. Там у тебя в непосредственной близости к выходу есть "ANDI R31,0xE0" что как бы уменьшает шансы на нормальное выделение диапазона, удивительно что оно тебе дает хоть что-то на выходе.
Бери там где у тебя на выходе имеется нормальное случайное число 0..255 хотябы.
Бери там где у тебя на выходе имеется нормальное случайное число 0..255 хотябы.
- Сообщения: 7
- Зарегистрирован: Вс май 27, 2012 17:43:37
Я очень сильно извиняюсь за свою бестолковость и надоедливость, но где найти это нормальное число на выходе???
Алгоритм сама разрабатывала? По какому принципу он работает?
Классика - это длинный сдвиговый регистр с обратными связями.
В ЭТОТ алгоритм я еще не вкурил, шибко он ээээ... непонятный и без коментариев.
Особенно важны комментарии к используемым переменным-регистрам.
Более того регистры R30 и R31 рабочие. Скопируй в конце с регистра R30 в R28 например и обрезай его тем алгоритмом что я дал. Нельзя менять значение регистров R30 и R31 это сбивает работу ГСЧ.
Классика - это длинный сдвиговый регистр с обратными связями.
В ЭТОТ алгоритм я еще не вкурил, шибко он ээээ... непонятный и без коментариев.
Особенно важны комментарии к используемым переменным-регистрам.
Более того регистры R30 и R31 рабочие. Скопируй в конце с регистра R30 в R28 например и обрезай его тем алгоритмом что я дал. Нельзя менять значение регистров R30 и R31 это сбивает работу ГСЧ.
- Сообщения: 1163
- Зарегистрирован: Ср янв 05, 2011 16:25:15
самый простой способ что бы получить интервал ...... нужно из исходного значения вычитать число на 1 большее максимального значения интервала, до тех пор, пока остаток больше вычитаемого......
- Реклама
- Сообщения: 7
- Зарегистрирован: Вс май 27, 2012 17:43:37
попробовала как вы сказали и получился диапазон от 0-7, ANDI R28, 0xE0 если ставить значение 0x0F ничего не выводит!Alexeyslav писал(а):Алгоритм сама разрабатывала? По какому принципу он работает?
Классика - это длинный сдвиговый регистр с обратными связями.
В ЭТОТ алгоритм я еще не вкурил, шибко он ээээ... непонятный и без коментариев.
Особенно важны комментарии к используемым переменным-регистрам.
Более того регистры R30 и R31 рабочие. Скопируй в конце с регистра R30 в R28 например и обрезай его тем алгоритмом что я дал. Нельзя менять значение регистров R30 и R31 это сбивает работу ГСЧ.
Код: Выделить всё
MOV R28,R30
ANDI R28, 0xE0
loop: CPI R28, 0x0A
BRLO next
; SUBI R28, 0x0A
; rjmp loop
next: SWAP R28
LSR R28
; INC R28
MOV random,R28Хорошо, а отладка что дает? какое значение находится в R30 R31 на момент начала выполнения этого кусочка алгоритма?
Чтобы что-то существенное появилось в R30 и R31 алгоритм надо прокрутить несколько раз.
И до меня только что дошло что это очень фиговый и предсказуемый ГСЧ, поэтому у тебя в первом варианте и пошла "интерференция" в виде повторяющихся чисел.
Копируй все-таки в R28 содержимое регистра R31.
и правильно будет ANDI R28, 0x0F и никак не иначе. Эта строчка должна ограничивать количество бит, чтобы зря не крутится в цикле вычитая 10. Но вообще, её можно убрать вообще. Только тогда алгоритм будет прокручивать вычитание от 0 до 25 раз чтобы результат попал в нужные рамки. Вобщем-то это самый простейший но ресурсоемкий вариант реализации функции деления чисел.
Чтобы что-то существенное появилось в R30 и R31 алгоритм надо прокрутить несколько раз.
И до меня только что дошло что это очень фиговый и предсказуемый ГСЧ, поэтому у тебя в первом варианте и пошла "интерференция" в виде повторяющихся чисел.
Копируй все-таки в R28 содержимое регистра R31.
и правильно будет ANDI R28, 0x0F и никак не иначе. Эта строчка должна ограничивать количество бит, чтобы зря не крутится в цикле вычитая 10. Но вообще, её можно убрать вообще. Только тогда алгоритм будет прокручивать вычитание от 0 до 25 раз чтобы результат попал в нужные рамки. Вобщем-то это самый простейший но ресурсоемкий вариант реализации функции деления чисел.
Оригинал линейного конгруентного генератора ПСЧ:
Код: Выделить всё
;
;X(i+1)= ( A*X(i) + B) mod 65536
;
;A= 77 (A mod 4= 1)
;B= 1 нечетное
;
;
random:
MOV R30,rnd_l ;N=X
MOV R31,rnd_h
LSL rnd_l ;*2
ROL rnd_h
LSL rnd_l ;*4
ROL rnd_h
ADD R30,rnd_l ;N=N+X*4
ADC R31,rnd_h
LSL rnd_l ;*8
ROL rnd_h
ADD R30,rnd_l ;N=N+X*8
ADC R31,rnd_h
LSL rnd_l ;*16
ROL rnd_h
LSL rnd_l ;*32
ROL rnd_h
LSL rnd_l ;*64
ROL rnd_h
ADD R30,rnd_l ;N=N+X*64 итого N= X*77
ADC R31,rnd_h
ADIW R30,1 ;N=N + 1
MOV rnd_l,R30 ;X=N
MOV rnd_h,R31
ANDI R31,0xE0 ;xxx0 0000
CPI R31,0xC0
BRCC random
; 0...5,0 0000
SWAP R31
LSR R31
INC R31 ;0000 0,1...6
MOV rnd,R31
RETDocendo discimus
Прошу помощи с обработкой данных в АЦП ATtiny13A. Решил осваивать ассемблер, но не все с ходу получается. Итак, есть устройство на данном МК. Его задача, используя АЦП, сравнивать полученные значения с пороговыми и зажигать светодиоды.
С инициализацией МК, портов, АЦП справился. Особых трудностей не возникло. После инициализации АЦП, запускаем однократное преобразование с разрешением прерывания и переводом МК в режим ADC Noise Reduction. По окончании преобразования, уходим по вектору прерывания ADCCaddr (ADC Conversion Complete) на подпрограмму считывающую значения старшего и младшего регистров АЦП
До этого момента в AVR симуляторе все проходит как и задумано.
Но дальше столкнулся с непониманием как мне сравнить эти считанные данные с пороговыми значениями, которые я посчитал заранее сам. То есть МК нужно только сравнивать с готовыми пороговыми значениями. Считать он ничего не будет сам. Нужен аналог команды If...Then...Else, но при этом надо как-то сравнивать двухбайтные числа.
Как пример, первое пороговое значение в десятичном виде равно 795 (АЦП 10 битный)
Вырвнивать результат по левому краю и переходить на 8 битный режим АЦП я не хочу. Снижается точность измерения напряжения с 0,014 В до 0,056 В. Меня это не устраивает
И вопрос №2, но он относится к вышеизложенному. Если я присвою метке значение
то можно ли потом как-то работать с этой меткой напрямую и сравнивать с преобразованным значением? Это связано просто с удобством изменения пороговых значений. Или необходимо делить на старший и младший байт?
С инициализацией МК, портов, АЦП справился. Особых трудностей не возникло. После инициализации АЦП, запускаем однократное преобразование с разрешением прерывания и переводом МК в режим ADC Noise Reduction. По окончании преобразования, уходим по вектору прерывания ADCCaddr (ADC Conversion Complete) на подпрограмму считывающую значения старшего и младшего регистров АЦП
Код: Выделить всё
adc_complete:
ldi zl, adcl ; Считываем младший байт
ldi zh, adch ; Считываем старший байт
reti ; возврат из пррыванияНо дальше столкнулся с непониманием как мне сравнить эти считанные данные с пороговыми значениями, которые я посчитал заранее сам. То есть МК нужно только сравнивать с готовыми пороговыми значениями. Считать он ничего не будет сам. Нужен аналог команды If...Then...Else, но при этом надо как-то сравнивать двухбайтные числа.
Как пример, первое пороговое значение в десятичном виде равно 795 (АЦП 10 битный)
Вырвнивать результат по левому краю и переходить на 8 битный режим АЦП я не хочу. Снижается точность измерения напряжения с 0,014 В до 0,056 В. Меня это не устраивает
И вопрос №2, но он относится к вышеизложенному. Если я присвою метке значение
Код: Выделить всё
.EQU U1 = 795"Чтобы правильно задать вопрос, нужно знать бо́льшую часть ответа." Ро́берт Ше́кли
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
- Сообщения: 1163
- Зарегистрирован: Ср янв 05, 2011 16:25:15
... так же как и однобайтные - анализируя флаги...... смотри встроенную справку по ассемблеру в AVR Studioserg_svd писал(а):но при этом надо как-то сравнивать двухбайтные числа.
serg_svd
Сравнивать двухбайтные числа просто: команда CPC (как и CP, только флаг переноса учитывает).
Ну например так:
Сравнивать двухбайтные числа просто: команда CPC (как и CP, только флаг переноса учитывает).
Ну например так:
Код: Выделить всё
.EQU my_const = 795 ; Наша константа
...
LDI R16, HIGH(my_const)
LDI R17, LOW(my_const)
CP ZH, R16
CPC ZL, R17
ляляляЯ не совсем понял где это там искать?ChipKiller писал(а): ... так же как и однобайтные - анализируя флаги...... смотри встроенную справку по ассемблеру в AVR Studio
Если можно поподробнее, я все же новичок в этом
"Чтобы правильно задать вопрос, нужно знать бо́льшую часть ответа." Ро́берт Ше́кли
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
Сравнивать числа несложно, достаточно вычесть пороговое из анализируемого и в зависимости от флагов делать то что нужно. Если результат равен нулю, после вычитания выставляется признак Z в статусе, далее можно использовать команду перехода BREQ, или лучше BRNE для перехода к следующей проверке.
Но тебе надо скорей всего проверять на условие БОЛЬШЕ или МЕНЬШЕ, используй другие признаки.
Например признак переноса C возникнет когда анализируемое число МЕНЬШЕ порога, поскольку в результате вычитания возникает заём. далее используй команды перехода BRxx в зависимости от необходимой логики.
Но тебе надо скорей всего проверять на условие БОЛЬШЕ или МЕНЬШЕ, используй другие признаки.
Например признак переноса C возникнет когда анализируемое число МЕНЬШЕ порога, поскольку в результате вычитания возникает заём. далее используй команды перехода BRxx в зависимости от необходимой логики.
Правильно и я понял ваши советы для преобразованного значения выше или равного пороговому?
Если все верно, то это лишь вершина айсберга. Далее мне нужно проверить следующие пороговые значения:
1) >=u2 AND <u1
2) >= u3 AND <u2
3) <u3
При этом u1>u2>u3. Подскажите пожалуйста как правильнее это реализовать и следует ли сразу из всех пороговых значений (констант) извлеч старший и младши байт в РАЗНЫЕ регистры (потребуется 6 регистров) Или можно сделать последовательный перебор условий и использовать при этом одни и теже 2 регистра (R17, R18)?
Код: Выделить всё
.EQU U1 = 795
..........
ldi R17, high(u1)
ldi R18, low(u1)
cp zh, R17
cpc zl, R18
brsh blue_ON1) >=u2 AND <u1
2) >= u3 AND <u2
3) <u3
При этом u1>u2>u3. Подскажите пожалуйста как правильнее это реализовать и следует ли сразу из всех пороговых значений (констант) извлеч старший и младши байт в РАЗНЫЕ регистры (потребуется 6 регистров) Или можно сделать последовательный перебор условий и использовать при этом одни и теже 2 регистра (R17, R18)?
"Чтобы правильно задать вопрос, нужно знать бо́льшую часть ответа." Ро́берт Ше́кли
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
Последовательно проверить в цикле не получится, потому что нужны будут ведь разные действия а это означает что одна и та же команда перехода в цикле должна будет отправлять по разным адресам.
Возможно, легче будет сделать подпрограмму которая бы по списку значений вернула бы результат равный номеру значения которое больше требуемого, тогда проверку можно прокрутить в цикле - как только очередное значение станет больше или равно - цикл прерывается а номер итерации будет указывать на индекс значения которое стало больше. вычитаем единицу, и получаем то что нам нужно либо изначально начинаем считать с 1 а инкремент делать после проверки.
С индексом уже можно построить проверку условий типа CASE которая использует простую проверку на НЕРАВНО.
Возможно, легче будет сделать подпрограмму которая бы по списку значений вернула бы результат равный номеру значения которое больше требуемого, тогда проверку можно прокрутить в цикле - как только очередное значение станет больше или равно - цикл прерывается а номер итерации будет указывать на индекс значения которое стало больше. вычитаем единицу, и получаем то что нам нужно либо изначально начинаем считать с 1 а инкремент делать после проверки.
С индексом уже можно построить проверку условий типа CASE которая использует простую проверку на НЕРАВНО.
- Сообщения: 5
- Зарегистрирован: Вс июн 10, 2012 17:50:32
привет всем, кто сидит в этой ветке)
у меня тупой вопрос, объясните плиз что делают эти строки
Они взяты из проекта USI-SPI для аттини, так вот реально подогнать эти строки под работу SPI атмега48?
у меня тупой вопрос, объясните плиз что делают эти строки
Код: Выделить всё
ldi r16,(1<<USIWM0)|(0<<USICS0)|(1<<USITC)
ldi r17,(1<<USIWM0)|(0<<USICS0)|(1<<USITC)|(1<<USICLK)- Сообщения: 1163
- Зарегистрирован: Ср янв 05, 2011 16:25:15
... формируют сигнал CLKgyparr писал(а):...что делают эти строкиКод: Выделить всё
ldi r16,(1<<USIWM0)|(0<<USICS0)|(1<<USITC) ldi r17,(1<<USIWM0)|(0<<USICS0)|(1<<USITC)|(1<<USICLK)
Это такой тест на внимательность форумчан?serg_svd писал(а):подпрограмму считывающую значения старшего и младшего регистров АЦПКод: Выделить всё
adc_complete: ldi zl, adcl ; Считываем младший байт ldi zh, adch ; Считываем старший байт reti ; возврат из пррывания
Ну так не прошли
Эта подпрограмма загружает константы, а не считывает порты.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
- Сообщения: 1163
- Зарегистрирован: Ср янв 05, 2011 16:25:15
... да уж - перескакивая с AVR на другие МК легко забыть про инструкции in и outavreal писал(а):Это такой тест на внимательность форумчан? Ну так не прошли
Теста никакого не было. Я пытаюсь учиться, но пока не знаю что выйдет из этого.avreal писал(а):Это такой тест на внимательность форумчан?![]()
Ну так не прошли
Эта подпрограмма загружает константы, а не считывает порты.
Команд много, в голове не все к сожалению удерживаются и тут я действительно упустил из виду команды in и out
Ну а насчет теста поясните пожалуйста мне вот такой пример
Код: Выделить всё
start:
sbic pinb, pinb0
cbi portb, pinb0
sbis pinb, pinb0
sbi portb, pinb0
rcall wait ; Пауза
rjmp startА в AVR симуляторе заметил, что после выполнения команды cbi вначале пеерключается регистр порта PORTB.0, и только на следующем такте PINB.0. И только за счет этого этот кусок кода работает, позволяя "запутать" команду sbis, которая думает, что бит в порту еще установлен.
В книге по микроконтроллерам семейста ATtiny в разделе описания портов этому я пояснения не нашел.
"Чтобы правильно задать вопрос, нужно знать бо́льшую часть ответа." Ро́берт Ше́кли
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.


