8051 (with C) questions.

Thread Starter

Chalma

Joined May 19, 2013
54
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
 

THE_RB

Joined Feb 11, 2008
5,438
...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 ...
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)
 

Arm_n_Legs

Joined Mar 7, 2007
186
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
 
Top