Monday, September 19, 2016

Interfacing Seven segment to PIC16F877a

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

}

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