Вы находитесь на странице: 1из 39

Examples

About the User's Installation Contact The Fundamental


Home Examples
Simulator Guide Instructions Us Simulations

This page contains example programs (mostly in assembly, but a few in C) for excercising the EdSim51 virtu

First, download for free the EdSim51 simulator - it's free and is very easy to install.

The simulator does not run in real time, of course. When a program is running, the amount of elapsed time (a
the field above the source code. The user can set the number of instructions executed between updates to the s
the Update Freq. menu. Certain update frequencies suit some programs better than others.
For example, if a program is multiplexing the four 7-segment displays, then it is best to run this program with
program is sending data to the serial port, then a higher update frequency might be used in order to see the da

1. Binary Pattern on the Port 1 LEDs


2. Echoing the Switches to the LEDs
3. Multiplexing the 7-segment Displays
4. LCD Module
plus a couple of CGRAM examples:
o Euro Symbol
o ADC Bar Graph Indicator on LCD
5. Ramp Signal on the DAC Output
6. Taking Samples from the ADC and Displaying them on the Scope via the DAC
7. Scanning the Keypad
8. Transmitting Data on the 8051 Serial Port
9. Receiving Data on the 8051 Serial Port

10. The Motor

Download the Examples source code: edsim51examples.zip

The peripheral logic diagram is shown below:


Logic Diagram Extracts:
• Logic diagram showing the LED bank, DAC and 7-segment display connections only.
• Logic diagram showing the LED bank, DAC and LCD Module connections only.
• Logic diagram showing the switch bank and ADC connections only.
• Logic diagram showing the comparator and DAC connections only.
• Logic diagram showing the motor and UART connections only.
• Logic diagram showing the keypad connections only.

1. Binary Pattern on the Port 1 LEDs - logic diagram extract

Notes on 8051 Parallel Input/Output

<- get the source code


; This program displays the binary pattern
; from 0 to 255 (and back to 0) on the LEDs
; interfaced with port 1.

; A 1 in the pattern is represented by the LED on,


; while a 0 in the pattern is represented by the LED off.

; However, logic 0 on a port 1 pin turns on the LED,


; therefore it is necessary to write the inverse of the
; pattern to the LEDs. The easiest way to do this is
; to send the data FFH to 0 (and back to FFH) to the LEDs.

; Since port 1 is initially at FFH all we need to do is


; continuously decrement port 1.

start:
DEC P1 ; decrement port 1
JMP start ; and repeat

When running this program, best viewed with Update Freq. set to 1.

2. Echoing the Switches to the LEDs - logic diagram extract

Notes on 8051 Parallel Input/Output

<-get the source code


; This program very simply echoes the
; switches on P2 to the LEDs on P1.

; When a switch is closed a logic 0 appears


; on that P2 pin, which is then copied to
; that P1 bit which turns on that LED.
; Therefore, a closed switch is seen as a lit
; LED and vice versa.

start:
MOV P1, P2 ; move data on P2 pins to P1
JMP start ; and repeat
When running this program, best viewed with Update Freq. set to 1.

3. Multiplexing the 7-segment Displays - logic diagram extract

Notes on Multiplexing

<- get the source code


; This program multiplexes the number 1234
; on the four 7-segment displays.

; Note: a logic 0 lights a display segment.

start:
SETB P3.3 ; |
SETB P3.4 ; | enable display 3
MOV P1, #11111001B ; put pattern for 1 on display
MOV P1, #0FFH ; clear the display
CLR P3.3 ; enable display 2
MOV P1, #10100100B ; put pattern for 2 on display
MOV P1, #0FFH ; clear the display
CLR P3.4 ; |
SETB P3.3 ; | enable display 1
MOV P1, #10110000B ; put pattern for 3 on display
MOV P1, #0FFH ; clear the display
CLR P3.3 ; enable display 0
MOV P1, #10011001B ; put pattern for 4 on display
MOV P1, #0FFH ; clear display
JMP start ; jump back to start

See what happens if you remove the clear the display (ie: MOV P1, #0FFH) lines from the program. You should
why the numbers don't appear in the correct order.

When running this program, best viewed with Update Freq. set to 1.

4. LCD Module - logic diagram extract

The example program for programming the LCD module is written in C. It was developed and compiled usin
write your own C programs for the 8051, get the free evaluation version of uVision3 - it downloads very quic
connection such as o2 broadband.

The EdSim51 simulator can only parse assembly programs. It cannot compile C programs, therefore do not
into EdSim51. Instead, you should compile the program in uVision3 and use the Intel HEX output file. This t
See notes on EdSim51 and Intel HEX files.

When the program below is running in the simulator, the user can shift the display right and left and can retur
and 7 (see the comment in the main program for details). Since the simulator is not real-time, to be able to se
to set the simulator update frequency to 100.

<- get the source code


You can also download the HEX file output which was generated by the uVision3 compiler.
#include <reg51.h>

sbit DB7 = P1^7;


sbit DB6 = P1^6;
sbit DB5 = P1^5;
sbit DB4 = P1^4;
sbit RS = P1^3;
sbit E = P1^2;

sbit clear = P2^4;


sbit ret = P2^5;
sbit left = P2^6;
sbit right = P2^7;

void returnHome(void);
void entryModeSet(bit id, bit s);
void displayOnOffControl(bit display, bit cursor, bit blinking);
void cursorOrDisplayShift(bit sc, bit rl);
void functionSet(void);
void setDdRamAddress(char address);

void sendChar(char c);


void sendString(char* str);
bit getBit(char c, char bitNumber);
void delay(void);

void main(void) {

functionSet();
entryModeSet(1, 0); // increment and no shift
displayOnOffControl(1, 1, 1); // display on, cursor on and blinking on
sendString("EdSim51 LCD Module Simulation");
setDdRamAddress(0x40); // set address to start of second line
sendString("Based on Hitachi HD44780");

// The program can be controlled via some of the switches on port 2.


// If switch 5 is closed the cursor returns home (address 0).
// Otherwise, switches 6 and 7 are read - if both switches are open or both swit
// are closed, the display does not shift.
// If switch 7 is closed, continuously shift left.
// If switch 6 is closed, continuously shift right.
while (1) {
if (ret == 0) {
returnHome();
}
else {
if (left == 0 && right == 1) {
cursorOrDisplayShift(1, 0); // shift display left
}
else if (left == 1 && right == 0) {
cursorOrDisplayShift(1, 1); // shift display right
}
}
}
}

// LCD Module instructions -------------------------------------------


// To understand why the pins are being set to the particular values in the functions
// below, see the instruction set.
// A full explanation of the LCD Module: HD44780.pdf

void returnHome(void) {
RS = 0;
DB7 = 0;
DB6 = 0;
DB5 = 0;
DB4 = 0;
E = 1;
E = 0;
DB5 = 1;
E = 1;
E = 0;
delay();
}

void entryModeSet(bit id, bit s) {


RS = 0;
DB7 = 0;
DB6 = 0;
DB5 = 0;
DB4 = 0;
E = 1;
E = 0;
DB6 = 1;
DB5 = id;
DB4 = s;
E = 1;
E = 0;
delay();
}

void displayOnOffControl(bit display, bit cursor, bit blinking) {


DB7 = 0;
DB6 = 0;
DB5 = 0;
DB4 = 0;
E = 1;
E = 0;
DB7 = 1;mov
DB6 = display;
DB5 = cursor;
DB4 = blinking;
E = 1;
E = 0;
delay();
}
void cursorOrDisplayShift(bit sc, bit rl) {
RS = 0;
DB7 = 0;
DB6 = 0;
DB5 = 0;
DB4 = 1;
E = 1;
E = 0;
DB7 = sc;
DB6 = rl;
E = 1;
E = 0;
delay();
}

void functionSet(void) {
// The high nibble for the function set is actually sent twice. Why? See 4-bit o
// on pages 39 and 42 of HD44780.pdf.
DB7 = 0;
DB6 = 0;
DB5 = 1;
DB4 = 0;
RS = 0;
E = 1;
E = 0;
delay();
E = 1;
E = 0;
DB7 = 1;
E = 1;
E = 0;
delay();
}

void setDdRamAddress(char address) {


RS = 0;
DB7 = 1;
DB6 = getBit(address, 6);
DB5 = getBit(address, 5);
DB4 = getBit(address, 4);
E = 1;
E = 0;
DB7 = getBit(address, 3);
DB6 = getBit(address, 2);
DB5 = getBit(address, 1);
DB4 = getBit(address, 0);
E = 1;
E = 0;
delay();
}

void sendChar(char c) {
DB7 = getBit(c, 7);
DB6 = getBit(c, 6);
DB5 = getBit(c, 5);
DB4 = getBit(c, 4);
RS = 1;
E = 1;
E = 0;
DB7 = getBit(c, 3);
DB6 = getBit(c, 2);
DB5 = getBit(c, 1);
DB4 = getBit(c, 0);
E = 1;
E = 0;
delay();
}

// -- End of LCD Module instructions


// --------------------------------------------------------------------

void sendString(char* str) {


int index = 0;
while (str[index] != 0) {
sendChar(str[index]);
index++;
}
}

bit getBit(char c, char bitNumber) {


return (c >> bitNumber) & 1;
}

void delay(void) {
char c;
for (c = 0; c < 50; c++);
}

An Assembly Program Example


The example below sends the text ABC to the display.
<-get the source code
; put data in RAM
MOV 30H, #'A'
MOV 31H, #'B'
MOV 32H, #'C'
MOV 33H, #0 ; end of data marker

; initialise the display


; see instruction set for details

CLR P1.3 ; clear RS - indicates that instructions are being sent t

; function set
CLR P1.7 ; |
CLR P1.6 ; |
SETB P1.5 ; |
CLR P1.4 ; | high nibble set

SETB P1.2 ; |
CLR P1.2 ; | negative edge on E

CALL delay ; wait for BF to clear


; function set sent for first time - tells module to go i
; Why is function set high nibble sent twice? See 4-bit operation on pages 39 and 42 of

SETB P1.2 ; |
CLR P1.2 ; | negative edge on E
; same function set high nibble sent a second time

SETB P1.7 ; low nibble set (only P1.7 needed to be changed)

SETB P1.2 ; |
CLR P1.2 ; | negative edge on E
; function set low nibble sent
CALL delay ; wait for BF to clear

; entry mode set


; set to increment with no shift
CLR P1.7 ; |
CLR P1.6 ; |
CLR P1.5 ; |
CLR P1.4 ; | high nibble set

SETB P1.2 ; |
CLR P1.2 ; | negative edge on E

SETB P1.6 ; |
SETB P1.5 ; |low nibble set

SETB P1.2 ; |
CLR P1.2 ; | negative edge on E

CALL delay ; wait for BF to clear

; display on/off control


; the display is turned on, the cursor is turned on and blinking is turned on
CLR P1.7 ; |
CLR P1.6 ; |
CLR P1.5 ; |
CLR P1.4 ; | high nibble set

SETB P1.2 ; |
CLR P1.2 ; | negative edge on E

SETB P1.7 ; |
SETB P1.6 ; |
SETB P1.5 ; |
SETB P1.4 ; | low nibble set

SETB P1.2 ; |
CLR P1.2 ; | negative edge on E

CALL delay ; wait for BF to clear

; send data
SETB P1.3 ; clear RS - indicates that data is being sent to module
MOV R1, #30H ; data to be sent to LCD is stored in 8051 RAM, starting
loop:
MOV A, @R1 ; move data pointed to by R1 to A
JZ finish ; if A is 0, then end of data has been reached - jump out
CALL sendCharacter ; send data in A to LCD module
INC R1 ; point to next piece of data
JMP loop ; repeat

finish:
JMP $

sendCharacter:
MOV C, ACC.7 ; |
MOV P1.7, C ; |
MOV C, ACC.6 ; |
MOV P1.6, C ; |
MOV C, ACC.5 ; |
MOV P1.5, C ; |
MOV C, ACC.4 ; |
MOV P1.4, C ; | high nibble set

SETB P1.2 ; |
CLR P1.2 ; | negative edge on E

MOV C, ACC.3 ; |
MOV P1.7, C ; |
MOV C, ACC.2 ; |
MOV P1.6, C ; |
MOV C, ACC.1 ; |
MOV P1.5, C ; |
MOV C, ACC.0 ; |
MOV P1.4, C ; | low nibble set

SETB P1.2 ; |
CLR P1.2 ; | negative edge on E

CALL delay ; wait for BF to clear

delay:
MOV R0, #50
DJNZ R0, $
RET

Two more LCD examples - these make use of CGRAM:


• Euro Symbol

• ADC Bar Graph Indicator on LCD

5. Ramp Signal on the DAC Output - logic diagram extract


<- get the source code
; This program generates a ramp on the DAC
; output.

; You can try adding values other than 8


; to the accumulator to see what this does
; to the ramp signal.

CLR P0.7 ; enable the DAC WR line


loop:
MOV P1, A ; move data in the accumulator to the ADC inputs (on P1)
ADD A, #8 ; increase accumulator by 8
JMP loop ; jump back to loop

When running this program, best viewed with Update Freq. set to 1.
The output on the scope should be something like this:

6. Taking Samples from the ADC and Displaying them on the Scope via the DAC - logic diagram extra

Note: When using the ADC, the switches in the switch bank must be open (the switches are blue when open,
switch bank and the ADC share the same port, as can be seen in the logic diagram extract.

Notes on ADC Interfacing.

<- get the source code


; This program reads the analogue input
; voltage on the ADC and displays it on
; the scope via the DAC.

; A sample is taken from the ADC every 20 us


; This is achieved by setting timer 0
; to interrupt the main program every 20 us.
; The timer 0 ISR then initiates an ADC
; conversion.

; When the conversion is complete the


; ADC interrupt line goes low. This line
; is interfaced with the 8051 external 0
; interrupt line. The external 0 ISR
; therefore takes the reading from the ADC
; on P2 and passes it to the DAC on P1.

; Therefore, while the program is running,


; the scope voltage level should be the
; same as the ADC input voltage.
; However, when a change is made to the
; ADC input voltage it will take some time
; for the scope to update (ie: until the
; next timer 0 interrupt). This simulates
; the 20 us delay between samples.

; Note: when running this program make sure


; the ADC is enabled (the blue button above
; the input voltage slider should say ADC Enabled).

ORG 0 ; reset vector


JMP main ; jump to the main program

ORG 3 ; external 0 interrupt vector


JMP ext0ISR ; jump to the external 0 ISR

ORG 0BH ; timer 0 interrupt vector


JMP timer0ISR ; jump to timer 0 ISR

ORG 30H ; main program starts here


main:
SETB IT0 ; set external 0 interrupt as edge-activated
SETB EX0 ; enable external 0 interrupt
CLR P0.7 ; enable DAC WR line
MOV TMOD, #2 ; set timer 0 as 8-bit auto-reload interval timer

MOV TH0, #-20 ; | put -20 into timer 0 high-byte - this reload value,
; | with system clock of 12 MHz, will result in a timer 0

MOV TL0, #-20 ; | put the same value in the low byte to ensure the time
; | 236 (256 - 20) rather than 0

SETB TR0 ; start timer 0


SETB ET0 ; enable timer 0 interrupt
SETB EA ; set the global interrupt enable bit
JMP $ ; jump back to the same line (ie: do nothing)
; end of main program

; timer 0 ISR - simply starts an ADC conversion


timer0ISR:
CLR P3.6 ; clear ADC WR line
SETB P3.6 ; then set it - this results in the required positive edg
RETI ; return from interrupt

; external 0 ISR - responds to the ADC conversion complete interrupt


ext0ISR:
CLR P3.7 ; clear the ADC RD line - this enables the data lines
MOV P1, P2 ; take the data from the ADC on P2 and send it to the DAC
SETB P3.7 ; disable the ADC data lines by setting RD
RETI ; return from interrupt

When running this program with Update Freq. set to 1, the student will observe the time delay between a cha
on the scope. In order to see this change appear on the scope more quickly, select a higher update frequency.
A Further exercise for the student might be to display, using multiplexing, the actual input signal voltage to th

7. Scanning the Keypad - logic diagram extract

Notes on Keypads

<- get the source code

The following program shows how to scan the keypad. The program halts (to be precise, sits in an endless loo
; This program scans the keypad.

; While no key is pressed the program


; scans row0, row1, row2, row3 and back to
; row0, continuously.

; When a key is pressed the key number


; is placed in R0.

; For this program, the keys are numbered


; as:

; +----+----+----+
; | 11 | 10 | 9 | row3
; +----+----+----+
; | 8 | 7 | 6 | row2
; +----+----|----+
; | 5 | 4 | 3 | row1
; +----+----+----+
; | 2 | 1 | 0 | row0
; +----+----+----+
; col2 col1 col0

; The pressed key number will be stored in


; R0. Therefore, R0 is initially cleared.
; Each key is scanned, and if it is not
; pressed R0 is incremented. In that way,
; when the pressed key is found, R0 will
; contain the key's number.

; The general purpose flag, F0, is used


; by the column-scan subroutine to indicate
; whether or not a pressed key was found
; in that column.
; If, after returning from colScan, F0 is
; set, this means the key was found.

start:

MOV R0, #0 ; clear R0 - the first key is key0

; scan row0
SETB P0.3 ; set row3
CLR P0.0 ; clear row0
CALL colScan ; call column-scan subroutine
JB F0, finish ; | if F0 is set, jump to end of program
; | (because the pressed key was found and its number is

; scan row1
SETB P0.0 ; set row0
CLR P0.1 ; clear row1
CALL colScan ; call column-scan subroutine
JB F0, finish ; | if F0 is set, jump to end of program
; | (because the pressed key was found and its number is

; scan row2
SETB P0.1 ; set row1
CLR P0.2 ; clear row2
CALL colScan ; call column-scan subroutine
JB F0, finish ; | if F0 is set, jump to end of program
; | (because the pressed key was found and its number is

; scan row3
SETB P0.2 ; set row2
CLR P0.3 ; clear row3
CALL colScan ; call column-scan subroutine
JB F0, finish ; | if F0 is set, jump to end of program
; | (because the pressed key was found and its number is

JMP start ; | go back to scan row 0


; | (this is why row3 is set at the start of the program
; | - when the program jumps back to start, row3 has just

finish:
JMP $ ; program execution arrives here when key is found - do n
; column-scan subroutine
colScan:
JNB P0.4, gotKey ; if col0 is cleared - key found
INC R0 ; otherwise move to next key
JNB P0.5, gotKey ; if col1 is cleared - key found
INC R0 ; otherwise move to next key
JNB P0.6, gotKey ; if col2 is cleared - key found
INC R0 ; otherwise move to next key
RET ; return from subroutine - key not found
gotKey:
SETB F0 ; key found - set F0
RET ; and return from subroutine

It may appear as if this program does nothing. Remember, the program simply scans the keypad until a key is
R0 and enters an endless loop, doing nothing. Therefore, to see that it has performed the task correctly, exami
pressed. Also remember that, if the update frequency is set to 1, it will take a short amount of time for they pr

Key number: the key number mentioned here is not the number on the key, but the key's position in the matr
key number 1, * key is key number 2, and so on.
Further exercises for the student might be:
• Modify the program so that the keypad is scanned continuously (ie: it doesn't stop after one key-press

• Write extra code that displays the key symbol on one of the 7-segment displays. For example, if key 4
display. If key 10 is pressed the number 2 appears on the display. (Note: the symbols # and * cannot b
some special characters could be invented and displayed instead.

8. Transmitting Data on the 8051 Serial Port - logic diagram extract

Notes on the 8051 Serial Port

<- get the source code


; This program sends the text abc down the
; 8051 serial port to the external UART at 4800 Baud.

; To generate this baud rate, timer 1 must overflow


; every 13 us with SMOD equal to 1 (this is as close as
; we can get to 4800 baud at a system clock frequency
; of 12 Mz).

; See the notes on the serial port for more information.

; The data is sent with even parity,


; therefore for it to be received correctly
; the external UART must be set to Even Parity

CLR SM0 ; |
SETB SM1 ; | put serial port in 8-bit UART mode

MOV A, PCON ; |
SETB ACC.7 ; |
MOV PCON, A ; | set SMOD in PCON to double baud rate

MOV TMOD, #20H ; put timer 1 in 8-bit auto-reload interval timing mode
MOV TH1, #243 ; put -13 in timer 1 high byte (timer will overflow every
MOV TL1, #243 ; put same value in low byte so when timer is first start
SETB TR1 ; start timer 1

MOV 30H, #'a' ; |


MOV 31H, #'b' ; |
MOV 32H, #'c' ; | put data to be sent in RAM, start address 30H

MOV 33H, #0 ; null-terminate the data (when the accumulator contains


MOV R0, #30H ; put data start address in R0
again:
MOV A, @R0 ; move from location pointed to by R0 to the accumulator
JZ finish ; if the accumulator contains 0, no more data to be sent,
MOV C, P ; otherwise, move parity bit to the carry
MOV ACC.7, C ; and move the carry to the accumulator MSB
MOV SBUF, A ; move data to be sent to the serial port
INC R0 ; increment R0 to point at next byte of data to be sent
JNB TI, $ ; wait for TI to be set, indicating serial port has finis
CLR TI ; clear TI
JMP again ; send next byte
finish:
JMP $ ; do nothing

Take note of what happens if the external UART is not set to Even Parity (ie: run the program with the UART
set to
Odd Parity). With the help of the ASCII table, see if you can explain the actual data that is displayed.

It takes quite some time (from the 8051's perspective of time) for data to be sent to the UART. If the user wis
quickly, it may be best, when running this program, to select an Update Freq. of 100 or 1000.

Further exercises for the student might be:


• Modify the program to transmit data with no parity.
• Modify the program to transmit data with odd parity.

• The above program uses busy-waiting. In other words, it sends a byte to the serial port, then sits in a l
serial port to say it's ready for another byte. Rewrite the program making use of the serial port interrup

9. Receiving Data on the Serial Port - logic diagram extract

Notes on the 8051 Serial Port


<- get the source code
; This program receives data on the 8051
; serial port. Once the program's
; initialisation is complete, it waits for
; data arriving on the RXD line (data
; that was transmitted by the external
; UART).

; Any text typed in the external UART is


; sent once the Tx Send button is pressed.
; As each character is transmitted fully,
; it disappears from the Tx window.
; The data is appended with the return
; character (0D HEX).

; The default external UART baud rate is 19,200. To


; generate this baud rate, TH1 must be set to -3.
; If the system clock is 12 MHz, the error when attempting
; to generate such a high baud rate such that very often
; garbage is received. Therefore, for 19,200 Baud, the
; system clock should be set to 11.059 HMz.

; See the notes on the serial port for more information.

; The program is written using busy-waiting.


; It continuously tests the RI flag. Once
; this flag is set by the 8051 hardware
; (a byte has been received) the program
; clears it and then moves the byte from
; SBUF to A.
; The received byte's value is checked to
; see if it is the terminating character (0D HEX).
; If it is the program jumps to the finish,
; otherwise it moves the byte to data memory
; and returns to waiting for the next byte.

CLR SM0 ; |
SETB SM1 ; | put serial port in 8-bit UART mode

SETB REN ; enable serial port receiver

MOV A, PCON ; |
SETB ACC.7 ; |
MOV PCON, A ; | set SMOD in PCON to double baud rate

MOV TMOD, #20H ; put timer 1 in 8-bit auto-reload interval timing mode
MOV TH1, #0FDH ; put -3 in timer 1 high byte (timer will overflow every
MOV TL1, #0FDH ; put same value in low byte so when timer is first start
3 us
SETB TR1 ; start timer 1
MOV R1, #30H ; put data start address in R1
again:
JNB RI, $ ; wait for byte to be received
CLR RI ; clear the RI flag
MOV A, SBUF ; move received byte to A
CJNE A, #0DH, skip ; compare it with 0DH - it it's not, skip next instructio
JMP finish ; if it is the terminating character, jump to the end of
skip:
MOV @R1, A ; move from A to location pointed to by R1
INC R1 ; increment R1 to point at next location where data will
JMP again ; jump back to waiting for next byte
finish:
JMP $ ; do nothing
Further exercises for the student might be:
• Modify the program to receive data with even parity.
• Modify the program to receive data with odd parity.
• Using parity checking, light LED0 (on port 1) if an error is detected in a received byte.
• The above program uses busy-waiting. In other words, it sits in a loop (testing the RI flag) waiting for
program making use of the serial port interrupt (get help with 8051 interrupts).

• Combine the transmit and receive programs to send back the data received from the external UART. I
UART Tx window should appear in the UART Rx window.

It takes quite some time (from the 8051's perspective of time) for data to be received from the UART. If the u
RAM quickly, it may be best, when running this program, to select an Update Freq. of 100 or 1000.

10. The Motor - logic diagram extract

Notes on DC Motors

<- get the source code


; This program exercises the motor.
; The motor is rotated in a clockwise
; direction and the number of revolutions
; is displayed on Display 0 (the 7-segment
; display). The display only shows up to
; nine revolutions and then resets.

; The motor sensor is connected to P3.5,


; which is the external clock source for
; timer 1. Therefore, timer 1 is put into
; event counting mode. In this way, the
; the timer increments once every motor
; revolution.

; The value in timer 1 low byte is moved


; to A and this value together with the
; data pointer (DPH and DPL) are used to
; get the 7-segment code from program memory.
; The code is then sent to P1 to put the
; appropriate number on the Display 0.

; The motor can be changed from clockwise


; to anti-clockwise by pressing SW0 (on P2.0).
; The motor direction is stored in F0 (1 for
; clockwise, 0 for anti-clockwise). The
; value in F0 is sent to Display 0's decimal
; point (P1.7). This indicates the motor's
; direction - if the decimal point is lit,
; the motor is rotating anti-clockwise, while
; if it is not lit the motor is rotating
; clockwise.

; The value in F0 is compared with the


; value of SW0. If they are the same the
; motor direction does not need to be
; changed. If they are not the same it means
; the user has pressed SW0 and the motor
; direction must be reversed. When this
; happens the new motor direction is then
; stored in F0.

MOV TMOD, #50H ; put timer 1 in event counting mode


SETB TR1 ; start timer 1

MOV DPL, #LOW(LEDcodes) ; | put the low byte of the start address
; | 7-segment code table into DPL

MOV DPH, #HIGH(LEDcodes) ; put the high byte into DPH

CLR P3.4 ; |
CLR P3.3 ; | enable Display 0
again:
CALL setDirection ; set the motor's direction
MOV A, TL1 ; move timer 1 low byte to A
CJNE A, #10, skip ; if the number of revolutions is not 10 skip next
CALL clearTimer ; if the number of revolutions is 10, reset timer
skip:
MOVC A, @A+DPTR ; | get 7-segment code from code table - the index
; | decided by the value in A
; | (example: the data pointer points to the start
; | table - if there are two revolutions, then A w
; | therefore the second code in the table will be

MOV C, F0 ; move motor direction value to the carry


MOV ACC.7, C ; and from there to ACC.7 (this will ensure Displa
; will indicate the motor's direction)

MOV P1, A ; | move (7-seg code for) number of revolutions an


; | indicator to Display 0

JMP again ; do it all again

setDirection:
PUSH ACC ; save value of A on stack
PUSH 20H ; save value of location 20H (first bit-addressabl
; location in RAM) on stack
CLR A ; clear A
MOV 20H, #0 ; clear location 20H
MOV C, P2.0 ; put SW0 value in carry
MOV ACC.0, C ; then move to ACC.0
MOV C, F0 ; move current motor direction in carry
MOV 0, C ; and move to LSB of location 20H (which has bit a

CJNE A, 20H, changeDir ; | compare SW0 (LSB of A) with F0 (LSB of 20H)


; | - if they are not the same, the motor's direct
JMP finish ; if they are the same, motor's direction does not
changeDir:
CLR P3.0 ; |
CLR P3.1 ; | stop motor

CALL clearTimer ; reset timer 1 (revolution count restarts when mo


MOV C, P2.0 ; move SW0 value to carry
MOV F0, C ; and then to F0 - this is the new motor direction
MOV P3.0, C ; move SW0 value (in carry) to motor control bit 1
CPL C ; invert the carry

MOV P3.1, C ; | and move it to motor control bit 0 (it will th


; | value to control bit 1 and the motor will star
; | again in the new direction)
finish:
POP 20H ; get original value for location 20H from the sta
POP ACC ; get original value for A from the stack
RET ; return from subroutine

clearTimer:
CLR A ; reset revolution count in A to zero
CLR TR1 ; stop timer 1
MOV TL1, #0 ; reset timer 1 low byte to zero
SETB TR1 ; start timer 1
RET ; return from subroutine

LEDcodes: ; | this label points to the start address of the 7-segment code table w
; | stored in program memory using the DB command below
DB 11000000B, 11111001B, 10100100B, 10110000B, 10011001B, 10010010B, 10000010B,

Note: The above program is a good illustration of what can go wrong if the sampling frequency is too low. T
full speed (use the slider to the right of the motor to increase the motor speed). You should notice the motor c
the display updates. In other words, the motor's highest speed is too fast for the 8051 running at system clock

Since the program only shows up to nine revolutions (displayed on the 7-segment display) and then starts cou
with an Update Freq. of 1. This allows the user observe the display count up from 0 to 9 and back to 0 agai
motor arm passing the sensor and the display update. Similarly, the delay between pressing the switch for a d
change occurring is evident. The student will learn that, while in real time these delays are not noticeable, to
quite some time.

Further exercises for the student might be:


• With the above program only up to nine revolutions are counted, then the display resets. Use multiple
to 99 revolutions. (Remember, when testing your program you do not have to sit idly by waiting for th
can pause the program, manually change the value in the timer 1 low byte - say to 98 - and then click

About the User's Installation Contact The Fundamental


Home Examples
Simulator Guide Instructions Us Simulations
Copyright (c) 2005-2010 James Rogers

Intel MCS-51
From Wikipedia, the free encyclopedia
Jump to: navigation, search

Intel P8051 microcontroller.

SAB-C515-LN by Infineon is based on the 8051

The Intel MCS-51 is a Harvard architecture, single chip microcontroller (µC) series
which was developed by Intel in 1980 for use in embedded systems.[1][2] Intel's original
versions were popular in the 1980s and early 1990s, but has today largely been
superseded by a vast range of faster and/or functionally enhanced 8051-compatible
devices manufactured by more than 20 independent manufacturers including Atmel,
Infineon Technologies (formerly Siemens AG), Maxim Integrated Products (via its
Dallas Semiconductor subsidiary), NXP (formerly Philips Semiconductor), Nuvoton
(formerly Winbond), ST Microelectronics, Silicon Laboratories (formerly Cygnal), Texas
Instruments, Ramtron International, Silicon Storage Technology, and Cypress
Semiconductor.
Intel's original MCS-51 family was developed using NMOS technology, but later
versions, identified by a letter C in their name (e.g., 80C51) used CMOS technology and
were less power-hungry than their NMOS predecessors. This made them more suitable
for battery-powered devices.

Contents
[hide]

• 1 Important features and applications


• 2 Memory Architecture
• 3 Programming
• 4 Instruction set
• 5 Related processors
• 6 Educational Use
• 7 References
• 8 Literature

• 9 External links

[edit] Important features and applications

i8051 microarchitecture.

The 8051 architecture provides many functions (CPU, RAM, ROM, I/O, interrupt logic,
timer, etc.) in a single package

• 8-bit ALU, Accumulator and 8-bit Registers; hence it is an 8-bit microcontroller


• 8-bit data bus – It can access 8 bits of data in one operation
• 16-bit address bus – It can access 216 memory locations – 64 KB (65536
locations) each of RAM and ROM
• On-chip RAM – 128 bytes (data memory)
• On-chip ROM – 4 kByte (program memory)
• Four byte bi-directional input/output port
• UART (serial port)
• Two 16-bit Counter/timers
• Two-level interrupt priority
• Power saving mode (on some derivatives)

A particularly useful feature of the 8051 core is the inclusion of a boolean processing
engine which allows bit-level boolean logic operations to be carried out directly and
efficiently on internal registers and RAM. This feature helped cement the 8051's
popularity in industrial control applications. Another valued feature is that it has four
separate register sets, which can be used to greatly reduce interrupt latency compared to
the more common method of storing interrupt context on a stack.

The MCS-51 UARTs make it simple to use the chip as a serial communications interface.
External pins can be configured to connect to internal shift registers in a variety of ways,
and the internal timers can also be used, allowing serial communications in a number of
modes, both synchronous and asynchronous. Some modes allow communications with no
external components. A mode compatible with an RS-485 multi-point communications
environment is achievable, but the 8051's real strength is fitting in with existing ad-hoc
protocols (e.g., when controlling serial-controlled devices).

Once a UART, and a timer if necessary, have been configured, the programmer needs
only to write a simple interrupt routine to refill the send shift register whenever the last
bit is shifted out by the UART and/or empty the full receive shift register (copy the data
somewhere else). The main program then performs serial reads and writes simply by
reading and writing 8-bit data to stacks.

MCS-51 based microcontrollers typically include one or two UARTs, two or three timers,
128 or 256 bytes of internal data RAM (16 bytes of which are bit-addressable), up to 128
bytes of I/O, 512 bytes to 64 kB of internal program memory, and sometimes a quantity
of extended data RAM (ERAM) located in the external data space. The original 8051
core ran at 12 clock cycles per machine cycle, with most instructions executing in one or
two machine cycles. With a 12 MHz clock frequency, the 8051 could thus execute 1
million one-cycle instructions per second or 500,000 two-cycle instructions per second.
Enhanced 8051 cores are now commonly used which run at six, four, two, or even one
clock per machine cycle, and have clock frequencies of up to 100 MHz, and are thus
capable of an even greater number of instructions per second. All SILabs, some Dallas
and a few Atmel devices have single cycle cores.

Common features included in modern 8051 based microcontrollers include built-in reset
timers with brown-out detection, on-chip oscillators, self-programmable Flash ROM
program memory, bootloader code in ROM, EEPROM non-volatile data storage, I²C,
SPI, and USB host interfaces, CAN or LIN bus, PWM generators, analog comparators,
A/D and D/A converters, RTCs, extra counters and timers, in-circuit debugging facilities,
more interrupt sources, and extra power saving modes.

[edit] Memory Architecture


The MCS-51 has four distinct types of memory – internal RAM, special function
registers, program memory, and external data memory.

Internal RAM (IRAM) is located from address 0 to address 0xFF. IRAM from 0x00 to
0x7F can be accessed directly, and the bytes from 0x20 to 0x2F are also bit-addressable.
IRAM from 0x80 to 0xFF must be accessed indirectly, using the @R0 or @R1 syntax,
with the address to access loaded in R0 or R1.

Special function registers (SFR) are located from address 0x80 to 0xFF, and are accessed
directly using the same instructions as for the lower half of IRAM. Some of the SFR's are
also bit-addressable.

Program memory (PMEM, though less common in usage than IRAM and XRAM) is
located starting at address 0. It may be on- or off-chip, depending on the particular model
of chip being used. Program memory is read-only, though some variants of the 8051 use
on-chip flash memory and provide a method of re-programming the memory in-system or
in-application. Aside from storing code, program memory can also store tables of
constants that can be accessed by MOVC A, @DPTR, using the 16-bit special function
register DPTR.

External data memory (XRAM) also starts at address 0. It can also be on- or off-chip;
what makes it "external" is that it must be accessed using the MOVX (Move eXternal)
instruction. Many variants of the 8051 include the standard 256 bytes of IRAM plus a
few KB of XRAM on the chip. If more XRAM is required by an application, the internal
XRAM can be disabled, and all MOVX instructions will fetch from the external bus.

[edit] Programming
There are various high-level programming language compilers for the 8051. Several C
compilers are available for the 8051, most of which feature extensions that allow the
programmer to specify where each variable should be stored in its six types of memory,
and provide access to 8051 specific hardware features such as the multiple register banks
and bit manipulation instructions. There are many commercial C compilers. SDCC is a
popular open source C compiler. Other high level languages such as Forth, BASIC,
Pascal/Object Pascal, PL/M and Modula-2 are available for the 8051, but they are less
widely used than C and assembly.

Because IRAM, XRAM, and PMEM all have an address 0, C compilers for the 8051
architecture provide compiler-specific pragmas or other extensions to indicate where a
particular piece of data should be stored (i.e. constants in PMEM or variables needing
fast access in IRAM). Since data could be in one of three memory spaces, a mechanism is
usually provided to allow determining to which memory a pointer refers, either by
constraining the pointer type to include the memory space, or by storing metadata with
the pointer.

[edit] Instruction set


The MCS-51 instruction set offers several addressing modes, including

• direct register, using ACC (the accumulator) and R0-R7


• direct memory, which access the internal RAM or the SFR's, depending on the
address
• indirect memory, using R0, R1, or DPTR to hold the memory address. The
instruction used may vary to access internal RAM, external RAM, or program
memory.
• individual bits of a range of IRAM and some of the SFR's

Many of the operations allow any addressing mode for the source or the destination, for
example, MOV 020h, 03fh will copy the value in memory location 0x3f in the internal
RAM to the memory location 0x20, also in internal RAM.

Because the 8051 is an accumulator-based architecture, all arithmetic operations must use
the accumulator, e.g. ADD A, 020h will add the value in memory location 0x20 in the
internal RAM to the accumulator.

One does not need to master these instructions to program the 8051. With the availability
of good quality C compilers, including open source SDCC, virtually all programs can be
written with high-level language.

[edit] Related processors

Intel 8031 processors


The 8051's predecessor, the 8048, was used in the keyboard of the first IBM PC, where it
converted keypresses into the serial data stream which is sent to the main unit of the
computer. The 8048 and derivatives are still used today for basic model keyboards.

The 8031 was a cut down version of the original Intel 8051 that did not contain any
internal program memory (ROM). To use this chip, external ROM had to be added
containing the program that the 8031 would fetch and execute. An 8051 chip could be
sold as a ROM-less 8031, as the 8051's internal ROM is disabled by the normal state of
the EA pin in an 8031-based design. A vendor might sell an 8051 as an 8031 for any
number of reasons, such as faulty code in the 8051's ROM, or simply an oversupply of
8051's and undersupply of 8031's.

The 8052 was an enhanced version of the original 8051 that featured 256 bytes of internal
RAM instead of 128 bytes, 8 KB of ROM instead of 4 KB, and a third 16-bit timer. The
8032 had these same features except for the internal ROM program memory. The 8052
and 8032 are largely considered to be obsolete because these features and more are
included in nearly all modern 8051 based microcontrollers.

Intel discontinued its MCS-51 product line in March 2007,[3] however there are plenty of
enhanced 8051 products or silicon IP added regularly from other vendors.

The 80C537 and 80C517 are CMOS versions, designed for the automotive industry.
Enhancements mostly new peripheral features and expanded arithmetic instructions. The
80C517 has fail save mechanisms, analog signal processing facilities and timer
capabilities and 8 KB on-chip program memory. Other features include:

• 256 byte on-chip RAM


• 256 directly addressable bits
• External program and data memory expandable up to 64 KB
• 8-bit A/D converter with 12 multiplexed inputs
• Arithmetic unit can make division, multiplication, shift and normalize operations
• Eight data pointers instead of one for indirect addressing of program and external
data memory
• Extended watchdog facilities
• Nine ports
• Two full-duplex serial interfaces with own baud rate generators
• Four priority level interrupt systems, 14 interrupt vectors
• Three power saving modes

[edit] Educational Use


In many engineering schools the 8051 microcontroller is used in introductory
microcontroller courses.

[edit] References
1. ^ John Wharton: An Introduction to the Intel® MCS-51TM Single-Chip
Microcomputer Family, Application Note AP-69, May 1980, Intel Corporation.
2. ^ John Wharton: Using the Intel® MCS-51TM Boolean Processing
Capabilities, Application Note AP-70, May 1980, Intel Corporation.
3. ^ Intel bows out, discontinues MCS-51.

[edit] Literature
• MCS® 51 Microcontroller Family User's Manual, February 1994, Publication
number 121517, Intel Corporation; PDF.
• MCS-51TM Macro Assembler User's Guide, Publication number 9800937, Intel
Corporation.
• Microcontroller Handbook. Intel 1984, Order number 210918-002.
• 8-Bit Embedded Controllers. Intel 1991, Order number 270645-003.
• Payne, William (December 19, 1990) [1990] (hardcover). Embedded Controller
FORTH for the 8051 Family. Boston: Academic Press. pp. 528. ISBN 978-
0125475709.

[edit] External links


• Detailed explanation of 8051 and 8051 microcontroller at EngineersGarage
• SDK-51 System Design Kit
• Complete tutorial for 8051 microcontrollers

v · d · eIntel microcontrollers

MCS-48 (8048 family) · MCS-51 (8051 family) · 8061 · MCS-96 (8x196 family) · MCS-
296 (8x296 family)
v · d · e8-bit microcontroller families

AVR · PIC · COP8 · MCS-48 · MCS-51 · Z8 · eZ80 · HC08 · HC11 · H8 · PSoC

This article was originally based on material from the Free On-line Dictionary of
Computing, which is licensed under the GFDL.

Retrieved from "http://en.wikipedia.org/wiki/Intel_MCS-51"


Categories: Microcontrollers
Hidden categories: Articles containing potentially dated statements from 2006 | All
articles containing potentially dated statements | Articles containing potentially dated
statements from 2007 | Wikipedia articles incorporating text from FOLDOC

Personal tools

• Log in / create account


Namespaces

• Article
• Discussion

Variants

Views

• Read
• Edit
• View history

Actions

Search

Navigation

• Main page
• Contents
• Featured content
• Current events
• Random article
• Donate to Wikipedia

Interaction

• Help
• About Wikipedia
• Community portal
• Recent changes
• Contact Wikipedia

Toolbox

• What links here


• Related changes
• Upload file
• Special pages
• Permanent link
• Cite this page

Print/export
• Create a book
• Download as PDF
• Printable version

Languages

• ‫العربية‬
• Català
• Česky
• Deutsch
• Ελληνικά
• Español
• Français
• 한국어
• Bahasa Indonesia
• Italiano
• ‫עברית‬
• Nederlands
• 日本語
• Polski
• Português
• Română
• Русский
• Српски / Srpski
• Svenska
• ไทย
• Türkçe
• Українська
• Tiếng Việt
• 中文

• This page was last modified on 4 March 2011 at 22:32.


• Text is available under the Creative Commons Attribution-ShareAlike License;
additional terms may apply. See Terms of Use for details.
Wikipedia® is a registered trademark of the Wikimedia Foundation, Inc., a non-
profit organization.
• Contact us

• Privacy policy
• About Wikipedia
• Disclaimers


Embedded Systems/8051 Microcontroller
From Wikibooks, open books for an open world
< Embedded Systems
Jump to: navigation, search
Embedded Systems

The Intel 8051 microcontroller is one of the most popular general purpose
microcontrollers in use today. The success of the Intel 8051 spawned a number of clones
which are collectively referred to as the MCS-51 family of microcontrollers, which
includes chips from vendors such as Atmel, Philips, Infineon, and Texas Instruments.

Contents
[hide]

• 1 About the 8051


• 2 Typical applications
• 3 Basic Pins
• 4 Ports
• 5 Oscillator Circuits
• 6 Internal Architecture
• 7 Data and Program Memory
• 8 Program Start Address
• 9 Direct Memory
• 10 Special Function Register
o 10.1 General Purpose Registers

o 10.2 A and B Registers

[edit] About the 8051


The Intel 8051 is an 8-bit microcontroller which means that most available operations are
limited to 8 bits. There are 3 basic "sizes" of the 8051: Short, Standard, and Extended.
The Short and Standard chips are often available in DIP (dual in-line package) form, but
the Extended 8051 models often have a different form factor, and are not "drop-in
compatible". All these things are called 8051 because they can all be programmed using
8051 assembly language, and they all share certain features (although the different
models all have their own special features).

Some of the features that have made the 8051 popular are:
• 64 KB on chip program memory.
• 128 bytes on chip data memory(RAM).
• 4 reg banks.
• 128 user defined software flags.
• 8-bit data bus
• 16-bit address bus
• 32 general purpose registers each of 8 bits
• 16 bit timers (usually 2, but may have more, or less).
• 3 internal and 2 external interrupts.
• Bit as well as byte addressable RAM area of 16 bytes.
• Four 8-bit ports, (short models have two 8-bit ports).
• 16-bit program counter and data pointer.
• 1 Microsecond instruction cycle with 12 MHz Crystal.

8051 models may also have a number of special, model-specific features, such as
UARTs, ADC, OpAmps, etc...

[edit] Typical applications


8051 chips are used in a wide variety of control systems, telecom applications, robotics as
well as in the automotive industry. By some estimations, 8051 family chips make up over
50% of the embedded chip market.

Pin diagram of the 8051 DIP

[edit] Basic Pins


PIN 9: PIN 9 is the reset pin which is used reset the microcontroller’s internal registers
and ports upon starting up. (Pin should be held high for 2 machine cycles.)
PINS 18 & 19: The 8051 has a built-in oscillator amplifier hence we need to only
connect a crystal at these pins to provide clock pulses to the circuit.

PIN 40 and 20: Pins 40 and 20 are VCC and ground respectively. The 8051 chip needs
+5V 500mA to function properly, although there are lower powered versions like the
Atmel 2051 which is a scaled down version of the 8051 which runs on +3V.

PINS 29, 30 & 31: As described in the features of the 8051, this chip contains a built-in
flash memory. In order to program this we need to supply a voltage of +12V at pin 31. If
external memory is connected then PIN 31, also called EA/VPP, should be connected to
ground to indicate the presence of external memory. PIN 30 is called ALE (address latch
enable), which is used when multiple memory chips are connected to the controller and
only one of them needs to be selected. We will deal with this in depth in the later
chapters. PIN 29 is called PSEN. This is "program store enable". In order to use the
external memory it is required to provide the low voltage (0) on both PSEN and EA pins.

[edit] Ports
There are 4 8-bit ports: P0, P1, P2 and P3.

PORT P1 (Pins 1 to 8): The port P1 is a general purpose input/output port which can be
used for a variety of interfacing tasks. The other ports P0, P2 and P3 have dual roles or
additional functions associated with them based upon the context of their usage.

PORT P3 (Pins 10 to 17): PORT P3 acts as a normal IO port, but Port P3 has additional
functions such as, serial transmit and receive pins, 2 external interrupt pins, 2 external
counter inputs, read and write pins for memory access.

PORT P2 (pins 21 to 28): PORT P2 can also be used as a general purpose 8 bit port
when no external memory is present, but if external memory access is required then
PORT P2 will act as an address bus in conjunction with PORT P0 to access external
memory. PORT P2 acts as A8-A15, as can be seen from fig 1.1

PORT P0 (pins 32 to 39) PORT P0 can be used as a general purpose 8 bit port when no
external memory is present, but if external memory access is required then PORT P0 acts
as a multiplexed address and data bus that can be used to access external memory in
conjunction with PORT P2. P0 acts as AD0-AD7, as can be seen from fig 1.1

[edit] Oscillator Circuits


The 8051 requires the existence of an external oscillator circuit. The oscillator circuit
usually runs around 12MHz, although the 8051 (depending on which specific model) is
capable of running at a maximum of 40MHz. Each machine cycle in the 8051 is 12 clock
cycles, giving an effective cycle rate at 1MHz (for a 12MHz clock) to 3.33MHz (for the
maximum 40MHz clock).
[edit] Internal Architecture
Internal schematics of the 8051.

[edit] Data and Program Memory


The 8051 Microprocessor can be programmed in PL/M, 8051 Assembly, C and a number
of other high-level languages. Many compilers even have support for compiling C++ for
an 8051.

Program memory in the 8051 is read-only, while the data memory is considered to be
read/write accessible. When stored on EEPROM or Flash, the program memory can be
rewritten when the microcontroller is in the special programmer circuit.

[edit] Program Start Address


The 8051 starts executing program instructions from address 0000 in the program
memory.

[edit] Direct Memory


The 8051 has 256 bytes of internal addressable RAM, although only the first 128 bytes
are available for general use by the programmer. The first 128 bytes of RAM (from 0x00
to 0x7F) are called the Direct Memory, and can be used to store data.

[edit] Special Function Register


The Special Function Register (SFR) is the upper area of addressable memory, from
address 0x80 to 0xFF. A, B, PSW, DPTR are called SFR.This area of memory cannot be
used for data or program storage, but is instead a series of memory-mapped ports and
registers. All port input and output can therefore be performed by memory mov
operations on specified addresses in the SFR. Also, different status registers are mapped
into the SFR, for use in checking the status of the 8051, and changing some operational
parameters of the 8051.

[edit] General Purpose Registers

The 8051 has 4 selectable banks of 8 addressable 8-bit registers, R0 to R7. This means
that there are essentially 32 available general purpose registers, although only 8 (one
bank) can be directly accessed at a time. To access the other banks, we need to change
the current bank number in the flag status register.

[edit] A and B Registers

The A register is located in the SFR memory location 0xE0. The A register works in a
similar fashion to the AX register of x86 processors. The A register is called the
accumulator, and by default it receives the result of all arithmetic operations. The B
register is used in a similar manner, except that it can receive the extended answers from
the multiply and divide operations. When not being used for multiplication and Division,
the B register is available as an extra general-purpose register.

Retrieved from
"http://en.wikibooks.org/wiki/Embedded_Systems/8051_Microcontroller"
Category: Embedded Systems
What do you think of this page?

Please take a moment to rate this page below. Your feedback is valuable and helps us
improve our website.

Reliability: Completeness: Neutrality:


Submit
Presentation:

Personal tools

• Log in / create account

Namespaces

• Book
• Discussion

Variants

Views

• Read
• Edit
• View history

Actions

Search

Navigation

• Main Page
• Help
• Browse
• Cookbook
• Wikijunior
• Featured books
• Recent changes
• Donations
• Random book

Community

• Reading room
• Community portal
• Bulletin Board
• Help out!
• Policies and guidelines
• Contact us

Toolbox

• Search this book


• What links here
• Related changes
• Upload file
• Special pages
• Permanent link
• Page rating

Sister projects

• Wikipedia
• Wikiversity
• Wiktionary
• Wikiquote
• Wikisource
• Wikinews
• Commons

Print/export

• Create a collection
• Download as PDF
• Printable version

• This page was last modified on 12 April 2011, at 18:45.


• Text is available under the Creative Commons Attribution-ShareAlike License;
additional terms may apply. See Terms of Use for details.

• Privacy policy
• About Wikibooks
• Disclaimers

Вам также может понравиться