EmbeddedRelated.com
Forums

LED Display Driver for use with PIC?

Started by Unknown December 7, 2004
On Thu, 09 Dec 2004 13:43:19 -0800, the renowned Noel Henson
<noel@noels-lab.com> wrote:

>Noel Henson wrote: > >> Spehro Pefhany wrote: >> >>> More than 10, counting save/restore context. But the order of >>> magnitude is correct. >>> >>> >>> Best regards, >>> Spehro Pefhany >> >> OK. Let's see how small we can make it. Perhaps it would make a good >> reference for others. >> >> I do love to make pins and ports do more than one thing so, let's consider >> 4 8-segment displays (7 plus a .) and 4 push-button switches for input. >> We'll only need 13 signals. >> >> Let's assume these variables: >> >> DIGIT3 the bit pattern for the left-most digit >> DIGIT2 the bit pattern for the left-center digit >> DIGIT1 the bit pattern for the left-center digit >> DIGIT0 the bit pattern for the right-most digit >> SELECT the shifter or counter >> >> Who wants to take the first stab at it? >> >> Noel > >I see that we need the code to support these functions: > > Initialize the timer > Enable the interrupt > Acknowledge the interrupt > Context save > Context restore > Index into the data storage array > Write the output > Scan the keys > >Did I miss anything? > >Noel
"Write the output" is typically composed of- fetch the new segment pattern, turn the old digit drive off, output the new segment pattern, turn the next digit drive on. You also have to increment the index modulo the number of digits. For "scan the keys", I'd put debouncing right in the ISR and also stuff any changes into a circular event queue, but that's just me. Best regards, Spehro Pefhany -- "it's the network..." "The Journey is the reward" speff@interlog.com Info for manufacturers: http://www.trexon.com Embedded software/hardware/analog Info for designers: http://www.speff.com
>Subject: Re: LED Display Driver for use with PIC? >From: Spehro Pefhany speffSNIP@interlogDOTyou.knowwhat
>>> Spehro Pefhany wrote: >>> >>>> More than 10, counting save/restore context. But the order of >>>> magnitude is correct.
>>> OK. Let's see how small we can make it. Perhaps it would make a good >>> reference for others. >>>
>>I see that we need the code to support these functions: >> >> Initialize the timer >> Enable the interrupt >> Acknowledge the interrupt >> Context save >> Context restore >> Index into the data storage array >> Write the output >> Scan the keys >> >>Did I miss anything? >> >>Noel
I did something similar recently for the pic16c870, 5 digits +6 buttons on 1 port with a 573 latch. The code wasn't written for smallest size just quick through the interrupt loop. Digit selection 14 instructions, digit drive and button read 6 instructions + a call to a 6 instruction macro + a call to a lookup table (bcd to 7 seg). Button debounce 6 instructions. Worst case time 28 instructions, best case time 22 instructions.
Spehro Pefhany wrote:

> On Thu, 09 Dec 2004 13:43:19 -0800, the renowned Noel Henson > <noel@noels-lab.com> wrote: > >>Noel Henson wrote: >> >>> Spehro Pefhany wrote: >>> >>>> More than 10, counting save/restore context. But the order of >>>> magnitude is correct. >>>> >>>> >>>> Best regards, >>>> Spehro Pefhany >>> >>> OK. Let's see how small we can make it. Perhaps it would make a good >>> reference for others. >>> >>> I do love to make pins and ports do more than one thing so, let's >>> consider 4 8-segment displays (7 plus a .) and 4 push-button switches >>> for input. We'll only need 13 signals. >>> >>> Let's assume these variables: >>> >>> DIGIT3 the bit pattern for the left-most digit >>> DIGIT2 the bit pattern for the left-center digit >>> DIGIT1 the bit pattern for the left-center digit >>> DIGIT0 the bit pattern for the right-most digit >>> SELECT the shifter or counter >>> >>> Who wants to take the first stab at it? >>> >>> Noel >> >>I see that we need the code to support these functions: >> >> Initialize the timer >> Enable the interrupt >> Acknowledge the interrupt >> Context save >> Context restore >> Index into the data storage array >> Write the output >> Scan the keys >> >>Did I miss anything? >> >>Noel > > "Write the output" is typically composed of- fetch the new > segment pattern, turn the old digit drive off, output the new > segment pattern, turn the next digit drive on. > > You also have to increment the index modulo the number of digits. > > For "scan the keys", I'd put debouncing right in the ISR and also > stuff any changes into a circular event queue, but that's just me. > > > Best regards, > Spehro Pefhany
'Write the output' could use a shift register so selecting the proper digit could be as easy as a shift but that would mean that other port bits could be affected in a destructive way; eg. rol PORTB. That would work in instances in which the other PORTB bits are inputs. Debouncing may or may not be necessary, depending upon the application. If one is needed, there is always the 'tried-and-true' counting approach. For an embedded application, I'd used flags instead of queues. They're much smaller. Cheers, Noel
CBarn24050 wrote:

>>Subject: Re: LED Display Driver for use with PIC? >>From: Spehro Pefhany speffSNIP@interlogDOTyou.knowwhat > >>>> Spehro Pefhany wrote: >>>> >>>>> More than 10, counting save/restore context. But the order of >>>>> magnitude is correct. > >>>> OK. Let's see how small we can make it. Perhaps it would make a good >>>> reference for others. >>>> > >>>I see that we need the code to support these functions: >>> >>> Initialize the timer >>> Enable the interrupt >>> Acknowledge the interrupt >>> Context save >>> Context restore >>> Index into the data storage array >>> Write the output >>> Scan the keys >>> >>>Did I miss anything? >>> >>>Noel > > I did something similar recently for the pic16c870, 5 digits +6 buttons on > 1 port with a 573 latch. The code wasn't written for smallest size just > quick through the interrupt loop. Digit selection 14 instructions, digit > drive and button read 6 instructions + a call to a 6 instruction macro + a > call to a lookup table (bcd to 7 seg). Button debounce 6 instructions. > Worst case time 28 instructions, best case time 22 instructions.
As mentioned before, "the order of magnitude is correct." Nice work. But if we were starting anew, how small could it be made? Noel
Noel Henson wrote:
> What took you so long? ;) What is the schematic? We'll need to know which > PIC pins do what. > > Noel > > PS: Nice work. Even an RS232 interface. > >
Thanks, I did this last year for a solar controller project. I need to locate the schematic, but I used port D for the segment drivers and port B ( 4 bits ) for the digit drivers. The interrupt was written in C. I fill a 4 byte array with the display values and set a flag. When the interrupt transfers all four bytes ( three digits and 4 LEDs ) to the display, I check the flag and update the display registers. ( another 4 byte array ) The interrupts run at 1 Milli-second. I turn off the digit drivers to blank the display, reload port D from the next location in the output array, then turn on the next digit driver. I also check the switches for any low bits, de-bounce the same bits and pass the key_value back to the main program. The interrupt runs at about 25 uSec for all of this. ( TEST_PNT is used as a timeing bit. ) 25 uSec out of every 1000 uSec = 2.5 % overhead. I also flash the digits without flashing the LEDs. I am sure it would be smaller code and faster ( less overhead ) but I wrote it over a weekend in C. // 1 mSec interrupts // run multiplex display void interrupt timer_0( void ) { TMR0 = -125; T0IF = 0; PORTB = 0x27; // turn off all digits TEST_PNT = 1; // running .1 sec timer if( !flash_cnt--) { flash_cnt = 100; tenth_sec_cntr++; if( !hund_count--) { hund_count =hund_count_input; if( flash_state_on ) flash_state_on=0; else flash_state_on=1; } } // display next digit if( mux_cntr == 0 ) { PORTD = DIGITS[ dsply_digit[0] ]; on_digit = ~0x01; // turn on hunds digit //digit_100 = 0; } else if( mux_cntr == 1 ) { PORTD = DIGITS[ dsply_digit[1] ]; on_digit = ~0x02; // turn on tens digit //digit_10 = 0; } else if( mux_cntr == 2 ) { PORTD = DIGITS[ dsply_digit[2] ]; on_digit = ~0x04; // turn on units digit //digit_1 = 0; } else if( mux_cntr == 3 ) { PORTD = dsply_digit[3]; on_digit = ~0x20; // turn on LEDs //digit_led = 0; if( dsply_flag ) { dsply_digit[0] = update_dsply[0]; dsply_digit[1] = update_dsply[1]; dsply_digit[2] = update_dsply[2]; dsply_digit[3] = update_dsply[3]; dsply_flag = 0; } } // check if blanking if( flash_state_on || cntr==3 ) PORTB = on_digit; // turn ON LED drive // shift too next digit mux_cntr++; mux_cntr &= 0x03; TEST_PNT = 0; // check buttons on ports RE0, RE1, RE2, AN3, AN4 }
>Subject: Re: LED Display Driver for use with PIC? >From: Noel Henson noel@noels-lab.com
>As mentioned before, "the order of magnitude is correct." Nice work. But if >we were starting anew, how small could it be made? > >Noel
I cant remeber the original spec now but lets say 4 digits with 4 buttons, buttons driven via a diode from the multiplex output feeding back to a single port pin. Digits and multiplex pattern alternated in the top 8 registers of a PIC 16c870. Button information returned in the msb of the multiplex register (only need the lower 4 bits for multiplexing). FSR reg dedicated to this thread (could be shared with care by other threads). Code in ISR something like movlw B'11111000' iorwf fsr,f movf 0,w movwf segment_port incf fsr,f movf 0,w movwf multiplex_port bcf 0,7 btfsc multiplex_port,7 ;(button input line) bsf 0,7 incf fsr,f Now I,ve written it I'll leave you to test and debug it. mo