8051 (with C) questions.

Discussion in 'Embedded Systems and Microcontrollers' started by Chalma, Oct 3, 2013.

  1. Chalma

    Thread Starter Member

    May 19, 2013
    54
    2
    any time I've ever programmed for the 8051 I've usually always cut and pasted. I have had the luxury of doing anything I've ever needed to using Atmels products via Arduino. The engineer on this project however wants me to learn 8051. I understand that he is trying to help me and that the 8051 is a vastly superior and in the long run a better product for me to learn. I went out and bought "C and the 8051" by Thomas Schultz ans well as the 8051 micro development kit. it would figure the very first startup program and I am already confused. The code can be found below:

    //------------------------------------------------------------------------------------
    // F02x_Blinky.c
    //------------------------------------------------------------------------------------
    // Copyright (C) 2007 Silicon Laboratories, Inc.
    //
    // AUTH: BW
    // DATE: 4 SEP 01
    //
    // This program flashes the green LED on the C8051F020 target board about five times
    // a second using the interrupt handler for Timer3.
    // Target: C8051F02x
    //
    // Tool chain: KEIL Eval 'c'
    //

    //------------------------------------------------------------------------------------
    // Includes
    //------------------------------------------------------------------------------------
    #include <c8051f020.h> // SFR declarations

    //------------------------------------------------------------------------------------
    // 16-bit SFR Definitions for 'F02x
    //------------------------------------------------------------------------------------

    sfr16 DP = 0x82; // data pointer
    sfr16 TMR3RL = 0x92; // Timer3 reload value
    sfr16 TMR3 = 0x94; // Timer3 counter
    sfr16 ADC0 = 0xbe; // ADC0 data
    sfr16 ADC0GT = 0xc4; // ADC0 greater than window
    sfr16 ADC0LT = 0xc6; // ADC0 less than window
    sfr16 RCAP2 = 0xca; // Timer2 capture/reload
    sfr16 T2 = 0xcc; // Timer2
    sfr16 RCAP4 = 0xe4; // Timer4 capture/reload
    sfr16 T4 = 0xf4; // Timer4
    sfr16 DAC0 = 0xd2; // DAC0 data
    sfr16 DAC1 = 0xd5; // DAC1 data

    //------------------------------------------------------------------------------------
    // Global CONSTANTS
    //------------------------------------------------------------------------------------

    #define SYSCLK 2000000 // approximate SYSCLK frequency in Hz

    sbit LED = P1^6; // green LED: '1' = ON; '0' = OFF

    //------------------------------------------------------------------------------------
    // Function PROTOTYPES
    //------------------------------------------------------------------------------------
    void PORT_Init (void);
    void Timer3_Init (int counts);
    void Timer3_ISR (void);

    //------------------------------------------------------------------------------------
    // MAIN Routine
    //------------------------------------------------------------------------------------
    void main (void) {

    // disable watchdog timer
    WDTCN = 0xde;
    WDTCN = 0xad;

    PORT_Init ();
    Timer3_Init (SYSCLK / 12 / 10); // Init Timer3 to generate interrupts
    // at a 10Hz rate.

    EA = 1; // enable global interrupts

    while (1) { // spin forever
    }
    }

    //------------------------------------------------------------------------------------
    // PORT_Init
    //------------------------------------------------------------------------------------
    //
    // Configure the Crossbar and GPIO ports
    //
    void PORT_Init (void)
    {
    XBR2 = 0x40; // Enable crossbar and weak pull-ups
    P1MDOUT |= 0x40; // enable P1.6 (LED) as push-pull output
    }

    //------------------------------------------------------------------------------------
    // Timer3_Init
    //------------------------------------------------------------------------------------
    //
    // Configure Timer3 to auto-reload and generate an interrupt at interval
    // specified by <counts> using SYSCLK/12 as its time base.
    //
    void Timer3_Init (int counts)
    {
    TMR3CN = 0x00; // Stop Timer3; Clear TF3;
    // use SYSCLK/12 as timebase
    TMR3RL = -counts; // Init reload values
    TMR3 = 0xffff; // set to reload immediately
    EIE2 |= 0x01; // enable Timer3 interrupts
    TMR3CN |= 0x04; // start Timer3
    }

    //------------------------------------------------------------------------------------
    // Interrupt Service Routines
    //------------------------------------------------------------------------------------

    //------------------------------------------------------------------------------------
    // Timer3_ISR
    //------------------------------------------------------------------------------------
    // This routine changes the state of the LED whenever Timer3 overflows.
    //
    void Timer3_ISR (void) interrupt 10
    {
    TMR3CN &= ~(0x80); // clear TF3
    LED = ~LED; // change state of LED
    }

    I just copied and pasted the code from example. What I'm concerned about is I don't understand the 10hz timer rate. 2000000 / 12 / 10 is roughly 1.67khz I tried dividing later on by 8Mhz (what I believe to be the internal crystal frequency) and no mater if I use (PEMDAS vs BODMAS shouldn't matter) I do not get my 10Hz. Would anyone mind telling me what is going on? I've tried to even factor in Instructions per second and still cannot arrive at 10.

    My second question is how does the Timer3_ISR interrupt excecute? I understand when the counting gets to about 17k that it resets but how does it know to go to that function? what if I wanted this function to execute every %100 == 0 or something to that effect? I don't see anything comparing or 'tripping' this to go.

    I apologize for my ignorance, I've done some pretty neat projects with easy things like the arduino and copied and pasted 8051 but it's like I have to start ALL over again. I know it is for the better however. Thanks
     
  2. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    The freq of toggling the LED appears to be the TMR3 overflow frequency. I don't know much about your chip, but it is likely to be an 8bit timer that overflows every 256 ticks;
    2MHz / 12 / 10 / 256 = 65 Hz

    (tha is correct if Sysclk is actually 2MHz)
     
  3. Arm_n_Legs

    Active Member

    Mar 7, 2007
    183
    10
    My second question is how does the Timer3_ISR interrupt excecute?

    Let me answer your second question first. It is build into the hardware that when the timer3 interrupt occurs, the program will jump to a specific location, which is code location 0053H (you can get this information from the datasheet of the chip).

    How do you write your timer 3 routine in code location 0053H? Refers to Keil manual - http://www.keil.com/support/man/docs/c51/c51_le_interruptfuncs.htm . The interrupt number is 10 (specific to Keil C51 only).

    The routine:
    void Timer3_ISR (void) interrupt 10
    written in C will be loaded to location 0053H. The name Timer3_ISR is not important. The number 10 is !

    Coming back to the first question.

    (SYSCLK / 12 / 10) gives you the number of count in timer 3 before it overflows. You need to find out how much time is taken per count. To understand the timer better, refer to the page 240 of the datasheet (http://www.keil.com/dd/docs/datashts/silabs/c8051f02x.pdf).

    :D
     
    Chalma likes this.
  4. Chalma

    Thread Starter Member

    May 19, 2013
    54
    2
    Thanks, I'll have to 'play' around more so I become more comfortable with both these concepts.
     
Loading...