CIRCUIT DIAGRAM
SOURCE CODE
#include <xc.h>
#define _XTAL_FREQ 4000000L
void port_initialise(void);
void DelayMs(unsigned int msCount);
#pragma config WDTE = OFF
#pragma config FOSC = HS
#pragma config PWRTE = ON
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config DEBUG = ON
#pragma config CP = OFF
const char SegLookUp[]={0x3f,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
unsigned char Digit1=1,Digit2=2; // digit1 and Digit2 holds the values to be discplayed
#define Digit1_En PORTBbits.RB0
#define Digit2_En PORTBbits.RB1 // digits enable transistor control
void main (void)
{ // main loop starts-------------
port_initialise(); // setting up I/O lines as input and output
Digit1=1;Digit2=2;
while(1) // Normally, every MCU programe is a never ending loop. here starts it
{ //while 1 loop starts----------
Digit2_En=0;
PORTD=SegLookUp[Digit1]; //SeglookUp is a array which hilds-
Digit2_En=1; // -the segment pattern for every digit.
DelayMs(10);
Digit2_En=0;
PORTD=SegLookUp[Digit2]; //SeglookUp is a array which hilds-
Digit1_En=1; // -the segment pattern for every digit.
DelayMs(1);
Digit1_En=0;//*******************//both the digits are illuminated once
} //while 1 loop ends------------
} // main loop ends--------------
void port_initialise (void)
{
TRISD = 0X00; // LED port is made as output
PORTD = 0X00; // and cleared
ADCON1 = 0b00000100; // A/D module not ued.All pins digital
TRISA = 0b00101011;
TRISE = 0B00000111;
PORTE = 0X00;
TRISB = 0B00000000;
PORTB = 0X00 ;
LEDenable=0;
}
void DelayMs(unsigned int msCount)
{
unsigned int locCnt;
for(locCnt=0;locCnt<=msCount;locCnt++)
{
__delay_ms(1); // This XC8 function creates a delay of 1 millisecond
} // looping this msCount times will give that much milliseconds delay
}
SOURCE CODE
#include <xc.h>
#define _XTAL_FREQ 4000000L
void port_initialise(void);
void DelayMs(unsigned int msCount);
#pragma config WDTE = OFF
#pragma config FOSC = HS
#pragma config PWRTE = ON
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config DEBUG = ON
#pragma config CP = OFF
const char SegLookUp[]={0x3f,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
unsigned char Digit1=1,Digit2=2; // digit1 and Digit2 holds the values to be discplayed
#define Digit1_En PORTBbits.RB0
#define Digit2_En PORTBbits.RB1 // digits enable transistor control
void main (void)
{ // main loop starts-------------
port_initialise(); // setting up I/O lines as input and output
Digit1=1;Digit2=2;
while(1) // Normally, every MCU programe is a never ending loop. here starts it
{ //while 1 loop starts----------
Digit2_En=0;
PORTD=SegLookUp[Digit1]; //SeglookUp is a array which hilds-
Digit2_En=1; // -the segment pattern for every digit.
DelayMs(10);
Digit2_En=0;
PORTD=SegLookUp[Digit2]; //SeglookUp is a array which hilds-
Digit1_En=1; // -the segment pattern for every digit.
DelayMs(1);
Digit1_En=0;//*******************//both the digits are illuminated once
} //while 1 loop ends------------
} // main loop ends--------------
void port_initialise (void)
{
TRISD = 0X00; // LED port is made as output
PORTD = 0X00; // and cleared
ADCON1 = 0b00000100; // A/D module not ued.All pins digital
TRISA = 0b00101011;
TRISE = 0B00000111;
PORTE = 0X00;
TRISB = 0B00000000;
PORTB = 0X00 ;
LEDenable=0;
}
void DelayMs(unsigned int msCount)
{
unsigned int locCnt;
for(locCnt=0;locCnt<=msCount;locCnt++)
{
__delay_ms(1); // This XC8 function creates a delay of 1 millisecond
} // looping this msCount times will give that much milliseconds delay
}
EXPLANATION
Our Seven
Segment LED display is having two digits. Each digit is 7 small segments-like
LEDs arranged to form the shape of numeral 8. There is one more led in each
digit block which is dot for showing decimal place if needed in the
application. So total 8 LEDs and their anodes are routed out through separate
pins and all the cathodes are shorted and bought out to form a common cathode.
So by selectively supplying to potential to different segment leds we can show
numerals from 0 to 9 in these digits. The PORTD from 16F877A is connected to
the segments so that we can show different numerals and thus numbers.
But we have to tackle another issue. We have two
digits-and 16 segments to lit up. That means 16 pins of MCU needs to be
connected to these digits which is highly impractical considering the low pin
count available on most of the MCUs. So a special system of display
multiplexing is used. In this case please refer the schematics to note down
that both the Digits have the same positioned segments shorted together which
means when we apply +5V from the pin of MCU , a particular segment in both
digits will light up which will jeopardize the entire purpose. We will make a
workaround using selectively switching the digits via two transistors.actually
these are providing the ground return path for the segment currents of the
corresponding digits. So we can place a digit pattern in both digits
simultaneously, but switch on one transistor only , then only one digit will
illuminate. Then we now have the capability to show different values in each
digit.
But that doesn’t permit us to show different values in
digits concurrently with hardware mechanism only. As we have already hinted our
human eyes have a ‘defect’ which we admirably called as ‘persistence of
vision’. So we will exploit that defect to our advantage here as lumiere
brothers did in the case of motion pictures.
We will show one value in one digit for a brief time
using that digit enabling transistor, then switch of that transistor, put the
value for next digit and enable the next transistor. Now the second digit will
lit up, showing its value. We then again lit the first digit with its value,
OFF it , lit the next digit, OFF it then, and keep it doing again and again. If
we can do it in such a high speed our eyes cannot detect the digit getting on
and off .Then we will see steady display as both digits are continuously on.
This technique is called Seven Segment display multiplexing. Many multi-digit displays
are working on this mechanism with very rare exceptions.
So we can place each digit value in Segments one by
one and switch corresponding digits ON to get a consistent display. But the
values we need to showare digits which are numerical values from 0 to 9. They,
if moved to port and thereby to segments, will not produce the pattern for
numerals in that digit block. For example suppose the value to be shown is 1,
if we moved it to port only 1 led will light, which is not the pattern for 1.
To show 1 we need to illuminate two segments on the right side of the digit. So
we need to derive a mechanism which can derive digit patterns from values we
increment or decrement which is to be shown.
We can use an array in C for that purpose which is
placed in the Program memory space.
const char
SegLookUp[]={0x3f,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
This is actually an array which will return a value
depending on the index.(See C tutorial). If we need the pattern of 0,
SegLookUp[0] will give you the pattern. 0x3F is that value and if it is moved
to Segments the digit block will light up as 0 and if SegLookUp[9] 0x6F will
show 9.
Actually only one press was intended. So we need a
mechanism to slow down the controller’s detection speed to make at par with
human operating speeds. That is the concept of Keyboard De bounce. The first
option comes to our mind will be a delay after a key press detection and it is
perfectly plausible in some cases. But in our case it is not a viable solution
as seven segment display is also present.
Let us see how our program is executing. All MCU
programs are generally never ending loops. So our MCU will check switch, if
detected (Pressed) increment or decrement and conduct seven segment display
–then back to check switch – manipulate digit- conduct display like that. this
is our never ending loop. The loop speed is adjusted in such a way that the
seven segment digits are illuminated with values so frequently that our eyes
wont detect the flicker. Considering the human eye characteristics plus the
possibility of stroboscopic effect from the AC line frequency (Which obviously
we are using to power these devices), the usual multiplexing frequency
preferred is just above 50Hz. So both digits should light up at least once in
every 20 milliseconds. So the timing of Display can be arranged so that the
complete digit frame scans 50 times in a second.
But if we introduce a delay whenever somebody presses
a key to create that de-bounce delay, program will lock up in that delay for a
few milliseconds and the timing of Segment lighting up will lag which will
result in what we call flicker of display. Technically the display routine will
fail to illuminate digits such that our eyes wont detect it. So calling a delay
is not desirable in our case.
We have to search for other mechanisms. To control the
integrity of operations conveniently we have deployed flag polling mechanisms
to divert sequences. Please refer the code in while(1) loop to see how it is
done. Seven segment display function is called irrespective of any conditions
to make sure it executes anyway. Actually the code checks for switch press and
if pressed, it will set (Means make logical 1 or ‘true’) two flags – one is
FlagIncri or FlagDecri depending on the switch pressed, and another one to
indicate the start of De-bounce period. The switch detection is doing nothing
else. When the next loop comes the digit changing flag is checked and digit
values are updated using the mechanism mentioned before which is simple
mathematics plus C syntax. Now as the FlagDebounce flag is set another count is
running to reach a time out. As this FlagDebounce is set we are now not checking
the switches. So even if the user’s hand remains in switch our program is not
going to check it or detect it. After 8 loops, that is when DebounceCnt reaches
9 ( can vary depending on the de bounce time you find suitable) the De bounce
flag is cleared and the program will start looking for key press again. So by
that flag mechanism we have successfully bypassed the key detection process for
a certain time with out calling delay which can affect our other time critical
tasks like seven segment display.
Now let us see how the seven segment display function
is performing. Using digit pattern array first the segment pattern is located,
then move it to port and then Switchon the transistor. First digit lights up.
Now call a delay to keep it on for some time and off the transistor. Get the
digit for the next value and light up- hold it for some time, then OFF. Now the
two digits are shown once. As this function is being called quite frequently we
will get constant and steady digits.
Please note init_variables() function. Both the digit
values are initialized to 0 there. Even though in the case of some variables
initial values are of no concern because the improper value may not have a
disastrous effect in our program. But in this case this particular value if
left un-initialized can crash our program. If that value is left un-initialized
it can contain any value while program loads up (Microchip doesn’t give us any
assurances to that effect! (as far as we know)). Suppose it has a value above 9
(10-255), when it is passed to pattern fetching array by the SevenSegDisaplay()
function, the argument will be out of bounds and the program can branch out of
control. As it is a runtime error compiler may not give us any warning.
Apart from all this arrangement to beep the buzzer for
every key press is also provided without blocking the thread.
No comments:
Post a Comment