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

 
 
> PIC16F84: Не срабатывает прерывание по заднему фронту на RB0/INT?
Dimchansky
сообщение Mar 27 2007, 13:13
Сообщение #1


Участник
*

Группа: Свой
Сообщений: 55
Регистрация: 10-07-05
Пользователь №: 6 685



Есть программа для PIC16F84, которая работает в Proteus и не пашет на практике.
Прерывание на RB0/INT по заднему фронту срабатывает только один раз.
Для теста вырезал код и переделал его немного.
На RB0/INT меняются уровни, по заднему фронту должны изменится на противоположное состояние уровни на RA0 и RB7. Я решил воспользоваться аппаратным прерыванием для этого (хотя програмная эмуляция того же самого работает на ура).
Чтобы было понятно, делаю вырезку кода на C, там много лишнего, но сути, надеюсь, не меняет..
Код
#include <pic.h>

// Setup the configuration word
#if defined (_16F84)
#warning PIC16F84 selected
__CONFIG(WDTDIS & XT & UNPROTECT); // 0x3FF9 for PIC16F84
#else
#error Unsupported PICmicro MCU selected
#endif

static volatile bit KEYPAD_DATA          @ PORTBIT(PORTA, 0);
static volatile bit KEYPAD_INT           @ PORTBIT(PORTB, 7);
static volatile bit KEYPAD_CLK           @ PORTBIT(PORTB, 0);
static volatile bit WORKINGBIT           @ PORTBIT(PORTB, 1);

//  Setup TMR0 to interrupt Mainline once every ~500 usecs
#define XTAL   (10000000)  // 10 MHZ
#define PRE    (8)         // prescaler
#define INT_HZ (2000)      // interrupt freq. is 2KHz
#define DIVIDE ((2*XTAL/4/PRE/INT_HZ+1)/2) // division ratio - must be < 256

#define KEYS_SAMPLING         (2*5)    // 5 ms
#define KEYS_PRE_REPEAT       (2*500)  // 500 ms
#define KEYS_REPEAT           (2*30)   // 30 ms
#define CONNECTION_TIMEOUT    (2*1)    // 1 ms
#define TIME_BEFORE_RECONNECT (2*1)    // 1 ms

#define MATRIXKEYPAD_ROWS      (3)

#if   PRE == 256
#define SET_PRESCALER { PS2 = 1; PS1 = 1; PS0 = 1; }
#elif PRE == 128
#define SET_PRESCALER { PS2 = 1; PS1 = 1; PS0 = 0; }
#elif PRE == 64
#define SET_PRESCALER { PS2 = 1; PS1 = 0; PS0 = 1; }
#elif PRE == 32
#define SET_PRESCALER { PS2 = 1; PS1 = 0; PS0 = 0; }
#elif PRE == 16
#define SET_PRESCALER { PS2 = 0; PS1 = 1; PS0 = 1; }
#elif PRE == 8
#define SET_PRESCALER { PS2 = 0; PS1 = 1; PS0 = 0; }
#elif PRE == 4
#define SET_PRESCALER { PS2 = 0; PS1 = 0; PS0 = 1; }
#elif PRE == 2
#define SET_PRESCALER { PS2 = 0; PS1 = 0; PS0 = 0; }
#else
#error Bad prescaler value.
#endif

//  Global Variables
volatile unsigned int RTC = 0;  //  Real Time Clock Counter

unsigned int idx = 0;  // index for cycles in interrupt handler
unsigned int keys = 0; // current keys pressed (each bit - is one key)
unsigned int keysLastSaved = 0;
unsigned char keys_column = 0; // keys pressed in current column (each bit - is one key)
unsigned int keysCount = 0;
unsigned int keysRepeat = 1;

volatile unsigned keysLastValid = 0;
volatile bit transferKeyPressing = 0;
volatile bit extInterruptOccured = 0;

//  Interrupt Handler
void interrupt isr(void)
{
  //  TMR0 Interrupt Handler
  if(T0IF)
  {  
    T0IF = 0;  //  Reset Interrupt Flag
    TMR0 = -DIVIDE;
  } // if(T0IF)
  
  //  Put Different Interrupt Handlers here
  if(INTF)
  {
    //  RB0/INT Pin Interrupt
    extInterruptOccured = 1;
    KEYPAD_DATA = !KEYPAD_DATA;
    KEYPAD_INT = !KEYPAD_INT;
    INTF = 0; //  Reset Interrupt
  }
}  //  End Interrupt Handler


//  Mainline
void main(void)       //  Template Mainline
{
//  unsigned char i;

  INTCON = 0;   // purpose of disabling the interrupts.

  RBPU = 0;     // enable internal pullups on PORTB
  PORTB = 0xFF; //
  TRISB = 0b00000001; // RB0 - inputs, RB1..RB7 - outputs

  PORTA = 0xFF;
  TRISA = 0b00011110; // RA0 - outputs, RA1-RA4 - inputs

  TMR0 = 0;     // Reset the TMR0 counter
  TMR0 = -DIVIDE;
  T0CS = 0;     // Enable timer to get the input from internal counter XTAL/4
  PSA = 0;     // Enable prescaler to divide the frequency
  SET_PRESCALER;
  T0IF = 0;     // Make Sure NO Pending Interrupt
  T0IE = 1;     // TMR0 overflow interrupt enable bit (1: enable TMR0)

  INTEDG = 0;   // Interrupt on Falling Edge of RB0
  INTF = 0;     // Make Sure NO Pending Interrupt
  INTE = 1;     // Enable RBO/INT Pin Interrupts

  GIE = 1;     // global interrupt enable bit (1: enable all)

  KEYPAD_DATA = KEYPAD_INT = KEYPAD_CLK;

  while(1)
  {
    WORKINGBIT = !WORKINGBIT;
  } // endwhile
} //  End of Mainline

собирал так:
picc -16F84 -ASMLIST -O -Zg -Etest.err -Otest.hex main.c
получил test.hex:
Код
:10000000830100308A001D288C0003088301A000B2
:100010000B1D0E280B1164308312810083128B1C80
:1000200018280D1401308506803086068B10831247
:10003000200883008C0E0C0E09000E3084001B304B
:1000400033200D3084000E303320830103309F00B5
:10005000FE309E001B3084001D3037208301CF2BE3
:1000600004068001840A0406031D302800349D0024
:1000700042208000840A04081D0603190034382831
:1000800083129E009F1B4B281F088A001E089E0A91
:1000900003199F0A820083131F1883171E089E0AE4
:0600A000840000080800C6
:10079E008B0183168113FF3083128600013083167E
:1007AE008600FF30831285001E308316850083126B
:1007BE00810164308100831681128111011181142F
:1007CE0001100B118B1601138B100B168B17831246
:1007DE00061CF32B8617F42B86138312861FF92B18
:1007EE000514FA2B0510831202308606FA2B0134FB
:0207FE000034C5
:02400E00F93F78
:00000001FF


На практике прерывание происходит ровно один раз. Потом ничего не меняется.
В Proteus всё работает, как задумывалось.
За нахождение граблей заранее благодарю.
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 27th June 2025 - 12:09
Рейтинг@Mail.ru


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