Atmega8 LTO (перенос кода с ардуино)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

BOOM пишет:

Komandir пишет:

В озу стек может наехать на данные. С флешем то никаких записей не производится !!!

То есть и 1 байт свободного места во флеше - это нормально?

И ноль - тоже нормально. Флешь во время исполнения ваще не изменяется от слова "никак".

Более того, некоторые считают, что оставлять память без дела - безобразие, т.к. добро пропадает. Например, тот парень, который, согласно легенде, решил запихнуть в оставшиеся свободным пару сотен байтов компьютера космического зонда "Вояджер" программу распознавания образов, чтобы добро не пропадало. Эта программа в полёте смогла открыть неизвестный ранее спутник Юпитера.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

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

Спасибо всем!

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

BOOM пишет:

Деда, как? Опять? Ты ж завизалл?!...

Код подобрал. 

Кот адабряе.

Green
Offline
Зарегистрирован: 01.10.2015

Конечно адабряе. Коту лишь бы пожрать чё было.)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

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

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А сколько (максимально) я могу "находиться" в прерывании по таймеру (по времени)?

Или как это вычислить, если точно не известно?

Kakmyc
Offline
Зарегистрирован: 15.01.2018

BOOM пишет:

А сколько (максимально) я могу "находиться" в прерывании по таймеру (по времени)?

Да хоть всю жисть, лишь бы это критически не влияло на саму программу.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Ну вот так можно?

Прерывание каждые 60 миллисекунд, в ISR() я отключаю прерывания (cli()) читаю пины, если мое условие выполняется, то включаю (или выключаю) пины с интервалом 200мс (dalay(200)). Перед выходом из прерывания включаю прерывания (sei()).

Я как-то давно пробовал всю логику программы в прерывание уложить - не получилось. Более грамотные товарищи сказали, что долго в прерывании находиться нельзя. А вот на сколько долго - не уточнили )))

Kakmyc
Offline
Зарегистрирован: 15.01.2018

BOOM пишет:

то включаю (или выключаю) пины с интервалом 200мс (dalay(200)).

delay() не работает в прерывании.

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

Green
Offline
Зарегистрирован: 01.10.2015

Совсем детские вопросы.) И cli() в ISR за тебя уже делает железо AVR.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Детские не детские - "ромашка устроиль" )))

Kakmyc пишет:
Для развернутого ответа на вопрос, нужно знать что происходит во время свободное от прерываний.

Если никак именно в самом прерывании не получается, то просто флаги буду тогда выставлять и в loop'е уже выполнять (куда деваться)...

 

Green
Offline
Зарегистрирован: 01.10.2015

Что именно не получается в прерывании?

Green
Offline
Зарегистрирован: 01.10.2015

А dalay() может быть таким:

#define dalay _delay_ms

Тогда и cli() не будет мешать.)

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Если долго находиться в прерывании, то прерывание, на котором живет millis не отработает и время станет не корректным. Интервал вызова системных прерываний достаточно большой.

Я все равно не представляю с какой целью долго сидеть в прерывании.

В конце концов внутри прерывания можно РАЗРЕШИТЬ прерывания, но надо быть уверенным что это не вызовет рекурсию вашего прерывания с завалом стека !

Green
Offline
Зарегистрирован: 01.10.2015

Komandir пишет:

Я все равно не представляю с какой целью долго сидеть в прерывании.


"Ну во первых, это красиво." Ну хочется человеку! А если сильно хочется, почему бы и нет.
Не используй системные функции связанные с прерываниями, и сиди скоко хош.) И всё будет ОК.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Green пишет:

"Ну во первых, это красиво." Ну хочется человеку! А если сильно хочется, почему бы и нет.
Не используй системные функции связанные с прерываниями, и сиди скоко хош.) И всё будет ОК.

Для этого я критичные скетчи пишу не в концепции setup loop, а в концепции main ...

Green
Offline
Зарегистрирован: 01.10.2015

Не обязательно. Можно и критичные писать в этой концепции:
 

int main() {
  setup();
  while (true)
    loop();
}

Я без этой концепции пишу только тогда, когда глубины стека не хватает (в некоторых МК).)
PS. Ещё бывает, когда не хочется глобальные переменные иметь, общие для setup и loop. Но это извращения.)

Green
Offline
Зарегистрирован: 01.10.2015

BOOM, ты бы спросил чего хотелось бы (задача?) - другие ответили бы, в меру своего понимания, а ты бы выбрал на свой вкус. Не?
Ну и многим (думаю) не лень было бы объяснить почему именно так, а не эдак. Глядишь и подучился бы. И/или других подучил.) Ибо, совместно учатся все - кто то больше, кто то меньше.)
Или это до следующего утра?)

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Green пишет:

BOOM, ты бы спросил чего хотелось бы (задача?)

Задача (в идеале) такая: Если  в прерывании выполнилось условие, то НЕ давая продолжить работу программе дальше, выполнить действие:

digitalWrite(PIN_N, LOW); 
delay(200);
digitalWrite(PIN_N, HIGH); 

Само прерывание вызывается каждые 60мс.

А безусловный переход (типа goto) из прерывания в определенное место программы возможен? Просто с флагами в прерывании я ведь вернусь в то место программы откуда и ушел в прерывание...

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Можно точку возврата в стеке подменить.

Green
Offline
Зарегистрирован: 01.10.2015

Ну, как у тебя получится 200 мс в прерывании, когда оно вызывается каждые 60мс?
Тогда при 200 мс задержке в прерывании, ты опять влетишь в очередное прерывание, которое пропустил за эти 200 мс.
И, как тебе уже сказали, delay(200) тоже использует прерывание, а тогда оно (в твоём прерывании) выполняться не будет!
Если хочешь использовать задержки, то используй _delay_ms - они будут работать в твоём прерывании.

Green
Offline
Зарегистрирован: 01.10.2015

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

Green
Offline
Зарегистрирован: 01.10.2015

Ну, то есть, если хочется задержки, то:

digitalWrite(PIN_N, LOW); 
_delay_ms(200);
digitalWrite(PIN_N, HIGH); 

Ну, или оформи delay для красивости через define.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Если прерывание вызывается безусловно, раз в 60мс, то очень быстро закончицца стек. 

Green
Offline
Зарегистрирован: 01.10.2015

Ну, это как посмотреть.)
- прерывание, чего то делаем 200 мс, похуй прерывания!
- прерывание, опять чего то делаем, и похуй что мы пропустили до этого кучу прерываний с 60 мс периодом!
Или нет?

Green
Offline
Зарегистрирован: 01.10.2015

Объясняю. Ты чего то делаешь, возникает прерывание. Я (МК) обрабатываю прерывание. Всё. С этого момента никаких прерываний быть не может! Они запрещены аппаратно. Ну а дальше всё зависит от тебя. Как быстро ты его (прерывание) обработаешь, разрешишь ли при этом обработку других (дополнительных) прерываних и т.п.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

BOOM пишет:

А безусловный переход (типа goto) из прерывания в определенное место программы возможен? 

Возможен, я даже примеры тут выкладывал, но это такое говнокодище! Собственно и пример был именно как пример говнокода.

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

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Заведи флаг сигнализирующий о том что ты уже в прерывании. Проверяй его на входе в прерывание и если ты уже в нем, то сразу на выход.... Взводи этот флаг до delay и разрешай прерывания. Снимай флаг после delay.

То что приходится рожать костыли говорит о том что ты не там ищешь ...

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Собственно говоря мне нужно сделать завершение программы вообще после выполнения условия в прерывании. То есть я в прерывании увидел выполнение условия, сделал «ногодрыг» для внешнего устройства и дальше нужно завершить программу вообще - уйти в бесконечный цикл. Это в идеале. То есть - вернуться из прерывания, продолжить программу (но уже ногодрыгнув) приемлемо (чтобы запустить по флагу бесконечный цикл и оповестить меня светодиодном о проблеме).
Вариант Green с _delay_ms надо попробовать.
Не умею я красиво писать - стал бы писателем)) Лучше спросите что я криво изложил (конечно же кто захочет это сделать)...

nik182
Offline
Зарегистрирован: 04.05.2015

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

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

всё таки ты хочешь странного  )))

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

nik182 пишет:
Ну а кто тебе мешает включить светодиод и уйти в бесконечный цикл в прерывании?

Я не знал, что можно уйти в бесконечный цикл в прерывании (выше писал почему)... ))

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

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Видимо так и не осилил даташит ни на английском ни на русском :-((

nik182
Offline
Зарегистрирован: 04.05.2015

BOOM пишет:

nik182 пишет:
Ну а кто тебе мешает включить светодиод и уйти в бесконечный цикл в прерывании?

Я не знал, что можно уйти в бесконечный цикл в прерывании (выше писал почему)... ))

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

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

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

А просто цикл запустить для нужной задержки без delay разных - это моветон ???

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

BOOM пишет:

Собственно говоря мне нужно сделать завершение программы вообще после выполнения условия в прерывании. То есть я в прерывании увидел выполнение условия, сделал «ногодрыг» для внешнего устройства и дальше нужно завершить программу вообще - уйти в бесконечный цикл. Это в идеале. 

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

cli();
while(true);

// Или, если хотите с блэкджеком и девочками, то вот так
for(cli(); true;);

Всё. Какие проблемы?

Можно не делать цикла, а уйти в сон в режиме POWER_DOWN, чтобы батарейку не жрать, кстати.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Что-то с утра туплю....

На дисплее LCD1602 вижу "62d!". Как преобразовать символы "62d!" в число uint8_t ? "62d!" получаю при таком выводе:

lcd.print((uint8_t)address);

Это вывод I2C сканера, только не в Serial (у меня его нет), а на дисплей 1602.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

char ch[] = "62d";

int val = (ch[0] - '0')*10 + (ch[1] - '0');

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

andriano пишет:

char ch[] = "62d";

int val = (ch[0] - '0')*10 + (ch[1] - '0');

Выводит просто 62. Это 0x3E в HEX, устройство по такому адресу не отзывается.

Я вот что подумал, может сначала преобразовать uint8_t в строку, а потом вывести на экран? Правда с itoa ничего не получилось ((

Если честно, я вообще не понимаю почему такой странный вывод "62d!"? Это же больше одного байта, да и вообще LCD.print() должен без проблем целые числа печатать...

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Ну и кусок кода I2C-сканера приведу (где правил под LCD):

    nDevices = 0;
    for(address = 8; address < 127; address++ ){
        Wire.beginTransmission(address);
        error = Wire.endTransmission();
 
        if (error == 0){
            lcd.setCursor(0, 0);
            lcd.print("Found: ");
            lcd.setCursor(0, 1);
            lcd.print("DEC = ");
            lcd.print(address);
/*
            char ch[] = "62d!";
            int val = (ch[0] - '0')*10 + (ch[1] - '0');
            lcd.print((uint8_t)(val));
*/ 
            nDevices++;
        }
    }
    delay (5000);

 

Green
Offline
Зарегистрирован: 01.10.2015

Экран очищай перед выводом, или добавляй пробелы после.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Green пишет:

Экран очищай перед выводом, или добавляй пробелы после.

Ой как стыдно.... Ты прав, долбаный "Hello World!" ))))

Короче адрес сканером определяется как 62 (в DEC), в HEX это = 0x3E. Значит все правильно. Буду дальше ковырять чего нет ответа с правильным адресом....

Green
Offline
Зарегистрирован: 01.10.2015

Ерунда. Бывает и не такое. Сразу всё не учтёшь.