Skip to content

Interrupt Driven 8-Digit Rotary Encoder Counter

This example C code can be used to implement a completely interrupt driven rotary encoder counter (incremental type)  using PIC16FXXX microcontrollers built-in timers and counters. This code was written in 2005 for a simple factory automation project I did. The code is written for HI-TECH PIC16 compilers. The microcontroller used was PIC16F877A. Note: This program supports only uni-directional counting. The encoder output should is connected to TMR1 module’s input pin (PORTC1).

Simple 8-digit SSD counter for PIC16 microcontrollers
To be compiled with HI-TECH PIC16 Compilers
Freely distributable in this original form.
(c) 2006 Pasan Hettiarachchi
(c) Microsolutions
Any questions or comments?

counting and displaying is completely interrupt driven.
Timer1 is used as the rotary encorder counter,
and Timer0 is used to scan the SSD display

#include <pic.h>


//following four lines defines pins used for seven digit SSD dispaly.
#define segments PORTB           //segments pins are connected (common anode SSD) to PORTB
#define segmentsDataDir TRISB	//segments pins data direction (should be outputs)
#define digitSelect PORTD		//digit selection transistors (PNP for common anode) are connected to PORTD
#define digiSelectDir TRISD		//digit select pins data direction (should be outputs)

unsigned long count;     //variable to hold the rotary encoder count
//segment data to display 0-9
unsigned char SSD[]={0xC0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
unsigned char digits[8];

/*Only one digit selection pin is 0 at a given time (for common anode type displays)
i.e. only one digit is displayed at a given time */

unsigned char digipattern[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

void interrupt myISR();

//the variable tmr1Rest together with 16bit Timer1 module makes a 32bit count possible
volatile unsigned int tmr1Rest; //Declared volatile because used in an interrupt handler

void decodeDigits();

void main(){

	tmr1Rest=0;			//intializing counter variables
	count=0;			//intializing counter variables

	while(GIE==1) GIE=0;			//Turn all interrupts off
	TMR1ON=0;			//Turn off timer1

	TRISC0=1;			//Rotary encoder input
	OPTION=0b11000100;	//timer0 internal clock
						//prescaler assigned to timer 0
	TMR1CS=1;			//External input to counter(Counter mode)
	T1SYNC=0;			//Synchronous timer
	T1OSCEN=0;			//external Oscillator is disbled
	tmr1Rest=0;			//Initialise Counter to 0
	TMR1L=0;			//Initialise Counter
	TMR1H=0;			//Initialise Counter

	PEIE=1;				//Peripheral interrupts are enabled
	TMR1IE=1;			//Timer1 interrupt is enabled(will be triggered when counter overflows)
	T0IE=1;				//Timer0 interrupt is enabled(will be triggered when counter overflows)

	segmentsDataDir=0x00;  //making port pins connected to SSD segments as outputs
	digiSelectDir=0x00;	   //making port pins connected to digit select transistors as outputs

	segments=0;				//segments are turned off
	digitSelect=0xff;		//digits are turned off

	GIE=1;					//Turn on interrupts
	TMR1ON=1;				//Turn on Timer1 counter

		//count is the 32bit long integer holding the rotary encoder count
		*(((unsigned char *)&count))=TMR1L;		//pointer arithmatic to access Word and bytes of a long integer
		*(((unsigned char *)&count)+1)=TMR1H;
		*(((unsigned int *)&count)+1)=tmr1Rest;


void decodeDigits(){
	unsigned long temp3;
	unsigned int temp;
	unsigned char temp2;
	digits[7]=count/10000000;	// 10 millionth digit
	digits[6]=temp3/1000000;	// millionth digit
	digits[5]=temp3/100000;		// 100 thousand's digit
	digits[4]=temp3/10000;		// ten thousand's digit

	digits[3]=temp3/1000;		// thousand's digit

	digits[2]=temp/100;		    // hundred's digit
	digits[1]=temp2/10;			// 10's digit
	digits[0]=temp2%10;			// 1's digit

void interrupt myISR(){
	unsigned char digit;

	if (TMR1IF){

	if (T0IF){
		if (digit==8) digit=0;
		digitSelect=0xff;				//turn off all digits to prevent ghosting

Download the source code: 8-digit counter

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.