Four-digit LED counter, multiplexingThe microcontroller operates as a four-digit counter here. Variable i is incremented (slow enough to be noticed) and its value is displayed on a four-digit LED display (9999-0). The objective is to convert a binary number into decimal and split it in four digits (thousands, hundreds, tens and ones). Since the LED display segments are connected in parallel, it is necessary to ensure that they change fast enough to make impression of simultaneous light emission (time-division multiplexing). In this example, timer TMR0 is in charge of the time-multiplexing, while the mask function is used to convert a binary number into decimal.
'Header****************************************************** program example_9 ' Program name dim shifter, portd_index as byte ' Variables shifter and portd_index are of byte type digit, number as word ' Variables digit and number are of word type portd_array as word ' Array portd_array has 4 members of word type sub function mask (dim num as Word) as Word ' Subroutine for masking select case num ' used to convert binary case 0 result = $3F ' numbers into appropriate case 1 result = $06 ' combination of bits to be case 2 result = $5B ' displayed on LED display case 3 result = $4F case 4 result = $66 case 5 result = $6D case 6 result = $7D case 7 result = $07 case 8 result = $7F case 9 result = $6F end select ' Case end end sub ' End of subroutine sub procedure interrupt ' Start of interrupt routine PORTA = 0 ' Turn off all 7-segment displays PORTD = portd_array [portd_index] ' Send appropriate value to PORTD PORTA = shifter ' Turn on appropriate 7-segment display shifter = shifter << 1 ' Move shifter to the next digit if (shifter > 8) then shifter = 1 end if Inc(portd_index) ' Increment portd_index if (portd_index > 3) then portd_index = 0 ' Turn on 1st, turn off 4th 7segment display end if TMR0 = 0 ' Reset TIMER0 value T0IF_bit = 0 ' Clear Timer0 interrupt flag end sub ' End of interrupt routine main: ' Start of program ANSEL = 0 ' Configure analog pins as digital I/O ANSELH = 0 OPTION_REG = $80 ' Timer0 settings (Timer0 work as timer with prescaler) digit = 0 ' Initial value of variable digit portd_index = 0 ' Turn on 1st LED display shifter = 1 ' Initial value of variable shifter TMR0 = 0 ' Clear Timer0 INTCON = $A0 ' Enable interrupt with GIE and T0IE bits PORTA = 0 ' Clear PORTA TRISA = 0 ' Set PORTA as output PORTD = 0 ' Clear PORTD TRISD = 0 ' Set PORTD as output number = 6789 ' Some initial value on LED display while TRUE ' Endless loop digit = number / 1000 ' Extract thousands portd_array = mask(digit) ' and store it to PORTD array digit = (number / 100) mod 10 ' Extract hundreds portd_array = mask(digit) ' and store it to PORTD array digit = (number / 10) mod 10 ' Extract tens portd_array = mask(digit) ' and store it to PORTD array digit = number mod 10 ' Extract ones portd_array = mask(digit) ' and store it to PORTD array Delay_ms(1000) ' One second delay Inc(number) ' Increment number if (number > 9999) then ' Start to count from zero number = 0 end if wend end. ' End of program