Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] 8051 Atmel 89C51 programming in C example

Status
Not open for further replies.

8051HELP

Member level 1
Joined
Nov 27, 2015
Messages
32
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
251
I need to write only numbers (every second) in string on display (memory mapped on 0x8001 adress) which are divding with 2 .

I must use counter not delay () for interrupt ...


Below is code which i imagine but dont work correctly...


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
#include <reg51.h>
#include <math.h>
typedef unsigned char byte;
byte a[3]= {2,1,8};
 
byte counter, frequency,displ;
int i=0;
byte xdata display _at_ 0x8001;
 
sbit switcher=P0^0;
 
 
void Inic(void) {
    EA=1;
    ET0=1;
    TMOD=1;
    TH0=0x3C;
    TL0=0xB0;
    TR0=1;
    counter=1;
    frequency=0;
}
 
void timer0(void) interrupt 1 using 2 {
    TR0=0;
    TH0=0x3C;
    TL0=0xB0;
    TR0=1;
 
if(switcher)    {
    if(!(--counter)) {
    counter=frequency;
            
        display=displ;    
        
    
                
        
    
            
    }}     }

 

i wrote main part but i dont know why didnt appear


Code:
void main(void) {
Inic();
while(1) {

if(switcher) {
for (i=0;i<3;i++) {
if(a/2) {
displ=a;
frequency=20;

} } } } }
 

There are several questions about how the project works ?

1. What is the frequency the 89C51 is running at ? 12Mhz ?
2. Is there a switch attached to PORT0, pin 0 ?
If so, does it put a logic high on the pin when pressed ?
3. If there is a switch, what is it's function ?
Is it a "start" switch to start checking for even numbers ?
Or, is it a "run" switch to only run while being held down continuously ?
4. What is the purpose of the 1 second delay ?
Does it write the string of all the even numbers once per second ?
Or, does it write only 1 of the even numbers once per second ?
 

1. Yes 12Mhz . Timer0 can count maximum 65536 , so I need counter to count to 1 million.
I realise that i need 50ms (hexa 3CB0=50 000)* 20= 1second. So, counter have value 20.
2. Yes
3.Switcher only start program,nothing else
4. 1 second for each number ,for every results. Or just how you wrote 1 number per second.
 

Attached below is a file with some ideas to look at. It is untested, but has comments on each line. I believe hexadecimal for 50,000 is C350 rather than 3C80. It's best to have a pull up resistor on PORT0 pin 0, to hold it high and have the switch pull it low when pressed. To set the pin 0 as an input, write a 1 to it. To test for even numbers, bit 0 is always a zero for even binary numbers.

View attachment even_numbers_c..txt
 
Attached below is a file with some ideas to look at. It is untested, but has comments on each line. I believe hexadecimal for 50,000 is C350 rather than 3C80. It's best to have a pull up resistor on PORT0 pin 0, to hold it high and have the switch pull it low when pressed. To set the pin 0 as an input, write a 1 to it. To test for even numbers, bit 0 is always a zero for even binary numbers.

View attachment 123561


I tested. Dont work correctly. Because hi changed both state (2,8)in one second. I have to change every number in 1 second . So, number per second.
When I put 6 numbers in string and try to test that , speed is diferent,faster change numbers and change only 2 and 8. But i change value if (i<3) to if(i<6) because I in another case I have 6 numbers (for example a[6]= {2,1,8,7,5,6}).
 

--Timer run bit(TR0) should be not be enabled in initc()

---enabling the interrupts (EA and ET0) also should not be done in initc() function
 
For a[6] you will need to change both
i<3 to i<6 and i=3 to i=6
Code:
 if(i < 6)     
            if((a[i] & 0x01) == 0)  // even numbers all have bit 0 = 0
               display=a[i];        // display the value in displ if even
         i++;             // increment i for next value in array "a"
         if(i == 6)
To slow down converting 1st number to a 1 second delay change line counter = 1 to counter = 20 in main()

Code:
counter = 20;   // counter to 1 to get first number
 
ATMEL 89C51 -example with string -programming in C

I had thread here but I still need help with the same example.

So, I need to write only numbers (every second) in string on display (memory
mapped on 0x8001 adress) which are divding with 3 .

I must use counter not delay () for interrupt ...

I got with code below only to printing all numbers in one second. FenTrenc member helped me to solve that problem.

I need 1 number per second, not all.

Somebody help again?

Code:
#include <reg51.h> 
#include <math.h>                  
typedef unsigned char byte;

byte a[9]= {7,5,16,3,1,4,11,9,6}; 

byte counter;
byte xdata display _at_ 0x8001;
byte started = 0;
int i=0;

sbit switcher=P0^0;
 
void Inic(void) 
{
    EA=1;         
    TMOD=1;       
    TH0=0x3C;     
    TL0=0xAF;    
    TR0=1;
    counter=1;    
}

 
void timer0(void) interrupt 1 using 2 
{    
    TH0=0x3C;  
    TL0=0xAF;                
    
  counter--; 
    if(counter == 0)         
          {
            counter = 20;        
       if(started == 1)  
         {
         if(i < 9)              
            if(!(a[i]%3) )       
               display=a[i];                            
         i++;             
         if(i == 9)                            
            {
            ET0 = 0;      
            TR0 = 0;     
            started = 0;  
            }
         }
    }   
}

void main(void) 
{
   Inic();        
   switcher = 1;  
   while(1)       
     {                    
     if(switcher == 0)    
       if(started == 0)   
          {         
          started = 1;    
          i = 0;          
          counter = 20;    
                         
          TH0=0x3C;       
          TL0=0xAF;      
          ET0=1;        
          TR0=1;            
          }
     }            
}
 
Last edited by a moderator:

You can use the modulus operator in C represented by the % sign. It returns the remainder of division.

In the previous even number code, try just changing the line in the timer0 interupt handler:

Code:
if((a[i] & 0x01) == 0)  // even numbers all have bit 0 = 0

to:

Code:
if((a[i] % 3) == 0)  // the remainder if a[i] is a multiple of 3 = 0
 

You can use the modulus operator in C represented by the % sign. It returns the remainder of division.

In the previous even number code, try just changing the line in the timer0 interupt handler:

Code:
if((a[i] & 0x01) == 0)  // even numbers all have bit 0 = 0

to:

Code:
if((a[i] % 3) == 0)  // the remainder if a[i] is a multiple of 3 = 0


Yes,I tried that option also.

Dividing works but I have problem to put on display every number per 1 sec. So, he put on display all numbers which are divided with, for example, with 3 in 1 second .

- - - Updated - - -

Need one number per second which is divided with some number... NOT ALL numbers which are divided with some number in 1 second

- - - Updated - - -

Maybe I need to do something else with interrupt or counter ..
But I dont know how to write that part of code which would be useful to interrupt every number on display...
 

See if these changes to the interrupt routine help with the timing.

Code:
void timer0(void) interrupt 1 using 2 
{   
    TH0 = 0xC3;           // set timer0 to C350 = 50,000
    TL0 = 0x50;           // after each interrupt                    
    
    counter--;            // count the interrupt
    if(counter == 0)      // count 20 interrupts for 1 sec delay       
       {
       counter = 20;      // reset counter to 20
       if(started == 1)   // if timer is started
         {   
         while(i < 9)     // go through array "a" to find a multiple of 3  
           {
           if( (a[i] % 3) == 0) // multiple of 3 has remainder = 0                 
              {
              display = (a[i]);  // display a matching number 
              i++;          // increment i to the next number in "a"
              break;      // break out of the while loop after displaying a number
              } 
           i++;            // increment i to the next number in "a"
           }                 // end while i < 9     
         if(i == 9)       // if 9, all numbers have been tested
           {
           ET0 = 0;       // disable timer 0 interrupt 
           TR0 = 0;       // stop timer0 - all of "a" has been checked 
           started = 0;   // started = 0, stop until switch pressed again   
           }
         }  // end if started == 1    
       }  // end if counter == 0
}

Also noticed that timer0 is using 0x3C80 again, instead of 0xC350. Maybe that's what works best ?
 
Last edited:

See if these changes to the interrupt routine help with the timing.

Code:
void timer0(void) interrupt 1 using 2 
{   
    TH0 = 0xC3;           // set timer0 to C350 = 50,000
    TL0 = 0x50;           // after each interrupt                    
    
    counter--;            // count the interrupt
    if(counter == 0)      // count 20 interrupts for 1 sec delay       
       {
       counter = 20;      // reset counter to 20
       if(started == 1)   // if timer is started
         {   
         while(i < 9)     // go through array "a" to find a multiple of 3  
           {
           if( (a[i] % 3) == 0) // multiple of 3 has remainder = 0                 
              {
              display = (a[i]);  // display a matching number 
              i++;          // increment i to the next number in "a"
              break;      // break out of the while loop after displaying a number
              } 
           i++;            // increment i to the next number in "a"
           }                 // end while i < 9     
         if(i == 9)       // if 9, all numbers have been tested
           {
           ET0 = 0;       // disable timer 0 interrupt 
           TR0 = 0;       // stop timer0 - all of "a" has been checked 
           started = 0;   // started = 0, stop until switch pressed again   
           }
         }  // end if started == 1    
       }  // end if counter == 0
}

Also noticed that timer0 is using 0x3C80 again, instead of 0xC350. Maybe that's what works best ?


DOnt work again. Its too fast changing of numbers..
That example make me crazy.. Nobody doesnt know the answer..
I asked on many forums. But vainly..
 

If it is too fast, increase the value of counter until the speed is what you want. It needs to be changed both in main, and in the interrupt routine where it is currently given a value of 20. (When testing on my AT89C51ED2 running at 60 Mhz at 2x I have to have counter = 200 to get the 1 second delay).
The interrupt routine posted above is designed to delay 1 second for each "multiple of three" number. In your example, this would take 3 seconds because 3 of the 9 numbers in "a" are multples of 3. The previous interrupt routine would have taken 9 seconds to check "a" since it was testing 1 number per second.
 

If it is too fast, increase the value of counter until the speed is what you want. It needs to be changed both in main, and in the interrupt routine where it is currently given a value of 20. (When testing on my AT89C51ED2 running at 60 Mhz at 2x I have to have counter = 200 to get the 1 second delay).
The interrupt routine posted above is designed to delay 1 second for each "multiple of three" number. In your example, this would take 3 seconds because 3 of the 9 numbers in "a" are multples of 3. The previous interrupt routine would have taken 9 seconds to check "a" since it was testing 1 number per second.


I trowed out one number which is divided with 3, and speed is the same just like old state of string.
I also put for counter value 200 and tried with value 0000-C350=3CB0 for timer..
Its slower but not real 1 s. I think that i have two state for one second. (maybe 500ms)

- - - Updated - - -

Another thing, when I increase counter through value 200 , speed is the same like with value 200..
 

The problem may be that TR0 needs to cleared to load TH0 and TL0.
The code change would be in the interrupt routine:
Code:
    TR0 = 0;                // stop counter 0 to reload
    TH0 = 0x3C;          // set timer0 to 3C80 to count up 50,000 before overflow
    TL0 = 0x80;           // after each interrupt
    TR0 = 1;                // start counter 0 after reload
I found in the Atmel C51 Hardare manual:
http://www.atmel.com/images/doc4316.pdf
"TH0 and TL0 can be read at any time but TRx bit must be cleared to preset their values, otherwise the behavior of the timer/counter is unpredictable."

Also on page 2-83 of the hardware manual, it shows the timer running at the system clock/6,
giving a 2 Mhz Timer Clock. That would account for your seeing 500 ms instead of 1 second. I think we were calculating 12 Mhz divided by 12 for a 1 Mhz Timer clock.
 
Last edited:

    V

    Points: 2
    Helpful Answer Positive Rating
The problem may be that TR0 needs to cleared to load TH0 and TL0.
The code change would be in the interrupt routine:
Code:
    TR0 = 0;                // stop counter 0 to reload
    TH0 = 0x3C;          // set timer0 to 3C80 to count up 50,000 before overflow
    TL0 = 0x80;           // after each interrupt
    TR0 = 1;                // start counter 0 after reload
I found in the Atmel C51 Hardare manual:
http://www.atmel.com/images/doc4316.pdf
"TH0 and TL0 can be read at any time but TRx bit must be cleared to preset their values, otherwise the behavior of the timer/counter is unpredictable."

Also on page 2-83 of the hardware manual, it shows the timer running at the system clock/6,
giving a 2 Mhz Timer Clock. That would account for your seeing 500 ms instead of 1 second. I think we were calculating 12 Mhz divided by 12 for a 1 Mhz Timer clock.


O.K.
Yes, maybe is that value 1 s for this timer... Maybe for my eyes that is faster
I also put 16 numbers in string and speed is the same..
Now, I want to try that with 4 string with 16 numbers . Because that is real example ... :laugh:
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top