Step 1.
Create a new project in MikroC using PIC 16f84a. Make the processor speed equal to 4Mhz.
Step 2 - Start Coding!
First we will declare all functions and variables, in MikroC type:
void PortSetup(void); // function that configures MCU's inputs and outputs
void TimerSetup(void); // function to set up timer to interrupt
void interrupt (void); // interrupt service routine
void Convert(void); // function to decode numbers for seven segment display
// global variables
int Huns,Seconds,Segment,Tens,Units;
Now we'll write the main program. Type the following:
void main(void)
{
PortSetup();
TimerSetup();
PORTA = 0b00001; // initialise display
while(1) //endless loop
{
Convert();
}
}
Step 3 - Start coding functions.
First we'll set up the ports on the MCU. For now, we know that all we will be having is outputs to the seven segment, its up to you if you want to include any input buttons at a later time. Type the following in MikroC:
void PortSetup(void)
{
PORTA=0; //clear internal buffers
PORTB=0;
TRISA=0b00000; // program I/O (0==output, 1==input)
TRISB=0b00000000;
Huns = 0;
Seconds = 0;
TMR0 = 100;
}
Next we'll code the time function to interrupt the "while(1)" loop. We want it to be as accurate to a second as possible so we'll make it interrupt every 10 milliseconds. We'll do the math for working out the seconds further on. Type the following in MikroC:
void TimerSetup(void)
{
// function to set up timer to interrupt
// program every 10 Ms
OPTION_REG.PSA = 0; //assigns prescalar to Timer not Watch dog
OPTION_REG.PS0 = 1; //PS2-PS0 assign the prescaler ratio
OPTION_REG.PS1 = 0; // 64
OPTION_REG.PS2 = 1; //
INTCON.GIE = 1; // switch on interrupts
INTCON.T0IE = 1; // enable timer interrupt
INTCON.T0IF = 0; // set interrupt flag
OPTION_REG.T0CS = 0; // start timer
}
The OPTION_REG and INTCON registers were configured using the 16F84a datasheet. If its hard to understand, refer to my values and comments to try and figure it out. Otherwise, just send me an email!
Next is the hardest part! We'll setup the interrupt service routine to deal with the math and multiplexing of the seven segment displays. Multiplexing in this application saves a whole lot of port space. For every seven segment display, eight pins are required; seven for each segment and one common cathode pin (or "on" switch). Instead of using 16 pins (which is impossible), we'll use seven for both displays' data and one extra pin for each common cathode. In short, the total pins used to power two seven segment displays is 9, to power three displays, we need 10 pins and so on. The concept is simple, if we turn on one cathode then we'll send the data on the seven pins that correspond to that display. So if we want to display "32" on both displays, we'll turn on the cathode for for the first display and send the seven seg equivalent of "3" on the seven ports. Then we'll turn of that cathode and turn on the other cathode while sending the seven seg equivalent of "2" on the seven pins. If we do this fast enough, it will appear that "32" is being displayed when in actual fact they are changing so fast our brains cannot keep up!
Type the following code and refer to comments to see what each line does:
void interrupt(void) // ISR
{
/*Work out math for seconds (dividing a number into its 'tens' and 'ones' so each value can be displayed independently)*/
OPTION_REG.T0CS=1; // stop counter
TMR0=100; // reload timer 256-156=100
asm{nop}; // pad out with 'nops'
asm{nop}; // for ten milli-seconds
OPTION_REG.T0CS=0; // start counter
Huns++;
if (Huns > 99) // if one hundred interrupts!
{
Seconds++;
Huns = 0;
}
if(Seconds > 59)
{
Seconds = 0;
}
Tens = Seconds/10;
Units = Seconds - (Tens * 10);
//Code for multiplexing and displaying values
if ( PORTA.F0 == 1 )
{
PORTA = 0B00010; // Tens on Units off
Segment = Units;
}
else if(PORTA.F1 == 1)
{
PORTA = 0B00001;
Segment = Tens;
}
INTCON.T0IF=0; // reset interrupt flag
}
Finally we'll set up the decoding function to translate a numeric value into its seven segment binary equivalent. Type the folling code into MikroC:
void Convert(void) //Seven Segment decoder
{
switch (Segment)
{
case 0 : PORTB = 0B01111110;
break;
case 1 : PORTB = 0B00001100;
break;
case 2 : PORTB = 0B10110110;
break;
case 3 : PORTB = 0B10011110;
break;
case 4 : PORTB = 0B11001100;
break;
case 5 : PORTB = 0B11011010;
break;
case 6 : PORTB = 0B11111010;
break;
case 7 : PORTB = 0B00001110;
break;
case 8 : PORTB = 0B11111110;
break;
case 9 : PORTB = 0B11001110;
}
}
And thats it! All we need to do now is compile it!
The schematic for isis (for simulation), .asm, .ppc and .c files can be downloaded here: http://factm8.com/glen/blogfiles/60Seccounter.rar
3 comments:
thank your share. ım new mikroC.
ım learning.
what ı say, could you learn me some command of mikroC?
ı want to know how we use timer0, what is tmr0 and intcon and gie and option_reg and...
if you learn me ı can be a little sponsor you.
evd123evd@hotmail.com
thanks
Hello!
Thank you for the program. But i can't download the rar archive because it is missing. Can you help me with the proteus schematic? Thanks a lot !
My email address is dragoss1986@yahoo.com
p.s. i compiled the program and i built the schematic in proteus but it does not display correctly the numbers. In the message box it says that the program do not run in real time; can this be the problem?
i cannot open the website where the schematic is,can u give me another source??
Post a Comment