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

Atmega8:Выход с прерывания по rjmp, с последующей корректировкой указателя стека и установкой флага глоб.прерывания (sei), слишком ли грубый ход ?

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

Получается так: сел в машину, нажал кнопку, и авто завелось, при этом автомобиль мог до этого стоять на «программе прогрева», соответственно «программа прогрева» должна быть прекращена.

Появились небольшие вопросы при реализации задуманного в программе.

Программа написана на асме, весь текст приводить не буду , напишу «обычным языком» и коротко без деталей и ньансов.

Вопрос:

Слишком ли будет грубо переходит из прерывания в основную программу, установив указатель стека в начало и установив флаг гл. прерывания («sei») так как он при вызове прерывания сбрасывается?

Решил сделать так, потому что команды от кнопок будут обрабатываться мгновенно не дожидаясь выполнения подпрограмм(паузы и т.д.)

 

Существует ли альтернатива этому механизму ?

 

Вот алгоритм программы

______________________________

Иницируем таймер опроса кнопок

Разрешаем прерывания по IRQ1 для тахометра (считать импульсы, решать завелась или незавелась)

Стек в начало;

 

Основной цикл:

 

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

Мигаем диодом, авто ждет команды

Rjmp Проверка статуса кнопок

 

// в основном цикле я разместил оба процесса, прогрев и заводим с кнопки

Прогрев:

Стек в начало;

«Ldi r16,low(RAMEND)

out SPL,r16

ldi r16,high(RAMEND)

out SPH,r16»

установим флаг гл.прерывания «sei»

Пауза 1 час

Rcall ЗавестиМашину

Пауза 5 минут

глушим

Rjmp Прогрев

 

ЗаводимСКнопки:

Стек в начало; установим флаг гл.прерывания;

 

//Проверка заведена ли машина

Если машина заведена то

rjmp Проверка статуса кнопок

Иначе rcall ЗавестиМашину

rjmp Проверка статуса кнопок

Rjmp ЗаводимСКнопки

 

Rjmp Основной цикл

 

ЗавестиМашину:

Запрещаем прерывание таймера опроса кнопок

Заводим включая зажигание и включая стартер по определенному алгоритму

Разрешаем прерывание таймера опроса кнопок

Ret

 

Прерывание таймера опроса кнопок:

// если нажали кнопку завести то сразу переходим на программу завести с кнопки

// тем самым команда ret не будет никогда выполнена

// мы заменим её в основной программе возвратом указателя стека и установкой флага

// глобального прерывания?!

Если нажата кнопку 1 (завести авто)

То rjmp ЗаводимСКнопки

 

Если нажата кнопку 2 (прогрев авто по таймеру)

То rjmp Прогрев

 

Ret

Изменено пользователем DmSk

Поделиться сообщением


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

Вместо такого описания, лучше бы нарисовали алгоритм, а там, глядишь и сами бы разобрались как надо правильно сделать. Я ничего не понял из Вашего описания, но у меня создалось стойкое ощущение что у Вас что-то глобально не правильно в программе, т.е. сама концепция программы не верна. И что значит "команды от кнопок будут обрабатываться мгновенно не дожидаясь выполнения подпрограмм"?

Поделиться сообщением


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

И что значит "команды от кнопок будут обрабатываться мгновенно не дожидаясь выполнения подпрограмм"?

 

нажал на кнопку - вызвалось прерывание из прерывания я сразу перехожу в нужный мне кусок кода - конкретно "завести авто".

 

если по другому сделать, то

это например я какойнить флаг бы выставил что нужно завести машину, а в это время выполняется кусок кода "прогрев авто" и висит пауза 60 минут, где я там буду проверять что нужно выйти из прогрева и заводить авто ?

 

даже незнаю как правильно, но мой вариант тоже рабочий :laughing:

Поделиться сообщением


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

А! обычная вещь - прерывание длиной в секунду.

Во-первых, нужно оценить все временнЫе параметры события: возможная частота событий, задержка реакции на событие. Например, датчик тахометра: частота может быть большой, время реакции критично не всегда. Датчик положения коленвала для запуска зажигания - тут критично время задержки. Для кнопки время срабатывания самой кнопки несколько миллисекунд, комфортное время реакции на нажатие 0,2-0,5 секунд.

Поэтому в прерывании нужно выставить флаг "нажата кнопка", и всё! Дальше основной цикл, зацепившись за этот флаг, выяснит, что за кнопка, что делать и т.д.

У Вас "Заводим включая зажигание и включая стартер по определенному алгоритму" может занять секунд 5 легко. И что - всё это время кнопки не работают? А прервать "определённый алгоритм" никак?

Поэтому. Алгоритм имеет тактирование от таймера, который (относительно редко, в прерывании?) наращивает регистр состояния алгоритма. В основном цикле (всё время) анализируется состояние алгоритма, состояние кнопок, ещё чего-то и предпринимаются необходимые движняки. Тогда, обнаружив нажатую кнопку, можно прервать или изменить "определённый алгоритм", чтобы остановить зажигание или там перейти на другой режим. Для осознания возможных состояний и движений алгоритма рисуется граф переходов. Вершины - состояния, рёбра - переходы. Рисуем на бумажке, подписываем все вершины (регистр состояния) и рёбра (условие перехода). Всё - программирование закончено, остаётся кодирование на ассемблере.

Изменено пользователем Maik-vs

Поделиться сообщением


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

кнопки по прерыванию можно только в одном случае - если тактовая частота 32 кгц и ниже. В остальном - смысла нет

Поделиться сообщением


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

А! обычная вещь - прерывание длиной в секунду.

Во-первых, нужно оценить все временнЫе параметры события: возможная частота событий, задержка реакции на событие. Например, датчик тахометра: частота может быть большой, время реакции критично не всегда. Датчик положения коленвала для запуска зажигания - тут критично время задержки. Для кнопки время срабатывания самой кнопки несколько миллисекунд, комфортное время реакции на нажатие 0,2-0,5 секунд.

Поэтому в прерывании нужно выставить флаг "нажата кнопка", и всё! Дальше основной цикл, зацепившись за этот флаг, выяснит, что за кнопка, что делать и т.д.

У Вас "Заводим включая зажигание и включая стартер по определенному алгоритму" может занять секунд 5 легко. И что - всё это время кнопки не работают? А прервать "определённый алгоритм" никак?

Поэтому. Алгоритм имеет тактирование от таймера, который (относительно редко, в прерывании?) наращивает регистр состояния алгоритма. В основном цикле (всё время) анализируется состояние алгоритма, состояние кнопок, ещё чего-то и предпринимаются необходимые движняки. Тогда, обнаружив нажатую кнопку, можно прервать или изменить "определённый алгоритм", чтобы остановить зажигание или там перейти на другой режим. Для осознания возможных состояний и движений алгоритма рисуется граф переходов. Вершины - состояния, рёбра - переходы. Рисуем на бумажке, подписываем все вершины (регистр состояния) и рёбра (условие перехода). Всё - программирование закончено, остаётся кодирование на ассемблере.

спасибо всё понятно, если процессов много то конечно, а у меня 2 + переписывать код полностью неохото потому .

 

всё же хотелось показать свой извратный код, пишу пример находу постараюсь, чтобы было понятно:

 

main:

 

ss:

 

rjmp ss

 

zavodim:

// вернем указатель стека ПОСКОЛЬКУ ВЫШЛИ ИЗ ПРЕРЫВАНИЯ ПО RJMP а не RET и возвращаться несобираемся !

ldi r16,Low(RAMEND)

out SPL,r16

ldi r16,High(RAMEND)

out SPH,r16

sei \\ выставим флаг прерываний ПОСКОЛЬКУ ВЫШЛИ ИЗ ПРЕРЫВАНИЯ ПО RJMP а не RET

rcall zavesti //процедура завода авто

 

rjmp main

 

timer_ovr:

 

sbis PINB,3

RCALL zavodim \\ ВЫХОДИМ ИЗ ПРЕРЫВАНИЯ ПО RJMP и невозвращамся ВООБЩЕ поскольку там куда идем:) указатель стека правим и гл.флаг прерывания возвращаем!

ret

 

 

таким образом я решилэту задачу без усложния кода..

Поделиться сообщением


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

это например я какойнить флаг бы выставил что нужно завести машину, а в это время выполняется кусок кода "прогрев авто" и висит пауза 60 минут, где я там буду проверять что нужно выйти из прогрева и заводить авто ?

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

 

P.S. Надеюсь, Вы делаете проверку что передача не включена перед стартом двигателя?

P.P.S. Может стоит перейти на Си, чтобы решать задачи без усложнения кода?

Поделиться сообщением


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

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

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

 

"компенсацию дребезга" - конечно будет, поскольку я пример упростил для наглядности

 

P.S. Надеюсь, Вы делаете проверку что передача не включена перед стартом двигателя?

P.P.S. Может стоит перейти на Си, чтобы решать задачи без усложнения кода?

да "защита от дурака стоит" :)

 

Поделиться сообщением


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

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

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

Поделиться сообщением


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

main:

 

ss:

 

rjmp ss

 

zavodim:

// вернем указатель стека ПОСКОЛЬКУ ВЫШЛИ ИЗ ПРЕРЫВАНИЯ ПО RJMP а не RET и возвращаться несобираемся !

ldi r16,Low(RAMEND)

out SPL,r16

ldi r16,High(RAMEND)

out SPH,r16

sei \\ выставим флаг прерываний ПОСКОЛЬКУ ВЫШЛИ ИЗ ПРЕРЫВАНИЯ ПО RJMP а не RET

rcall zavesti //процедура завода авто

 

rjmp main

 

timer_ovr:

 

sbis PINB,3

RCALL zavodim \\ ВЫХОДИМ ИЗ ПРЕРЫВАНИЯ ПО RJMP и невозвращамся ВООБЩЕ поскольку там куда идем:) указатель стека правим и гл.флаг прерывания возвращаем!

ret

 

 

таким образом я решилэту задачу без усложния кода..

 

1: Я бы sei и инициализацию стека сделал сразу после метки main а в процедуре zavodim вообще стек не трогал.

2: Выход из прерывания timer_ovr может всетаки reti?

 

Atmega8:Выход с прерывания по rjmp, с последующей корректировкой указателя стека и установкой флага глоб.прерывания (sei), слишком ли грубый ход ?

Как по мне это абсолютно нормальный ход если это действительно необходимо.

Поделиться сообщением


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

спасибо всё понятно, если процессов много то конечно, а у меня 2 + переписывать код полностью неохото потому .

 

Если всё понято, то надо так и делать. Не "процессов много" а событий больше одного. У вас: несколько кнопок, датчик спидометра, датчик нейтральной передачи, много состояний (стадий выполнения) этих двух процессов. Прерывания нужны для отслеживания неотложных событий или очень редких, чтобы не тратить время на постоянный опрос (для контроллеров не очень актуально). Нарисуйте граф своих процессов (гуглить картинки "граф состояний", "граф переходов") - увидите, что вершин не меньше 4-6-ти. И не я один вам это говорю. Кроме того, получите заготовку программы для следующих проектов.

 

Хотя, если "неохото"... ну, купите готовое

Поделиться сообщением


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

 

2: Выход из прерывания timer_ovr может всетаки reti?

Как по мне это абсолютно нормальный ход если это действительно необходимо.

Опечатался, конечно reti, так как прерывание а не процедура

 

1: Я бы sei и инициализацию стека сделал сразу после метки main а в процедуре zavodim вообще стек не трогал.

если в процедуре флаг по sei не поднять то, прерывания не будут вообще работать, так как я из прерывания сразу шагаю по rjmp в "Заводим", а этот флаг назад выставляется по "reti", а поскольку у меня его не будут, то приходится его руками выставлять.

 

Со стеком такая же беда, нет rety, нет возврата указателя, таким образаом вызывая прерывания и не возвращаясь на место у нас стек переполнится

 

Если всё понято, то надо так и делать. Не "процессов много" а событий больше одного. У вас: несколько кнопок, датчик спидометра, датчик нейтральной передачи, много состояний (стадий выполнения) этих двух процессов. Прерывания нужны для отслеживания неотложных событий или очень редких, чтобы не тратить время на постоянный опрос (для контроллеров не очень актуально). Нарисуйте граф своих процессов (гуглить картинки "граф состояний", "граф переходов") - увидите, что вершин не меньше 4-6-ти. И не я один вам это говорю. Кроме того, получите заготовку программы для следующих проектов.

 

Хотя, если "неохото"... ну, купите готовое

 

Спасибо, можете дать ссылку в инете на какойнить шаблон/пример программы, чтобы не совсем с нуля писать ?

 

Поделиться сообщением


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

если в процедуре флаг по sei не поднять то, прерывания не будут вообще работать, так как я из прерывания сразу шагаю по rjmp в "Заводим", а этот флаг назад выставляется по "reti", а поскольку у меня его не будут, то приходится его руками выставлять.

 

Со стеком такая же беда, нет rety, нет возврата указателя, таким образаом вызывая прерывания и не возвращаясь на место у нас стек переполнится

Ну тогда правильно! А я подумал что прерывание всего одно.

И еще: а не нужно ли в таком случае запрещать прерывание timer_ovr? Чтоб избежать повторного входа!

 

 

Поделиться сообщением


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

Ну тогда правильно! А я подумал что прерывание всего одно.

И еще: а не нужно ли в таком случае запрещать прерывание timer_ovr? Чтоб избежать повторного входа!

 

а я в прерывании буду смотреть статус процесса (какой процесс выполняется),

если нажали кнопку "завести" и статус процесса сейчас"завести", то тогда нормально по reti возвращаемся ничего не сделав никуда не шагнув,

если нажалии кнопку "прогрев по таймеру", а статус процесса "заводим" - то rjmp(переходим) на процесс "прогрев по таймеру" ,

, естественно если в это время крутили стартер, то всё отрубаем,

таким образом можно играться кнопками до бесконечности, время реакции системы 4 такта !

дребезг по таакому алгоритму обрабатывать ненужно ?

 

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

Спасибо, придется изучать професиональное програмирование :)

Поделиться сообщением


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

дребезг по таакому алгоритму обрабатывать ненужно ?

Применительно к вашему алгоритму трудно сказать необходимо ли антидребезгом заниматься.

Но я в своих изделиях обязательно устраняю дребезг во избежание ложных срабатываний (отсекаю заведомо короткие импульсы).

Например от электрошокера или пьезоэлементов.

 

Поделиться сообщением


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

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

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

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

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

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

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

×
×
  • Создать...