problem with timer project using at89s51 mcu

Status
Not open for further replies.

adrian.eremencu

Newbie level 3
Joined
May 25, 2013
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Visit site
Activity points
1,356
Hello,

I want to build a timer using the AT89s51 mcu. I am using keil to compile and debug my code and proteus to visualise the effect.
This is a personal project to help me understand better C language and electronic.

I have a lot of questions and a lot of problems but i will focus on the most pressing ones.

The program should do the following:
1)it shows all the segments(digits) with the value 0
2)if the select button is pressed it enables one segment and disable the others. if the select btn is pressed again it enables the next segment and disable the other ...
3)if the increment btn is pressed while one segment is selected it increments its value by one.
4)if the start button is pressed it starts the timer 1 and use the interrupt dispay function to display all segments using multiplexing.
5)if the values are not equal to 0 it start the coundown.
6)if the pause button is pressed it stops the countdown and if it is pressed again the countdown starts.
7)after the countdown is complete a buzzer rings, the timer is stoped and the program goes at the begining.

Now about my code.
I have tested most of the code and it gives the desired result. I have a big problem with the countdown function. It works but when the countdown reaches 0 it does not stop... it continues forever.
The other problem i have is with the interrupt and delay functions. I am using the overflow flag on timer 1 to call the display function, displaying all the segment with their value. This is the first time i use the interrupt and proteus can't animate this fast (or i don't know how to use proteus very well) so i get weird results. I have tested the delay_1s() function with keil performance analizer and i got averange time to complete near 1 s. But in the countdown the time that passes until the value of the second digit is changed is +20 seconds.
The way i see it there is two posibiles problems:
1) because i use the interrupt it changes the time to complete the countdown function.(If someone has a link or an explanation for better understanding the usage of interrupts please help me)
2) the countdown function does not work with the delay i provided.
Here is the full code of my timer and thank you in advance for the help.

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
#include <reg51.h>
 
 
int sec1, sec2, min1, min2; // variables for minutes and seconds
const char dig_val[]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90}; // hex values (0 thru 9) to be dispayed by 7 seg display
int selected_dig=1; // variable for the select function
int increment_dig; // variable for the increment function
int stop = 0; // variable for pause function
int pause_case = 1; // variable for pause function
 
sbit dig_min2=P2^0; // defining the pins used
sbit dig_min1=P2^1;
sbit dig_sec2=P2^2;
sbit dig_sec1=P2^3;
sbit slct=P2^5;
sbit incr=P2^6;
sbit start=P2^4;
sbit pause_btn=P2^7;
sbit buzzer=P0^0;
 
void select(void); // funtions prototypes
void delay(int a);
void increment(void);
void display(void);
void pause(void);
void countdown(void);
void delay_1s(void);
 
 
 
void main()
 {
  min2 = min1 = sec2 = sec1 = 0;    // init variables 
    slct = incr = start = pause_btn = 1;
    buzzer = 0;
     
    while (1) // main loop 
    {
        dig_min2 = dig_min1 = dig_sec2 = dig_sec1 = 1; 
      P1 = dig_val[min2]; // all segments are active and displays 0
        while (start != 0) // check if start button is pressed
        {
            select();
            increment();
        }
        IE=0x88; // defining interrupts and timer
      TMOD=0x11;
      TL1=0x00;
      TH1=0xff;
      TR1=1;
        while ( (min2 != 0) || (min1 != 0) || (sec2 != 0) || (sec1 != 0)) // checks if modification are made to the initial values
        {
        countdown(); // start countdown         
        }
        TR1=0; // stop timer, clear flag and ring buzzer 
        TF1=0;
        buzzer=1; //after this last instruction it should turn back to the begining of my main loop and repeat the procces 
    }   
 }
 
 
 void display() interrupt 3 // funtion for displaying the digits using multiplexing
{
    switch(1)
    {
        case 1:
            dig_min2=1;
            dig_min1=0;
            dig_sec2=0;
            dig_sec1=0;
            P1=dig_val[min2];
        case 2:
            dig_min2=0;
            dig_min1=1;
            dig_sec2=0;
            dig_sec1=0;
            P1=dig_val[min1];
        case 3:
            dig_min2=0;
            dig_min1=0;
            dig_sec2=1;
            dig_sec1=0;
            P1=dig_val[sec2];
        case 4:
            dig_min2=0;
            dig_min1=0;
            dig_sec2=0;
            dig_sec1=1;
            P1=dig_val[sec1];
    }
    TF1=0;//clears the flag
}
void select(void)// the select function 
 {
    switch(selected_dig)
     {
         case 1:
             if(slct == 0)
             {
                 dig_min2=1;
                 dig_min1=0;
                 dig_sec2=0;
                 dig_sec1=0;
                 P1=dig_val[min2];
                 selected_dig=2;
                 increment_dig=1;
                 delay_1s();
             }
             break;
             
         case 2:
             if(slct == 0)
             {
                 dig_min2=0;
                 dig_min1=1;
                 dig_sec2=0;
                 dig_sec1=0;
                 P1=dig_val[min1];
                 selected_dig=3;
                 increment_dig=2;
                 delay_1s();
             }
             break;
         
         case 3:
             if(slct==0)
             {
                 dig_min2=0;
                 dig_min1=0;
                 dig_sec2=1;
                 dig_sec1=0;
                 P1=dig_val[sec2];
                 selected_dig=4;
                 increment_dig=3;
                 delay_1s();
             }
             break;
             
         case 4:
             if(slct==0)
             {
                 dig_min2=0;
                 dig_min2=0;
                 dig_sec2=0;
                 dig_sec1=1;
                 P1=dig_val[sec1];
                 selected_dig=1;
                 increment_dig=4;
                 delay_1s();
             }
             break;
         }
 }
 
 void increment(void)// the increment function
 {
     switch(increment_dig)
     {
         case 1:
             if(incr==0)
             {
                 min2++;
                 if(min2==6) min2=0;
                 P1=dig_val[min2];
                 delay_1s();
             } break;
             
            case 2:
                if(incr==0)
                {
                    min1++;
                    if(min1==10) min1=0;
                    P1=dig_val[min1];
                    delay_1s();
                } break;
                
             case 3:
                 if(incr==0)
                 {
                     sec2++;
                     if(sec2==6) sec2=0;
                     P1=dig_val[sec2];
                     delay_1s();
                 } break;
                 
             case 4:
                 if(incr==0)
                 {
                     sec1++;
                     if(sec1==10) sec1=0;
                     P1=dig_val[sec1];
                     delay_1s();
                 } break; 
            }
}
 
void countdown(void)  // the countdown
{
    while ( min2 >= 0)
    {
        while (min1 >= 0)
        {
            while (sec2 >= 0)
            {
                while ( sec1 >=0)
                {
                    while (stop == 1)pause();
                    sec1--;
                    delay_1s();
                    pause();
                }
                sec1 = 9;
                sec2--;
            }
            sec2 = 5;
            min1--;
        }
        min1 = 9;
        min2--;
    }
}
 
void pause(void) //pause function
{
    switch (pause_case)
    {
        case 1:
            if (pause_btn == 0)
            {
                stop = 1;
                pause_case = 2;
            } break;
        
        case 2:
            if (pause_btn == 0)
            {
                stop = 0;
                pause_case = 1;
            } break;
    }
}
 
void delay_1s(void)   // the delay function ... i have checked with keil performance analizer and got 1 second for the mcu to go thru this function
{
    int i;
    for (i=0; i < 27027; i++)
    {
    TL0=0x00;
    TH0=0xff;
    TR0=1;
    while (TF0 == 0);
    TF0=0;
    }
}

 

as u are using while (1) so make condition like this while (count>0 ){countdown();.....}. your time 'seconds' problem wil be only in proteus not on real harware
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…