Featured post

A reason to exercise.

It's been two years since I started going to the gym and this post is just a summary of my experience. Before going to the gym. Iv...

Thursday, 29 October 2015

Going back in time....to 8051.

It's been a long time since my last post.College work and tests have been keeping me busy for quite a while now.
In the midst of all this was the phase 1 of my final year project.My final year project is a rubik's cube solver robot.The plan is to make use of the ARM Cortex M0+ based FRDM KL25Z board from Freescale semiconductor.This board was introduced to me when I took part in "THE FREESCALE CUP" competition held by Freescale semiconductors.It's a very neat little board and I have had a lot of fun doing projects with this board.More about this on my following posts.
In the process of my final year project, I have been concentrating a great deal on the ARM and AVR based boards that it's been a long time since I came back to 8051.
I decided to build a tribute to this great architecture(yes, 8051 is an architecture and not an microcontroller.Most people are unaware of this),a clock.
It started off by first testing if I still remembered the architecture and all the details necessary to work with this architecture.
The microcontroller I'm making use of is Atmel's AT89S52.A great little guy!!
Next was to blink an LED followed by an 7 segment display(mine's a common cathode).
There were a few techniques used to "multiplex" the 6 "7 segments".
First two are indicative of "hours",the next two are for "minutes" followed by the last two which indicate "seconds".
The arrangement of the displays too are not in order but are in alternates as seen in the picture below.

4 bit mode

                             

I knew from the start that I had to "multiplex" the 7 segments if pins had to be saved on the UC.

                                     



ugly cross over of wires!!
uglier cross over of wires!!

                                          

                                       

All of the 8 pins of port P0 is used to drive the display(a to g,and dp).
The plan was to connect the "COM" pins of the displays to pins of port 2.
P2^7=COM6;
P2^6=COM5;
P2^5=COM4;
P2^4=COM3;
P2^3=COM2;
P2^2= COM1;
So whenever the COM pin is set to "0", it is "grounded":the circuit to that display is completed and whatever is the value of the pins of P0 is displayed.
Keep in mind that as the displays are all not in order but alternate,two functions have to be written.
One is when the display is upright and the other is when the display is inverted.
An upright "4" is an inverted "h".
An upright "6" is an inverted "9" and vice versa.
an upright "3" is an inverted X-axis mirror image.
The truth table for the two modes is as shown.

truth table

The first circuit has the disadvantage of using an resistor for each of the pins(apart from the ground) of the display.
This means that as the number as display segments increase,more resistors have to be used to drive the 7 segment array.


At first though I had not a clue on how to tackle this situation, and I was running out of resistors!!.
After pondering over the problem for a couple of days..,EUREKA.
The solution was as simple as it could be and I just slapped myself for not having thought of this answer.
Since in my code only one segment is active at a time, why don't I short all the appropriate pins of the display, and just connect the resistors to the first display.
Since only one display is active at a time, it is equivalent to the resistors being part of that display.

The initial plan was to make use of 4 displays,two to display hours and two to display minutes.
The first code written too were concentrated on driving 4 displays.
All this was great but when the clock took life,there wasn't much interesting going on.
As you can see,the device works perfectly alright but it didn't give me the urge to look at it with
the curiosity of a child.
So to spice things up a bit, another two displays were added to act as "seconds",the circuit made a little tidier and the code more refined.
There are two types of code I have written for this project.
The first one does not make use of the timer concept.All of the delays have been tested out by trial and error.
You can make use of this code if you are unaware of using the timers of the 8051.
The second code however makes use of the timer concept.
8051 provides us with two timers T0 and T1.
They are 16 bit each. These timers also act as counters.
The difference is that a timer is like a clock,it just keeps ticking.a counter on the other hand count based on the voltage change on an external pin.
One very important point to note is that the 8051 has a "mod-12" counter inside of it.
What it means is that whatever is the frequency of the crystal you are using is divided by 12 internally before being used by the CPU.
Mine's a 11.0592 Mhz crystal.
Divide by 12 makes it a 921.6Khz signal,the reciprocal of which is 1.085us.
1.085us is the pulse duration of each cycle.
There are two control registers provided for timer control, they are TCON (Timer control) and TMOD (Timer mode).






calculating timing

Several different codes have been written and tested.Take a look and you can adopt any of the techniques suited to your style.


If you are in need of a clock that only displays minutes and hours,use the code below.

                         CODE 0:no timer,all delays found by trial and error.So the 1 second delay may not be                                         accurate
========================================================================

#include<reg52.h>
sbit seven_seg=P0;
sbit com1=P2^7;           //connected to "tens" place of hours
sbit com2=P2^6;           //connected to "ones" place of hours
sbit com3=P2^5;          //connected to "tens" place of minutes
sbit com4=P2^4;          //connected to "ones" place of minutes
int i=0;int hours=100;int minutes=100;int seconds=100;int temp_hours=0;int temp_minutes=0;int temp_seconds=0;int val=0;
void delay_small(void);
void display_straight(int);//the code for the numbers has decimal point as high
void display_inverted(int);//the code for the numbers has decimal point as high
void main()
{
while(1)
{
temp_hours=hours;
temp_minutes=minutes;
temp_seconds=seconds;
for(i=0;i<=100;i++)
{
com4=0;
display_straight(minutes%10);
delay_small();
com4=1;
minutes/=10;
com3=0;
display_inverted(minutes%10);
delay_small();
com3=1;
com2=0;
display_straight(hours%10);
delay_small();
com2=1;
hours/=10;
com1=0;
display_straight(hours%10);
delay_small();
com1=1;
val+=1;
}

  hours=temp_hours;
minutes=temp_minutes;
seconds=temp_seconds;
if(val==35)
{
seconds+=1;
val=0;
}

if(seconds==160)
{
seconds=100;
minutes+=1;
}
if(minutes==160)
{
minutes=100;
hours+=1;
}
if(hours==124)
{
hours=100;
}
}
}

void delay_small(void)
{
for(i=0;i<=800;i++);
}

void display_straight(int a)
{
if(a==0)
{
P0=0XFD;
}
else if(a==1)
{
P0=0X61;
}
else if(a==2)
{
P0=0XDB;
}
else if(a==3)
{
P0=0XF3;
}
else if(a==4)
{
P0=0X67;
}
else if(a==5)
{
P0=0XB7;
}
else if(a==6)
{
P0=0XBF;
}
else if(a==7)
{
P0=0XE1;
}
else if(a==8)
{
P0=0XFF;
}
else if(a==9)
{
P0=0XF7;
}
else
{
}
}

void display_inverted(int a)
{
if(a==0)
{
P0=0XFD;
}
else if(a==1)
{
P0=0X0D;
}
else if(a==2)
{
P0=0XDB;
}
else if(a==3)
{
P0=0X9F;
}
else if(a==4)
{
P0=0X2F;
}
else if(a==5)
{
P0=0XB7;
}
else if(a==6)
{
P0=0XF7;
}
else if(a==7)
{
P0=0X1D;
}
else if(a==8)
{
P0=0XFF;
}
else if(a==9)
{
P0=0XBF;
}
else
{
}
}


========================================================================


However adding the seconds makes the clock much more interesting to look at.

                                             CODE 1:no timer,all delays were found out by trial and                                                                                          error.You could make use of this code if you are                                                                                      just starting up with 8051
========================================================================

#include<reg52.h>
sbit seven_seg=P0;
sbit com1=P2^7;
sbit com2=P2^6;
sbit com3=P2^5;
sbit com4=P2^4;
sbit com5=P2^3;
sbit com6=P2^2;
int i=0;int hours=100;int minutes=100;int seconds=100;int temp_hours=0;int temp_minutes=0;int temp_seconds=0;int val=0;
void delay_small(void);
void display_straight(int);//the code for the numbers has decimal point as high
void display_inverted(int);//the code for the numbers has decimal point as high
void main()
{
while(1)
{
temp_hours=hours;
temp_minutes=minutes;
temp_seconds=seconds;
for(i=0;i<=100;i++)
{
com6=0;
display_straight(seconds%10);
delay_small();
com6=1;
seconds/=10;
com5=0;
display_inverted(seconds%10);
delay_small();
com5=1;
com4=0;
display_straight(minutes%10);
delay_small();
com4=1;
minutes/=10;
com3=0;
display_inverted(minutes%10);
delay_small();
com3=1;
com2=0;
display_straight(hours%10);
delay_small();
com2=1;
hours/=10;
com1=0;
display_straight(hours%10);
delay_small();
com1=1;
val+=1;
}

 hours=temp_hours;
minutes=temp_minutes;
seconds=temp_seconds;
if(val==35)
{
seconds+=1;
val=0;
}

if(seconds==160)
{
seconds=100;
minutes+=1;
}
if(minutes==160)
{
minutes=100;
hours+=1;
}
if(hours==124)
{
hours=100;
}
}
}

void delay_small(void)
{
for(i=0;i<=800;i++);
}

void display_straight(int a)
{
if(a==0)
{
P0=0XFD;
}
else if(a==1)
{
P0=0X61;
}
else if(a==2)
{
P0=0XDB;
}
else if(a==3)
{
P0=0XF3;
}
else if(a==4)
{
P0=0X67;
}
else if(a==5)
{
P0=0XB7;
}
else if(a==6)
{
P0=0XBF;
}
else if(a==7)
{
P0=0XE1;
}
else if(a==8)
{
P0=0XFF;
}
else if(a==9)
{
P0=0XF7;
}
else
{
}
}

void display_inverted(int a)
{
if(a==0)
{
P0=0XFD;
}
else if(a==1)
{
P0=0X0D;
}
else if(a==2)
{
P0=0XDB;
}
else if(a==3)
{
P0=0X9F;
}
else if(a==4)
{
P0=0X2F;
}
else if(a==5)
{
P0=0XB7;
}
else if(a==6)
{
P0=0XF7;
}
else if(a==7)
{
P0=0X1D;
}
else if(a==8)
{
P0=0XFF;
}
else if(a==9)
{
P0=0XBF;
}
else
{
}
}

                                                                        CODE 2:uses timer feature of 8051
========================================================================

#include<reg52.h>
sbit seven_seg=P0;
sbit com1=P2^7;
sbit com2=P2^6;
sbit com3=P2^5;
sbit com4=P2^4;
sbit com5=P2^3;
sbit com6=P2^2;
int hours=100;int minutes=100;int seconds=100;//its better to initialize to 100;initializing to 0 will make it difficult
int temp_hours=0;int temp_minutes=0;int temp_seconds=0;//temp variables
int timer_count=0;//
void display_straight(int);//function for upright 7 segments
void display_inverted(int);//function for inverted 7 segments
void delay_t0(void);//delay function for 2ms;uses T0;
void main()
{
while(1)
{
timer_count=0;

while(timer_count<=77)//this number has been found by trial and error
{
//store values into temp variables
temp_hours=hours;
temp_minutes=minutes;
temp_seconds=seconds;
//the display sequence starts from this point of code
//steps are:
//turn the COM pin "low" i.e, 0
//call the appropriate display action
//wait for some time
//turn the pin "high";1
 com6=0;
 display_straight(seconds%10);
 delay_t0();
 com6=1;
 seconds/=10;
 com5=0;
 display_inverted(seconds%10);
 delay_t0();
 com5=1;
com4=0;
display_straight(minutes%10);
delay_t0();
com4=1;
minutes/=10;
com3=0;
display_inverted(minutes%10);
delay_t0();
com3=1;
com2=0;
display_straight(hours%10);
delay_t0();
com2=1;
hours/=10;
com1=0;
display_straight(hours%10);
delay_t0();
com1=1;
//reload values from temp to main variables
seconds=temp_seconds;
minutes=temp_minutes;
hours=temp_hours;
//increment counter
timer_count+=1;
}

    seconds=seconds+1;

//seconds command was posted here initially
if(seconds==160)
{
seconds=100;
minutes+=1;
}
if(minutes==160)
{
minutes=100;
hours+=1;
}
if(hours==124)
{
hours=100;
}

}
}

//delay is for 2ms
void delay_t0(void)
{
TMOD=0x01;//select timer0;T0
TH0=0xF8;//feed higher byte
TL0=0xCC;//feed lower byte
TF0=0;//initially reset the flag
TR0=1;//run timer
while(TF0==0);//wait for overflow
TF0=0;//reset flag
TR0=0;//stop timer run
}

//this code is written from truth table
void display_straight(int a)
{
if(a==0)
{
P0=0XFD;
}
else if(a==1)
{
P0=0X61;
}
else if(a==2)
{
P0=0XDB;
}
else if(a==3)
{
P0=0XF3;
}
else if(a==4)
{
P0=0X67;
}
else if(a==5)
{
P0=0XB7;
}
else if(a==6)
{
P0=0XBF;
}
else if(a==7)
{
P0=0XE1;
}
else if(a==8)
{
P0=0XFF;
}
else if(a==9)
{
P0=0XF7;
}
else
{
}
}

//this code is written from truth table
void display_inverted(int a)
{
if(a==0)
{
P0=0XFD;
}
else if(a==1)
{
P0=0X0D;
}
else if(a==2)
{
P0=0XDB;
}
else if(a==3)
{
P0=0X9F;
}
else if(a==4)
{
P0=0X2F;
}
else if(a==5)
{
P0=0XB7;
}
else if(a==6)
{
P0=0XF7;
}
else if(a==7)
{
P0=0X1D;
}
else if(a==8)
{
P0=0XFF;
}
else if(a==9)
{
P0=0XBF;
}
else
{
}
}
                                                                             CODE 3:tidied up code 2
========================================================================

#include<reg52.h>
sbit seven_segment=P0;
sbit com1=P2^7;
sbit com2=P2^6;
sbit com3=P2^5;
sbit com4=P2^4;
sbit com5=P2^3;
sbit com6=P2^2;
float i=0;int j=0;
int hours=100;int minutes=100;int seconds=100;int temp_hours=0;int temp_minutes=0;int temp_seconds=0;
void display_straight(int);
void display_inverted(int);

void main()
{
TMOD=0x01;
while(1)
{

TH0=0x00;
TL0=0x00;
TF0=0;
TR0=1;
while(i<=6.5)//reduce this guy aopropriately
{
temp_hours=hours;
temp_minutes=minutes;
temp_seconds=seconds;
com6=0;
display_straight(seconds%10);
for(j=0;j<=500;j++);
com6=1;
seconds/=10;
com5=0;
display_inverted(seconds%10);
for(j=0;j<=500;j++);
com5=1;
com4=0;
display_straight(minutes%10);
for(j=0;j<=500;j++);
com4=1;
minutes/=10;
com3=0;
display_inverted(minutes%10);
for(j=0;j<=500;j++);
com3=1;
com2=0;
display_straight(hours%10);
for(j=0;j<=500;j++);
com2=1;
hours/=10;
com1=0;
display_straight(hours%10);
for(j=0;j<=500;j++);
com1=1;
//once the flag raises,i is incremented and flag reset
if(TF0==1)
{
i+=0.5;
TF0=0;
}
hours=temp_hours;
minutes=temp_minutes;
seconds=temp_seconds;
}
i=0;
TF0=0;
TR0=0;

seconds+=1;
if(seconds==160)
{
seconds=100;
minutes+=1;
}
if(minutes==160)
{
minutes=100;
hours+=1;
}
if(hours==124)
{
hours=100;
}
}
}

void display_straight(int a)
{
if(a==0)
{
P0=0XFD;
}
else if(a==1)
{
P0=0X61;
}
else if(a==2)
{
P0=0XDB;
}
else if(a==3)
{
P0=0XF3;
}
else if(a==4)
{
P0=0X67;
}
else if(a==5)
{
P0=0XB7;
}
else if(a==6)
{
P0=0XBF;
}
else if(a==7)
{
P0=0XE1;
}
else if(a==8)
{
P0=0XFF;
}
else if(a==9)
{
P0=0XF7;
}
else
{
}
}

void display_inverted(int a)
{
if(a==0)
{
P0=0XFD;
}
else if(a==1)
{
P0=0X0D;
}
else if(a==2)
{
P0=0XDB;
}
else if(a==3)
{
P0=0X9F;
}
else if(a==4)
{
P0=0X2F;
}
else if(a==5)
{
P0=0XB7;
}
else if(a==6)
{
P0=0XF7;
}
else if(a==7)
{
P0=0X1D;
}
else if(a==8)
{
P0=0XFF;
}
else if(a==9)
{
P0=0XBF;
}
else
{
}
}


========================================================================























4 bit counter arrangement

clock arrangement for minutes and seconds







clock arrangement



6 7segment display arrangement; hours:minutes:seconds format



refined 4 bit clock mode








































No comments:

Post a Comment