|
|
View previous topic :: View next topic |
Author |
Message |
rfjhh
Joined: 31 Mar 2011 Posts: 51 Location: Mexico
|
PortB on change interrupts |
Posted: Tue Apr 18, 2017 4:16 pm |
|
|
I'm writing a code for manage a keyboard using the portb on change interrupts.
The program runs well in simulation, but doesn't for real. I'm monitoring the INTCON register and in simulation the RBIF is turned off as it must to be after each CLEAR, but in the prototype, at the beginning is turned off, but after the first interrupt, it remains turned on.
I've read something in the datasheet:
"MCLR and WDT Reset do not affect the previous value data latch. The RBIF bit will be cleared upon Reset but will set again if the mismatch exists"
I don't understand what does it mean.
The program is as follow:
Code: |
#include<16f887.h>
#device adc=10
#use delay (clock = 8 MHz)
#fuses INTRC, NOWDT, NOBROWNOUT, NOLVP, NOPROTECT, NOIESO, NOFCMEN, PUT
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#include<LCD.c>
#define use_portd_lcd TRUE
int16 t_data=0;
int8 conta_1min = 0, conta_125 = 0, cols = 0;
void lee_tec_mat()
{
int8 i, j, dato;
int8 fila[4]={1, 2, 4, 8};
int8 columna[4]={1, 2, 4, 8};
int16 num[4][4]={{ 1, 2, 3, 10},
{ 4, 5, 6, 11},
{ 7, 8, 9, 12},
{14, 0, 15, 13}};
for(i=0;i<4;i++)
{
output_b(fila[i]);
for(j=0;j<4;j++)
{
dato = (input_b()>>4)&0x0f;
if(dato==columna[j])
{
t_data=num[i][j];
i=3; j=3;
}
}
}
}
void main()
{
int8 conta = 0, err = 0;
int32 clave = 0, num = 0;
set_tris_a(0xf9);
set_tris_b(0xf0);
set_tris_c(0x00);
setup_oscillator(OSC_8MHZ);
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_8 );
lcd_init();
/*Habilito interrupciones en PuertoB para entrada de teclado*/
enable_interrupts(GLOBAL); // INTCON<7:6>
enable_interrupts(INT_RB4); // INTCON<3>, IOCB<4>
enable_interrupts(INT_RB5); // INTCON<3>, IOCB<5>
enable_interrupts(INT_RB6); // INTCON<3>, IOCB<6>
enable_interrupts(INT_RB7); // INTCON<3>, IOCB<7>
t_data = 16;
for(;;)
{
output_b(0x0f);
output_c(*0x0b);
delay_ms(100);
if(cols != 0)
{
lee_tec_mat();
if(t_data == 11) // borrar
{
num = 0;
conta = 0;
lcd_putc("\f");
}
else
{
if(t_data == 10) // Aceptar
{
if(input(PIN_A0)) // Selector
{
clave = num;
lcd_gotoxy(1,1);
printf(lcd_putc, " Clave aceptada ");
}
else
{
if(num == clave) // Número correcto
{
lcd_gotoxy(1,1);
printf(lcd_putc, " Acceso ");
lcd_gotoxy(1,2);
printf(lcd_putc, " concedido ");
bit_set(*0x05, 1);
err = 0;
}
else // Número erróneo
{
err++;
if(err == 3)
{
lcd_gotoxy(1,1);
printf(lcd_putc, " Clave erronea ");
lcd_gotoxy(1,2);
printf(lcd_putc, "Espere un minuto");
enable_interrupts(INT_TIMER1);
conta_1min = 0;
while(conta_1min <= 6)
{
conta_125 = 0;
bit_set(*0x05, 2);
set_timer1(15524);
while(conta_125 <= 2)
{
}
conta_125 = 0;
bit_clear(*0x05, 2);
set_timer1(15524);
while(conta_125 <= 2)
{
}
conta_1min++;
}
err = 0;
}
else
{
lcd_gotoxy(1,2);
printf(lcd_putc, "Error %1u", err);
}
}
}
delay_ms(2000);
num = 0;
conta = 0;
lcd_putc("\f");
bit_clear(*0x05, 1); // Borra RA1
}
else // Número
{
conta++;
if(conta <= 5) // Menos de 5 cifras
{
num = num*10 + t_data;
lcd_gotoxy(5,1);
printf(lcd_putc, "%5Lu", num);
t_data = 16;
}
}
}
do
{clear_interrupt(INT_RB);
}while(((input_b()>>4)&0x0f)!=0);
clear_interrupt(INT_RB);
delay_ms(10);
bit_set(*0x0b,3); // habilito interrupción RB
t_data = 16;
cols = 0;
}
}
}
#int_timer1
void inter_t1()
{
conta_125++;
set_timer1(15524);
clear_interrupt(INT_TIMER1);
}
#int_rb
void inter_tecla()
{
int8 i, j = 0;
//******* temporización por rebote de entrada
for(i=0;i<250;i++)
{
for(j=0;j<5;j++)
{}
}
cols = (input_b()>>4)&0x0f;
output_b(input_b());
clear_interrupt(INT_RB);
bit_clear(*0x0b, 3); // deshabilito INT_RB (INTCON<3> = 0)
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 18, 2017 6:53 pm |
|
|
1. Is the keyboard a 3x4 keypad, similar to the link below?
https://www.digikey.com/product-detail/en/grayhill-inc/96AB2-102-F/GH5001-ND/180929
2. Do you have pull-up resistors (10K) on the Interrupt-on-change pins on PortB ?
3. In your program you have many lines of code like this:
Are you aware that you can do the same thing with CCS code ? Example:
Code: | output_high(PIN_A1); |
If you do it the CCS way, the code is a lot easier to read.
4. What is your CCS compiler version ? |
|
|
rfjhh
Joined: 31 Mar 2011 Posts: 51 Location: Mexico
|
|
Posted: Wed Apr 19, 2017 11:19 am |
|
|
The keyboard is a 4x4keypad.
I have pulldown resistors in PORTB<7:4>.
I use bit_set(*0x0b, 3) because I try to enable or disable RBINT. I dont use it for a port.
I have the version 5
The note: "MCLR and WDT Reset do not affect the previous value data latch. The RBIF bit will be cleared upon Reset but will set again if the mismatch exists" what does it mean? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Wed Apr 19, 2017 12:12 pm |
|
|
You need to use fast_io.
Otherwise, this line:
output_b(input_b());
Will set the whole port as output, and nothing will ever work again.....
It also doesn't make any sense as a line anyway.... |
|
|
rfjhh
Joined: 31 Mar 2011 Posts: 51 Location: Mexico
|
|
Posted: Wed Apr 19, 2017 12:19 pm |
|
|
I'm already using fast_io:
"******************
#include<16f887.h>
#device adc=10
#use delay (clock = 8 MHz)
#fuses INTRC, NOWDT, NOBROWNOUT, NOLVP, NOPROTECT, NOIESO, NOFCMEN, PUT
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#include<LCD.c>
#define use_portd_lcd TRUE
.
.
.
.
void main()
{
int8 conta = 0, err = 0;
int32 clave = 0, num = 0;
set_tris_a(0xf9);
set_tris_b(0xf0);
set_tris_c(0x00); |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|