7 Segment Display Interfacing with PIC Microcontroller
7 Segment Display Interfacing with PIC Microcontroller
EMBEDDED
This is our 8th tutorial of Learning PIC microcontrollers using MPLAB and XC8. We have come up all the way from installing MPLABX to using a LCD with PIC MCU. If you are new here, then look at previous tutorials where you can learn timers, blinking LED, interfacing LCD etc.. You can find all our PIC Tutorials here. In our last tutorial we saw how we can generate Custom characters with our 16*2 LCD display, now let us equip our self with another type of display module called the 7-segment display and interface it with PIC Microcontroller.
Although 16x2 LCD is much more comfortable than 7-segment display but there are few scenarios where a 7-segment display would come in handier than a LCD display. LCD suffers from the drawback of having low character size and will be overkill for your project if you are just planning to display some numeric values. 7-segments also have the advantage against poor lighting condition and can be viewed from lager angles than a normal LCD screen. So, let us start knowing it.
7-Segment and 4-Digit 7-Segment Display Module:
7 Segment Display has seven segments in it and each segment has one LED inside it to display the numbers by lighting up the corresponding segments. Like if you want the 7-segment to display the number "5" then you need to glow segment a,f,g,c, and d by making their corresponding pins high. There are two types of 7-segment displays: Common Cathode and Common Anode, here we are using Common Cathode seven segment display. Learn more about 7 segment display here.
Now we know how to display our desired numeric character on a single 7-segment display. But, it is pretty evident that we would need more than one 7-segment display to convey any information that is more than one digit. So, in this tutorial we will be using a 4-digit 7-Segment Display Module as shown below.
As we can see there are Four Seven Segment Displays connected together. We know that each 7-segment module will have 10 pins and for 4 seven segment displays there would be 40 pins in total and it would be hectic for anyone to solder them on a dot board, so I would highly recommend anyone to buy a module or make your own PCB for using a 4-digit 7-segment display. The connection schematic for the same is shown below:
To understand how 4-digit seven segment module works we have to look into the above schematics, as shown the A pins of all four display is connected to gather as one A and the same for B,C.... upto DP. So, basically if trigger A on, then all four A's should go high right?
But, that does not happen. We have additional four pins from D0 to D3 (D0, D1, D2 and D3) which can be used to control which display out of the four should go high. For example: If I need my output to be present only on the second display then only D1 should be made high while keeping other pins (D0, D2, and D3) as low. Simply we can select which display has to go active using the pins from D0 to D3 and what character to be display using the pins from A to DP.
Connecting 4-Digit Seven Segment Module with PIC Microcontroller:
Here we have used PIC microcontroller PIC16F877A and the schematic for the circuit is shown below.
We have 12 output pins from the module out of which 8 is used to display the characters and four is used to select one display out of four. Hence all the 8 character pins are assigned to PORTD and the display selection pins are assigned to first four pins of PORTC.
Note: Ground pin of the module should also be connected to the ground of the MCU which is not shown here.
Programming using PIC16F877A:
Now, that we know how this module actually works, let us learn how to program PIC16F877A to make it display a 4 digit number. Let us increment a variable from 0 to 1000 and print it on the 7-segment display. Launch the MPLABX program and create new project, let us start with the configuration bits.
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled) #pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled) #pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming) #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off) #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
As usual we use the set configuration bits window to set these bits. If you are not sure what they mean then visit the LED blinking tutorial here.
Next let us define the output pins for toggling between each digit of the display.
//***Define the signal pins of all four displays***// #define s1 RC0 #define s2 RC1 #define s3 RC2 #define s4 RC3 //***End of definition**////
Here the pins RC0, RC1, RC2 and RC3 are used for selecting between the four digits of our 7-segment display module. These pins are defined as s1, s2, s3 and s4 respectively.
Next let us jump into void main(), inside which we have the following variable declaration:
int i = 0; //the 4-digit value that is to be displayed int flag =0; //for creating delay unsigned int a,b,c,d,e,f,g,h; //just variables unsigned int seg[]={0X3F, //Hex value to display the number 0 0X06, //Hex value to display the number 1 0X5B, //Hex value to display the number 2 0X4F, //Hex value to display the number 3 0X66, //Hex value to display the number 4 0X6D, //Hex value to display the number 5 0X7C, //Hex value to display the number 6 0X07, //Hex value to display the number 7 0X7F, //Hex value to display the number 8 0X6F //Hex value to display the number 9 }; //End of Array for displaying numbers from 0 to 9
Here the variables i and flag are used for storing the values to be displayed and creating a delay respectively. The unsigned integer variables a to h are used to break the four digit numbers into single digits and store them (which will be explained later here).
One key thing to note here is the "seg[]" array declaration. In this program we are using a new data type called Array. Array is nothing but a collection of similar data-type values. Here, we have used this array to store all the equivalent hex values for displaying a number from 0 to 9.
The address of the array always starts from zero. So this array will have the hex value of a numeric number (0-9) stored in the address which is same as that of the number as shown below
Variable:
|
seg[0]
|
seg[1]
|
seg[2]
|
seg[3]
|
seg[4]
|
seg[5]
|
seg[6]
|
seg[7]
|
seg[8]
|
seg[9]
|
Hex Code:
|
0X3F
|
0X06
|
0X5B
|
0X4F
|
0X66
|
0X6D
|
0X7C
|
0X07
|
0X7F
|
0X6F
|
Eq. Numeric number:
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
9
|
So simply, if you want to display the number 0 on your 7-segment you can call seg[0], likewise if you want to display the number 6 you just have to use seg[6].
To understand how the HEX value was actually obtained let us look into the below table. The equivalent HEX value for each decimal number is stored in the array so that it can be called to display one particular number.
Now, let us move on to the next part of the code which is the I/O configuration:
//*****I/O Configuration****// TRISC=0X00; PORTC=0X00; TRISD=0x00; PORTD=0X00; //***End of I/O configuration**///
I/ O configuration is simple because all the pins on our 7-segment are output pins, and the connections are shown in the circuit diagram above, so simply declare them as outputs and initialize them to zero.
Now let us jump into our infinite loop (while(1)). Here we have to split the value of "i" into four digits and display them on the 7-segment. First let us start by splitting the value on "i"
//***Splitting "i" into four digits***// a=i%10;//4th digit is saved here b=i/10; c=b%10;//3rd digit is saved here d=b/10; e=d%10; //2nd digit is saved here f=d/10; g=f%10; //1st digit is saved here h=f/10; //***End of splitting***//
By using simple modulus and division operation the 4 digit number (i) is separated into individual numbers. In our case let us take an example where the value of "i" is 4578. Then at the end of this process the variable g=4, e=5, c=7, and a=8. So now it will be easy to display each digit by simply using that variable.
PORTD=seg[g];s1=1; //Turn ON display 1 and print 4th digit __delay_ms(5);s1=0; //Turn OFF display 1 after 5ms delay PORTD=seg[e];s2=1; //Turn ON display 2 and print 3rd digit __delay_ms(5);s2=0; //Turn OFF display 2 after 5ms delay PORTD=seg[c];s3=1; //Turn ON display 3 and print 2nd digit __delay_ms(5);s3=0; //Turn OFF display 3 after 5ms delay PORTD=seg[a];s4=1; //Turn ON display 4 and print 1st digit __delay_ms(5);s4=0; //Turn OFF display 4 after 5ms delay
This is the actual place where the MCU talks with the 7-segment. As we know we can display only one digit at a time, but we have four digits to be displayed and only if all the four digits are On the complete four digit number will be visible for the user.
So, how do we go with this?
Lucky for us our MCU is very much faster than a human eye, so what we actually do: we display one digit at a time but we do it very fast as shown above.
We select one digit display it wait for 5ms so that the MCU and 7-segment can process it and then turn off that digit and move on to the next digit and do the same till we reach the last digit. This delay of 5ms cannot be observed by a human eye and all the four digits appeared to be On at the same time.
That is it, finally we just increment the value of displayed digit using a delay as shown below
if(flag>=100) //wait till flag reaches 100 { i++;flag=0; //only if flag is hundred "i" will be incremented } flag++; //increment flag for each flash
ความคิดเห็น
แสดงความคิดเห็น