Sunday, December 6, 2015

Three-digit 7-segment display counter with multiplexing and shift register

Interface PIC12F1822 with 7 segment display

This example shows how to make a 3-digit counter using PIC12F1822. This counter counts from 0 to 999 and its value incremented when a push button is pressed. The 3 digits segments are connected in parallel which means they have to change fast(multiplexing). A serial-in parallel-out shift register is used in order to minimize number of used pins specially when a small microcontroller is used.
3-Digit 7-segment display and PIC12F1822 circuit:
Circuit schematic diagram is shown below.

pic12f1822 7 segment display mikroc

Internal oscillator of the microcontroller is used and MCLR pin function is disabled.
The push button is connected to RA3 pin. The shift register used is 74HC164 but other types can work properly like 74HC595 or CD4094.
In this example all pins of PIC12F1822 are used and there is no free pin.
3-Digit 7-segment display and PIC12F1822 mikroC code:
MikroC edit project configuration are shows below:

pic12f1822 7 segment display mikroc
 
 // 3-Digit 7-segment display counter
 // Used microcontroller: PIC12F1822
 // Written by: BENCHEROUDA Okba
 // electronnote@gmail.com
 // http://elecnote.blogspot.com/
 // Internal oscillator used @ 32MHz
 // Use at your own risk

unsigned short j, digit;
bit st;
unsigned i;
unsigned short mask(unsigned short num) {
switch (num) {
   case 0 : return 0xC0;
   case 1 : return 0xF9;
   case 2 : return 0xA4;
   case 3 : return 0xB0;
   case 4 : return 0x99;
   case 5 : return 0x92;
   case 6 : return 0x82;
   case 7 : return 0xF8;
   case 8 : return 0x80;
   case 9 : return 0x90;
  }
}
void main() {
 OSCCON = 0xF0; // Internal oscillator 8MHz and PLL enabled (gives 32MHz)
 ANSELA = 0;    // All I/O pins are configured as digital
 ADCON0 = 0;    // Disable ADC module
 PORTA = 0;     // Initial value of port A bits
 TRISA = 8;
 OPTION_REG = 0;
 WPUA = 8;     // Enable pull-up resistor for RA3
  PORTA = 7;
 while(1){
  if (PORTA.F3)
  st = 1;
  if(st == 1)
  if (!PORTA.F3){
   i++;
   st = 0;
   }
  if (i > 999)
    i = 0;
  PORTA = 7;            // Turn off all displays
  digit = i % 10;
  digit = mask(digit);
  for ( j = 1; j < 0x80; j = j << 1){
    if(digit & j)
      PORTA.F4 = 1;
    else
      PORTA.F4 = 0;
    Delay_us(10);
    PORTA.F5 = 1;
    Delay_us(10);
    PORTA.F5 = 0;
  }
  PORTA = 3;            // Turn on display for ones
  Delay_ms(5);
  PORTA = 7;             // Turn off all displays
  digit = (i / 10) % 10;
  digit = mask(digit);
  for ( j = 1; j < 0x80; j = j << 1){
    if(digit & j)
      PORTA.F4 = 1;
    else
      PORTA.F4 = 0;
    Delay_us(10);
    PORTA.F5 = 1;
    Delay_us(10);
    PORTA.F5 = 0;
  }
  PORTA = 5;            // Turn on display for tens
  Delay_ms(5);
  PORTA = 7;             // Turn off all displays
  digit = (i /100) % 10;
  digit = mask(digit);
  for ( j = 1; j < 0x80; j = j << 1){
    if(digit & j)
      PORTA.F4 = 1;
    else
      PORTA.F4 = 0;
    Delay_us(10);
    PORTA.F5 = 1;
    Delay_us(10);
    PORTA.F5 = 0;
  }
  PORTA = 6;           // Turn on display for hundreds
  Delay_ms(5);
 }
}

3-Digit 7-segment display and PIC12F1822 example video: