Saturday, October 10, 2009

Experiment No. 5: Multiplexed Seven Segment Displays

In this experiment, we are going to learn how to interface more than one 7-segment LED display to a PIC Port using multiplexing technique. We are going to interface a 4-digit common cathode seven segment display to our PIC board. The multiplexing circuit is already built up in the board using 4 transistors and few resistors (Read Make Your Own PIC Development Board). The basic idea of multiplexing is that all seven segment displays are connected to the microcontroller in parallel and the microcontroller alternately prints ones, tens, hundreds, and thousands digits, selecting one at a time. The switching among the digits is so fast that it gives an impression of simultaneous light emission.

Experimental Setup:

1. Connect RA0 through RA3 to 7-Segment Digit Select headers DG1, DG2, DG3, and DG4 using jumper wires.
2. Insert 7FR5641AS 4-Digit Seven Segment module in to its place on the board.




Software:
/*
 * Project name:
     4-Digit UP Counter with Four 7-Segment Display Multiplexing
 * Copyright:
     (c) Rajendra Bhatt, 2009.
 * Description:
     This code is an example of multiplexing 4 Seven Segment Displays.

 * Test configuration:
     MCU:             PIC16F628A
     The common cathode of four seven segment dispalys are
     connected to RA0, RA1, RA2 and RA3
*/
//-------------- Function to Return mask for common cathode 7-seg. display
unsigned short mask(unsigned short num) {
  switch (num) {
    case 0 : return 0x3F;
    case 1 : return 0x06;
    case 2 : return 0x5B;
    case 3 : return 0x4F;
    case 4 : return 0x66;
    case 5 : return 0x6D;
    case 6 : return 0x7D;
    case 7 : return 0x07;
    case 8 : return 0x7F;
    case 9 : return 0x6F;
  } //case end
}
unsigned short i, DD0, DD1, DD2, DD3, NUM  ;
void main() {
  CMCON  |= 7;      // Disable Comparators
  TRISB = 0x00;    // Set PORTB direction to be output
  PORTB = 0xff;    // Turn OFF LEDs on PORTB
  TRISA0_bit = 0;  // RA.0 to RA3 Output
  TRISA1_bit = 0;
  TRISA2_bit = 0;
  TRISA3_bit = 0;
  TRISA4_bit = 1;      // RA.4 is Input only

  NUM   =    0;  // Initial Value of Counter

  do {
  DD0 = NUM%10;  // Extract Ones Digit
  DD0 = mask(DD0);
  DD1 = (NUM/10)%10; // Extract Tens Digit
  DD1 = mask(DD1);
  DD2 = (NUM/100)%10; // Extract Hundreds Digit
  DD2 = mask(DD2);
  DD3 = (NUM/1000);  // Extract Thousands Digit
  DD3 = mask(DD3);

  for (i = 0; i<=50; i++) {
      PORTB = DD0;
      RA0_bit = 1;          // Select Ones Digit
      RA1_bit = 0;
      RA2_bit = 0;
      RA3_bit = 0;
      delay_ms(5);
      PORTB = DD1;
      RA0_bit = 0;
      RA1_bit = 1;        // Select Tens Digit
      RA2_bit = 0;
      RA3_bit = 0;
      delay_ms(5);
      PORTB = DD2;
      RA0_bit = 0;
      RA1_bit = 0;
      RA2_bit = 1;         // Select Hundreds Digit
      RA3_bit = 0;
      delay_ms(5);
      PORTB   = DD3;
      RA0_bit = 0;
      RA1_bit = 0;
      RA2_bit = 0;
      RA3_bit = 1;         // Select Thousands Digit
      delay_ms(5);
      }
      NUM = NUM + 1 ;
  } while(1);                             // endless loop
}

Experimental Output Video:


9 comments:

  1. Hi Raj this project is very helpfull for me in stepping into programming BCD 7 segment project .I manage to run this code well on my board, thanks a lot. Raj, i am also looking to apply timers/interrupt concept to run the same project, could you please post any codes on for this projects applying timers/interrupts?

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. I built a dev board based on your posting but my 4 7-segment leds show 4 zero's and counts to 255 then resets and starts over.... any idea?

    ReplyDelete
  4. This is because the variable NUM is defined as unsigned short (which is 8-bit), so it can hold values only up to 255. Try replacing

    unsigned short i, DD0, DD1, DD2, DD3, NUM ;

    with

    unsigned short i, DD0, DD1, DD2, DD3;
    int NUM;

    and see what happens.

    ReplyDelete
  5. How to drive only using MPLAB assembly code?

    ReplyDelete
  6. Hello RAJ
    Can you please tell me what changes are to be made in above program while using a common anode multiplexed seven segment display?

    ReplyDelete
  7. For common anode display, first you need to make some changes in the circuit (which I hope you would be able to do). Next you have to redefine the return values in the mask() function. Here are the changes:

    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 0x7D;
    case 7 : return 0x82;
    case 8 : return 0x80;
    case 9 : return 0x90;
    } //case end
    }

    ReplyDelete
  8. Thanks for telling changes in software. In hardware, I used NPN transistors to switch all segments of the seven segment Display and I connected the selector pins directly to PORTA pins. Can you please tell me whether I changed my hardware correctly or there are to be some further modifications in the hardware?

    Thanks in anticipation.

    ReplyDelete
  9. Sorry, I have made mistake with number 6 & 7. The correct numbers for Common Anode are
    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;
    } //case end

    ReplyDelete

Microcontroller-based Embedded Systems Design