simple multitasking program

19
; SIMPLE MULTITASKING PROGRAM $MOD51 $NOPRINT $INCLUDE(MYPAULM2.EQU) LED equ P1.7 CR EQU 13 DSEG AT 20H FLAG1: DS 1 TICK: DS 1 SEC: DS 1 MIN: DS 1 HOUR: DS 1 TIMER1: DS 1 TIMER2: DS 1 TIMER3: DS 1 TIMER4: DS 1 COMMAND: DS 1 CSEG AT 8000H jmp main ORG 8100H ; 10ms tick ; ____|____|____|____|____ ; WAIT_TICK: JNB TF0,$ CLR TF0 ORL TH0,#0DCH INC TICK RET UPDATE_CLOCK: MOV A,TICK CJNE A,#100,EXIT_CLOCK MOV TICK,#0 SETB FLAG1.0 ; flag that signals print time function SETB FLAG1.1 ; for tick led

Upload: fatilily

Post on 10-Nov-2015

213 views

Category:

Documents


0 download

DESCRIPTION

Aboutmultitasking

TRANSCRIPT

; SIMPLE MULTITASKING PROGRAM

$MOD51$NOPRINT$INCLUDE(MYPAULM2.EQU)

LED equ P1.7CR EQU 13

DSEG AT 20HFLAG1: DS 1

TICK: DS 1SEC: DS 1MIN: DS 1HOUR: DS 1TIMER1: DS 1TIMER2: DS 1TIMER3: DS 1TIMER4: DS 1COMMAND: DS 1

CSEG AT 8000H jmp main

ORG 8100H

; 10ms tick; ____|____|____|____|____;

WAIT_TICK:

JNB TF0,$ CLR TF0

ORL TH0,#0DCH INC TICK RET

UPDATE_CLOCK: MOV A,TICK CJNE A,#100,EXIT_CLOCK MOV TICK,#0

SETB FLAG1.0 ; flag that signals print time function SETB FLAG1.1 ; for tick led

MOV A,SEC ADD A,#1 DA A MOV SEC,A CJNE A,#60H,EXIT_CLOCK MOV SEC,#0

MOV A,MIN ADD A,#1 DA A MOV MIN,A CJNE A,#60H,EXIT_CLOCK MOV MIN,#0

MOV A,HOUR ADD A,#1 DA A MOV HOUR,A CJNE A,#24H,EXIT_CLOCK MOV HOUR,#0

EXIT_CLOCK: RET

; MAKE LED ON EVERY ONE SECOND; ------______------------------------------______-----------------; |50ms|; |-------------------- 1000ms -------|;

TICK_LED:

JNB FLAG1.1,EXIT1 CLR LED INC TIMER1 MOV A,TIMER1 CJNE A,#5,EXIT1 SETB LED CLR FLAG1.1 MOV TIMER1,#0 EXIT1: RET

; check serial port every 10ms; exit: COMMAND == -1 NO CHARACTER; COMMAND != -1 ASCII CODE

GETCHAR: JNB RI,EXIT2 CLR RI MOV A,SBUF MOV COMMAND,A RET

EXIT2: MOV COMMAND,#-1 RET

; PRINT TIME TO TERMINAL EVERY SECOND

PRINT_TIME:

JNB FLAG1.0,EXIT_PRINT_TIME

CLR FLAG1.0

PRINT_TIME1: MOV A,#CR CALL COUT MOV A,HOUR CALL PHEX MOV A,#':' CALL COUT MOV A,MIN CALL PHEX MOV A,#':' CALL COUT MOV A,SEC CALL PHEX

EXIT_PRINT_TIME: RET

HOUR_KEY: MOV A,COMMAND CJNE A,#'h',EXIT_HOUR_KEY MOV A,HOUR ADD A,#1 DA A MOV HOUR,A CJNE A,#24H,SKIP_CLEAR_HOUR MOV HOUR,#0

SKIP_CLEAR_HOUR:

CALL PRINT_TIME1

EXIT_HOUR_KEY:

RET

MIN_KEY: MOV A,COMMAND CJNE A,#'m',EXIT_MIN_KEY MOV A,MIN ADD A,#1 DA A MOV MIN,A CJNE A,#60H,SKIP_CLEAR_MIN MOV MIN,#0

SKIP_CLEAR_MIN: CALL PRINT_TIME1

EXIT_MIN_KEY: RET

;*************************** MAIN ***************************

main: ORL TMOD,#1 SETB TR0 MOV SEC,#0 MOV MIN,#55H MOV HOUR,#17H MOV TICK,#0 CALL NEWLINE

; main 10ms loop

LOOP: CALL WAIT_TICK

; following tasks will be executed every 10ms CALL TICK_LED CALL UPDATE_CLOCK CALL GETCHAR CALL PRINT_TIME CALL HOUR_KEY CALL MIN_KEY JMP LOOP

END

>>>>>>>>>>>>week7:; SIMPLE MULTITASKING PROGRAM

$MOD51$NOPRINT$INCLUDE(MYPAULM2.EQU)

LED equ P1.7CR EQU 13GPIO2 equ 200H ; 8-bit input port

DSEG AT 20HFLAG1: DS 1

TICK: DS 1SEC: DS 1MIN: DS 1HOUR: DS 1TIMER1: DS 1TIMER2: DS 1TIMER3: DS 1TIMER4: DS 1COMMAND: DS 1

CSEG AT 8000H jmp main

ORG 8100H

; 10ms tick; ____|____|____|____|____;

WAIT_TICK:

JNB TF0,$ CLR TF0

ORL TH0,#0DCH INC TICK RET

UPDATE_CLOCK: MOV A,TICK CJNE A,#100,EXIT_CLOCK MOV TICK,#0

SETB FLAG1.0 ; flag that signals print time function SETB FLAG1.1 ; for tick led SETB FLAG1.2 ; signals print lcd function

MOV A,SEC ADD A,#1 DA A MOV SEC,A CJNE A,#60H,EXIT_CLOCK MOV SEC,#0

MOV A,MIN ADD A,#1 DA A MOV MIN,A CJNE A,#60H,EXIT_CLOCK MOV MIN,#0

MOV A,HOUR ADD A,#1 DA A MOV HOUR,A CJNE A,#24H,EXIT_CLOCK MOV HOUR,#0

EXIT_CLOCK: RET

; MAKE LED ON EVERY ONE SECOND; ------______------------------------------______-----------------; |50ms|; |-------------------- 1000ms -------|;

TICK_LED:

JNB FLAG1.1,EXIT1 CLR LED INC TIMER1 MOV A,TIMER1 CJNE A,#5,EXIT1 SETB LED CLR FLAG1.1 MOV TIMER1,#0 EXIT1: RET

; check serial port every 10ms; exit: COMMAND == -1 NO CHARACTER; COMMAND != -1 ASCII CODE

GETCHAR: JNB RI,EXIT2 CLR RI MOV A,SBUF MOV COMMAND,A RET

EXIT2: MOV COMMAND,#-1 RET

; PRINT TIME TO TERMINAL EVERY SECOND

PRINT_TIME:

JNB FLAG1.0,EXIT_PRINT_TIME

CLR FLAG1.0

PRINT_TIME1: MOV A,#CR CALL COUT MOV A,HOUR CALL PHEX MOV A,#':' CALL COUT MOV A,MIN CALL PHEX MOV A,#':' CALL COUT MOV A,SEC CALL PHEX

EXIT_PRINT_TIME: RET

HOUR_KEY: MOV A,COMMAND CJNE A,#'h',EXIT_HOUR_KEY MOV A,HOUR ADD A,#1 DA A MOV HOUR,A CJNE A,#24H,SKIP_CLEAR_HOUR MOV HOUR,#0

SKIP_CLEAR_HOUR:

CALL PRINT_TIME1

EXIT_HOUR_KEY:

RET

MIN_KEY: MOV A,COMMAND CJNE A,#'m',EXIT_MIN_KEY MOV A,MIN ADD A,#1 DA A MOV MIN,A CJNE A,#60H,SKIP_CLEAR_MIN MOV MIN,#0

SKIP_CLEAR_MIN: CALL PRINT_TIME1

EXIT_MIN_KEY: RET

; PRINT BYTE TO LCD; INPUT BYTE MUST BE TWO DIGITS BCD NUMBER

PRINT_BYTE: PUSH ACC ANL A,#0F0H SWAP A ADD A,#'0' CALL PUTCH_LCD POP ACC ANL A,#0FH ADD A,#'0' CALL PUTCH_LCD RET

PRINT_TIME_LCD:

JNB FLAG1.2, EXIT_PRINT_LCD CLR FLAG1.2

PRINT_TIME_LCD1:

MOV A,#00H ; A = X MOV B,#00H ; B = Y CALL goto_xy

MOV A,HOUR CALL PRINT_BYTE MOV A,#':' CALL PUTCH_LCD MOV A,MIN CALL PRINT_BYTE MOV A,#':' CALL PUTCH_LCD MOV A,SEC CALL PRINT_BYTE

EXIT_PRINT_LCD: RET

READ_KEY: MOV DPTR,#GPIO2 MOVX A,@DPTR JB ACC.4, CHECK_NEXT_KEY MOV A,#1 RET

CHECK_NEXT_KEY: JB ACC.5, EXIT_CHECK_KEY MOV A,#2 RET

EXIT_CHECK_KEY: MOV A,#-1 RET

EXE_KEY: CALL READ_KEY CJNE A,#1,EXE_KEY2 MOV A,HOUR ADD A,#1 DA A MOV HOUR,A CJNE A,#24H,SKIP_CLEAR_HOUR1 MOV HOUR,#0

SKIP_CLEAR_HOUR1:

CALL PRINT_TIME_LCD1

EXIT_HOUR_KEY1:

RET

EXE_KEY2: CJNE A,#2,EXIT_KEY2

MOV A,MIN ADD A,#1 DA A MOV MIN,A CJNE A,#60H,SKIP_CLEAR_MIN1 MOV MIN,#0

SKIP_CLEAR_MIN1: CALL PRINT_TIME_LCD1

EXIT_KEY2: RET

SCAN_KEY: INC TIMER2 MOV A,TIMER2 CJNE A,#20,EXIT_SCAN ; 200ms MOV TIMER2,#0 CALL EXE_KEY

EXIT_SCAN: RET

;*************************** MAIN ***************************

main: ORL TMOD,#1 SETB TR0 MOV SEC,#0 MOV MIN,#55H MOV HOUR,#17H MOV TICK,#0 CALL NEWLINE

CALL INITLCD

; main 10ms loop

LOOP: CALL WAIT_TICK

; following tasks will be executed every 10ms CALL TICK_LED CALL UPDATE_CLOCK CALL GETCHAR CALL PRINT_TIME CALL HOUR_KEY CALL MIN_KEY CALL PRINT_TIME_LCD CALL SCAN_KEY JMP LOOP

$include(lcddrv.asm)

END>>>>>>>>>>>.; LCD driver for 8051SBC

BUSY EQU 80H

; below LCD's registers are mapped into external data memory

command_write EQU 0000Hdata_write EQU 0001Hcommand_read EQU 0002Hdata_read EQU 0003H

CSEG

; wait until LCD ready bit set

LcdReady: PUSH ACC MOV DPTR,#command_read?ready: MOVX A,@DPTR JB ACC.7,?ready ; loop if busy flag = 1 POP ACC RET

LCD_command_write: CALL LcdReady MOV DPTR,#command_write MOVX @DPTR,A RET

LCD_data_write: PUSH DPL PUSH DPH CALL LcdReady MOV DPTR,#data_write MOVX @DPTR,A POP DPH POP DPL RET

clr_screen: CALL LcdReady MOV A,#1 CALL LCD_command_write RET

InitLcd: MOV A,#38H CALL LCD_command_write MOV A,#0CH CALL LCD_command_write CALL clr_screen MOV A,#00H ; A = X MOV B,#00H ; B = Y CALL goto_xy RET

; goto_xy(x,y); entry: A = y position; B = x position

goto_xy: CJNE A,#0,case1 MOV A,B ADD A,#80H CALL LCD_command_write RET

case1: CJNE A,#1,case2 MOV A,B ADD A,#0C0H CALL LCD_command_write RET

case2: RET

; send_string; entry: DPTR

send_string: MOVX A,@DPTR CJNE A,#0,send_string1 RETsend_string1: CALL LCD_data_write INC DPTR JMP send_string

; write ASCII code to LCD at current position; entry: A

putch_lcd: CALL LcdReady CALL LCD_data_write RET

>>>>>>>>>>>>>>>After you have understood thetutorialonIntroduction to assembly languagewhich includes simple instruction sets like input/output operations,now its time to learn how to create loops, function calls and jumps while writing a code in assembly language.Let us first discuss an important concept that relates RAM & ROM. You can skip this section if you wish but it is an important to understand registers which helps in building up understanding of architecture of microcontrollers.How aprogramwhich is burned in ROM gets executed in RAM?Theprogramyou write is burned in ROM and thisprogramis executed in RAM. The data burned is in the form of logics or binary digits (0 & 1) also called an Opcode or machine code. Theprogramwritten in assembly language is converted to opcode byassembler.Each line of the assembly code is assigned a unique opcode by theassembleras shown below. These opcodes are then stored in ROM one after another.There is aregistercalledProgramCounter (PC)which always points to the current opcode being executed. When the power is switched on it sets itself to zero and it keeps on incrementing itself as opcodes are executed one after another. Thisinformationis used by RAM to extract correct opcode from ROM which is then executed. This process goes on line by line till the wholeprogramis executed.

Lets take an example:-PCMnemonic, Operand Opcode (Machine code)0000 ORG0H0000 MOVR0, #0 78000002 MOV A, #55H74550004 JZ NEXT 60030006 INCR0 080007 AGAIN: INCA 040008 INCA 040009 NEXT: ADDA, #77H 2477000B JNC OVER 5005000D CLRA E4000E MOV R0, A F8000F MOV R1, A F90010 MOV R2, A FA0011 MOV R3, A FB0012 OVER: ADD, R3 2B0013 JNC AGAIN 50F20015 HERE: SJMP HERE 80FE0017 ENDWe can clearly see that the PC increases with execution ofprogram. The PC starts with zero when ORG 00H line is executed and then in subsequent lines PC keeps on incrementingas machine codes are executed one after another.ProgramCounter is a 2 byte or 16 bitregister.Therefore we cannot have internal ROM of more than the number thisregistercan hold (i.e. not exceeding the FFFF hex value).LOOP AND JUMP INSTRUCTIONSLet us start with a simple example that will help you to learn how to create loops in assembly. In the following code the instruction DJNZ is used to reduce the counter and is repeated till the counter becomes zero.Eg-1: ORG0H MOVA, #0; clear A MOVR1, #10; load counter R1 =10AGAIN: ADDA, # 05; add five toregisterA DJNZR1, AGAIN ; repeat until R1=0 (10 times) MOVR3, A; save A in R3 ENDIn this code R1 acts as a counter. The counter value is initialized i.e. 10 HEX is loaded to R1. In each iteration, the instruction DJNZ decrements R1 by one until it becomes zero. This loop adds 5 HEX to A every time it runs. After ten iterations R1 becomes zero and the instructions below it are executed.Note: - Some Jump statements can only be performed on some specialregisterA (or bit CY) as mentioned in the table below.

Nested loops:ORG 0HMOVA, #55H ; A= 55 hexMOVR1, #100; the outer counter R1 =100NEXT:MOVR2, # 20 ; the inner counterAGAIN: CPLA, # 05 ; add five toregisterA DJNZR2, AGAIN ; repeat until R1=0 (100 times) DJNZR1, NEXT ; repeat till 20 times (outer loop)ENDSJMP refers to short jump and LJMP refers to long jump. All the conditional jumps are short jumps.SJMP:This instruction is of two bytes in which first one is opcode & second is the address. The relative address of the instruction called should be in between -127 to 127 bytes from the currentprogramcounter (PC).LJMP:This instruction is of three bytes in which the first is the opcode and the second & third are for address. The relative address of the instruction can be anywhere on the ROM.So it is clear from the aboveexamplesthat we can use different jump instructions with a condition or counter called conditional loop. And when we create loop inside an existing loop it is called nested loop.CALL INSTRUCTIONS:Example:LCALL (long call)ORG0HBACK :MOVA, #55H ; load A= 55 hex value MOVP1, A ; issue value ofregisterA to port1 LCALLDELAY; to call DELAY function created below MOV A, #0AAH ;load AAH hex value to A MOV P1,A ;issue value ofregisterA to port 1LCALLDELAY; to call DELAY function as created belowSJMPBACK ; keep doing this; ________ this is the delay subroutineDELAY:MOVR5, #0FFH; R5= 255 hex, the counterAGAIN:DJNZR5, AGAIN; stay here until R5 becomes zeroRET; return to callerENDIn this code we keep on toggling the value of theregisterof port 1 with two different hex values and a DELAY subroutine is used to control how fast the value is changing. Here in DELAY subroutine theprogramis kept busy by running an idle loop and counting 256 counts.After the DELAY subroutine is executed once the value of port 1 is toggled and this process goes on infinitely.By using DELAY we can create PWM (Pulse Width Modulation) to control motors or LED blinking for further details view ourtutorialon Input/ output instructions in Assembly Language[coming soon].We can also use ACALL i.e. absolute call for calling a subroutine that is within 2K byte of PC.http://www.botskool.com/tutorials/electronics/8051/input-output-instructions-8051-assembly-languagehttp://www.botskool.com/tutorials/electronics/8051/input-output-instructions-8051-assembly-languagehttp://www.hobbyprojects.com/8051_tutorial/http://www.docstoc.com/docs/112797230/8051-Tutorial-en#

Code ASM - [collapse]

1234567891011121314151617181920212223242526272829303132333435363738394041424344

org 0000hsjmp startorg 0050hstart: mov a,#00h setb p0.0 x:jnb p1.0,is1 jnb p1.1,ds2 cjne a,#00h,x11 sjmp x x11: clr p0.0 mov r2,a x1: lcall delay djnz r2,x1 setb p0.0 mov r1,a mov a,#64h subb a,r1 ; a = a - r1 mov r2,a ; result into r2 reg mov a,r1 ; a old value from r1 x12: lcall delay djnz r2,x12 sjmp xis1: add a,#10h loop: jnb p1.0,loop sjmp x11ds2: subb a,#10h loop1: jnb p1.1,loop1 sjmp x11delay: mov r3,#0ffh q:djnz r3,q retend