Yup, agreed with most of the discussion here.
Let's look the connection from PIC pin to 7-segment on PTK40A. As hyng and robosang highlighted, there are plenty of method to use 7-segment, direct IO to each segment. and for more than 1one 7-segment, you can either use multiplexing using transistor or encoder such as CD4511. PTK40A uses 4511 to encode and latch the 7-segment output.
Looking at the schematic for the 7-segment section, you will notice that RD0 to RD3 is connected to four input pin of 4511 which will decide the output on 7-segment, either blank, to display 0 to 9.
while the LT and BL is being pullup to 5V, we will utilize the LE (Latch Enable) to offer multiplex two 7-segment since both 4511 is connected to same four output from PIC (RD0 to RD3)
one 7-segment can only display digit from 0 to 9 according to the true table above and the digit is related to input at D0, D1, D2 and D3 (schematic). Yes, moving 1 to PORTD will display 1 at 7-segment, but moving 10 to PORTD will not display '1' and '0' at 7-segment. We need to utilize the latch and also to single digit, if the value is 10, it should be '1' for 1st 7-segment and '0' for 2nd 7-segment.
Please refer to the 7seg.c for the function that you can use.
- CODE: SELECT_ALL_CODE
/* The protocol for the CD4511
LE D C B A a b c d e f g Display
0 0 0 0 0 1 1 1 1 1 1 0 '0'
0 0 0 0 1 0 1 1 0 0 0 0 '1'
0 0 0 1 0 1 1 0 1 1 0 1 '2'
0 0 0 1 1 1 1 1 1 0 0 1 '3'
0 0 1 0 0 0 1 1 0 0 1 1 '4'
0 0 1 0 1 1 0 1 1 0 1 1 '5'
0 0 1 1 0 0 0 1 1 1 1 1 '6'
0 0 1 1 1 1 1 1 0 0 0 0 '7'
0 1 0 0 0 1 1 1 1 1 1 1 '8'
0 1 0 0 1 1 1 1 0 0 1 1 '9'
0 1 0 1 0 0 0 0 0 0 0 0 ' ' (blank)
0 1 0 1 1 0 0 0 0 0 0 0 ' ' (blank)
0 1 1 0 0 0 0 0 0 0 0 0 ' ' (blank)
0 1 1 0 1 0 0 0 0 0 0 0 ' ' (blank)
0 1 1 1 0 0 0 0 0 0 0 0 ' ' (blank)
0 1 1 1 1 0 0 0 0 0 0 0 ' ' (blank)
1 X X X X * * * * * * * '*' (depend on the value at ABCD during LE from 0 to 1
X = Don't care
* = special condition
/*******************************************************************************
* PUBLIC FUNCTION: seg7_initialize
*
* PARAMETERS:
* ~ void
*
* RETURN:
* ~ void
*
* DESCRIPTIONS:
* Initialize and clear the 7 segment LED
*
*******************************************************************************/
void seg7_initialize(void)
{
S7_L1 = 0;
S7_L2 = 0;
S7_DATA = (S7_DATA & 0xf0) | 0x0A;
__delay_ms(1); //delay for a while
S7_L1 = 1; //holding the state before this, which is blank
S7_L2 = 1; //holding the state before this, which is blank
S7_DATA = S7_DATA & 0xf0;
}
/*******************************************************************************
* PUBLIC FUNCTION: seg7_1_dis(unsigned char uc_number)
*
* PARAMETERS:
* ~ uc_number which will be display on 7 segment, 0 to 9, other value will result in blank.
*
* RETURN:
* ~ void
*
* DESCRIPTIONS:
* Display the value of uc_number on 7 segment 1 and hold it
*
*******************************************************************************/
void seg7_1_dis(unsigned char uc_number)
{
S7_L1 = 0;
S7_DATA = (S7_DATA & 0xf0) | uc_number;
__delay_ms(1); //delay for a while
S7_L1 = 1; //holding the state before this, which is the uc_number
S7_DATA = S7_DATA & 0xf0;
}
/*******************************************************************************
* PUBLIC FUNCTION: seg7_2_dis(unsigned char uc_number)
*
* PARAMETERS:
* ~ uc_number which will be display on 7 segment, 0 to 9, other value will result in blank.
*
* RETURN:
* ~ void
*
* DESCRIPTIONS:
* Display the value of uc_number on 7 segment 2 and hold it
*
*******************************************************************************/
void seg7_2_dis(unsigned char uc_number)
{
S7_L2 = 0;
S7_DATA = (S7_DATA & 0xf0) | uc_number;
__delay_ms(1); //delay for a while
S7_L2 = 1; //holding the state before this, which is the uc_number
S7_DATA = S7_DATA & 0xf0;
}
/*******************************************************************************
* PUBLIC FUNCTION: seg7_com_dis(unsigned char uc_number)
*
* PARAMETERS:
* ~ uc_number which will be display on both 7 segment, 0 to 99, other value will result in blank.
*
* RETURN:
* ~ void
*
* DESCRIPTIONS:
* Display the value of uc_number on both 7 segment and hold it
*
*******************************************************************************/
void seg7_com_dis(unsigned char uc_number)
{
if(uc_number > 99)
{
seg7_1_dis(0x0A); //blank
seg7_2_dis(0x0A); //blank
}
else
{
seg7_1_dis(uc_number%10); //display the 1st 10 based digit
seg7_2_dis(uc_number/10); //display the 2nd 10 based digit
}
}
Not to forget the point highlighted by Brian, robosang and shahrul, switch deboucing and checking routine.