реклама на сайте
подробности

 
 
> volatile
_Артём_
сообщение Mar 26 2007, 23:30
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Пример:
Код
volatile unsigned char CntB;
volatile unsigned long CntL;
__interrupt void VeryFastInterrupt(void)
{
    if (SomeConditon) {
        // накопление некоторого счётчика в байт
        CntB++;
    }
}

__interrupt void SlowInterrupt(void)
{
    enable_interrupt();
    // добавление байтового счётчика CntB к CntL
    // и обнуление CntL
    if (CntB) {
        CntL+=CntB;
        CntB=0;
    }
}


В быстром прерывании по некому событию инкрементируется байт, в медленном прерывании
накопленное в CntB значение добавляется к CntL и обнуляется CntB. Если в момент перед обнулением
CntB произойдёт прерывание VeryFastInterrupt, то значение CntB (если произойдёт инкремент) будет потеряно.
Правильно ли я понимаю, что объявление переменной CntB, как volatile не исключит потерю значения?
Может помочь только запрет прерываний? Например так:
Код
    if (CntB) {
        disable_interrupt();
        CntL+=CntB;
        CntB=0;
        enable_interrupt();
    }
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 1)
rezident
сообщение Mar 27 2007, 00:20
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Да, правильно понимаете. Если вам так важно не пропустить инкремент, то либо запрещайте прерывание перед операцией, либо используйте другой механизм, не требующий обнуления CntB. Например, плюсуйте к CntL не абсолютное значение CntB, а приращение его между двумя вызовами SlowInterrupt. Правда для этого нужна еще одна статическая переменная, которая может быть локальной для SlowInterrupt.
Код
__interrupt void SlowInterrupt(void)
{  static unsigned char tmpCntB=0;
    enable_interrupt();
    // добавление байтового счётчика CntB к CntL
    // без обнуления CntB
    unsigned char tmp=CntB;
    CntL+=tmp-tmpCntB;
        if (tmp==CntB) tmpCntB=tmp;
        else tmpCntB=CntB;
}

Естественно период вызова SlowInterrupt должен быть заведомо меньше, чем время за которое возможно переполнение переменной CntB.
P.S. кстати, поскольку у вас и CntL и CntB определены как volatile, то IAR должен был бы выдать предупреждение насчет такой вот конструкции
Код
CntL+=CntB;

чтобы избежать этого я в своем примере ввел промежуточную локальную переменную tmp, которую компилятор наверняка соптимизирует, поместив ее в регистр.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 18:08
Рейтинг@Mail.ru


Страница сгенерированна за 0.01332 секунд с 7
ELECTRONIX ©2004-2016