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 interrupt on change
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
vtrx



Joined: 11 Oct 2017
Posts: 140

View user's profile Send private message

PORTB interrupt on change
PostPosted: Wed Jun 29, 2022 5:29 pm     Reply with quote

I'm testing some routines for reading a rotary encoder.
I intend to use the example from the link, but using the 18F45K50.
https://simple-circuit.com/pic18f46k22-rotary-encoder-7-segment-ccs/

the example defines:
#BYTE IOCB = 0x0F62 register address,but in the datasheet I didn't find this reference, I found 0x0F86.
what is the reference for the 18F45K50?
the code works with both(0x0F62/0x0F86 ).
PCM programmer



Joined: 06 Sep 2003
Posts: 21687

View user's profile Send private message

PostPosted: Wed Jun 29, 2022 6:30 pm     Reply with quote

The example code uses 18F46K22. It uses 0xF62 for the IOCB register.

Your PIC is the 18F45K50. It uses 0xF86 for the IOCB register address.

Different PICs. Different addresses.
Ttelmah



Joined: 11 Mar 2010
Posts: 18376

View user's profile Send private message

PostPosted: Thu Jun 30, 2022 12:18 am     Reply with quote

And, this is why in recent years, we have tended to advise people to use
the compiler's ability to locate registers by name, rather than coding an
address into the program:

#BYTE IOCB = getenv("SFR:IOCB")

Makes the program much more portable and easy to move from chip
to chip.

It is 'interesting' that it works with either. The address is listed as UCNFG
(presumably 'unconfigured'), but that it works, suggests it may have a
'ghost' copy of the IOCB register actually there!...
temtronic



Joined: 01 Jul 2010
Posts: 8701
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Jun 30, 2022 5:41 am     Reply with quote

Hay Mr. T...

where did you see the UNCFG for the address ?

My datasheet copy...
DS40001412G-page 82

also looked at the PortB reg stuuf, IOC area, can't see 'UNCFG'
either I'm going more blind or maybe you have a different version of the datasheet ?

jest curious

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 18376

View user's profile Send private message

PostPosted: Thu Jun 30, 2022 7:06 am     Reply with quote

The whole point is it is not the interrupt on change area.

On the 48K22, the IOCB register is 0xF62. In the 45K50, the IOCB
register is 0xF86. If you look at 0xF62, in the register listing for the
45K50, (and only here), it says UNCFG. Doesn't refer to it anywhere
else.
Now what is interesting is that the poster found that this did work as
well. Suggests that it does actually contain a ghost copy of the register.
JAM2014



Joined: 24 Apr 2014
Posts: 137

View user's profile Send private message

PostPosted: Thu Jun 30, 2022 7:54 am     Reply with quote

Hi All,

To the OP, have you see this thread?: http://www.ccsinfo.com/forum/viewtopic.php?t=59778

It's a complete, working example of using a rotary encoder with the PIC you are using.

Also, why mess with manipulating individual registers? Look at the .h file for this PIC, and you'll see that CCS supports enabling individual pins on Port B for IOC. I'm not sure why doing it otherwise is being suggested here? You'll note that the example code does not manipulate the IOCB register directly.

Jack
temtronic



Joined: 01 Jul 2010
Posts: 8701
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Jun 30, 2022 7:57 am     Reply with quote

OK, now it makes sense, needed to look at the 45K50 regs NOT the 46K22.

too many PICs !!
vtrx



Joined: 11 Oct 2017
Posts: 140

View user's profile Send private message

PostPosted: Thu Jun 30, 2022 3:49 pm     Reply with quote

I tested four codes and the best one for my hardware was the one in the link I posted, but sometimes the count 'fails' in 1 step.
temtronic



Joined: 01 Jul 2010
Posts: 8701
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Jun 30, 2022 5:47 pm     Reply with quote

simple test...
increase the clock ! It's only 8MHz, chip is good for 64 MHz though you'll have to recalculate the timer values...
Ttelmah



Joined: 11 Mar 2010
Posts: 18376

View user's profile Send private message

PostPosted: Fri Jul 01, 2022 12:21 am     Reply with quote

Have you a data sheet for the encoder you are using?.
If so, post a link.

There is always the potential to miss a count, if the encoder does not
guarantee a minimum pulse width, in the situation when you reverse
direction. If the encoder does give such a guarantee, then the key is
to design the handler to be able to deal with this minimum time.
Going faster will help massively to do this.

Do you need to use any other interrupt at the same time?. Remember
you can use polling for a lot of things. If not, then the fastest encoder
'possible' (though at this point somebody will post a version that is faster),
is the routine I published some years ago, and then copied here:

http://www.ccsinfo.com/forum/viewtopic.php?t=44491

This has in the past merrily handled a 10000 line encoder at up to 100RPM
and has never missed a count (always precisely re-indexing when the
system goes back to zero), on a PIC at 40MHz, for now in some cases
over twenty years.
temtronic



Joined: 01 Jul 2010
Posts: 8701
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Jul 01, 2022 6:00 am     Reply with quote

hmm encoder.....
wondering how 'clean' the signals are from it ?
if 'noisy', that can lead to miscounts...
perhaps stiffer pullups, use an ST buffer ??
vtrx



Joined: 11 Oct 2017
Posts: 140

View user's profile Send private message

PostPosted: Fri Jul 01, 2022 8:52 am     Reply with quote

I found this method, reading is very fast, I changed it to use interrupt on change.
There is a problem, the result jumps two values, eg 1,3,5,7 both forward and backward.
Any ideas how I can get around this?

Code:
#include <18F45K50.h>
...
#use delay(int, clock=48MHz, USB_FULL, act=USB)
...
#use fast_io(b)
...
#BYTE IOCB = getenv("SFR:IOCB")
...

 int16 counter = 0;
 int8 currentStateCLK;
 int8 previousStateCLK;
...
#INT_RB    // PORTB interrupt on change ISR
void RB_IOC_ISR(void)
{
   // Read the current state of inputCLK
   currentStateCLK = input_state(PIN_B4); //clk
      clear_interrupt(INT_RB);    // clear RB IOC flag
   
   // If the previous and the current state of the inputCLK are different then a pulse has occured
   if (currentStateCLK != previousStateCLK){
       
     // If the inputDT state is different than the inputCLK state then
     // the encoder is rotating counterclockwise
     if (input_state(PIN_B7) != currentStateCLK) {
       counter -= 1;
       
     } else {
       // Encoder is rotating clockwise
       counter += 1;
     }

   }
   // Update previousStateCLK with the current state
   previousStateCLK = currentStateCLK;

}
//-----------------------------------------------------------------------------
void main(void)
 {
   SETUP_ADC(ADC_OFF);
   setup_adc_ports(NO_ANALOGS);
   setup_comparator(NC_NC_NC_NC);
   SETUP_CCP1(CCP_OFF);
   SETUP_CCP2(CCP_OFF);
   port_b_pullups(0b11111111);
...
   enable_interrupts(GLOBAL);      // enable global interrupts
   clear_interrupt(INT_RB);    // clear RB IOC flag
   enable_interrupts(INT_RB);  // enable RB IOC
   IOCB = 0b00010000;                // enable RB4 & RB7 IOC
  currentStateCLK = input(PIN_B4); //clk
    while(true)                     
     {
        usb_task();
        usb_debug_task();
//.............................................................................       
        if(usb_enumerated())
           {
            if(usb_kbhit(1))
               {
                usb_get_packet(1, in_data,USB_EP1_RX_SIZE);
                if(in_data[0] =='4')
                  {
                   out_data[0] = make8(counter,1);
                   out_data[1] = make8(counter,0);                 
                   usb_put_packet(1,out_data,USB_EP1_TX_SIZE,USB_DTS_TOGGLE);
                  }
                if(in_data[0] =='5')
                  {
                 
                  }                 
              }
           }
//.............................................................................
       delay_ms(5);
    }
}
...


I intend to use a joystick interface, the result is transferred using USB HID.
I'm monitoring the results using my own program that makes the HID reading of the result every 5 milliseconds.
I did a test disabling the interrupt and using the reading inside the loop to check if there were two interrupts in a row, but it didn't change anything.
Ttelmah



Joined: 11 Mar 2010
Posts: 18376

View user's profile Send private message

PostPosted: Fri Jul 01, 2022 10:06 am     Reply with quote

Two values for what?.

Understand that the normal use for a quadrature interface, would give
four counts for a single cycle of either signal. Four edges. This is the
'quad' bit of quadrature. A single count is a single edge on either of the
two signals.
Now you are only triggering off one signal, so a 'birature' count would
be expected. Two counts for a single pulse. One on the rising edge, and
one on the falling edge. So if you are testing with your own pulse, two
counts would be expected for a single pulse.
vtrx



Joined: 11 Oct 2017
Posts: 140

View user's profile Send private message

PostPosted: Sun Jul 03, 2022 8:37 am     Reply with quote

I'll use the code from the link, it was the best for my hardware.
https://simple-circuit.com/pic18f46k22-rotary-encoder-7-segment-ccs/
I used two rotary encoders using the interrupt in portB, I couldn't use three because the 18F45K50 only uses the interrupt for change of state in the RB4...RB7.
Ttelmah



Joined: 11 Mar 2010
Posts: 18376

View user's profile Send private message

PostPosted: Mon Jul 04, 2022 12:52 am     Reply with quote

You have IOC available on Port C as well. C0, C1, C2, C4, C5, C6, C7.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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