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 CCS Technical Support

IOC with the 18F45K50

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



Joined: 24 Apr 2014
Posts: 138

View user's profile Send private message

IOC with the 18F45K50
PostPosted: Mon Feb 10, 2020 5:10 pm     Reply with quote

Hi All,

I'm in the process of updating a design based on the 18F45K50. This design uses a rotary encoder type switch (with 'A' and 'B' outputs) and an integral SPST switch. I currently 'poll' these three inputs using a timer interrupt, and the functionality is 'adequate', but not 100%. I'm thinking that using the IOC functionality with improve the responsiveness of the rotary switch and SPST switch input.

So, I need three IOC inputs. According to the datasheet, these inputs can be found on B4:7 and C0:2. Pin C2 is out because I need PWM out as well. Pins B6 & B7 are out because I use ICSP.

Questions:

1. Can I use individual pins from both port B and port C to get the three IOC pins I need?

2. Can I use a different pin for PWM output?

3. Can I use the alternate ICSP clock and data pins?

4. Should I consider a different PIC that doesn't have these limitations? I do need USB functionality!

Sorry, I've been reading the datasheet to find these answers, but it's not clear enough for me to proceed with a new board design at this point!

Thanks,

Jack
temtronic



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

View user's profile Send private message

PostPosted: Mon Feb 10, 2020 9:09 pm     Reply with quote

While I don't use that PIC.....
1) Probably but may depend upon speed needed for the encoder and what else the PIC has to do.
2) Again, speed might be an issue (SW vs HW PWM).
3) If offered, yes, just be sure to program it correctly.
4) A 'bigger' PIC will always be better, even if it costs a little more.

Often not considered is the true cost of R&D. Say it's $100/hr. Option 'A', spend more than an hour TRYING to work out a USB 'bug'. Option 'B', buy a TTL-USB module for $1. USB can be problematic (layout, parts, code space), so an hour's wasted labour could have bought 100 pieces of troublefree INSTANT working USB. 'B' is what I've done. Sure I played with the 18F4550 when it came out but quickly realized it was better, faster, cheaper to use a premade module. OK, maybe after quantity of 500-1000pcs, it MIGHT be cheaper to have a PIC with integral USB. I've never done the 'break even' analysis.

The same hold for encoders. I've used LSICSI chips for decades, never had one fail. They, well, work...

For 'simple' upgrades, perhaps choose a faster running PIC ? Just be real careful about PCB layout, power supply, etc.

ICSP pins can be used for 'real world' interfacing, though I just use big PICs and dedicate them, cheaper in the overall picture.
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Wed Feb 12, 2020 3:42 am     Reply with quote

Now, questions. You talk about three pins for the encoder. Sounds as if
this is a 2 pin encoder, with a 'zero' switch pulse output?. If so, the third
pin doesn't want IOC. So wire this just to a normal interrupt RB0, 1 or 2.

Then IOC for the two encoder phase pins. C6 & C7 would be good.

Now a lot does depend on how fast this encoder may be changing.
How many pulses per rev?. What maximum shaft speed?. If the product
of these results in a high figure, then first the code itself for the interrupt
will start to become a little more complex, and if the figure gets really high
a hardware decoder may be the better choice.

Give us the encoder part number, and the maximum rotation rate. We
may then be able to give some advice.

Your pin numbers for IOC seem 'odd'. Data sheet has IOC on B4 to B7, and
C0 to C7 (missing C3 since this is VddCore).
JAM2014



Joined: 24 Apr 2014
Posts: 138

View user's profile Send private message

PostPosted: Wed Feb 12, 2020 4:41 pm     Reply with quote

Hi,

The rotary encoder is a CTE 290VAB0R201B2. Digikey was the supplier: https://www.digikey.com/products/en?keywords=ct3007-nd.

It has two quadrature outputs, 'A' and 'B', and a momentary switch.

This rotary switch is used to control a menu, and enter data. The momentary switch acts like an 'enter' key, while the rotary switch acts like a 'decrement' key (CCW), and an 'increment' key (CW). I'm not sure how to estimate the maximum shaft speed, maybe 120 RPM (2 revs./sec.)?

OK, the momentary switch seems well-suited to a normal interrupt, like RB0.

As for pin numbers for the IOC, the data sheet says the following:
Quote:

10.11 PORTB/PORTC Interrupt-on-Change: An input change on PORTB<7:4> or PORTC<2:0> sets flag bit IOCIF of the INTCON register.


Am I reading this incorrectly?

Thanks,

Jack
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Thu Feb 13, 2020 12:37 am     Reply with quote

Looks like a misprint. If you look at the IOCC register it has entries for
the whole of Port C. I'll look later at my datasheet and see if it has that line.
JAM2014



Joined: 24 Apr 2014
Posts: 138

View user's profile Send private message

PostPosted: Fri Feb 14, 2020 8:24 am     Reply with quote

Hi Ttelmah,

I agree there is a misprint. The text I quoted is in the current datasheet for the 18f45K50 device. I also note that the IOCC register map shows all port C pins, except C3, as IOC pins.

The question is, which one is correct?

Thanks,

Jack
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Fri Feb 14, 2020 9:32 am     Reply with quote

I'd say it's that one paragraph.
It is defined on all pins in too many other places. The IOCC register map.
The pin diagrams (all show IOCC0, 1, 2, 4, 5, 6, 7).
The pin descriptions (again all pins listed).
Then the register description for this as well.
I haven't got the K50 handy, but I seem to remember using the upper
pins for IOC a while ago.

Point it out to MicroChip. They are usually quick to answer an irregularity
like this, then you will know for sure. Very Happy
temtronic



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

View user's profile Send private message

PostPosted: Fri Feb 14, 2020 9:51 am     Reply with quote

My compiler is way too old, but, have a look at the 'processor header ' file to see what CCS thinks the PIC has to offer.
I assume IOC.3 isn't there because it's some form of USB pin ?

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Fri Feb 14, 2020 10:08 am     Reply with quote

It's the VDDCore regulator pin.

CCS doesn't have any support for these interrupt sources. You have to
set the bits in IOCB and IOCC yourself. All they give is the single INT_RB
interrupt triggered by these.
Unlike later chips where the mask bits allow you to also specify the edge
and CCS added support for these, this one is just like the old INT_RB
on the upper four bits of PORT B, but it also triggers on a number of
bits on PORT C. The question is 'how many'.... Very Happy
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Sat Feb 15, 2020 12:01 pm     Reply with quote

Sorry I'm "late to the party". The example code I wanted to post earlier in the week is only found at home, and since I'm now at home, here it is.

The following won't be complete because I'm not going to bother posting the LCD driver. That said, the LCD code is irrelevant anyway. This was a very simple example I would give to students in a lab environment many years ago. The encoder's A and B lines are routed to an 18F452's port B (port B interrupt on change). The code also sets up a timer to "race" the encoder. If it's turned slowly (timer wins), the code gives a slow change to whatever it is you are changing. If the encoder is turned quickly, the timer loses and that results in a faster change (larger increment/decrement) as the knob is turned.

Code:
#include <18F452.h>
#device adc=8
#use delay(clock=4000000,RESTART_WDT)
#fuses XT, BROWNOUT, BORV20, PUT, STVREN, NOLVP, WDT

#byte portb = 0xf81 // RAM address of port b
#use fast_io(B) // tells the compiler not to alter our direction register for port b

#include "lcd_driver.c"

int8 port_b_state, old_b_state = 3, count = 0, step;
int1 cw = FALSE, ccw = FALSE;

// want a simple program to display an 8 bit integer on the lcd, and if the knob is turned CW, the number increases,
// and if it is turned CCW, the number decreases
// want it to be intelligent - i.e. sense the rotation speed:  slow, increase/decrease by 1; fast, increase/dec by more than 1
// want to update the screen only when the knob is in the detent position

// we'll wire the encoder to the pic as follows:  A (left lead) to B4, B (right lead) to B5, and middle lead (COM) to GND
// CW:  3 2 0 1 3
// CCW: 3 1 0 2 3

#int_RB
RB_isr() {
   port_b_state = (portb & 0x30) >> 4; // read portb to clear the mismatch
   set_timer0(0); // user has beat the timer, so reset the timer
   switch (port_b_state) {
      case 0:
         if (old_b_state == 2) {
            step++;
         }
         else if (old_b_state == 1) {
            step++;
         }
         break;
      case 1:
         if (old_b_state == 0) {
            step++;
         }
         else if (old_b_state == 3) {
            step = 1; // user just started to turn the knob, so set step to 1 now
         }
         break;
      case 2:
         if (old_b_state == 3) {
            step = 1; // user just started to turn the knob, so set step to 1 now
         }
         else if (old_b_state == 0) {
            step++;
         }
         break;
      case 3: // knob is now in detent - okay to signal to update screen now
         if (old_b_state == 1) {
            cw = TRUE;
            step++;
         }
         else if (old_b_state == 2) {
            ccw = TRUE;
            step++;
         }
         break;
   }
   old_b_state = port_b_state; // save a copy of this state of portb, which will become our old state the next time thru
}

#int_RTCC
RTCC_isr() {
   if (step > 0) {
      step--; // the clock beat the human, take one away from step
   }
}

void main() {
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_wdt(WDT_ON);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32|RTCC_8_BIT); // overflows every 8 ms
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   enable_interrupts(INT_RTCC);
   enable_interrupts(INT_RB);
   enable_interrupts(GLOBAL);
   
   port_b_pullups(TRUE); // enable port b's pullups
   set_tris_b(0xff); // make portb all input
   
   set_tris_e(0x00); // need port E output for the lcd's control lines
   lcd_init();
   
   printf(lcd_putc,"\fCount = %03u",count); // %03u means print 3 digits, with leading zeroes
   
   while (TRUE) {
      restart_wdt();
      if (cw) {
         cw = FALSE; // cw means count up
         count = count + step; // add step to count
         lcd_gotoxy(9,1); // go to where count is actually being displayed
         printf(lcd_putc,"%03u",count); // ...and print it out
      }
      if (ccw) {
         ccw = FALSE;
         count = count - step; // subtract step from count
         lcd_gotoxy(9,1); // go to where count is actually being displayed
         printf(lcd_putc,"%03u",count); // ...and print it out
      }
   }
}
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