Jump to content

    
Sign in to follow this  
SergeyVas

суммирование в прерывании

Recommended Posts

Требуется в программе обработки прерывания от пина по фронту прибавлять 1 к переменной до тех пор пока не будет 255.  Прерывании возникает с частотой несколько десятков кгц.  сейчас такой код :

if(interruptcounter <254) interruptcounter++;

Из за проверки переменной есть ветвление, а без проверки счет иногда перескакивает через ноль. Есть способ выполнить быстрее эту операцию?

Share this post


Link to post
Share on other sites
9 минут назад, SergeyVas сказал:

Требуется в программе обработки прерывания от пина по фронту прибавлять 1 к переменной до тех пор пока не будет 255.  Прерывании возникает с частотой несколько десятков кгц.  сейчас такой код :


if(interruptcounter <254) interruptcounter++;

Из за проверки переменной есть ветвление, а без проверки счет иногда перескакивает через ноль. Есть способ выполнить быстрее эту операцию?

Какая задача решается? Зачем этот счёт? Почему не используется какой нибудь аппаратный счётчик для этих целей? Зачем ручной счёт?

Share this post


Link to post
Share on other sites

Нужно в основном цикле программы обнулять переменную 

 interruptcounter

и через некоторое время (зависит от событий ) считывать значение переменной 

 interruptcounter

и отсылать через spi.  переменная должна увеличиваться с каждым прерыванием на 1 до 255. 

Ветвление время забирает думал может можно как то сделать битовыми операциями или может есть способы сделать это быстрее.  

__interrupt pbisr(void)
{
  ....
    if(interruptcounter <254) interruptcounter++;
    .....
  
}

 архитектура st7/

Схема уже собрана к этим портам не подключен аппаратный счетчик

Share this post


Link to post
Share on other sites

В ассемблерный листинг вы заглядывали? Почему не сравниваете с 255?

В прерывании еще что-то делается. Может, там экономить такты?

Share this post


Link to post
Share on other sites

Да там проверка перед инкрементом переменной через ветвление. Поменяю 254 на 255. просто в процессе отладки что бы быть уверенным что переменная не перескакивает через ноль сделал на один меньше. 

Share this post


Link to post
Share on other sites
57 минут назад, SergeyVas сказал:

Из за проверки переменной есть ветвление, а без проверки счет иногда перескакивает через ноль. Есть способ выполнить быстрее эту операцию?

Откуда идея про скорость? Перескакивание через ноль говорит о том что прерывание отрабатывает отлично. А вот программа которая вычитывает не успевает обрабатывать с той же скоростью. Т.е. основная программа видит например 254 потом приходит два прерывания и программа при очередном опросе видит уже 0. Т.е. вопрос уже скорее в обработке а не в прерывании.
По хорошему надо бы счётчик сделать более длинным а в основной программе проверять больше ли число 255 и если больше то отнимать 255 и считать дальше.

Опять же задача так и осталась не пояснённой. Ибо текущий костыль останавливает счёт. И дальше идёт потеря тактов. Если это допустимо то может и проблемы нет. 

Что является проблемой ради которой нужно поднять скорость ещё больше?

Share this post


Link to post
Share on other sites

Основной цикл программы по времени не стабильный, опрос ацп датчиков, интерфейс и другие действия. Иногда нужно послать импульс и подсчитать количество прерываний на входе. то что будут пропуски не страшно, хуже когда в счетчике будет например 5 а на самом деле было 260 импульсов. Сильно расходует время два прерывания на двух портах частота  от 30 до 50кгц фаза независима обоих сигналов. микроконтроллер не высокой производительности. хотелось как можно быстрее выполнить эту процедуру. Что бы выделить больше времени на другие операции в основном цикле.

Share this post


Link to post
Share on other sites

Без ветвления можно сделать так

volatile u8 cnt;

ISR()
{
  s16 i = (s16)(cnt - (u16)255) >> 15;
  cnt   = cnt - i;
}

Однако сначала надо проверить, что сдвиг вправо отрицательного числа компилятор делает арифметическим сдвигом (т.е. сохраняя знак).
Иначе конструкция не будет работать, т.к. вообще говоря, сдвиг отрицательного вправо, как гласит Стандарт Си, это implementation-defined behavior.

Но, ИМХО, на этой архитектуре этот код будет проигрывать обычному ветвлению типа if(cnt < 255) ++cnt.

Share this post


Link to post
Share on other sites

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

Также стоит помнить, что interruptcounter - volatile-переменная, а значит в прерывании надо завести ее локальную копию, чтобы компилятор не лазал в каждой операции за ней в память.

Share this post


Link to post
Share on other sites
1 час назад, SergeyVas сказал:

Из за проверки переменной есть ветвление, а без проверки счет иногда перескакивает через ноль. Есть способ выполнить быстрее эту операцию?

interruptcounter = __USAT(interruptcounter + 1, 8);

Скомпилится всего в 4 команды (вместе с чтение/записью в память) и без ветвления.

Или:

uint i = interruptcounter + 1;
interruptcounter = i - (i >> 8);

те же 4 команды.

 

57 минут назад, SergeyVas сказал:

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

:biggrin::biggrin::biggrin:

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this