CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

PortB on change interrupts

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
rfjhh



Joined: 31 Mar 2011
Posts: 51
Location: Mexico

View user's profile Send private message

PortB on change interrupts
PostPosted: Tue Apr 18, 2017 4:16 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Apr 18, 2017 6:53 pm     Reply with quote

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:
Code:
bit_set(*0x05, 1);

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

View user's profile Send private message

PostPosted: Wed Apr 19, 2017 11:19 am     Reply with quote

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: 19219

View user's profile Send private message

PostPosted: Wed Apr 19, 2017 12:12 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Apr 19, 2017 12:19 pm     Reply with quote

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);
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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