Перейти к содержанию

Помогите с ассемблер AVR


Рекомендуемые сообщения

Приветствую всех! Помогите написать программу на ассемблере, генератор прямоугольных импульсов, нужно чтобы была кнопка и при каждом нажатии частота увеличивалось, от 1 до 10 гц, скважность 50%. Имею в наличии Attiny2313a и Attiny13.

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

7 часов назад, Alex сказал:

На чём застряли ?

Начал изучать микроконтроллеры и ассемблер, в принципе мне кажется мигание светодиодом нужной частотой и есть генератор импульсов, но вот хотел увидеть пример как можно кнопкой поменять частоту мигания, в книгах которые я читаю нет примеров такого и инете не нашел такого, хотелось бы узнать как происходить изменение частоты кнопкой, делается это прерыванием и еще как.

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

{

delay_ms(N);

PORTx.y= 1;

delay_ms(N);

PORTx.y= 0;

}

Это на С. Меняйте N кнопкой и будет то, что нужно. Ну и, само собой, перевести на асм.

N от 50 до 500 мс.

Я не раздаю удочки. Я продаю рыбу.

Ссылка на комментарий
Поделиться на другие сайты

1 час назад, солар сказал:

PORTx.y= 1;

Вот это - плохая идея. Использование "расширения" cvavr делает программу непереносимой на другие компиляторы и не дает никаких преимуществ. На Си можно записать короче:

PORTx ^= (1<<y);
for(i=0;i<N;i++)_delay_ms(10); //функция _delay_ms() не умеет принимать переменную

 

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Так напиши на ассемблере процедуру задержки с переменной длительностью, а дальше уже по накатанной... обработка кнопок, "+" "-" и т.д.

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

п.с. а может, лучше задействовать ШИМ с переменным периодом? У таймеров есть режимы работы для генерации меандра на пине, останется только программой период устанавливать.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

5 часов назад, COKPOWEHEU сказал:

делает программу непереносимой на другие компиляторы

Ах беда бедная.

Я не раздаю удочки. Я продаю рыбу.

Ссылка на комментарий
Поделиться на другие сайты

21 минуту назад, salova322 сказал:

обратно становится 1Гц?

Да. Не принципиально ровно 1 или 10, смысл в переключении между двумя вариантами от одной кнопки.

Ссылка на комментарий
Поделиться на другие сайты

7 минут назад, AdamBeno сказал:

Да. Не принципиально ровно 1 или 10, смысл в переключении между двумя вариантами от одной кнопки.

Просто по прерыванию инкрементируй регистр. с 0 до 9 допустим. Если число в регистре 10 - сбрасывай в 0. и в зависимости от значения этого регистра в таймере будет выбираться предделитель и начало отсчета. 

Ссылка на комментарий
Поделиться на другие сайты

4 часа назад, salova322 сказал:

Просто по прерыванию

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

Ссылка на комментарий
Поделиться на другие сайты

19 часов назад, AdamBeno сказал:

Ничего не понял из этого

инкремент - прибавить единицу. 

что конкретно не понятно? с регистрами работал? с таймером? с прерываниями?

Ссылка на комментарий
Поделиться на другие сайты

1 минуту назад, salova322 сказал:

что конкретно не понятно?

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

Ссылка на комментарий
Поделиться на другие сайты

2 часа назад, AdamBeno сказал:

хотелось бы посмотреть какой нибудь пример или шаблон как вызвать прерывание с кнопки. 

Возьмем за пример Attiny13. Для того, чтобы срабатывало прерывание по кнопке, тебе необходимо понять к какой линии нужно подключить кнопку. В данном случае выбираем линию PB1(INT0). Далее необходимо настроить регистры прерывания. Разрешаем прерывания по INT0:

ldi r17,0b01000000
out GIMSK,r17

Далее задаем, что прерывание будет срабатывать по спаду:

ldi r17,0b00000010
out MCUCR,r17

И разрешаем глобально прерывания одной командой:

sei 

В начале программы необходимо указать метку на основную программу и метку на прерывание с указанием вектора, соответствующему данному прерываню:

.org 0x00
rjmp main

.org 0x01
rjmp interrupt

Программа будет начинать выполняться с метки main:, а прерывание с метки interrupt: (название меток произвольное) для выхода из прерывания используется команда reti.

 

Изменено пользователем salova322
Ссылка на комментарий
Поделиться на другие сайты

33 минуты назад, salova322 сказал:

Возьмем за пример Attiny13.

...необходимо понять к какой линии нужно подключить кнопку...

Для Attiny13 нет необходимости "понять", нужно просто "решить" к какой линии подключать кнопку, т.к. в этом камне есть прерывание "Pin Change Interrupt Request 0", возникающее по изменению состояния линий порта.

Ссылка на комментарий
Поделиться на другие сайты

Проблема в том что Pin Change Interrupt не различает фронт и спад, срабатывает на оба. И вообще, начинать обработку кнопок через прерывания это как-то слишком для начала - слишком много граблей расставлено на этом пути. Если так сделать без специальных мер противодействия дребезгу контактов ваша программа будет работать скорей генератором случайных чисел чем переключателем частоты по кнопке.

Знакомство с кнопкой лучше всего начинать с простого опроса в цикле с периодом в 20мс - это убережёт от дребезга. Можете потом поэксперементировать, уменьшая период опроса(повышая частоту опроса) на каком значении начнутся "проблемы" с кнопкой - это довольно познавательно.

Да, считать кнопку в цикле это ещё половина дела, надо ведь определить момент нажатия...

Для этого считываем порт(команда IN R1, PINx) на котором висит кнопка, обнуляем все его биты которые НЕ ИМЕЮТ отношения к кнопке простой операцией AND со значением с "1" в том бите(выражение 1<<n где n - номер бита порта с кнопкой) где висит кнопка. и сравниваем его с заранее сохраненным предыдущим значением... командой XOR. Если было изменение - в соответствующем бите будет лог.1, смотрим на считанное в начале цикла значение и решаем какое именно это было изменение нажатие или отпускание и выполняем нужное действие.

Для условных переходов по отдельным битам регистров можно использовать команды SBRC/SBRS либо арифметику и переход по BRxx. Удобно использовать переход по BREQ после операции XOR в конец цикла, когда ни одна кнопка не нажата и в результате будет 0 в регистре.

В конце цикла копируем сохранённое в начале состояние кнопки в регистр с "предыдущим" таким образом подготовив предыдущее значение к следующей итерации.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

6 часов назад, Alexeyslav сказал:

Проблема в том что Pin Change Interrupt не различает фронт и спад, срабатывает на оба.

Я бы не стал называть это проблемой.

При грамотном подходе, такой режим можно использовать в качестве защиты от дребезга.

Ссылка на комментарий
Поделиться на другие сайты

@Alexeyslav @Геннадий Уважаемые знатоки, вот пример того, до чего я дошел, но теперь я хотел бы знать как вызвать прерывание кнопкой, к примеру подключенной  PB3, как первоначально сделать чтобы программа ушла в прерывание по соответствующему вектору. Если это не сложно вставьте  в этот код вызов прерывание PB3, чтобы изменить константу в подпрограмме задержки wait. Или я не правильно мыслю?

.include "tn2313adef.inc"    ; Присоединение файла описаний
.list                        ; Включение листинга

;------------------------- Начало программного кода

.cseg                 ; Выбор сегмента программного кода
.org    0            ; Устанеовка текущего адреса на ноль

.def    temp = r16    ; Определение главного рабочего регистра
.def    loop = r17    ; Определение регистра организации цикла


;-------------------------- Инициализация стека
    
        ldi        temp, 0x7F    ; Выбор адреса вершины стека 
        out        SPL, temp    ; Запись его в регистр стека

;-------------------------- Инициализация Главного предделителя

        ldi        temp, 0x80  ; Записываем число $80 в регистр temp
        out        CLKPR, temp    ; Записываем в регистр CLKPR
        ldi        temp, 0        ; Записываем 0 в регистр temp
        out        CLKPR, temp    ; Записываем этот ноль в CLKPR

;-------------------------- Инициализация портов ВВ
    
        out        DDRD, temp    ; Записываем этот ноль в DDRD (порт PD на ввод)

        ldi        temp, 0xFF    ; Записываем число $FF в регистр temp
        out        DDRB, temp    ; Записываем это число в DDRB (порт PB на вывод)
        out        PORTB, temp    ; Записываем то же число в PORTB (потушить светодиод)
        out        PORTD, temp    ; Записываем его же в PORTD (включаем внутр. резисторы)

;--------------------------- Инициализация компаратора

        ldi     temp, 0x80        ; Выключение компаратора
        out        ACSR, temp

;-------------------------- Начало основного цикла
main:
        in        temp, PIND    ; Читаем содержимое порта PD
        sbrc    temp, 0        ; Проверка младшего разряда
        rjmp    main        ; Если не ноль, переходим в начало
        rcall    wait        ; Вызов подпрограммы задержки

;-------------------------------- Переключение светодиода

        in        temp, PINB    ; Читаем содержимое порта PB
        sbrc    temp, 0        ; Проверка младшего разряда
        rjmp    m1
        sbi        PORTB, 0    ; Установка выход PB0 в единицу
        rjmp    m2
m1:        cbi        PORTB, 0    ; Сброс PB0 в ноль

;-------------------------------- Цикл ожидания отпускания кнопки
m2:        in        temp, PIND    ; Читаем содержимое порта PD
        sbrs    temp, 0        ; Проверка младшего разряда
        rjmp    m2            ; Продолжить ожидание отпускания кнопки

        rcall    wait        ; Вызов подпрограммы задержки
        rjmp    main        ; К началу цикла


;--------------------------------- Подпрограмма задержки

wait:    push    loop        ; Сохраняем содержимое регистра loop
        ldi        loop, 200    ; Помещаем в loop константу задержки
                            ; Цикл задержки
wt1:    dec        loop        ; Уменьшаем значение регистра loop
        brne    wt1            ; Если не ноль, продолжаем цикл

        pop        loop        ; Восстанавливаем значение регистра loop
        ret                    ; Выход из подпрограммы
 

Flash led.asm

Ссылка на комментарий
Поделиться на другие сайты

На выводе PB3 "висит" прерывание PCINT3. Для его разрешения нужно записать маску в регистр PCMSK

ldi r16,(PCINT3<<1) или ldi r16,0b00001000

out PCMSK,r16

Следующим шагом будет разрешение прерывания Pin Change Interrupt. Установим бит PCIE в регистре GIMSK.

ldi r16,0b00100000

out GIMSK,r16

И последнее - разрешим прерывания.

sei

Ссылка на комментарий
Поделиться на другие сайты

1 час назад, AdamBeno сказал:

как первоначально сделать чтобы программа ушла в прерывание по соответствующему вектору.

.org 0  обозначает адрес памяти где будут располагаться последующие инструкции программы во флэш.

надо написать так:

.def    temp = r16    ; Определение главного рабочего регистра
.def    loop = r17    ; Определение регистра организации цикла

.org    0            ; Установка текущего адреса на ноль

rjmp reset; он же interruptVector0 - нулевой адрес флэш - это откуда начинается выполнение прг после включения или сброса

rjmp interruptVector1; это куда переходит прг после прерывания "тип1" - смотри таблицу в ПДФ на процессор!

rjmp interruptVector2; это куда переходит прг после прерывания "тип2" - смотри таблицу в ПДФ на процессор!

...

;-------------------------- Инициализация стека и вход в основную программу

reset:
        ldi        temp, 0x7F    ; Выбор адреса вершины стека 

...

 

таблица в ПДФ на процессор! например:

10.2. Interrupt Vectors
Interrupt vectors are described in the table below.

в ПДФ Atmel-8127-AVR-8-bit-Microcontroller-ATtiny4-ATtiny5-ATtiny9-ATtiny10_Datasheet.pdf:

8-bit AVR Microcontroller
ATtiny4 / ATtiny5 / ATtiny9 / ATtiny10
DATASHEET COMPLETE

Можно сделать все! Но чем больше можно, тем больше нельзя!

Ссылка на комментарий
Поделиться на другие сайты

4 часа назад, AdamBeno сказал:

@Геннадий Это нужно писать до начала основного цикла?

Да. В модуле инициализации периферии. И, как правильно заметил ruhi, в таблице прерываний указать переход на обработчик.

Ссылка на комментарий
Поделиться на другие сайты

11 час назад, AdamBeno сказал:

как первоначально сделать чтобы программа ушла в прерывание по соответствующему вектору.

омг, я тебе все объяснил, а ты ничего не понял...

1-10.asm

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы публикуете как гость. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...