Есть программа для 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 всё работает, как задумывалось.
За нахождение граблей заранее благодарю.