Program is divided into three independently co-operating sections:
Notice: However we publish full source code, it is copyrighted
by:
© High Pressure Research Centre, Polish Academy of Sciences, Warsaw,
Poland, http://www.unipress.waw.pl/
© roman pielaszek, pielasze@unipress.waw.pl, http://www.unipress.waw.pl/~pielasze
You can freely include part of or entire code without permission for non-commercial use, referencing to above copyrights.
;/////////////////////////////////////////////////////////// ; att_brd.h - attenuator board layout ; --------- ----------------------- ; ; This file defines labels corresponding to physical ; circuit wirings. ; ; 15:18 20.11.1999 Hamburg, roman pielaszek ; ; ;LCD conn. ;----------- ;pin# name ;1 +5V ;2 contrast ;3 E 5 P1.4 ;4 nc ;5 RS 7 P1.6 ;6 GND ;7 D7 32 P0.7 ;8 D6 33 P0.6 ;9 D5 34 P0.5 ;10 D4 35 P0.4 ;11 D3 36 P0.3 ;12 D2 37 P0.2 ;13 D1 38 P0.1 ;14 D0 39 P0.0 ;15 nc ;16 R/W 6 P1.5 ; ;/////////////////////////////////////////////////////////// ; LCD labels should be already defined in hardware board section (e.g. att_brd.h or 80c535.h) ! ; ---------- ; LCD_E EQU P1.4 LCD_RW EQU P1.5 LCD_RS EQU P1.6 LCD_DATA EQU P0 ; ; ; ; ; ;KBD conn. GAL16V8 8951 meaning (active: 0VDC) ;----------- ------------ ------------ --------------- ;pin# name pin# name pin# name ; 1 I0 8 P1.7 M1: reset switch signal (???) ;11 2 I1 25 P2.4 M1: direction: left ;2 3 I2 26 P2.5 M1: direction: right ;6 4 I3 27 P2.6 M1: motor on/off ; 5 I4 28 P2.7 M1: limit switch signal ;13 6 I5 21 P2.0 M0: direction: left ;5 7 I6 22 P2.1 M0: direction: right ;9 8 I7 23 P2.2 M0: motor on/off ; 9 I8 24 P2.3 M0: limit switch signal ; ; 11 I9 4 P1.3 M0: reset switch signal (???) ; ;KBD connector GAL16V8 ;------------- ------------ ;pin# name pin# name ;1 GND ;2 3 ;3 ;4 ;5 7 ;6 4 ;7 ;8 GND ;9 8 ;10 ;11 2 ;12 GND ;13 6 ; ; MOTOR_REG EQU P2 M0_LEFT EQU P2.0 M0_RIGHT EQU P2.1 M0_ON EQU P2.2 M0_LIMIT_SW EQU P2.3 M1_LEFT EQU P2.4 M1_RIGHT EQU P2.5 M1_ON EQU P2.6 M1_LIMIT_SW EQU P2.7 M0_RESET_SW EQU P1.3 M1_RESET_SW EQU P1.7 ;KBD_H1 EQU P5.5 ;KBD_H4 EQU P5.3 ;KBD_V1 EQU P5.7 ;KBD_V2 EQU P5.4 ;KBD_V3 EQU P5.2 KEY_M0_LEFT EQU P3.6 KEY_M0_RES EQU P1.1 KEY_M0_RIGHT EQU P3.7 KEY_M1_LEFT EQU P1.0 KEY_M1_RES EQU KEY_M0_RES KEY_M1_RIGHT EQU P1.2 ;/////////////////////////////////////////////////////////// ; att_main.asm - main attenuator program ; ------------ ----------------------- ; ; ; Motor registers occupy bank#1 ; M0_CURR_POS EQU 8 ;0-9 M0_DEST_POS EQU 9 ;0-9 M0_STAT EQU 10 ;b7=phase #, b1=reset bit M0_PHASE_AGE EQU 11 M1_CURR_POS EQU 12 ;0-9 M1_DEST_POS EQU 13 ;0-9 M1_STAT EQU 14 ;b7=phase #, b1=reset bit M1_PHASE_AGE EQU 15 ; ;shadow registers - used for comparisons (when parameters on the display ; should be updated) M0_CURR_POS_SH EQU 16 ; 0-9 M0_DEST_POS_SH EQU 17 ; 0-9 M0_STAT_SH EQU 18 TR1_DELAY EQU 19 ; counter used for delay int_tr1 M1_CURR_POS_SH EQU 20 ; 0-9 M1_DEST_POS_SH EQU 21 ; 0-9 M1_STAT_SH EQU 22 MOTOR_REG_SH EQU 23 ;shadows hardware registers MOTOR_REG, and so on PHASE0_LENGTH EQU 10 ;starting (1->0 on limit switch) history PHASE1_LENGTH EQU 3 ;stopping (0->1 on limit switch) history ; ; ;/////////////////////////////////////////////////////////// ; Interrupt routines ; ------------------ ; ORG 0000H LJMP BEGIN ;begin of the programm ORG 0003H ; LJMP INT_GPIB ;PRZERWANIE OD NEC'A org 000Bh ljmp INT_TR0 ;TR0 interrupt (motors' movements) org 0013h reti ;EX1 interrupt org 001Bh ljmp INT_TR1 ;TR1 interrupt (display update) org 0023H LJMP INT_RS ;przerwanie od wewnetrznego RS232 org 002BH reti ;przerwanie od Timer 2 org 0043H reti ;przerwanie od IADC org 004BH reti ;przerwanie od IEX2 org 0053H reti ;przerwanie od IEX3 org 005BH reti ;przerwanie od IEX4 org 0063H reti ;przerwanie od IEX5 org 006BH reti ;przerwanie od IEX6 ; ; ;/////////////////////////////////////////////////////////// ; Initializations of interrupts, timers and external hardware ; ----------------------------------------------------------- ; ; org 073h ; Konfiguracja wyswietlacza LCD dla 8-bitowego dwu(cztero!)linijkowca ; wykonanie komend F, C, A i D tak, aby ustawic: ; - transmisja 8 bitow, ilosc linii = 2, czcionka 5x7 ; - inkrementacja kursora przy przesuwie, brak przewijania ; - czyszczenie ekranu i ustawienie kursora w polozenie 0 ; - wlaczenie ekranu, kursora, brak migania BEGIN: ; stack pointer goes higher (default is 8) mov SP,#48 ; LCD requires some initialization lcall LCD_INIT ; RS-232 will setup itself to UART 9600,8N1 ; and will run Timer 1 as a clock mov a, #-3 ;set speed to 9600 lcall RS_INIT ; Timer 0 we use as a source of interrupts ; used to motor maintenance mov a, #0 ;set frequency to 112Hz lcall TR0_INIT ; As mentioned, RS_INIT setups Timer 1 (TR1), ; butt RS-232 doesn't need any interrupt ; from TR1 - requires just a clock. ; We use TR1 also as a source of interrupts ; which will maintain display update ; So, we have to enable TR1 int-s. setb ET1 ;enable TR1 interrupt ; Please notice, that interrupts are still ; switched off: flag EA is cleared ; ; ;/////////////////////////////////////////////////////////// ; ; Initialization of Variables ; --------------------------- ; ; mov MOTOR_REG, #0FFh mov MOTOR_REG_SH, #0 mov M0_CURR_POS, #0 mov M0_CURR_POS_SH, #1 mov M0_DEST_POS, #0 mov M0_DEST_POS_SH, #1 mov M0_PHASE_AGE, #0 mov M0_STAT, #0 mov M0_STAT_SH, #0 mov M1_CURR_POS, #0 mov M1_CURR_POS_SH, #1 mov M1_DEST_POS, #0 mov M1_DEST_POS_SH, #1 mov M1_PHASE_AGE, #0 mov M1_STAT, #0 mov M1_STAT_SH, #0 ; Time for an advertisement mov DPTR, #TITLE_LINE1_3 lcall LCD_PRINT_LINE_1 mov DPTR, #TITLE_LINE2_4 lcall LCD_PRINT_LINE_2 mov r0, #100 j: lcall LCD_WAIT_FIXED_TIME djnz r0, j ; Turn on interrupts (means: start maintain motors, ; update display, read keyboard and so on)! clr ES ;disable irq from serial port ; clr ET1 ;disable irq from timer1 (display) ; clr ET0 ;disable irq from timer0 (motors) setb EA ;enable interrupts !! ; Central point is Command Interpreter. ; He and interrupts do all the work. ; ; Interrupts keep relations: ; ; TR0: Variables <-> motors (run motors according to var. values) ; TR1: Variables <-> display (update display when necessary) ; TR1: Variables <-> keyboard (read keyboard and modify vars.) ; ; Command Interpreter keeps relation: ; ; Variables <-> RS-232 port k: mov DPTR, #att_cmdtable mov a, #32 ; first analyzed char (spaces are ignored) lcall cmdinterp sjmp k ; ; ;/////////////////////////////////////////////////////////// ; main - data definitions ; ---- ---------------- ; TITLE_LINE1_3 DB 'Attenuator Ctrl.' DB 'UNIPRESS (c)1999',0 TITLE_LINE2_4 DB ' ver. 1.5.1 ' DB 'RS-232: 9600,8N1',0 COPYRIGHT DB 'Copyright by High Pressure Research Center,',0 DB 'roman pielaszek, pielasze@unipress.waw.pl',0 DB 'Warsaw, Poland, 1996-1999',0 ; ;/////////////////////////////////////////////////////////// ; cmdlib data definitions ; ----------------------- ; ; att_cmdtable: DB 9 ;row width DB 2,HIGH(att) ,LOW(att), '*ATT ' DB 2,HIGH(attq) ,LOW(attq), '*ATT? ' DB 2,HIGH(attql) ,LOW(attql), '*ATTL?' DB 2,HIGH(help) ,LOW(help), '*HELP ' DB 2,HIGH(help) ,LOW(help), '*HELP?' DB 2,HIGH(idnq) ,LOW(idnq), '*IDN? ' DB 2,HIGH(print) ,LOW(print), '*PRINT' DB 2,HIGH(res) ,LOW(res), '*RES ' DB 2,HIGH(resq) ,LOW(resq), '*RES? ' DB 2,HIGH(help) ,LOW(help), '? ' DB 2,HIGH(help) ,LOW(help), 'HELP ' DB 2,HIGH(help) ,LOW(help), 'HELP? ' cmdnf: DB 2,HIGH(cmdnfv) ,LOW(cmdnfv), ' ' ; ; ;/////////////////////////////////////////////////////////// ; *HELP, *HELP?, HELP, HELP, ? commands ; ; help: mov a,b jz help1 lcall cmd_vacuum_till_eol help1: mov DPTR, #help_msg ljmp cmd_print_msg help_msg: DB 'Attenuator Controller v.1.5.1 Help',13,10 DB '----------------------------------',13,10 DB 'Keyboard: [4] left [5] reset [6] right - 1st wheel (MS)',13,10 DB ' [7] left [8] reset [9] right - 2nd wheel (LS)',13,10 DB 'Connection: RS-232 9600,8N1 <-fixed setting. Commands:',13,10 DB '?, HELP, *HELP, HELP?, *HELP? - display this message',13,10 DB '*ATT ij - sets attenuation foils to pos. ij, where i and j are',13,10 DB ' integers 0-9 (single chars!) ',13,10 DB ' i - wheel#1 (MSign.) position (0,1,2,..9)',13,10 DB ' j - wheel#0 (LSign.) position (0,1,2,..9)',13,10 DB ' e.g. "*ATT 13", "*ATT 00"',13,10 DB '*ATT? - currnet pos. of wheels, e.g. "00", "52"',13,10 DB '*ATTL? - current pos. in long format, e.g. "0:none\n 1:0.05mmAl"',13,10 DB '*IDN? - SCAPII string of manufacturer',13,10 DB '*RES i - reset i (0 or 1) wheel or both if no "i" is given',13,10 DB '*RES? - status of resetting: "00"=completed "01","10" or "11"=not yet',13,10 DB '*PRINT - display string',13,10 DB '-----------',13,10 DB 'More help: pielasze@unipress.waw.pl, +48 22 364433,',13,10 DB 'Ref.:http://www.unipress.waw.pl/xray/desy/attenuator/',13,10 DB '(c)1999, High Pressure Research Center "UNIPRESS", Warsaw',13,10 DB '(c)1999, roman pielaszek, http://www.unipress.waw.pl/~pielasze',13,10 DB '',0 ; ; ;/////////////////////////////////////////////////////////// ; *ATT ; ; att: mov a, b ; we expect some data jz att1 lcall cmd_vacuum_whitespaces jz att1 clr C subb a, #'0' ; check if a>'0' jc att2 ; if not -> exit push ACC subb a, #10 ; check if a <= 9 jnc att2 ; if not -> exit pop ACC ; now a is indeed in range 0-9 mov M1_DEST_POS, a ; run motor 1 lcall cmd_getchar jz att1 clr C subb a, #'0' ; check if a>'0' jc att2 ; if not -> exit push ACC subb a, #10 ; check if a <= 9 jnc att2 ; if not -> exit pop ACC ; now a is indeed in range 0-9 mov M0_DEST_POS, a ; run motor 1 att2: lcall cmd_vacuum_till_eol att1: ret ; ; ;/////////////////////////////////////////////////////////// ; *ATT? ; ; attq: mov a, b jz attq1 lcall cmd_vacuum_till_eol attq1: mov a, M1_CURR_POS add a, #'0' lcall cmd_putchar mov a, M0_CURR_POS add a, #'0' lcall cmd_putchar mov a, #0 ljmp cmd_putchar ; ; ;/////////////////////////////////////////////////////////// ; *ATTL? ; ; attql: mov a, b jz attql1 lcall cmd_vacuum_till_eol attql1: mov a, M1_CURR_POS ; for definition of these symbols mov b, #LABEL_SIZE ; look in att_tr1.asm mul ab add a, #LOW(M1_LABELS) mov dpl,a mov a,b addc a, #HIGH(M1_LABELS) mov dph,a lcall cmd_print_msg mov a, M0_CURR_POS mov b, #LABEL_SIZE mul ab add a, #LOW(M0_LABELS) mov dpl,a mov a,b addc a, #HIGH(M0_LABELS) mov dph,a ljmp cmd_print_msg ; ; ;/////////////////////////////////////////////////////////// ; *IDN? ; ; idnq: mov a,b jz idnq1 lcall cmd_vacuum_till_eol idnq1: mov DPTR, #idnq_msg ljmp cmd_print_msg idnq_msg: DB 'UNIPRESS (c)1999,X-Ray Attenuator Controller,S00001,V1.5.1',0 ; ; ;/////////////////////////////////////////////////////////// ; *RES ; ; res: mov a, b ; we don't expect any data jz res1 ; if no parameters -> reset both lcall cmd_vacuum_whitespaces jz res1 cjne a, #'0', res2 mov M0_STAT, #00000001b ; reset motor 0 ret res2: cjne a, #'1', res3 mov M1_STAT, #00000001b ; reset motor 1 ret res1: mov M0_STAT, #00000001b ; reset motor 0 mov M1_STAT, #00000001b ; reset motor 1 ret res3: lcall cmd_vacuum_till_eol ret ; ; ;/////////////////////////////////////////////////////////// ; *RES? ; ; resq: mov a,b jz resq1 lcall cmd_vacuum_till_eol resq1: mov a, M1_STAT anl a, #00000001b add a, #'0' lcall cmd_putchar mov a, M0_STAT anl a, #00000001b add a, #'0' lcall cmd_putchar mov a, #0 ljmp cmd_putchar ; ; ;/////////////////////////////////////////////////////////// ; *PRINT ; ; print: mov a, b jz pr4 mov r0, #0 lcall cmd_vacuum_whitespaces jz pr4 sjmp pr3 pr2: lcall cmd_getchar jz pr1 pr3: mov b, a mov a, #50h ; 3rd line on the display add a, r0 clr EA ; turn off interrupts lcall LCD_ADDRESS mov a, b lcall LCD_OUT setb EA ; turn on interrupts inc r0 cjne r0, #16, pr2 lcall cmd_vacuum_till_eol pr1: ret pr4: mov DPTR, #LCD_CLEAR16 clr ET1 lcall LCD_PRINT_LINE_4 setb ET1 ret ; ; ;/////////////////////////////////////////////////////////// ; Command Not Yey Interpreted ; ; cnyi: mov a,b jz cnyi1 lcall cmd_vacuum_till_eol cnyi1: mov DPTR, #cnyi_msg ljmp cmd_print_msg cnyi_msg: DB 'COMMAND NOT YET INTERPRETED',0 ; ; ;/////////////////////////////////////////////////////////// ; Command Not Found - 'BAD COMMAND' message ; ; cmdnfv: mov a,b jz cnfv1 lcall cmd_vacuum_till_eol cnfv1: mov DPTR, #cmdnf_msg ljmp cmd_print_msg cmdnf_msg: DB 'BAD COMMAND',0 ; ; ; ; END OF att_main.asm ;/////////////////////////////////////////////////////////// ;/////////////////////////////////////////////////////////// ; att_tr0.asm - TR0 interrupt routines ; ----------- ---------------------- ; TR0_INIT: ;give speed in ACC (see below) ; ; Inicjowanie pracy Timera 0 ; Tryb 16-bit licznika z automatycznym przeladowaniem ; podzial 32x1200Hz ; th0= - (28800 / nasza_czestotliwosc) mov TH0, A ;speed of com, e.g. -3=9600; -2=14400; -1=28800 mov A, TMOD ;try to change lower 4 bits without touching upper anl A, #0F0h orl A, #00000010b ;C/T (Counter/Timer) --> Timer mov TMOD,A ;tryb 2: 8-bit timer z automatycznym ; przeladowaniem setb IT0 ;active for slope (doesn't matter for timer) setb TR0 ;start timera setb ET0 ;enable TR0 interrupts ret ; ; ;/////////////////////////////////////////////////////////// ; Interrupt TR1 service routine ; ----------------------------- ; INT_TR0: ; push PSW push ACC push DPL push DPH jb M0_ON, ITR0M0_CMP ; when motor if off don't check dynamics mov A, M0_STAT anl A,#10000000b ;get phase of the movement cjne A, #0, phase1 phase0: ;phase zero of movemment means climbing from the gap in atten. wheel ;we want to reach stable 0 on M0_LIMIT_SW and leave switch noise behind ; inc M0_PHASE_AGE ;make the phase older, but... jnb M0_LIMIT_SW, phase0_1 ;while still in previous position... mov M0_PHASE_AGE, #0 ;reset age, we'll count again phase0_1: mov A, M0_PHASE_AGE cjne A, #PHASE0_LENGTH, ITR0M0_CMP mov A, M0_STAT anl A, #01111111b orl A, #10000000b ;set phase=1 without affecting other bits mov M0_STAT, A mov M0_PHASE_AGE, #0 ;phase 1 just begun phase1: ;phase one of movement means descending to destination gap in atten. wheel ;we want to reach stable 1 on M0_LIMIT_SW and leave switch noise behind ; inc M0_PHASE_AGE ;make the phase older, but... jb M0_LIMIT_SW, phase1_1 ;while still in previous position... mov M0_PHASE_AGE, #0 ;reset age, we'll count again phase1_1: mov A, M0_PHASE_AGE cjne A, #PHASE1_LENGTH, ITR0M0_CMP ; ;well, we just arrived to next gap ;let's set phase again to zero and modify M0_CURR_POS ; mov M0_PHASE_AGE, #0 mov a, M0_STAT anl a, #01111111b mov M0_STAT, a ;set phase=0 jb M0_RIGHT, M0_minus inc M0_CURR_POS mov A, M0_CURR_POS cjne A, #10, M0_DEFINED mov M0_CURR_POS, #0 sjmp M0_DEFINED M0_minus: jb M0_LEFT, M0_DEFINED dec M0_CURR_POS mov A, M0_CURR_POS cjne A, #-1, M0_DEFINED mov M0_CURR_POS, #9 M0_DEFINED: ; setb M0_ON ;stop motor ; setb M0_LEFT ; setb M0_RIGHT sjmp ITR0M0_CMP ITR0M0_CHK_RESET: jnb M0_RESET_SW, ITR0M0_MOVE_RIGHT jnb M0_LIMIT_SW, ITR0M0_MOVE_RIGHT mov M0_CURR_POS, #0 ;set origin right here mov M0_DEST_POS, #0 mov a, M0_STAT anl a, #01111110b; ;clear reset bit and set phase=0 mov M0_STAT, a mov M0_PHASE_AGE, #0 ITR0M0_CMP: mov a, M0_STAT anl a, #00000001b; ;get reset bit jnz ITR0M0_CHK_RESET ;in reset mode - go right itr0m0_cmp2: mov A, M0_CURR_POS cjne A, M0_DEST_POS, ITR0M0_MOVE setb M0_ON ;OK, we're on place. Stop motors. setb M0_LEFT setb M0_RIGHT sjmp INT_TR0_M1 ;go to motor 1 ITR0M0_MOVE: mov A, M0_CURR_POS setb C subb A, M0_DEST_POS jnb ACC.7,ITR0M0_MOVE_LEFT ;jump if result=dest-curr is negative ITR0M0_MOVE_RIGHT: jb M0_LEFT, it0m0mrr2 ;if turns left and we want to change direction... mov a,M0_STAT anl a,#10000000b; ;get phase bit jz it0m0mrr2 ;if phase==0 we can leave dec M0_CURR_POS ;in case we change direction in the mov A, M0_CURR_POS ;middle of movement, we have to assume cjne A, #-1, it0m0mrr2 ;that we have reached destination mov M0_CURR_POS, #9 ;already (-1), because in close future ;programm will increase (+1) mo_curr_pos ;being at the same position as before it0m0mrr2: setb M0_LEFT clr M0_RIGHT ;begin right turn clr M0_ON sjmp INT_TR0_M1 ITR0M0_MOVE_LEFT: jb M0_RIGHT, it0m0mlr2 ;if turns left and we want to change diirection... mov a, M0_STAT anl a, #10000000b; ;get phase bit jz it0m0mlr2 ;if phase==0 we can leave inc M0_CURR_POS ;in case we change direction in the mov A, M0_CURR_POS ;middle of movement, we have to assume cjne A, #10, it0m0mlr2 ;that we have reached destination mov M0_CURR_POS, #0 ;already (+1), because in close future ;programm will decrease (-1) mo_curr_pos ;being at the same position as before it0m0mlr2: setb M0_RIGHT clr M0_LEFT clr M0_ON ; ;/////////////////////////////////////////////////////////// ; Routines for motor 1 ; -------------------- ; INT_TR0_M1: jb M1_ON, ITR0M1_CMP ; when motor if off don't check dynamics mov A, M1_STAT anl A,#10000000b ;get phase of the movement cjne A, #0, m1phase1 m1phase0: ;phase zero of movemment means climbing from the gap in atten. wheel ;we want to reach stable 0 on M0_LIMIT_SW and leave switch noise behind ; inc M1_PHASE_AGE ;make the phase older, but... jnb M1_LIMIT_SW, m1phase0_1 ;while still in previous position... mov M1_PHASE_AGE, #0 ;reset age, we'll count again m1phase0_1: mov A, M1_PHASE_AGE cjne A, #PHASE0_LENGTH, ITR0M1_CMP mov A, M1_STAT anl A, #01111111b orl A, #10000000b ;set phase=1 without affecting other bits mov M1_STAT, A mov M1_PHASE_AGE, #0 ;phase 1 just begun m1phase1: ;phase zero of movement means descending to destination gap in atten. wheel ;we want to reach stable 1 on M0_LIMIT_SW and leave switch noise behind ; inc M1_PHASE_AGE ;make the phase older, but... jb M1_LIMIT_SW, m1phase1_1 ;while still in previous position... mov M1_PHASE_AGE, #0 ;reset age, we'll count again m1phase1_1: mov A, M1_PHASE_AGE cjne A, #PHASE1_LENGTH, ITR0M1_CMP ; ;well, we just arrived to next gap ;let's set phase again to zero and modify M0_CURR_POS ; mov M1_PHASE_AGE, #0 mov a, M1_STAT anl a, #01111111b mov M1_STAT, a ;set phase=0 jb M1_RIGHT, M1_minus inc M1_CURR_POS mov A, M1_CURR_POS cjne A, #10, M1_DEFINED mov M1_CURR_POS, #0 sjmp M1_DEFINED M1_minus: jb M1_LEFT, M1_DEFINED dec M1_CURR_POS mov A, M1_CURR_POS cjne A, #-1, M1_DEFINED mov M1_CURR_POS, #9 M1_DEFINED: ; setb M1_ON ;stop motor ; setb M1_LEFT ; setb M1_RIGHT sjmp ITR0M1_CMP ITR0M1_CHK_RESET: jnb M1_RESET_SW, ITR0M1_MOVE_RIGHT jnb M1_LIMIT_SW, ITR0M1_MOVE_RIGHT mov M1_CURR_POS, #0 ;set origin right here mov M1_DEST_POS, #0 mov a, M1_STAT anl a, #01111110b; ;clear reset bit and set phase=0 mov M1_STAT, a mov M0_PHASE_AGE, #0 ITR0M1_CMP: mov a, M1_STAT anl a, #00000001b; ;get reset bit jnz ITR0M1_CHK_RESET ;if in reset mode - go right itr0m1_cmp2: mov A, M1_CURR_POS cjne A, M1_DEST_POS, ITR0M1_MOVE setb M1_ON ;OK, we're on place. Stop motors. setb M1_LEFT setb M1_RIGHT sjmp INT_TR0_M2 ;go to motor 2 (exit) ITR0M1_MOVE: mov A, M1_CURR_POS setb C subb A, M1_DEST_POS jnb ACC.7,ITR0M1_MOVE_LEFT ;jump if result=dest-curr is negative ITR0M1_MOVE_RIGHT: jb M1_LEFT, it0m1mrr2 ;if turns left and we want to change direction... mov a,M1_STAT anl a,#10000000b; ;get phase bit jz it0m1mrr2 ;if phase==0 we can leave dec M1_CURR_POS ;in case we change direction in the mov A, M1_CURR_POS ;middle of movement, we have to assume cjne A, #-1, it0m1mrr2 ;that we have reached destination mov M1_CURR_POS, #9 ;already (-1), because in close future ;programm will increase (+1) mo_curr_pos ;being at the same position as before it0m1mrr2: setb M1_LEFT clr M1_RIGHT ;begin right turn clr M1_ON sjmp INT_TR0_M2 ITR0M1_MOVE_LEFT: jb M1_RIGHT, it0m1mlr2 ;if turns left and we want to change diirection... mov a,M1_STAT anl a,#10000000b; ;get phase bit jz it0m1mlr2 ;if phase==0 we can leave inc M1_CURR_POS ;in case we change direction in the mov A, M1_CURR_POS ;middle of movement, we have to assume cjne A, #10, it0m1mlr2 ;that we have reached destination mov M1_CURR_POS, #0 ;already (+1), because in close future ;programm will decrease (-1) mo_curr_pos ;being at the same position as before it0m1mlr2: setb M1_RIGHT clr M1_LEFT clr M1_ON INT_TR0_M2: INT_TR0_EXIT: pop DPH pop DPL pop ACC pop PSW reti ; ; ; ; ; END OF att_tr0.asm ;/////////////////////////////////////////////////////////// ;/////////////////////////////////////////////////////////// ; att_kbd.asm - keyboard routines ; ----------- ----------------- ; ; ; [1] --- [2] --- [3] --- KBD_H1 (horizontal line #1) ; ; | | | ; | | | ; ; [4] --- [5] --- [6] --- KBD_H2 (horizontal line #2) ; ; | | | ; | | | ; ; [7] --- [8] --- [9] --- KBD_H3 (horizontal line #3) ; ; | | | ; | | | ; ; [*] --- [0] --- [#] --- KBD_H4 (horizontal line #4) ; ; ; | | | ; | | | ; ; KBD_V1 KBD_V2 KBD_V3 <--- vertical lines ; ; ATT_KBD: ; keyboard behaves differently depending on reset status: ; -while in 'reset query' state will wait for reset ; confirmation or cancel ; -while in 'normal' operating mode, will wait for: ; * turning into 'reset query' mode ; * attenuator wheel(s) movement(s) ; check for 'reset query' mode ; check if reset pressed jnb KEY_M0_RES, kbd_reset mov a, M0_STAT anl a, #11111101b ; clear 'reset query' bit mov M0_STAT, a ; ;motor movements ; ; ;motor 0 ; mov a, M0_CURR_POS ; is it moving already? cjne a, M0_DEST_POS, kbd1 ; if so -> even don't check keys jb KEY_M0_LEFT, kbd2 ; '-1' key pressed? dec M0_DEST_POS ; decrement dest.pos. of motor 0 mov a, M0_DEST_POS cjne a, #-1, kbd1 mov M0_DEST_POS, #9 sjmp kbd1 kbd2: jb KEY_M0_RIGHT, kbd1 ; motor 0; '+1' key pressed inc M0_DEST_POS mov a, M0_DEST_POS cjne a, #10, kbd1 mov M0_DEST_POS, #0 ; ;motor 1 ; kbd1: mov a, M1_CURR_POS ; is it moving already? cjne a, M1_DEST_POS, kbd3 ; if so -> even don't check keys jb KEY_M1_LEFT, kbd4 ; motor 0; key '-1' pressed? dec M1_DEST_POS ; decrement dest.pos. of motor 0 mov a, M1_DEST_POS cjne a, #-1, kbd3 mov M1_DEST_POS, #9 sjmp kbd3 kbd4: jb KEY_M1_RIGHT, kbd3 ; motor 0; key '+1' pressed? inc M1_DEST_POS mov a, M1_DEST_POS cjne a, #10, kbd3 mov M1_DEST_POS, #0 kbd3: sjmp kbd_exit ; 'normal' movement section completed kbd_reset: mov a, M0_STAT orl a, #00000010b ; set 'reset query' bit mov M0_STAT, a jb KEY_M0_RIGHT, kbd5 ; '+1' pressed? (reset confirmation) mov a, M0_STAT orl a, #00000001b ; give him reset mov M0_STAT, a kbd5: jb KEY_M0_LEFT, kbd6 mov a, M0_STAT anl a, #11111110b ; take him out from reset mode mov M0_STAT, a kbd6: jb KEY_M1_RIGHT, kbd7 ; '+1' pressed? (reset confirmation) mov a, M1_STAT orl a, #00000001b ; give him reset mov M1_STAT, a kbd7: jb KEY_M1_LEFT, kbd8 mov a, M1_STAT anl a, #11111110b ; take him out from reset mode mov M1_STAT, a kbd8: kbd_exit: ret ; ; ; ; ; END OF att_kbd.asm ;/////////////////////////////////////////////////////////// ;/////////////////////////////////////////////////////////// ; att_tr1.asm - TR1 interrupt routines ; ----------- ---------------------- ; ; TR1_INIT: ;give speed in ACC (see below) ; ; Inicjowanie pracy Timera 1 pelniacego role zegara ; transmisyjnego ; Tryb 8-bit licznika z automatycznym przeladowaniem ; podzial 32x1200Hz ; th1= - (28800 / nasza_czestotliwosc) mov TH1, A ;speed of com, e.g. -3=9600; -2=14400; -1=28800 mov A, TMOD ;try to change upper 4 bits without touching lower; anl A, #0Fh orl A, #00100000b ;C/T (Counter/Timer) --> Timer mov TMOD,A ;tryb 2: 8-bit timer z automatycznym ; przeladowaniem setb IT1 ;active for slope (doesn't matter for timer) setb TR1 ;start timera setb ET1 ;enable interrupt ret ; ; ;/////////////////////////////////////////////////////////// ; Interrupt TR0 serviice routine ; ------------------------------ ; INT_TR1: ; push PSW push ACC push DPL push DPH inc TR1_DELAY mov a, TR1_DELAY jz it1m0 ljmp INT_TR1_EXIT ; ;call keyboard routines being in separate file "att_kbd.asm" ; ; it1m0: lcall ATT_KBD ; ;calculate differences between registers and their shadows ;while the difference appears - update display ; mov a, M0_CURR_POS ;check curr_pos clr c subb a, M0_CURR_POS_SH jz it1m0_dest mov M0_CURR_POS_SH, M0_CURR_POS lcall M0_PRINT_NEW_CURR_POS it1m0_dest: ;check dest_pos mov a, M0_DEST_POS clr c subb a, M0_DEST_POS_SH jz it1m0_resq mov M0_DEST_POS_SH, M0_DEST_POS lcall M0_PRINT_NEW_DEST_POS it1m0_resq: ;check if 'reset query' bit changed mov a, M0_STAT xrl a, M0_STAT_SH anl a, #00000010b ;'reset query' bit jz it1m0_res mov a, M0_STAT ;changed: now check the value anl a, #00000010b ;if present -> print it jz it1m0_resq_clear mov DPTR, #M0RSTQ lcall LCD_PRINT_LINE_3 sjmp it1m0_res it1m0_resq_clear: mov DPTR, #LCD_CLEAR16 lcall LCD_PRINT_LINE_3 it1m0_res: ;check if reset bit changed mov a, M0_STAT xrl a, M0_STAT_SH anl a, #00000001b ;reset bit jz it1m0_mov mov a, M0_STAT ;changed: now check the value anl a, #00000001b ;if present -> print it jz it1m0_res_clear mov DPTR, #M0RST lcall M0_PRINT_NEW_STAT sjmp it1m1 it1m0_res_clear: mov DPTR, #M0STOP lcall M0_PRINT_NEW_STAT it1m0_mov: ;check reset bit mov a, M0_STAT anl a, #00000001b jnz it1m1 ;don't change status while resetting mov a, MOTOR_REG xrl a, MOTOR_REG_SH anl a, #01110111b ;ignore change of limit switches anl a, #00001111b ;interested only in motor 0 jz it1m1 mov a, MOTOR_REG anl a, #00001111b lcall CALC_STAT_LABEL lcall M0_PRINT_NEW_STAT ; ;/////////////////////////////////////////////////////////// ; Routines for MOTOR1 ; ------------------- ; ; it1m1: mov a, M1_CURR_POS ;check curr_pos clr c subb a, M1_CURR_POS_SH jz it1m1_dest mov M1_CURR_POS_SH, M1_CURR_POS lcall M1_PRINT_NEW_CURR_POS it1m1_dest: ;check dest_pos mov a, M1_DEST_POS clr c subb a, M1_DEST_POS_SH jz it1m1_resq mov M1_DEST_POS_SH, M1_DEST_POS lcall M1_PRINT_NEW_DEST_POS it1m1_resq: ;check if 'reset query' bit changed mov a, M1_STAT xrl a, M1_STAT_SH anl a, #00000010b ;'reset query' bit jz it1m1_res mov a, M1_STAT ;changed: now check the value anl a, #00000010b ;if present -> print it jz it1m1_resq_clear mov DPTR, #M0RSTQ lcall LCD_PRINT_LINE_3 sjmp it1m1_res it1m1_resq_clear: mov DPTR, #LCD_CLEAR16 lcall LCD_PRINT_LINE_3 it1m1_res: ;check if reset bit changed mov a, M1_STAT xrl a, M1_STAT_SH anl a, #00000001b jz it1m1_mov mov a, M1_STAT ;changed: now check the value anl a, #00000001b ;if present -> print it jz it1m1_res_clear mov DPTR, #M0RST lcall M1_PRINT_NEW_STAT sjmp it1_exit it1m1_res_clear: mov DPTR, #M0STOP lcall M1_PRINT_NEW_STAT sjmp it1_exit it1m1_mov: ;check reset bit mov a, M1_STAT anl a, #00000001b jnz it1_exit ;don't change status while resetting mov a, MOTOR_REG xrl a, MOTOR_REG_SH anl a, #01110111b ;ignore change of limit switches swap a ;interrested only in motor 1 anl a, #00001111b jz it1_exit mov a, MOTOR_REG swap a anl a, #00001111b lcall CALC_STAT_LABEL lcall M1_PRINT_NEW_STAT it1_exit: mov MOTOR_REG_SH, MOTOR_REG mov M0_STAT_SH, M0_STAT mov M1_STAT_SH, M1_STAT INT_TR1_EXIT: pop DPH pop DPL pop ACC pop PSW reti ; ; ;/////////////////////////////////////////////////////////// ; display routines related to motor positions ; ------------------------------------------- ; ; LABEL_SIZE EQU 12 M0_PRINT_NEW_CURR_POS: mov a, M0_CURR_POS mov b, #LABEL_SIZE mul ab add a, #LOW(M0_LABELS) mov dpl,a mov a,b addc a, #HIGH(M0_LABELS) mov dph,a ljmp LCD_PRINT_LINE_2 M0_LABELS: DB '0:none ',0 DB '1:0.05mmAl ',0 DB '2:0.10mmAl ',0 DB '3:0.15mmAl ',0 DB '4:0.20mmAl ',0 DB '5:0.25mmAl ',0 DB '6:0.30mmAl ',0 DB '7:0.35mmAl ',0 DB '8:0.40mmAl ',0 DB '9:0.45mmAl ',0 M1_PRINT_NEW_CURR_POS: mov a, M1_CURR_POS mov b, #LABEL_SIZE mul ab add a, #LOW(M1_LABELS) mov dpl,a mov a,b addc a, #HIGH(M1_LABELS) mov dph,a ljmp LCD_PRINT_LINE_1 M1_LABELS: DB '0:none ',0 DB '1:0.50mmAl ',0 DB '2:1.00mmAl ',0 DB '3:1.50mmAl ',0 DB '4:2.00mmAl ',0 DB '5:2.50mmAl ',0 DB '6:3.00mmAl ',0 DB '7:2.00mmPb ',0 DB '8:3.00mmPb ',0 DB '9:User`s ',0 M0_PRINT_NEW_DEST_POS: mov a,#4Fh lcall LCD_ADDRESS mov a, M0_DEST_POS lcall LCD_PRINT_DIGIT_9 ret M1_PRINT_NEW_DEST_POS: mov a,#0Fh lcall LCD_ADDRESS mov a, M1_DEST_POS lcall LCD_PRINT_DIGIT_9 ret CALC_STAT_LABEL: jnb ACC.2, csl_turns mov DPTR, #M0STOP ret csl_turns: jb ACC.0, csl_right mov DPTR, #M0LEFT ret csl_right: jb ACC.1, csl_exit mov DPTR, #M0RGHT csl_exit: ret M0LEFT: DB '<---',0 M0RGHT: DB '--->',0 M0STOP: DB ' OK ',0 M0RST: DB 'RES.',0 M0RSTQ: DB '-no RESET? yes+',0 M0_PRINT_NEW_STAT: mov a,#4Bh lcall LCD_ADDRESS lcall LCD_PRINTF ret M1_PRINT_NEW_STAT: mov a,#0Bh lcall LCD_ADDRESS lcall LCD_PRINTF ret ; ; ; ; ; END OF att_tr1.asm ;/////////////////////////////////////////////////////////// ;/////////////////////////////////////////////////////////// ; cmdlib.asm - Command Interpreter ; ---------- ------------------- ; ; ; This routine will read char-by-char from an input (e.g. serial port), ; look in appended commands' table (look at the end of this section for ; structure of the table) and jump to respective user-defined procedures. ; ; EOL EQU 13 ; ; User has to change routines cmd_getchar and cmd_putchar ; according to his needs. Now, they read a byte from serial ; port and send output to serial too. ; You have also to adjust EOL sign to be agreed with your ; system. ; cmd_getchar: lcall SP_IN cjne a, #EOL, cmdgc mov a, #0 ; replace EOL with 0 cmdgc: jnb ACC.6, cmdgc2 clr ACC.5 ; lower-case to upper-case cmdgc2: ret ; ; ; ; ; cmd_putchar: push ACC jnz cmdpc mov a, #10 lcall SP_OUT mov a, #EOL cmdpc: lcall SP_OUT pop ACC ret ; ; ;/////////////////////////////////////////////////////////// ; cmdinterp - main interpreting routine ; --------- ------------------------- ; ;Input: DPTR - Address of table of commands (table starts ; with CMD_ROW_LGTH constant) ; ACC - A first char from input stream. Sometimes ; happens, that your reading routine read ; one char too much. Put it to ACC. If ; whitespace (e.g. space) will be ignored. ; ;Output: dependent on command routines (cmdinterp jumps to them) ; Last charater read is ported to called routine in B reg. ;Changes: ACC,B,DPTR,r0,r1,r2,r3,r4,r5,r6 ; ;Notice: You have to use bank#0 of registers (absolute addresses ; are used) ; LAST_CHAR EQU 5 ; means cell of register R5 CMD_ROW_LGTH EQU 6 ; means cell of register R6 cmdinterp: push ACC ; in ACC we have first char read already by ; calling procedure. If space -> ignore him! mov r1, #0 ; row number in commands table mov r0, #3 ; columne number in command table (+2 -> routine address) mov a, #0 ; initialize constant CMD_ROW_LGTH, which movc a,@A+DPTR ; comes as first byte, before right comd. table mov CMD_ROW_LGTH,a ; begining mov a, #1 ; add to DPTR this one byte of offset to the add a, dpl ; begining of data in commands' table mov dpl, a mov a, #0 addc a, dph mov dph, a mov r2, dpl mov r3, dph pop ACC lcall cmd_is_whitespace jnc cmd11 cmd1: ; First of all pull out all the whitespaces which may appear befor ; a command. lcall cmd_vacuum_whitespaces jnz cmd11 ; ignore empty strings ret ; now, in ACC, there is first character of the command. ; Calculate begining of the commands' table. cmd11: mov LAST_CHAR, a lcall cmd_curr_row_DPTR mov a, r0 movc a,@a+DPTR ;get value in current row mov b, a mov a, LAST_CHAR sjmp cmd20 ; we have to jump-in-to central loop which will read all chars ; of the command cmd2: inc r0 ;scan current line mov a, r0 movc a,@a+DPTR ;get value in current row mov b, a lcall cmd_getchar ;load new char to ACC cmd20: mov LAST_CHAR, a mov a, r0 clr C subb a, CMD_ROW_LGTH jz cmd_found ;we are after last char in row ;all row matches -> call service routine ;for further investigations mov a, LAST_CHAR cmd201: ; lcall cmd_putchar ; push ACC ; mov a,b ; lcall cmd_putchar ; mov b,a ; pop ACC cjne a, b, cmd21 ; perform comparison! lcall cmd_is_whitespace jnc cmd2 ; no, it's regular char -> do another loop mov LAST_CHAR, a sjmp cmd_found ; the characters don't fit. We have two options: ; 1) EOL appeared at getchar, and so: ; - if in table we have whitespace here (end of word) -> ok ; - if we have a regular letter - they do not fit indeed ; 2) There is maybe a wildcard char in the table here? -> continue ; 3) they really do not fit -> try in another row of table cmd21: ; First, clearify question of EOL - not EOL jnz cmd22 ; Try if we have EOL at getchar mov LAST_CHAR, a ; yes, save EOL char for further routines mov a, b ; restore value read from table lcall cmd_is_whitespace ; was a whitespace in table at this pos? jc cmd_found ; Yes! -> we won! sjmp cmd_not_found ; word in table was too log - aparently ; was nothing better befor cmd22: ; What we know here is: ; 1) There was a misfit getchar<->table ; 2) There is no EOL at getchar ; 3) This is not end of table ; Check for wildcard in the table. If so -> continue search. mov LAST_CHAR, a ; store getchar mov a, b ; restore that from table cjne a, #'~', cmd3 ; was it wildcard '~' ? sjmp cmd2 ; yes, make loop again cmd_found: ;we found matching string! mov a, #0 mov b, LAST_CHAR ;send last char to the procedure jmp @A+DPTR ;jump at the address from begining of the row cmd_not_found: ;there is no such a command mov a, LAST_CHAR ; vacuum input till EOL (wait for EOL) ; jz cmdnf1 ; if last char was EOL, ; lcall cmd_vacuum_till_eol ; don't try to getchar again! ; ;cmdnf1: mov DPTR, #cmdnf_msg ; now send a message to output ; ljmp cmd_print_msg ; There is another epiloque below, you can call routine as other items iin table mov DPTR, #cmdnf mov a, #0 mov b, LAST_CHAR jmp @A+DPTR ; ; ; section 2: try to move system to next row if they fit at least till ; the position we stopped last scan, e.g.: ; ;if text received so far is: "ala_ma_p", and in table we have: ; ala_ma_kota ; ala_ma_pchly ;they fit till--------^ this position (7th char == char of index #6) ;and index r0 is here--^ right now (r0 == 7+2 == 9 ) ;It means: index r0 is now on the first misfitting position ; ; cmd3: ; check if received value is lt or gt that in table mov a, r0 movc a,@A+DPTR clr C subb a, LAST_CHAR ; if char in table is gt LAST_CHAR... jnb ACC.7, cmd_not_found ; there will be nothing better below ; since table is in alphabetical order ; we're about to compare two rows from the begining (3rd char) ; till the position we stopped previous loop. cmd4: mov r4,#2 ; r4 will be loop index, ; start at val=3 (2+inc r4 below) cmd41: inc r4 ; scan current line mov a, r4 ; check counters: we don't want to exceed clr C ; value of old index (r0) subb a, r0 jz cmd421 ; ok, till index==r0 strings are identical cmd42: mov a, r4 movc a,@a+DPTR ; get value in current row... mov b, a ; ...and store in B mov a, r4 add a, CMD_ROW_LGTH movc a,@a+DPTR ; get value in next row... ; lcall cmd_putchar ; push ACC ; mov a,b ; lcall cmd_putchar ; mov b,a ; pop ACC cjne a, b, cmd43 sjmp cmd41 ; ok, string being below is identical till the position we suspended ; last scan. Thus we can increment row counter (r1) and continue from ; the point we stopped cmd421: inc r1 mov a, LAST_CHAR ljmp cmd11 cmd43: cjne a, #'~', cmd44 ;wildcards '~' are also welcome -> continue sjmp cmd41 ; here, there is no successor: last line cmd44: sjmp cmd_not_found ; was bad, we can't continue with this one ; as well cmd_curr_row_DPTR: push ACC push B mov a, r1 ;calculate offset to begining of current row mov b, CMD_ROW_LGTH mul ab add a, r2 ;add the offset to begining of the table mov dpl, a mov a, b addc a, r3 ;original DPTR is stored in r2,r3 mov dph, a ;now we have in DPTR address of begining of current row pop B pop ACC ret ; ; ;/////////////////////////////////////////////////////////// ; Supporting cmd_ routines ; ------------------------ ; ; cmd_is_whitespace: clr C cjne a, #EOL, cmdiw1 setb C ret cmdiw1: cjne a, #32, cmdiw2 setb C ret cmdiw2: push ACC anl a, #11100000b jnz cmdiw3 setb C cmdiw3: pop ACC ret cmd_vacuum_whitespaces: lcall cmd_getchar lcall cmd_is_whitespace jc cmd_vacuum_whitespaces ret cmd_vacuum_till_eol: lcall cmd_getchar jnz cmd_vacuum_till_eol ret cmd_print_msg: mov a, r0 push ACC mov r0, #-1 cmdpm1: inc r0 mov a,r0 movc a,@A+DPTR lcall cmd_putchar jz cmdpm2 cjne r0, #255, cmdpm1 inc dph sjmp cmdpm1 cmdpm2: pop ACC mov r0, a ret ; ;/////////////////////////////////////////////////////////// ; cmdlib data definitions ; ----------------------- ; ;WARNING! Phrases in the table MUST be in alphabetical order !!! ; ; ;cmdtable: ; DB 16 ;row width ; DB 2,HIGH(cyc) ,LOW(cyc), 'cyc ' ; DB 2,HIGH(dupa) ,LOW(dupa), 'dupa ' ; DB 2,HIGH(idn) ,LOW(idn), 'idn ' ;cmdnf: DB 2,HIGH(cmdnfv) ,LOW(cmdnfv), ' ' ; ; ;dupa: ;lcall cmd_vacuum_till_eol ; mov DPTR, #dupa_msg ; ljmp cmd_print_msg ;dupa_msg: ; DB 'DUPA jest OK!',0 ; ; ;cyc: ;lcall cmd_vacuum_till_eol ; mov DPTR, #cyc_msg ; ljmp cmd_print_msg ;cyc_msg: ; DB 'CYC jest OK!',0 ; ; ;idn: mov DPTR, #cmdidn_msg ; ljmp cmd_print_msg ;cmdidn_msg: ; DB 'IDN jest OK!',0 ; ; ;cmdnfv: mov DPTR, #cmdnf_msg ; ljmp cmd_print_msg ; ;cmdnf_msg: ; DB 'LAST LINE - BAD COMMAND',0 ; ; ; ; END OF cmdlib.asm ;/////////////////////////////////////////////////////////// ; ;RS Interrupt routine ; INT_RS: push PSW push ACC push DPL push DPH ;przerwanie z powodu nowo odebranego bajtu ;czy prosba o nadanie kolejnego? jb TI,RS_DATA_SENT jb RI,RS_DATA_RECEIVED RS_IRQ_EXIT: pop DPH pop DPL pop ACC pop PSW reti RS_DATA_SENT: clr TI sjmp RS_IRQ_EXIT RS_DATA_RECEIVED: mov A,SBUF ;odczytanie danej z bufora odbiornika lcall LCD_OUT clr RI ;przygotowanie do odbioru nastepnej danej sjmp RS_IRQ_EXIT ;************************************************* ;* INICJACJA PORTU SZEREGOWEGO * ;************************************************* ; Inicjowanie pracy portu szeregowego ; Tryb 8-bit UART, ; Flaga gotowosci nadawania ustawiona RS_INIT: mov SCON, #01010010b setb ES ; setb PS ;sets higher irq priority ; Inicjowanie pracy Timera 1 pelniacego role zegara ; transmisyjnego ; Tryb 16-bit licznika z automatycznym przeladowaniem ; podzial 32x1200Hz ; th1= - (28800 / nasza_czestotliwosc) T1_INIT: ; mov A,#-3 ; 9600bps ;get speed parameter from calling programm sjmp RS_TR1_INIT ;call initialisation of timer1 and exit routine ;SP_OUT Wysyla znak przez port szeregowy, jesli jest on gotowy ; ; SP_OUT: jnb TI,$ ;oczekiwanie na zwolnienie nadajnika clr TI mov SBUF,A ;wyslanie danej ret ;SP_IN Odbiera znak z portu szeregowego ; ; SP_IN: jnb RI,$ ;oczekiwanie na pojawienie sie danej clr RI ;przygotowanie do odbioru nastepnej danej mov A,SBUF ;odczytanie danej z bufora odbiornika ret RS_TR1_INIT: ;give speed in ACC (see below) ; ; Inicjowanie pracy Timera 1 pelniacego role zegara ; transmisyjnego ; Tryb 16-bit licznika z automatycznym przeladowaniem ; podzial 32x1200Hz ; th1= - (28800 / nasza_czestotliwosc) mov TH1, A ;speed of com, e.g. -3=9600; -2=14400; -1=28800 mov A, TMOD ;try to change upper 4 bits without touching lower anl A, #0Fh orl A, #00100000b ;C/T (Counter/Timer) --> Timer mov TMOD,A ;tryb 2: 8-bit timer z automatycznym ; przeladowaniem ; mov TMOD, #00100000b ; setb IT1 ;active for slope (doesn't matter for timer) setb TR1 ;start timera ret ;/////////////////////////////////////////////////////////// ; lcdlib.asm - LCD routines ; ---------- ------------ ; ; ;/////////////////////////////////////////////////////////// ; LCD labels should be already defined in hardware board section (e.g. att_brd.h or 80c535.h) ! ; ---------- ; ;LCD_E EQU P3.5 ;LCD_RW EQU P3.4 ;LCD_RS EQU P3.3 ;LCD_DATA EQU P4 ; ; ;User should lcall LCD_INIT routine then the other ; ; LCD Init ; -------- ; Konfiguracja wyswietlacza LCD dla 8-bitowego dwu(cztero!)linijkowca ; wykonanie komend F, C, A i D tak, aby ustawic: ; - transmisja 8 bitow, ilosc linii = 2, czcionka 5x7 ; - inkrementacja kursora przy przesuwie, brak przewijania ; - czyszczenie ekranu i ustawienie kursora w polozenie 0 ; - wlaczenie ekranu, kursora, brak migania ; LCD_INIT: ; wykonujemy F, C, A i D ; F: ustawienie na 8bit, 1 linia, czcionka 5x7 mov a, #00111000b lcall LCD_COMMAND ; C: kierunek przesuwu kursora: inkrementacja, nieprzewijanie mov a, #00000110b lcall LCD_COMMAND ; A: czysci DRAM i ustawia kursor w polozenie 0 mov a, #00000001b lcall LCD_COMMAND ; D: wlaczony ekran, kursor i wylaczone miganie mov a, #00001110b lcall LCD_COMMAND ret LCD_LINE_1: mov a, #10000000b ; 128 + adres 0 lcall LCD_COMMAND ret LCD_LINE_2: mov a, #11000000b ; 128 + adres 64 lcall LCD_COMMAND ret LCD_LINE_3: mov a, #10010000b ; 128 + adres 16 lcall LCD_COMMAND ret LCD_LINE_4: mov a, #11010000b ; 128 + adres 64 + 16 lcall LCD_COMMAND ret LCD_PRINT_LINE_1: mov a, #10000000b ; 128 + adres 0 lcall LCD_COMMAND lcall LCD_PRINTF ret LCD_PRINT_LINE_2: mov a, #11000000b ; 128 + adres 64 lcall LCD_COMMAND lcall LCD_PRINTF ret LCD_PRINT_LINE_3: mov a, #10010000b ; 128 + adres 16 lcall LCD_COMMAND lcall LCD_PRINTF ret LCD_PRINT_LINE_4: mov a, #11010000b ; 128 + adres 64 + 16 lcall LCD_COMMAND lcall LCD_PRINTF ret LCD_ADDRESS: setb ACC.7 lcall LCD_COMMAND ret REFRESH_DISPLAY: ; Odswieza wyswietlacz mov a, #00000001b lcall LCD_COMMAND ret LCD_PRINT_HEX: push DPL push DPH mov DPTR, #HEX_TABLE mov B, A swap A anl A, #0Fh movc A, @A+DPTR lcall LCD_OUT mov A, B anl A, #0Fh movc A, @A+DPTR lcall LCD_OUT pop DPH pop DPL ret LCD_PRINT_SINT: JNB ACC.7,LCD_PRINT_USINT CPL A INC A LCD_PRINT_USINT: push dpl push dph MOV B,#100 DIV AB ADD A,#'0' PUSH B PUSH ACC LCALL LCD_OUT POP ACC POP B MOV A,B MOV B,#10 DIV AB ADD A,#'0' PUSH ACC PUSH B LCALL LCD_OUT POP B POP ACC MOV A,B ADD A,#'0' LCALL LCD_OUT pop dph pop dpl RET LCD_PRINT_DIGIT: mov B, #100 div AB add A, #48 lcall LCD_OUT mov A, B mov B, #10 div AB add A, #48 lcall LCD_OUT mov A, B add A, #48 lcall LCD_OUT ret LCD_PRINT_DIGIT_99: mov B, #10 div AB add A, #48 lcall LCD_OUT mov A, B add A, #48 lcall LCD_OUT ret LCD_PRINT_DIGIT_9: add A, #48 lcall LCD_OUT ret LCD_PRINTF: push ACC mov a, r1 push ACC mov R1, #0 lpf1 mov a, R1 movc a, @A+DPTR jz lpfexit lcall LCD_OUT inc R1 sjmp lpf1 lpfexit pop ACC mov r1, a pop ACC ret LCD_WAIT_FIXED_TIME: push ACC mov a, r7 push ACC mov r7,#255 empty: nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop djnz r7, empty pop ACC mov r7, a pop ACC ret LCD_WAIT: push ACC clr LCD_RS setb LCD_RW lwib1: setb LCD_E mov a, LCD_DATA ; czytaj Busy Flag clr LCD_E jb ACC.7, lwib1 clr LCD_RW pop ACC ret STROB_E: setb LCD_E lcall LCD_WAIT_FIXED_TIME clr LCD_E ret LCD_COMMAND: push ACC lcall LCD_WAIT mov LCD_DATA, a ; wystaw dane na magistrale wyswietlacza clr LCD_RS ; ustaw sygnaly do zapisu komendy clr LCD_RW lcall STROB_E ; E=1 pop ACC ret LCD_OUT: push ACC lcall LCD_WAIT mov LCD_DATA, a ; dane na magistrale clr LCD_RW ; ustaw zapis setb LCD_RS ; RS=1, czyli dana do wyslania lcall STROB_E clr LCD_RS pop ACC ret ;************************************** ;** ** ;** LCD DATA DEFINITIONS ** ;** ** ;************************************** LCD_CLEAR16 DB ' ',0 ala DB 'ALA MA KOTA', 0,0 HEX_TABLE DB '0123456789ABCDEF' ; ; ; ; ; END OF LCD routines (lcdlib.asm) ;/////////////////////////////////////////////////////////// END