Форум Микро-Чип
Поиск и заказ электронных компонентов
 

Вернуться   Форум Микро-Чип > Вопросы начинающих

Вопросы начинающих Прежде чем задать вопрос, стоит воспользоваться поиском

Ответ
 
Опции темы Опции просмотра
Старый 05.12.2016, 10:16   #1
reg33
Member
 
Регистрация: 11.11.2012
Возраст: 35
Сообщений: 57
Вес репутации: 85/0
reg33 will become famous soon enough
По умолчанию Не работают прерывания PORTB pic16F877a

Доброго времени суток!

Я новичок в програмировании и решил организовать обработку кнопки порта PORTB. Но при установки пина RBIE=1 в регистре INTCON в итоге в PROTEUS программа зацыкливается в обработке прерывания. Непойму что я делаю не так. Для проверки работоспособности прерывания реализовал прерывания по переполнению TMR0. Листинг кода прилагаю

PHP код:
configpic()
ADCON0=0b11000001;// PS0-1 модуль АЦП включен/биты 7 и 6 (PS7/6)--11 внутрений RC генератор PS5-PS3>>000 AN0 нулевой пин                   
 
ADCON1=0b10001110//
 
OPTION_REG=0b11000001//коэфф деления 1:4 таймер срабатывает через 1024мс (PS0-PS2)/ PS7-поддягивающие рез.включены /PS6-прерывание по переднему фронту
 
INTCON=0b10101000//  GIE=1  >>    PS7-прерывания разрешены
                    //
                    // T0IF=1  >>    PS5-прерывания от таймера TMR 0
                    // RBIE=1  >>    PS3-перрывания от портов  RB4, RB5, RB6 и RB7
 
TRISA=0b11111111;
 
TRISB=0b00110000;
 
TRISC=0b00000000;
 
TRISD=0b00000000;
 } 

и непосредственно сама функция перывания

PHP код:
 void interrupt isr(void)// прерывание по нажатию кнопки примерно 1024 мкС
{
    if(
T0IF){    //    Обрабатываем прерывания по таймеру понял что прерывания по таймеру
            
T0IF=0// сбрасываю флаг прерывания
            
RTC++;
               
// инкремент

             
if (RA4==0)      //кнопка нажата?
                       
{
                       if(
ButtonPress<20)  // кнопка нажата примерно 20 mS    надо прикинуть правильный интервал
                        
ButtonPress++;
                       }
                 else  if(
ButtonPress!=0)  // кнопка отжата делаем антидребезг при отпускании кнопки плюс инкремент ALG
                     
{  ButtonPress--;
                         if ((
RA4!=0)&&(ButtonPress==0))
                         {
                          
ALG++;
                           if (
ALG==3)// если кнопка нажата 3 раза то обнуляемся
                            
{ALG=0;}
              }
                }


        }
// конец обработки прерываний по прерыванию таймеру
                 

        
        
if(RBIF)
        {  
// Обрабатываем прерывания на входах PORTB< 4:7>
           
if(RB4==)
            { 
RC7=RC7^1;
              
RBIF=0//  сбрасываем флаг
            
}          // конец обработки прерывания на входах
        
}  // конец обработки прерывания на входах
                  //if ((RTC%512)==0)
 
}                 // { RD0=RD0^1;} 
reg33 вне форума   Ответить с цитированием
Старый 05.12.2016, 10:54   #2
HeKeD
Member
 
Регистрация: 13.10.2016
Адрес: Minsk
Возраст: 27
Сообщений: 39
Вес репутации: 100/6
HeKeD will become famous soon enoughHeKeD will become famous soon enough
По умолчанию Re: Не работают прерывания PORTB pic16F877a

а на входе RB4 у тебя точно '0' ?
я бы попробовал так:
Код:
if(RBIF) 
{  // Обрабатываем прерывания на входах PORTB< 4:7> 
    if(RB4==0 ) 
    { 
        RC7=RC7^1; 
    }// конец обработки прерывания на входах 
    RBIF=0; //  сбрасываем флаг 
}
просто если на RB4 установлена '1', то флаг RBIF у тебя не сбрасывается и как раз программа зависнет в прерывании
HeKeD вне форума   Ответить с цитированием
Старый 05.12.2016, 11:39   #3
Zhuk72
Member
 
Аватар для Zhuk72
 
Регистрация: 09.11.2015
Адрес: Baku
Возраст: 45
Сообщений: 98
Вес репутации: 431/12
Zhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really nice
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Из ДШ:
Цитата:
The user, in the Interrupt Service Routine, can clear the interrupt in the following manner:
a) Any read or write of PORTB. This will end the mismatch condition.
b) Clear flag bit RBIF.
Если у вас появилось нажатие на RB4, то пока не прочтете порт, в прерывании вы не пройдете проверку if (RB4 == 0) и, соответственно, не очистится флаг. Отсюда и постоянный заворот.

Я бы перед if (RB4 == 0) вписал
Код:
asm("movf _PORTB,f");
или, например,
Код:
PORTB &= 0xFF;

Последний раз редактировалось Zhuk72; 05.12.2016 в 11:55. Причина: Дополнил.
Zhuk72 вне форума   Ответить с цитированием
Старый 05.12.2016, 12:11   #4
reg33
Member
 
Регистрация: 11.11.2012
Возраст: 35
Сообщений: 57
Вес репутации: 85/0
reg33 will become famous soon enough
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Цитата:
Сообщение от HeKeD Посмотреть сообщение
а на входе RB4 у тебя точно '0' ?
я бы попробовал так:
Код:
if(RBIF) 
{  // Обрабатываем прерывания на входах PORTB< 4:7> 
    if(RB4==0 ) 
    { 
        RC7=RC7^1; 
    }// конец обработки прерывания на входах 
    RBIF=0; //  сбрасываем флаг 
}
просто если на RB4 установлена '1', то флаг RBIF у тебя не сбрасывается и как раз программа зависнет в прерывании

на входе у меня лог 1. Я вообще хотел чтоб по изменению стостояния с лог 1 на лог 0 происходило срабатывание. Схему прилагаю
Миниатюры
testI2C.png  
reg33 вне форума   Ответить с цитированием
Старый 05.12.2016, 12:13   #5
reg33
Member
 
Регистрация: 11.11.2012
Возраст: 35
Сообщений: 57
Вес репутации: 85/0
reg33 will become famous soon enough
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Цитата:
Сообщение от Zhuk72 Посмотреть сообщение
Из ДШ:
Если у вас появилось нажатие на RB4, то пока не прочтете порт, в прерывании вы не пройдете проверку if (RB4 == 0) и, соответственно, не очистится флаг. Отсюда и постоянный заворот.

Я бы перед if (RB4 == 0) вписал
Код:
asm("movf _PORTB,f");
или, например,
Код:
PORTB &= 0xFF;
не совсем понял про прочтение порта?

Разве PORTB &= 0xFF; будет вялятся чтением?
reg33 вне форума   Ответить с цитированием
Старый 05.12.2016, 12:21   #6
Zhuk72
Member
 
Аватар для Zhuk72
 
Регистрация: 09.11.2015
Адрес: Baku
Возраст: 45
Сообщений: 98
Вес репутации: 431/12
Zhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really nice
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Будет. Это равносильно PORTB = PORTB & 0xFF, т.е. чтение порта, выделение всех битов и сохранение в него же.
Или асм вариант. То же самое, но без маски.
Zhuk72 вне форума   Ответить с цитированием
Старый 05.12.2016, 15:22   #7
reg33
Member
 
Регистрация: 11.11.2012
Возраст: 35
Сообщений: 57
Вес репутации: 85/0
reg33 will become famous soon enough
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Цитата:
Сообщение от Zhuk72 Посмотреть сообщение
Будет. Это равносильно PORTB = PORTB & 0xFF, т.е. чтение порта, выделение всех битов и сохранение в него же.
Или асм вариант. То же самое, но без маски.
заработало но как то не логично в голове не укладывается прям при добавлении строчки PORTB = PORTB & 0xFF перед if (RB4 == 0) ситуация не поменялась я но при нажатии кнопки (перехода пина из состояния 1 в состояние 0) программа выходит из прерывания. Ну и интуитивно взял и изменил на if (RB4 == 1) все работает но как то странно и нелогично
reg33 вне форума   Ответить с цитированием
Старый 05.12.2016, 15:23   #8
Zhuk72
Member
 
Аватар для Zhuk72
 
Регистрация: 09.11.2015
Адрес: Baku
Возраст: 45
Сообщений: 98
Вес репутации: 431/12
Zhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really nice
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Это в Протеусе ведь, верно?
Zhuk72 вне форума   Ответить с цитированием
Старый 05.12.2016, 16:09   #9
reg33
Member
 
Регистрация: 11.11.2012
Возраст: 35
Сообщений: 57
Вес репутации: 85/0
reg33 will become famous soon enough
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Цитата:
Сообщение от Zhuk72 Посмотреть сообщение
Это в Протеусе ведь, верно?
ну да в протеусе
reg33 вне форума   Ответить с цитированием
Старый 05.12.2016, 16:16   #10
Zhuk72
Member
 
Аватар для Zhuk72
 
Регистрация: 09.11.2015
Адрес: Baku
Возраст: 45
Сообщений: 98
Вес репутации: 431/12
Zhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really nice
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Особо на Протеус полагаться не стоит, особенно это касается кнопок.
Если стоит break на входе в прерывание, то убрать. Просто повесить светик на один из выводов, а в прерывании по нажатию делать LED = ~LED; Ну или просто следить за цветами на выходе.
Если это отрабатывается правильно, то и в железе с большой вероятностью будет работать.
Zhuk72 вне форума   Ответить с цитированием
Старый 05.12.2016, 16:37   #11
reg33
Member
 
Регистрация: 11.11.2012
Возраст: 35
Сообщений: 57
Вес репутации: 85/0
reg33 will become famous soon enough
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Цитата:
Сообщение от Zhuk72 Посмотреть сообщение
Особо на Протеус полагаться не стоит, особенно это касается кнопок.
Если стоит break на входе в прерывание, то убрать. Просто повесить светик на один из выводов, а в прерывании по нажатию делать LED = ~LED; Ну или просто следить за цветами на выходе.
Если это отрабатывается правильно, то и в железе с большой вероятностью будет работать.
единственное еще что непонятно надо ли организовывать " антидребезг контактов " ели надо то по какому принцыпу? я так понимаю "тики"
я посчитать не смогу ?
reg33 вне форума   Ответить с цитированием
Старый 05.12.2016, 16:53   #12
Zhuk72
Member
 
Аватар для Zhuk72
 
Регистрация: 09.11.2015
Адрес: Baku
Возраст: 45
Сообщений: 98
Вес репутации: 431/12
Zhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really nice
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Не знаю кто как, но я не люблю ловить кнопки по прерываниям по изменению состояний. Предпочитаю в прерываниях таймера опрашивать кнопочные порты и сравнивать с предыдущим считанным значением. Если дважды зафиксировал одинаковое нажатое состояние, значит кнопка нажата. Обычно периодичность опроса кнопок делаю от 20 до 50 мс.
Zhuk72 вне форума   Ответить с цитированием
Старый 05.12.2016, 17:09   #13
reg33
Member
 
Регистрация: 11.11.2012
Возраст: 35
Сообщений: 57
Вес репутации: 85/0
reg33 will become famous soon enough
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Цитата:
Сообщение от Zhuk72 Посмотреть сообщение
Не знаю кто как, но я не люблю ловить кнопки по прерываниям по изменению состояний. Предпочитаю в прерываниях таймера опрашивать кнопочные порты и сравнивать с предыдущим считанным значением. Если дважды зафиксировал одинаковое нажатое состояние, значит кнопка нажата. Обычно периодичность опроса кнопок делаю от 20 до 50 мс.

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

void interrupt isr(void)// прерывание по нажатию кнопки примерно 1024 мкС
{
PHP код:
    if(T0IF){    //    Обрабатываем прерывания по таймеру понял что прерывания по таймеру
            
T0IF=0// сбрасываю флаг прерывания
            
RTC++;
              
// инкремент

             
if (RA4==0)      //кнопка нажата?
                       
{
                       if(
ButtonPress<20)  // кнопка нажата примерно 20 mS    надо прикинуть правильный интервал
                        
ButtonPress++;
                       }
                 else  if(
ButtonPress!=0)  // кнопка отжата делаем антидребезг при отпускании кнопки плюс инкремент ALG
                     
{  ButtonPress--;
                         if ((
RA4!=0)&&(ButtonPress==0))
                         {
                          
ALG++;
                           if (
ALG==3)// если кнопка нажата 3 раза то обнуляемся
                            
{ALG=0;}
              }
                }

                            if(
RA1==0)
                             {                    
//
                             
if(ButtonPress_1<20)  //
                             
ButtonPress_1++;
                             }
                                  else
                                      if(
ButtonPress_1!=0)
                                 {                          
//
                                     
ButtonPress_1--;
                                     if ((
RA4!=0)&&(ButtonPress_1==0))
                                    {
                                       
ALG==4;  
                                       
higt++; 
                                    }
                                }
}

reg33 вне форума   Ответить с цитированием
Старый 05.12.2016, 19:00   #14
Zhuk72
Member
 
Аватар для Zhuk72
 
Регистрация: 09.11.2015
Адрес: Baku
Возраст: 45
Сообщений: 98
Вес репутации: 431/12
Zhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really nice
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Если кнопки сидят на одном порту, советую опрашивать целый порт, а не кнопки по одной. В вашем случае это RA4 и RA1, следовательно
Код:
unsigned char btn_now = 0, btn_prev = 0;   // Это в список глобальных переменных
bit btn_pressed = 0;
...
#define BTN (~PORTA & 0b00010010)    // маска для выделения битов 4 и 1

// в прерывании
if (BTN)    // если есть нажатие
{
    btn_now = BTN;
    if (btn_now == btn_prev)
    {
        btn_pressed = 1;
        btn_prev = 0;
    }
        else btn_prev = btn_now;
}
А в основном цикле периодически опрашиваете btn_pressed и как только зафиксировали единицу, обрабатываете.
Код:
void main (void)
{
....
    while (1)
    {
....
        if (btn_pressed)
       {
              btn_pressed = 0;
              switch (btn_now)
              {
                     case 0x10:
                     {
                            // код для RA4
                     }; break;

                     case 0x02:
                     {
                            // код для RA1
                     }; break;

                     case 0x12:
                     {
                            // обе нажаты
                     }; break;
              }
       }
....
    }
}
Примерно так. Возможны варианты, когда требуется обрабатывать одно короткое нажатие, длинное, нажатие с удержанием с автосработкой и однократной. Тут уже сами придумаете. Используйте битовые флаги на нажатие, удержание, отпускание, хотя и не все их любят в Си. Можно их завести в структуры, будет удобно.
Zhuk72 вне форума   Ответить с цитированием
Старый 05.12.2016, 22:38   #15
=L.A.=
Senior Member
 
Регистрация: 26.02.2007
Адрес: Москва РФ
Сообщений: 262
Вес репутации: 232/44
=L.A.= has a spectacular aura about=L.A.= has a spectacular aura about=L.A.= has a spectacular aura about
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Цитата:
Сообщение от reg33 Посмотреть сообщение
работает только первая кнопка вторая игнорится если поменять местами то будет работать вторая
Не надо городить. Надо делать проще и тогда начнет получаться.
Также настоятельно рекомендую не пользоваться различными "Протезами", а тестировать все проги на реальном железе. Для схемы с вашей картинки:

Код:
   
MainLoop:
//     
    if (!RB4)      // кнопка нажата?       
      RC6 = 1;   // зажгем светодиод  
    else        
      RC6 = 0;   // иначе погасим светодиод
//     
    goto MainLoop;
//
=L.A.= вне форума   Ответить с цитированием
Старый 06.12.2016, 07:26   #16
Zhuk72
Member
 
Аватар для Zhuk72
 
Регистрация: 09.11.2015
Адрес: Baku
Возраст: 45
Сообщений: 98
Вес репутации: 431/12
Zhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really nice
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Только что заметил схему ))
Кнопок у вас, как оказалось, много, к тому же на двух портах.
Следовательно маску нужно поменять, можно даже объединить проверку обеих портов, скомпоновав их в одну переменную парой логических операций. Подсказывать не буду, попробуйте сами
Zhuk72 вне форума   Ответить с цитированием
Старый 07.12.2016, 09:39   #17
reg33
Member
 
Регистрация: 11.11.2012
Возраст: 35
Сообщений: 57
Вес репутации: 85/0
reg33 will become famous soon enough
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Цитата:
Сообщение от Zhuk72 Посмотреть сообщение
Если кнопки сидят на одном порту, советую опрашивать целый порт, а не кнопки по одной. В вашем случае это RA4 и RA1, следовательно
Код:
unsigned char btn_now = 0, btn_prev = 0;   // Это в список глобальных переменных
bit btn_pressed = 0;
...
#define BTN (~PORTA & 0b00010010)    // маска для выделения битов 4 и 1

// в прерывании
if (BTN)    // если есть нажатие
{
    btn_now = BTN;
    if (btn_now == btn_prev)
    {
        btn_pressed = 1;
        btn_prev = 0;
    }
        else btn_prev = btn_now;
}
А в основном цикле периодически опрашиваете btn_pressed и как только зафиксировали единицу, обрабатываете.
Код:
void main (void)
{
....
    while (1)
    {
....
        if (btn_pressed)
       {
              btn_pressed = 0;
              switch (btn_now)
              {
                     case 0x10:
                     {
                            // код для RA4
                     }; break;

                     case 0x02:
                     {
                            // код для RA1
                     }; break;

                     case 0x12:
                     {
                            // обе нажаты
                     }; break;
              }
       }
....
    }
}
Примерно так. Возможны варианты, когда требуется обрабатывать одно короткое нажатие, длинное, нажатие с удержанием с автосработкой и однократной. Тут уже сами придумаете. Используйте битовые флаги на нажатие, удержание, отпускание, хотя и не все их любят в Си. Можно их завести в структуры, будет удобно.
спасибо с этим вроди как все понятно ну нету подавления дребезга контактов этоже повлияет на обработку кнопки или неправильную реакцию не так ли?
reg33 вне форума   Ответить с цитированием
Старый 07.12.2016, 11:30   #18
Zhuk72
Member
 
Аватар для Zhuk72
 
Регистрация: 09.11.2015
Адрес: Baku
Возраст: 45
Сообщений: 98
Вес репутации: 431/12
Zhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really nice
По умолчанию Re: Не работают прерывания PORTB pic16F877a

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

А дальше уже можно либо автоповтор организовать, либо наоборот, не повторять действие пока кнопку не отпустят. Это уже от задачи зависит.
Zhuk72 вне форума   Ответить с цитированием
Старый 07.12.2016, 15:11   #19
DmitrijVDN
Senior Member
 
Регистрация: 09.04.2010
Сообщений: 733
Вес репутации: 1308/48
DmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud of
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Цитата:
Сообщение от Zhuk72 Посмотреть сообщение
Особо на Протеус полагаться не стоит, особенно это касается кнопок.
еще как стоит, просто их надо правильно уметь готовить, в протезе даже реакцию МК на дребезг кнопок можно отладить
вот пример кода с кнопками на разных портах , с обработкой антидребезга, формированием импульса по нажатию кнопок up/down и
up-включает мигание СД , down -выключает.
Код:
#include <pic.h> 
//__PICC CHIP=pic16f628a ;
//__CONFIG(0x03F6A); 
 __CONFIG(INTIO & WDTDIS & LVPDIS & PWRTDIS & UNPROTECT & MCLREN);   

#define CONST_TMR1 10 - 1000 // system clock 1ms
#define BATTON_UP      RA1
#define BATTON_DOWN    RA0
#define BATTON_SENSOR  RB1
#define BATTON_KONCEV  RB3
#define BATTON_SWITCH  RB7
#define LED            RB2
#define MOTOR          RB4
#define DRAG           RB5 
 

void init(void);
void button_test(void);
void generetion_imp_up(void);
void generetion_imp_down(void);
void generetion_imp_LED(void);

volatile       unsigned int    TMR1        @ 0x0E;

volatile struct flag_type {
  unsigned BUTTON_ON        : 1;
  unsigned BUTTON_ON_old    : 1;
  unsigned START            : 1;
  unsigned FL1MS            : 1;
  unsigned STOP             : 1;
  unsigned LED_ON           : 1;
  unsigned                  : 1;
  unsigned                  : 1;
} flag;


volatile struct batton_type {
  unsigned UP               : 1;
  unsigned DOWN             : 1;
  unsigned SENSOR           : 1;
  unsigned KONCEV           : 1;
  unsigned SWITCH           : 1;
  unsigned                  : 1;
  unsigned                  : 1;
  unsigned                  : 1;
} ;

 union{                      // объединяем(совмещаем в памяти)
  struct batton_type    BIT;  
  unsigned char       byte;                   
 }BUTTON,BUTTON_new,BUTTON_old,BUTTON_temp;





// основная программа 
void main(void)
{
   init();

   while(1)
     {
      while(!flag.FL1MS);
       flag.FL1MS=0;
      button_test();
      generetion_imp_up();
      generetion_imp_down();
      generetion_imp_LED();
      NOP();
     }  
}// end main

//******************************************************
// инициализация МК
//******************************************************
void init(void)
{
        INTCON=0x00;
        PIE1=0x00;
        OPTION=0x00; //устанавливаем предделительRTCC=f/2
        RBPU=1;
        CMCON=0x07; 
        PORTB=0;
        PORTA=0;
        TRISB=0b10001010;     //выводы портаВ = выход
        TRISA=0b00100011;     //выводы портаВ = выход
        PORTB=0;
        PORTA=0; 

        T1CON=0x00;
        TMR1= CONST_TMR1 ; // сброс таймер1
 
        TMR1ON=1;     
        TMR1IE=1;
        PEIE=1;
        GIE=1;  
} // end init

//*****************************************************
/* подпрограмма обработки прерываний */
//****************************************************
void interrupt timer1_isr(void)
{
if (TMR1IF)
   {
     TMR1IF=0;
        T1CON=0x00;
        TMR1= CONST_TMR1 ; // сброс таймер1
        TMR1ON=1; 
        flag.FL1MS=1;
   }
NOP();
}// end interrupt timer0_isr

//****************************************************
// опрос кнопки... 
//******************************************************
void button_test(void)
{ static unsigned char count ;
  BUTTON_new.BIT.UP = !BATTON_UP ;
  BUTTON_new.BIT.DOWN = !BATTON_DOWN ;
  BUTTON_new.BIT.SENSOR = !BATTON_SENSOR ;
  BUTTON_new.BIT.KONCEV = !BATTON_KONCEV ;
  BUTTON_new.BIT.SWITCH = !BATTON_SWITCH ;

  if(BUTTON_old.byte==BUTTON_new.byte)
      {
        if(count==5)
         {
          BUTTON.byte=BUTTON_new.byte;     
         }
         else
         {
          count++;
         }
      }
      else
      {
       BUTTON_old.byte=BUTTON_new.byte;
       count=0; 
      }

     
   
}// end button_test

//****************************************************
// генерация импульса вверх 
//******************************************************
void generetion_imp_up(void)
{ //static unsigned char count ;
  

  if(BUTTON.BIT.UP && !BUTTON_temp.BIT.UP)
      {
       flag.START=1;
      }
      else
      {
       flag.START=0;
      }
  BUTTON_temp.BIT.UP=BUTTON.BIT.UP;   
   
}// end generetion_imp_up

//****************************************************
// генерация импульса вверх 
//******************************************************
void generetion_imp_down(void)
{ //static unsigned char count ;
  

  if(BUTTON.BIT.DOWN && !BUTTON_temp.BIT.DOWN)
      {
       flag.STOP=1;
      }
      else
      {
       flag.STOP=0;
      }
  BUTTON_temp.BIT.DOWN=BUTTON.BIT.DOWN;     
   
}// end generetion_imp_down

//****************************************************
// мигаем LED 
//******************************************************
void generetion_imp_LED(void)
{ static unsigned int count ;
  

  if(flag.START)
      {
       flag.LED_ON=1;
      }
  if(flag.STOP)
      {
       flag.LED_ON=0;
      }
  if(flag.LED_ON)
      {
       if(count==500)
         {LED=!LED;
          count=0;         
         }
         else
         {
          count++; 
         }
      }
      else
      {
       LED=0; 
      } 
     
   
}// end generetion_imp_down
DmitrijVDN на форуме   Ответить с цитированием
Старый 07.12.2016, 17:44   #20
reg33
Member
 
Регистрация: 11.11.2012
Возраст: 35
Сообщений: 57
Вес репутации: 85/0
reg33 will become famous soon enough
По умолчанию Re: Не работают прерывания PORTB pic16F877a

[QUOTE=DmitrijVDN;228587]еще как стоит, просто их надо правильно уметь готовить, в протезе даже реакцию МК на дребезг кнопок можно отладить
вот пример кода с кнопками на разных портах , с обработкой антидребезга, формированием импульса по нажатию кнопок up/down и
up-включает мигание СД , down -выключает.
Код:
#include <pic.h> 
//__PICC CHIP=pic16f628a ;
//__CONFIG(0x03F6A); 
 __CONFIG(INTIO & WDTDIS & LVPDIS & PWRTDIS & UNPROTECT & MCLREN);   

#define CONST_TMR1 10 - 1000 // system clock 1ms
#define BATTON_UP      RA1
#define BATTON_DOWN    RA0
#define BATTON_SENSOR  RB1
#define BATTON_KONCEV  RB3
#define BATTON_SWITCH  RB7
#define LED            RB2
#define MOTOR          RB4
#define DRAG           RB5 
 

void init(void);
void button_test(void);
void generetion_imp_up(void);
void generetion_imp_down(void);
void generetion_imp_LED(void);

volatile       unsigned int    TMR1        @ 0x0E;

volatile struct flag_type {
  unsigned BUTTON_ON        : 1;
  unsigned BUTTON_ON_old    : 1;
  unsigned START            : 1;
  unsigned FL1MS            : 1;
  unsigned STOP             : 1;
  unsigned LED_ON           : 1;
  unsigned                  : 1;
  unsigned                  : 1;
} flag;


volatile struct batton_type {
  unsigned UP               : 1;
  unsigned DOWN             : 1;
  unsigned SENSOR           : 1;
  unsigned KONCEV           : 1;
  unsigned SWITCH           : 1;
  unsigned                  : 1;
  unsigned                  : 1;
  unsigned                  : 1;
} ;

 union{                      // объединяем(совмещаем в памяти)
  struct batton_type    BIT;  
  unsigned char       byte;                   
 }BUTTON,BUTTON_new,BUTTON_old,BUTTON_temp;





// основная программа 
void main(void)
{
   init();

   while(1)
     {
      while(!flag.FL1MS);
       flag.FL1MS=0;
      button_test();
      generetion_imp_up();
      generetion_imp_down();
      generetion_imp_LED();
      NOP();
     }  
}// end main

//******************************************************
// инициализация МК
//******************************************************
void init(void)
{
        INTCON=0x00;
        PIE1=0x00;
        OPTION=0x00; //устанавливаем предделительRTCC=f/2
        RBPU=1;
        CMCON=0x07; 
        PORTB=0;
        PORTA=0;
        TRISB=0b10001010;     //выводы портаВ = выход
        TRISA=0b00100011;     //выводы портаВ = выход
        PORTB=0;
        PORTA=0; 

        T1CON=0x00;
        TMR1= CONST_TMR1 ; // сброс таймер1
 
        TMR1ON=1;     
        TMR1IE=1;
        PEIE=1;
        GIE=1;  
} // end init

//*****************************************************
/* подпрограмма обработки прерываний */
//****************************************************
void interrupt timer1_isr(void)
{
if (TMR1IF)
   {
     TMR1IF=0;
        T1CON=0x00;
        TMR1= CONST_TMR1 ; // сброс таймер1
        TMR1ON=1; 
        flag.FL1MS=1;
   }
NOP();
}// end interrupt timer0_isr

//****************************************************
// опрос кнопки... 
//******************************************************
void button_test(void)
{ static unsigned char count ;
  BUTTON_new.BIT.UP = !BATTON_UP ;
  BUTTON_new.BIT.DOWN = !BATTON_DOWN ;
  BUTTON_new.BIT.SENSOR = !BATTON_SENSOR ;
  BUTTON_new.BIT.KONCEV = !BATTON_KONCEV ;
  BUTTON_new.BIT.SWITCH = !BATTON_SWITCH ;

  if(BUTTON_old.byte==BUTTON_new.byte)
      {
        if(count==5)
         {
          BUTTON.byte=BUTTON_new.byte;     
         }
         else
         {
          count++;
         }
      }
      else
      {
       BUTTON_old.byte=BUTTON_new.byte;
       count=0; 
      }

     
   
}// end button_test

//****************************************************
// генерация импульса вверх 
//******************************************************
void generetion_imp_up(void)
{ //static unsigned char count ;
  

  if(BUTTON.BIT.UP && !BUTTON_temp.BIT.UP)
      {
       flag.START=1;
      }
      else
      {
       flag.START=0;
      }
  BUTTON_temp.BIT.UP=BUTTON.BIT.UP;   
   
}// end generetion_imp_up

//****************************************************
// генерация импульса вверх 
//******************************************************
void generetion_imp_down(void)
{ //static unsigned char count ;
  

  if(BUTTON.BIT.DOWN && !BUTTON_temp.BIT.DOWN)
      {
       flag.STOP=1;
      }
      else
      {
       flag.STOP=0;
      }
  BUTTON_temp.BIT.DOWN=BUTTON.BIT.DOWN;     
   
}// end generetion_imp_down

//****************************************************
// мигаем LED 
//******************************************************
void generetion_imp_LED(void)
{ static unsigned int count ;
  

  if(flag.START)
      {
       flag.LED_ON=1;
      }
  if(flag.STOP)
      {
       flag.LED_ON=0;
      }
  if(flag.LED_ON)
      {
       if(count==500)
         {LED=!LED;
          count=0;         
         }
         else
         {
          count++; 
         }
      }
      else
      {
       LED=0; 
      } 
     
   
}// end generetion_imp_down
[/QUOTE

честно сказать пока разбираюсь с вашим кодом с ходу все моменты пока уловить не удается. Моя задача именно обработать кнопку в прерываниях так как по задумке будет автономно зацыкленные куски кода и выйти от туда можно только нажав кнопку. Вот борюсь с прерыванием по состоянию на PORTB (RB4-RB7). Вот написал код где по задумке в функции обработке прерывания обрабатываются прерывания по состоянию на пинах PORTB. В итоге при нажатии кнопки и изменения состояния RB4 моргает диод на пине RC7 и с небольшой задержкой RC6 и соотвественно наоборот при нажатии RB5. ЭТО ГЛЮК ПРОТЕУС?

Код:
void interrupt isr(void)// прерывание по нажатию кнопки примерно 1024 мкС
{

   if(RBIF)
        {  // Обрабатываем прерывания на входах PORTB< 4:7>
         PORTB = PORTB & 0xFF; //читаем значение порта
           if(RB4==1 )     //кнопка_1 нажата?
            { RC7=RC7^1;}
           if(RB5==1)      //кнопка_2 нажата?
            {RC6=RC6^1;}
              RBIF=0; //  сбрасываем флаг
            }          // конец обработки прерывания на входах
        } 

 }
reg33 вне форума   Ответить с цитированием
Старый 07.12.2016, 18:30   #21
Zhuk72
Member
 
Аватар для Zhuk72
 
Регистрация: 09.11.2015
Адрес: Baku
Возраст: 45
Сообщений: 98
Вес репутации: 431/12
Zhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really nice
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Нажатая кнопка сажает вывод в ноль, а вы проверяете на единицу.
Zhuk72 вне форума   Ответить с цитированием
Старый 07.12.2016, 19:48   #22
reg33
Member
 
Регистрация: 11.11.2012
Возраст: 35
Сообщений: 57
Вес репутации: 85/0
reg33 will become famous soon enough
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Цитата:
Сообщение от Zhuk72 Посмотреть сообщение
Нажатая кнопка сажает вывод в ноль, а вы проверяете на единицу.
ранее ставил
Код:
if(RB4==0 )     //кнопка_1 нажата?
вообщее не было ни какой реакции при нажатии на кнопку
поставил RB4==1 появилась реакция. Правда пришлось грузонуть проект. А пошагово как то не хочет шагать протеус как то глючит. Щас хочу макетку собрать хотя ни разу камень не шил.
reg33 вне форума   Ответить с цитированием
Старый 07.12.2016, 19:55   #23
DmitrijVDN
Senior Member
 
Регистрация: 09.04.2010
Сообщений: 733
Вес репутации: 1308/48
DmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud of
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Цитата:
Сообщение от reg33 Посмотреть сообщение
ЭТО ГЛЮК ПРОТЕУС?
да блин нету глюков в протезе, что написали то и получили...
ИМХО пользовать прерывания по изменению для обработки нажатия кнопок имеет смысл только в одном случае вывести МК из сна, в ином варианте это тупо глупость.
DmitrijVDN на форуме   Ответить с цитированием
Старый 07.12.2016, 20:03   #24
DmitrijVDN
Senior Member
 
Регистрация: 09.04.2010
Сообщений: 733
Вес репутации: 1308/48
DmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud of
По умолчанию Re: Не работают прерывания PORTB pic16F877a

как понимаю компилятор хайтек, и это:
Цитата:
Сообщение от reg33 Посмотреть сообщение
Код:
   if(RB4==1 )     //кнопка_1 нажата?
            { RC7=RC7^1;}
           if(RB5==1)      //кнопка_2 нажата?
            {RC6=RC6^1;}
выглядит жутью
все проще и компилятор ее воспримет более адекватно
Код:
   if(RB4)     //кнопка_1 нажата?
            { RC7= !RC7;}
           if(RB5)      //кнопка_2 нажата?
            {RC6= !RC6;}
DmitrijVDN на форуме   Ответить с цитированием
Старый 07.12.2016, 20:07   #25
Zhuk72
Member
 
Аватар для Zhuk72
 
Регистрация: 09.11.2015
Адрес: Baku
Возраст: 45
Сообщений: 98
Вес репутации: 431/12
Zhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really niceZhuk72 is just really nice
По умолчанию Re: Не работают прерывания PORTB pic16F877a

Цитата:
Сообщение от reg33 Посмотреть сообщение
ранее ставил if(RB4==0 ) вообщее не было ни какой реакции при нажатии на кнопку поставил RB4==1 появилась реакция.
Метод околонаучного тыка?
Если кнопка нажата (в вашем и наиболее распространенном случае), на выводе ноль. Вариантов нет.

Я вам выше предлагал отказаться от ловли изменений на порту в пользу периодического опроса кнопок по таймеру. Чем вам такой вариант не нравится?
Zhuk72 вне форума   Ответить с цитированием
Ответ


Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
STM32F4 discovery не срабатывают прерывания по I2C Kopranych Вопросы начинающих 0 20.11.2016 15:54
Не записывает в EEPROM dposm Вопросы начинающих 29 13.09.2013 23:52
Не работает PIC16F876A-I/SP Ибрагим Николаевич Вопросы начинающих 6 22.07.2011 17:28
Графические среды Vidoc Общетехнические вопросы 47 10.02.2010 06:18
Программная симуляция pic16F876 в MPLAB Timik Продукция MICROCHIP 2 12.10.2007 15:12


Часовой пояс GMT +3, время: 01:57.


Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd. Перевод: zCarot