Indirect Memory Addressing Truncation
beardcm
Posts: 12
I am programming the SX28AC and am receiving a message from the debugger:
Warning 237 - pass 2:· Literal truncated to 8 bits.
My question is:
We need to be able to pass a 16 bit number into a subroutine.· What is the best method for accomplishing this?
Program Code:
SX28AC
TEST1
················································································
SX_Key
; ** Baud Rates for UART 1 **
U1B1200 ;baud rate of 1.2 Kbps
; ** Baud Rates for UART 2· **
U2B9600 ;baud rate of 9.6 kbps
IFDEF SX_Key ;SX-Key Directives
· IFDEF SX28AC ;SX28AC device directives for SX-Key
device SX28,oschs2,turbo,stackx,optionx
· ENDIF
· IFDEF SX48_52 ;SX48/52/BD device directives for SX-Key
device oschs2
· ENDIF
freq 50_000_000
ELSE · ;SASM Directives
·
· IFDEF SX28AC ;SX28AC device directives for SASM
device SX28,oschs2,turbo,stackx,optionx
· ENDIF
·
· IFDEF SX48_52 ;SX48BD or SX52BD device directives for SASM
device SX52,oschs2·
· ENDIF
ENDIF
id '2UART VP' ;
reset resetEntry ; set reset vector
IRC_CAL IRC_FAST
;*********************************************************************************************
;
Macro's
; Macro: _bank
; Sets the bank appropriately for all revisions of SX.
;
; This is required since the bank instruction has only a 3-bit
operand, it cannot be used to
; access all 16 banks of the SX48/52.· FSR.7 (SX48/52bd production
release) needs to be set
; appropriately, depending on the bank address being accessed. This
macro fixes this.
;
; So, instead of using the bank instruction to switch between banks,
use _bank instead.
;*********************************************************************************************
_bank macro 1
· noexpand
bank \1
IFDEF SX48_52
·· IF \1 & %10000000 ;SX48BD and SX52BD (production release) bank
instruction
· expand
setb fsr.7 ;modifies FSR bits 4,5 and 6. FSR.7 needs to be set by
software.
· noexpand
··· ·· ELSE
· expand
clrb fsr.7
· noexpand
········· ENDIF
ENDIF
endm
;*********************************************************************************************
; Macro: _mode
; Sets the MODE register appropriately for all revisions of SX.
;
; This is required since the MODE (or MOV M,#) instruction has only a
4-bit operand.
; The SX28AC use only 4 bits of the MODE register, however the
SX48/52BD have
; the added ability of reading or writing some of the MODE registers,
and therefore use
; 5-bits of the MODE register. The· MOV M,W instruction modifies all
8-bits of the
; MODE register, so this instruction must be used on the SX48/52BD to
make sure the MODE
; register is written with the correct value. This macro fixes this.
;
; So, instead of using the MODE or MOV M,# instructions to load the M
register, use
;· _mode instead.
;*********************************************************************************************
_mode macro 1
· noexpand
IFDEF SX48_52
· expand
mov w,#\1·········· ;loads the M register correctly for the SX48BD
and SX52BD
mov m,w
· noexpand
ELSE
· expand
mov m,#\1··· ;loads the M register correctly for the SX18AC, SX20AC
;and SX28AC
· noexpand
ENDIF
endm
;*********************************************************************************************
······· ; INCP/DECP macros for incrementing/decrementing pointers to
RAM
······· ; used to compensate for incompatibilities between SX28AC and
SX52BD
;*********************************************************************************************
INCP macro 1 ; Increments a pointer to RAM
inc··· \1
IFNDEF SX48_52
setb· \1.4 ; If SX18 or SX28AC,keep bit 4 of the pointer = 1
ENDIF ; to jump from $1f to $30,etc
endm
DECP macro 1 ; Decrements a pointer to RAM
IFDEF SX48_52
dec··· \1
ELSE
clrb·· \1.4 ; If SX18 or SX28AC, forces rollover to next bank
dec··· \1 ; if it rolls over. (skips banks with bit 4 = 0)
setb·· \1.4············ ; Eg: $30 ---> $20 ---> $1f ---> $1f
ENDIF·························· ; AND: $31 ---> $21 ---> $20 ---> $30
endm
;*********************************************************************************************
······· ; Error generating macros
······· ; Used to generate an error message if the label is
intentionally moved into the second page.
······· ; Use for lookup tables.
;*********************************************************************************************
tablestart macro 0 ; Generates an error message if code that MUST be
in
; the first half of a page is moved into the second half
if $ & $100
ERROR····· 'Must be located in the first half of a page.'
endif
endm
tableEnd macro 0 ; Generates an error message if code that MUST be in
; the first half of a page is moved into the second half
if $ & $100
ERROR····· 'Must be located in the first half of a page.'
endif
endm
;*********************************************************************************************
;
Memory Organization
;*********************************************************************************************
;*********************************************************************************************
;
Data Memory address
definitions
; These definitions ensure the proper address is used for banks 0 - 7
for 2K SX devices
; (SX28) and 4K SX devices (SX48/52).
;*********************************************************************************************
IFDEF SX48_52
global_org = $0A
bank0_org = $00
bank1_org = $10
bank2_org = $20
bank3_org = $30
bank4_org = $40
bank5_org = $50
bank6_org = $60
bank7_org = $70
ELSE
global_org = $08
bank0_org = $10
bank1_org = $30
bank2_org = $50
bank3_org = $70
bank4_org = $90
bank5_org = $B0
bank6_org = $D0
bank7_org = $F0
ENDIF
;*********************************************************************************************
;
Global Register
definitions
; NOTE: Global data memory starts at $0A on SX48/52 and $08 on
SX18/20/28.
;*********************************************************************************************
org···· global_org
flags0 equ global_org + 0 ; stores bit-wise operators like flags
; and function-enabling bits (semaphores)
;
VP: RS232
Receive
rs232Tx1Flag equ flags0.0 ;indicates that UART1 is transmitting if set
or not transmitting if reset
rs232Tx2Flag equ flags0.1 ;indicates that UART2 is transmitting if set
or not transmitting if reset
rs232Rx1Flag equ flags0.2 ;indicates that UART1 has received a byte if
set
rs232Rx2Flag equ flags0.3 ;indicates that UART2 has received a byte if
set
isrTemp0 equ global_org + 1 ; Interrupt Service Routine's temp
register.·
; Don't use this register in the mainline.
localTemp0 equ global_org + 2 ; temporary storage register
; Used by first level of nesting
; Never guaranteed to maintain data
localTemp1 equ global_org + 3 ; temporary storage register
; Used by second level of nesting
; or when a routine needs more than one
; temporary global register.
localTemp2 equ global_org + 4 ; temporary storage register
; Used by third level of nesting or by
; main loop routines that need a loop
; counter, etc.
;*********************************************************************************************
;
RAM Bank Register
definitions
;*********************************************************************************************
;*********************************************************************************
; Bank 0
;*********************************************************************************
org···· bank0_org
bank0 = $
;*********************************************************************************
; Bank 1
;*********************************************************************************
org···· bank1_org
bank1 = $
rs232TxBank =······ $ ;UART Transmit bank
rs232Tx1High ds····· 1 ;High Byte to be· transmitted
rs232Tx1Low ds····· 1 ;Low· Byte to be transmitted
rs232Tx1Count ds····· 1 ;counter to keep track of the bits sent
rs232Tx1Divide ds····· 1 ;xmit timing counter
rs232Tx1Byte ds 1 ;store the byte to be sent in this buffer
rs232Tx2High ds····· 1 ;High Byte to be· transmitted
rs232Tx2Low ds····· 1 ;Low· Byte to be transmitted
rs232Tx2Count ds····· 1 ;counter to keep track of the bits sent
rs232Tx2Divide ds····· 1 ;xmit timing counter
rs232Tx2Byte ds 1 ;store the byte to be sent in this buffer
MultiplexBank = $ ;Multipler Bank
isrMultiplex · ds····· 1· ;Used to jump between the ISR Threads when
; an Interrupt occurs
;*********************************************************************************
; Bank 2
;*********************************************************************************
org···· bank2_org
bank2 = $
rs232RxBank = $
rs232Rx1Count ds····· 1 ;counter to keep track of the number of bits
received
rs232Rx1Divide ds····· 1 ;receive timing counter
rs232Rx1Byte ds····· 1 ;buffer for incoming byte
rs232Byte1 ds 1 ;Used by serial routines
rs232Rx2Count ds····· 1 ;counter to keep track of the number of bits
received
rs232Rx2Divide ds····· 1 ;receive timing counter
rs232Rx2Byte ds····· 1 ;buffer for incoming byte
rs232Byte2 ds 1 ;used by serial routines
;*********************************************************************************
; Bank 3
;*********************************************************************************
org···· bank3_org
bank3 = $
;*********************************************************************************
; Bank 4
;*********************************************************************************
org···· bank4_org
bank4 = $
;*********************************************************************************
; Bank 5
;*********************************************************************************
org···· bank5_org
bank5 = $
;*********************************************************************************
; Bank 6
;*********************************************************************************
org···· bank6_org
bank6 = $
;*********************************************************************************
; Bank 7
;*********************************************************************************
org···· bank7_org
bank7 = $
IFDEF SX48_52
;*********************************************************************************
; Bank 8
;*********************************************************************************
org $80 ;bank 8 address on SX52
bank8 = $
;*********************************************************************************
; Bank 9
;*********************************************************************************
org $90 ;bank 9 address on SX52
bank9 = $
;*********************************************************************************
; Bank A
;*********************************************************************************
org $A0 ;bank A address on SX52
bankA = $
;*********************************************************************************
; Bank B
;*********************************************************************************
org $B0 ;bank B address on SX52
bankB = $
;*********************************************************************************
; Bank C
;*********************************************************************************
org $C0 ;bank C address on SX52
bankC = $
;*********************************************************************************
; Bank D
;*********************************************************************************
org $D0 ;bank D address on SX52
bankD = $
;*********************************************************************************
; Bank E
;*********************************************************************************
org $E0 ;bank E address on SX52
bankE = $
;*********************************************************************************
; Bank F
;*********************************************************************************
org $F0 ;bank F address on SX52
bankF = $
ENDIF
;*****************************************************************************************
;
Port Assignment
;*****************************************************************************************
RA_latch equ %00000000 ;SX28/48/52 port A latch init ;intial value
after reset
RA_DDIR equ %11111111 ;SX28/48/52 port A DDIR value ;0=Output,1=Input
RA_LVL equ %00000000 ;SX28/48/52 port A LVL value ;0=CMOS,1=TTL
RA_PLP equ %00000000 ;SX28/48/52 port A PLP value ;0=Enable,1=Disable
RB_latch equ %10001000 ;SX28/48/52 port B latch init ;intial value
after reset
RB_DDIR equ %01110111 ;SX28/48/52 port B DDIR value ;0=Output,1=Input
RB_ST equ %11111111 ;SX28/48/52 port B ST value ;0=Enable,1=Disable
RB_LVL equ %00000000 ;SX28/48/52 port B LVL value ;0=CMOS,1=TTL
RB_PLP equ %11001100 ;SX28/48/52 port B PLP value ;0=Enable,1=Disable
RC_latch equ %00000000 ;SX28/48/52 port C latch init ;intial value
after reset
RC_DDIR equ %11111111 ;SX28/48/52 port C DDIR value ;0=Output,1=Input
RC_ST equ %11111111 ;SX28/48/52 port C ST value ;0=Enable,1=Disable
RC_LVL equ %00000000 ;SX28/48/52 port C LVL value ;0=CMOS,1=TTL
RC_PLP equ %00000000 ;SX28/48/52 port C PLP value ;0=Enable,1=Disable
IFDEF SX48_52
RD_latch equ %00000000 ;SX48/52 port D latch init ;intial value after
reset
RD_DDIR equ %11111111 ;SX48/52 port D DDIR value ;0=Output,1=Input
RD_ST equ %11111111 ;SX48/52 port D ST value ;0=Enable,1=Disable
RD_LVL equ %00000000 ;SX48/52 port D LVL value ;0=CMOS,1=TTL
RD_PLP equ %00000000 ;SX48/52 port D PLP value ;0=Enable,1=Disable
RE_latch equ %00000000 ;SX48/52 port E latch init ;intial value after
reset
RE_DDIR equ %11111111 ;SX48/52 port E DDIR value ;0=Output,1=Input
RE_ST equ %11111111 ;SX48/52 port E ST value ;0=Enable,1=Disable
RE_LVL equ %00000000 ;SX48/52 port E LVL value ;0=CMOS,1=TTL
RE_PLP equ %00000000 ;SX48/52 port E PLP value ;0=Enable,1=Disable
ENDIF
;*********************************************************************************************
;
Pin Definitions
;*********************************************************************************************
rs232Rxpin1····· equ···· rb.6 ;UART1 receive input
rs232Txpin1····· equ···· rb.7 ;UART1 transmit output
rs232Rxpin2····· equ···· rb.2 ;UART2 receive input
rs232Txpin2····· equ···· rb.3 ;UART2 transmit output
;*********************************************************************************************
;
Program constants
;*********************************************************************************************
;*********************************************************************************************
; UART Constants values
;*********************************************************************************************
intPeriod = 217
UARTfs = 230400
Num = 4 ; Number of times ISR thread1 is called in the
; ISRMultiplexer
IFDEF· U1B1200
UARTBaud1 = 1200
ENDIF
IFDEF· U1B2400
UARTBaud1 = 2400
ENDIF
IFDEF· U1B4800
UARTBaud1 = 4800
ENDIF
IFDEF· U1B9600
UARTBaud1 = 9600
ENDIF
IFDEF· U1B1920
UARTBaud1 = 19200
ENDIF
IFDEF· U1B5760
UARTBaud1 = 57600
ENDIF
UARTDivide1 = (UARTfs/(UARTBaud1*Num)) ;48
UARTStDelay1 = UARTDivide1 +(UARTDivide1/2)+1
IFDEF· U2B1200
UARTBaud2 = 1200
ENDIF
IFDEF· U2B2400
UARTBaud2 = 2400
ENDIF
IFDEF· U2B4800
UARTBaud2 = 4800
ENDIF
IFDEF· U2B9600
UARTBaud2 = 9600
ENDIF
IFDEF· U2B1920
UARTBaud2 = 19200
ENDIF
IFDEF· U2B5760
UARTBaud2 = 57600
ENDIF
UARTDivide2 = (UARTfs/(UARTBaud2*Num)) ;6
UARTStDelay2 = UARTDivide2 +(UARTDivide2/2)+1
IFDEF SX48_52
;*********************************************************************************************
; SX48BD/52BD Mode addresses
; *On SX48BD/52BD, most registers addressed via mode are read and
write, with the
; exception of CMP and WKPND which do an exchange with W.
;*********************************************************************************************
;
Timer (read) addresses
TCPL_R equ $00 ;Read Timer Capture register low byte
TCPH_R equ $01 ;Read Timer Capture register high byte
TR2CML_R equ $02 ;Read Timer R2 low byte
TR2CMH_R equ $03 ;Read Timer R2 high byte
TR1CML_R equ $04 ;Read Timer R1 low byte
TR1CMH_R equ $05 ;Read Timer R1 high byte
TCNTB_R equ $06 ;Read Timer control register B
TCNTA_R equ $07 ;Read Timer control register A
;
Exchange addresses
CMP equ $08 ;Exchange Comparator enable/status register with W
WKPND equ $09 ;Exchange MIWU/RB Interrupts pending with W
;
Port setup (read)
addresses
WKED_R equ $0A ;Read MIWU/RB Interrupt edge setup, 1 = falling, 0 =
rising
WKEN_R equ $0B ;Read MIWU/RB Interrupt edge setup, 0 = enabled, 1 =
disabled
ST_R equ $0C ;Read Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
LVL_R equ $0D ;Read Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
PLP_R equ $0E ;Read Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
DDIR_R equ $0F ;Read Port Direction
;
Timer (write)
addresses
CLR_TMR equ $10 ;Resets 16-bit Timer
TR2CML_W equ $12 ;Write Timer R2 low byte
TR2CMH_W equ $13 ;Write Timer R2 high byte
TR1CML_W equ $14 ;Write Timer R1 low byte
TR1CMH_W equ $15 ;Write Timer R1 high byte
TCNTB_W equ $16 ;Write Timer control register B
TCNTA_W equ $17 ;Write Timer control register A
;
Port setup (write)
addresses
WKED_W equ $1A ;Write MIWU/RB Interrupt edge setup, 1 = falling, 0 =
rising
WKEN_W equ $1B ;Write MIWU/RB Interrupt edge setup, 0 = enabled, 1 =
disabled
ST_W equ $1C ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
LVL_W equ $1D ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
PLP_W equ $1E ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
DDIR_W equ $1F ;Write Port Direction
ELSE
;*********************************************************************************************
; SX28AC Mode addresses
; *On SX28, all registers addressed via mode are write only, with the
exception of
; CMP and WKPND which do an exchange with W.
;*********************************************************************************************
;
Exchange
addresses
CMP equ $08 ;Exchange Comparator enable/status register with W
WKPND equ $09 ;Exchange MIWU/RB Interrupts pending with W
;
Port setup (read)
addresses
WKED_W equ $0A ;Write MIWU/RB Interrupt edge setup, 1 = falling, 0 =
rising
WKEN_W equ $0B ;Write MIWU/RB Interrupt edge setup, 0 = enabled, 1 =
disabled
ST_W equ $0C ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
LVL_W equ $0D ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
PLP_W equ $0E ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
DDIR_W equ $0F ;Write Port Direction
ENDIF
;*********************************************************************************************
;
Program memory ORG defines
;*********************************************************************************************
INTERRUPT_ORG equ $0 ; Interrupt must always start at location zero
RESETENTRY_ORG equ $1FB ; The program will jump here on reset
SUBROUTINES_ORG equ $200 ; The subroutines are in this location
STRINGS_ORG equ $300 ; The strings are in the location $300
PAGE3_ORG equ $400 ; Page 3 is empty
MAINPROGRAM_ORG equ $600 ; The main program is in the lastpage of
program memory
;*********************************************************************************************
org INTERRUPT_ORG······· ; First location in program memory.
;*********************************************************************************************
;*********************************************************************************************
;
Interrupt Service Routine
; Note 1: The interrupt code must always originate at address $0.
; · Interrupt Frequency = (Cycle Frequency / -(retiw value))·
; · For example: With a retiw value of -217 and an oscillator frequency
; · of 50MHz, this code runs every 4.32us.
; Note 2: Mode Register 'M' is not saved in SX 28 but saved in SX 52
when an Interrupt
; · occurs. If the code is to run on a SX 28 and 'M' register is used
in the ISR,
; · then the 'M' register has to be saved at the Start of ISR and
restored at the
; · End of ISR.
;*********************************************************************************************
org···· $0
interrupt ;3
;*********************************************************************************************
; Interrupt
; Interrupt Frequency = (Cycle Frequency / -(retiw value))· For
example:
; With a retiw value of -217 and an oscillator frequency of 50MHz, this
code runs
; every 4.32us.
;*********************************************************************************************
;*********************************************************************************************
;
VP:VP
Multitasker
; Virtual Peripheral Multitasker : up to 16 individual threads, each
running at the
; (interrupt rate/16). Change them below:
;Input variable(s): isrmultiplex: variable used to choose threads
;Output variable(s): None,executes the next thread
;Variable(s) affected: isrmultiplex
;Flag(s) affected: None
;Program Cycles: 9 cycles (turbo mode)
;*********************************************************************************************
··············· _bank········· Multiplexbank······· ;
··············· inc··········· isrMultiplex········ ; toggle interrupt
rate
··············· mov··········· w,isrMultiplex······ ;
;*********************************************************************************************
; The code between the tableStart and tableEnd statements MUST be
completely within the first
; half of a page. The routines it is jumping to must be in the same
page as this table.
;*********************************************************************************************
········ tableStart································ ; Start all tables
with this macro
··············· jmp··········· pc+w················ ;
··············· jmp··········· isrThread1·········· ;
··············· jmp··········· isrThread2·········· ;
··············· jmp··········· isrThread3·········· ;·
··············· jmp··········· isrThread4·········· ;
··············· jmp··········· isrThread1·········· ;
··············· jmp··········· isrThread5·········· ;
··············· jmp··········· isrThread6·········· ;·
··············· jmp··········· isrThread7·········· ;
··············· jmp··········· isrThread1·········· ;
··············· jmp··········· isrThread8·········· ;
··············· jmp··········· isrThread9·········· ;
··············· jmp··········· isrThread10········· ;·
··············· jmp··········· isrThread1·········· ;
··············· jmp··········· isrThread11········· ;
··············· jmp··········· isrThread12········· ;
··············· jmp··········· isrThread13········· ;
········ tableEnd·································· ; End all tables
with this macro.··
;*********************************************************************************************
;VP: VP Multitasker
; ISR TASKS
;*********************************************************************************************
isrThread1········································· ; Serviced at ISR
rate/4
;*********************************************************************************************
; Virtual Peripheral: Universal Asynchronous Receiver Transmitter
(UART) These routines send
; and receive RS232 serial data, and are currently configured (though
modifications can be
; made) for the popular "No parity-checking, 8 data bit, 1 stop bit"
(N,8,1) data format.
;
; The VP below has 2 UARTS implemented - UART1 & UART2. Both the UARTs
can work at independent
; Baud Rates.
;
; RECEIVING: The rs232Rx1flag & rs232Rx2flag are set high whenever a
valid byte of data has
; been received and it is the calling routine's responsibility to reset
this flag once the
; incoming data has been collected.
;
; TRANSMITTING: The transmit routine requires the data to be inverted
and loaded
; (rs232Txhigh+rs232Txlow) register pair (with the inverted 8 data bits
stored in
; rs232Txhigh and rs232Txlow bit 7 set high to act as a start bit).
Then the number of bits
; ready for transmission (10=1 start + 8 data + 1 stop) must be loaded
into the rs232Txcount
; register. As soon as this latter is done, the transmit routine
immediately begins sending
; the data. This routine has a varying execution rate and therefore
should always be
; placed after any timing-critical virtual peripherals such as timers,
; adcs, pwms, etc.
; Note: The transmit and receive routines are independent and either
may be removed for each
; of the UARTs. The initial "_bank rs232TxBank" & "_bank rs232RxBank"
(common)
; instruction is kept for Transmit & Receive routines.
;······ Input variable(s) : rs232Tx1Low (only high bit used),
rs232Tx1High, rs232Tx1Count
; If rs232Tx1Flag SET, then transmit on UART1
; rs232Tx2Low (only high bit used), rs232Tx2High, rs232Tx2Count
; If rs232Tx2Flag SET, then transmit on UART2
;······ Output variable(s) : rs232Rx1Flag, rs232Rx1Byte
; rs232Rx2Flag, rs232Rx2Byte
;······ Variable(s) affected : rs232Tx1Divide, rs232Rx1Divide,
rs232Rx1Count
; rs232Tx2Divide, rs232Rx2Divide, rs232Rx2Count
;······ Flag(s) affected : rs232Tx1Flag, rs232Tx2Flag
; rs232Rx1Flag, rs232Rx1Flag
; Program cycles: 22 worst case for Tx, 23 worst case for Rx
; Variable Length?· Yes.
;*********************************************************************************************
UART1
rs232Transmit
_bank rs232TxBank ;2 switch to serial register bank
sb rs232Tx1FLag ;1
jmp rs232Receive1 ;1
decsz rs232Tx1Divide ;1 only execute the transmit routine
jmp rs232Receive1 ;1
mov w,#UARTDivide1 ;1 load UART1 baud rate (50MHz)
mov rs232Tx1Divide,w ;1·
test··· rs232Tx1Count ;1 are we sending?
snz ;1·
jmp rs232Receive1 ;1
:txbit clc···························· ;1 yes, ready stop bit
rr····· rs232Tx1High ;1· and shift to next bit
rr····· rs232Tx1Low ;1·
dec···· rs232Tx1Count ;1 decrement bit counter
snb rs232Tx1Low.6 ;1 output next bit
clrb rs232TxPin1 ;1·
sb rs232Tx1Low.6 ;1·
setb rs232TxPin1 ;1·
test··· rs232Tx1Count ;1 are we sending?
snz ;1·
clrb rs232Tx1Flag ;1,22
rs232Receive1
_bank rs232RxBank ;2
······· sb rs232RxPin1 ;1 get current rx bit
······· clc ;1·
······· snb rs232RxPin1 ;1·
······· stc ;1·
test··· rs232Rx1Count·········· ;1 currently receiving byte?
sz ;1·
jmp :rxbit················· ;1 if so, jump ahead
mov···· w,#9··················· ;1 in case start, ready 9 bits
mov···· rs232Rx1Count,w ;1 it is, so renew bit count
mov···· w,#UARTStDelay1 ;1 ready 1.5 bit periods (50MHz)
mov···· rs232Rx1Divide,w ;1·
:rxbit········· decsz rs232Rx1Divide ;1 middle of next bit?
········· jmp :rs232RxOut1 ;1
mov w,#UARTDivide1 ;1 yes, ready 1 bit period (50MHz)
mov rs232Rx1Divide,w ;1·
dec···· rs232Rx1Count·········· ;1 last bit?
sz····························· ;1 if not
rr····· rs232Rx1Byte··········· ;1· then save bit
snz···························· ;1 if so,
setb··· rs232Rx1Flag·········· ;1,23· then set flag
:rs232RxOut1
UART2
_bank rs232TxBank ;2 switch to serial register bank
sb rs232Tx2flag ;1
jmp rs232Receive2 ;1
decsz rs232Tx2Divide ;1 only execute the transmit routine
jmp rs232Receive2 ;1
mov w,#UARTDivide2 ;1 load UART2 baud rate (50MHz)
mov rs232Tx2Divide,w ;1·
test··· rs232Tx2Count ;1 are we sending?
snz ;1
jmp rs232Receive2 ;1
:txbit stc···························· ;1 yes, ready stop bit
rr····· rs232Tx2High ;1· and shift to next bit
rr····· rs232Tx2Low ;1·
dec···· rs232Tx2Count ;1 decrement bit counter
snb rs232Tx2Low.6 ;1 output next bit
clrb rs232TxPin2 ;1·
sb rs232Tx2Low.6 ;1·
setb rs232TxPin2 ;1·
test··· rs232Tx2Count ;1 are we sending?
snz ;1·
clrb rs232Tx2Flag ;1,22
rs232Receive2
_bank rs232RxBank ;2
······· sb rs232RxPin2 ;1 get current rx bit
······· clc ;1·
······· snb rs232RxPin2 ;1·
······· stc ;1·
test··· rs232Rx2Count·········· ;1 currently receiving byte?
sz ;1·
jmp :rxbit················· ;1 if so, jump ahead
mov···· w,#9··················· ;1 in case start, ready 9 bits
sc ;1 skip ahead if not start bit
mov···· rs232Rx2Count,w ;1 it is, so renew bit count
mov···· w,#UARTStDelay2 ;1 ready 1.5 bit periods (50MHz)
mov···· rs232Rx2Divide,w ;1·
:rxbit········· decsz rs232Rx2Divide ;1 middle of next bit?
········· jmp :rs232RxOut2 ;1
mov w,#UARTDivide2 ;1 yes, ready 1 bit period (50MHz)
mov rs232Rx2Divide,w ;1·
dec···· rs232Rx2Count·········· ;1 last bit?
sz····························· ;1 if not
rr····· rs232Rx2Byte··········· ;1· then save bit
snz···························· ;1 if so,
setb··· rs232Rx2Flag·········· ;1,23· then set flag
:rs232RxOut2
UARTOut
;*********************************************************************************************
;===================================== PUT YOUR OWN VPs
HERE==================================
; Virtual Peripheral:
;
; Input variable(s):
; Output variable(s):
; Variable(s) affected:
; Flag(s) affected:
;*********************************************************************************************
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread2 ; Serviced at ISR rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread3····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread4····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread5····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread6····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread7····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread8····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread9····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread10···································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread11···································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread12···································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread13···································· ; Serviced at ISR
rate/16
·············································· ; This thread must
reload the isrMultiplex register
·············· _bank Multiplexbank
··············· mov isrMultiplex,#255 ;reload isrMultiplex so
isrThread1 will be run on the
··············································· ; next interrupt.
··············· jmp isrOut·········· ; 7 cycles until mainline program
resumes execution
; This thread must reload the isrMultiplex register
··············································· ; since it is the last
one to run in a rotation.
;
isrOut
;*********************************************************************************
; Set Interrupt Rate
;*********************************************************************************
isr_end
mov w,#intPeriod ;refresh RTCC on return
;(RTCC = 217, no. of instructions executed in the ISR)
retiw ;return from the interrupt
;*****************************************************************************************
; End of the Interrupt Service Routine
;*****************************************************************************************
;*****************************************************************************************
; RESET VECTOR
;*****************************************************************************************
;*****************************************************************************************
;
Reset
Entry
;*****************************************************************************************
org RESETENTRY_ORG
resetEntry ; Program starts here on power-up
·· page _resetEntry
jmp _resetEntry
;*****************************************************************************************
;
UART
Subroutines
;*****************************************************************************************
org SUBROUTINES_ORG
;*****************************************************************************************
; Function : getbyte
; INPUTS : rs232RX1Flag,rs232Rx2Flag
; OUTPUTS : Received byte in rs232Rx1Byte or rs232Rx2Byte
; Get byte via serial port and echo it back to the serial port
;*****************************************************************************************
getbyte
getbyte1
_bank rs232RxBank ; switch to rs232 bank
sb rs232RX1Flag ; check if byte has been received by UART1
jmp getbyte2
clrb··· rs232Rx1Flag ; reset the receive flag
mov···· w,rs232Rx1Byte ; store byte (copy using W)
mov rs232Byte1,w
getbyte2 sb rs232Rx2Flag ; check if byte has been received by UART2
jmp [noparse]:o[/noparse]ut
clrb··· rs232Rx2Flag
mov w,rs232Rx2Byte
mov rs232Byte2,w
[noparse]:o[/noparse]ut retp
;****************************************************************************************
; Function : sendbyte
; INPUTS : rs232Tx1Flag set, rs232Tx1Byte - the byte to be sent via
UART1
; · rs232Tx2Flag set, rs232Tx2Byte- the byte to be sent via UART2
; OUTPUTS : Outputs The byte via RS-232 UART1/UART2
; Send byte via serial port
;
; Note: Before calling a sendbyte in Main, it should be ensured that
respective
; ····· flag of the UART rs232Tx1Flag/rs232Tx2Flag is CLEAR, and if
clear then a
; ····· byte can be sent, then the respective UART flag must be SET.
;****************************************************************************************
sendbyte···
sendbyte1
_bank··· rs232TxBank
test rs232Tx1Count
sz
jmp sendbyte2
sb rs232Tx1Flag
jmp sendbyte2
···· mov w,rs232Tx1Byte
not···· w ; ready bits (inverse logic)
mov···· rs232Tx1High,w········· ; store data byte
setb··· rs232Tx1Low.7·········· ; set up start bit
mov···· w,#10 ; 1 start + 8 data + 1 stop bit
mov···· rs232Tx1Count,w
sendbyte2 test rs232Tx2Count
sz
jmp sendbyte1
sb rs232Tx2Flag
jmp [noparse]:o[/noparse]ut
mov w,rs232Tx2Byte
not w
mov···· rs232Tx2High,w········· ; store data byte
setb··· rs232Tx2Low.7·········· ; set up start bit
mov···· w,#10 ; 1 start + 8 data + 1 stop bit
mov···· rs232Tx2Count,w
[noparse]:o[/noparse]ut retp··························· ; leave and fix page bits
;*********************************************************************************
; Function : sendstring1
; · Care should be taken that the srings are located within program
; · memory locations $300-$3ff as the area
; INPUTS : 'w', The address of a null-terminated string in program
memory
; OUTPUTS : outputs the string via RS-232 UART1
; Send string pointed to by address in W register
; Note: This routine is a locking routine in the sense that the
function returns
; to 'main' (the calling function) only after all the bytes of the
string
; are transmitted (until 00H is encountered).
;*********************************************************************************
sendstring1 _bank rs232TxBank
mov···· localTemp1,w··········· ; store string address
:string test rs232Tx1Count
sz
jmp :string
setb rs232Tx1Flag ; SET flag for UART1
mov w,#STRINGS_ORG>>8 ; with indirect addressing
mov m,w
mov···· w,localTemp1··········· ; read next string character
iread·························· ; using the mode register
test··· w······················ ; are we at the last char?
snz···························· ; if not=0, skip ahead
jmp [noparse]:o[/noparse]ut··················· ; yes, leave & fix page bits
_bank rs232TxBank
mov rs232Tx1Byte,w
call··· sendByte1············· ; not 0, so send character
_bank rs232TxBank
inc···· localTemp1············· ; point to next character
jmp···· :string············ ; loop until done
[noparse]:o[/noparse]ut clrb rs232Tx1Flag
mov w,#$1F ; reset the mode register
mov m,w
retp
;*********************************************************************************
; Function : sendstring2
; · Care should be taken that the srings are located within program
; · memory locations $300-$3ff as the area
; INPUTS : 'w', The address of a null-terminated string in program
memory
; OUTPUTS : outputs the string via RS-232 UART2
; Send string pointed to by address in W register
; Note: This routine is a locking routine in the sense that the
function returns
; to 'main' (the calling function) only after all the bytes of the
string
; are transmitted (until 00H is encountered).
;*********************************************************************************
sendstring2 _bank rs232TxBank
mov···· localTemp1,w·········· ; store string address
:string test rs232Tx2Count
sz
jmp :string
setb rs232Tx2Flag ; SET flag for UART2
mov w,#STRINGS_ORG>>8 ; with indirect addressing
mov m,w
mov···· w,localTemp1··········· ; read next string character
iread·························· ; using the mode register
test··· w······················ ; are we at the last char?
snz···························· ; if not=0, skip ahead
jmp [noparse]:o[/noparse]ut··················· ; yes, leave & fix page bits
_bank rs232TxBank
mov rs232Tx2Byte,w
call··· sendByte2·············· ; not 0, so send character
_bank rs232TxBank
inc···· localTemp1············· ; point to next character
jmp···· :string············ ; loop until done
[noparse]:o[/noparse]ut clrb rs232Tx2Flag
mov w,#$1F ; reset the mode register
mov m,w
retp
;******************************************************************************************
org··· STRINGS_ORG···· ; This label defines where strings are kept in
program space.
;******************************************************************************************
;******************************************************************************************
;
String Data
;******************************************************************************************
;VP: RS232 Transmit
_welcome dw 191, 7, 131, 140, 7, 198, 7, 148, 7, 134, 8, 191, 139, 148,
0
_zero dw 167, 7, 128, 7, 149, 164, 0
_one dw 147, 14, 136, 8, 141, 0
_two dw 8, 191, 162, 0
_three dw 8, 190, 148, 8, 128, 0
_four dw 186, 7, 137, 153, 0
_five dw 186, 157, 166, 0
_six dw 8, 187, 129, 14, 194, 7, 187, 0
_seven dw 8, 187, 7, 131, 166, 131, 141, 0
_eight dw 154, 4, 191, 0
_nine dw 141, 14, 157, 141, 0
_point dw 7, 199, 7, 156, 15, 141, 15, 191, 0
_desee dw 8, 174, 128, 128, 5, 6, 8, 187, 128, 128, 0
_asee dw 8, 154, 1, 6, 8, 187, 26, 2, 128, 128, 0
_volts dw 166, 26, 1, 164, 26, 1, 146, 193, 0
_amps dw 133, 133, 140, 140, 199, 199, 8, 193, 0
_temper dw 191, 7, 131, 140, 7, 0, 198, 7, 148, 7, 134, 8, 191, 139,
148,0
_milli dw 140, 129, 145, 145, 128, 128, 0
_micro dw 140, 140, 157, 196, 196, 7, 148, 136, 8, 137, 0
_kilo dw 194, 7, 128, 14, 146, 137, 0
_mega dw 22, 88, 23, 5,0
_nano dw 14, 141, 7, 131, 0, 141, 141, 164,0
_hertz dw 183, 14, 148, 191, 193, 0
_negative dw 141, 130, 178, 133, 191, 129, 166, 0
_henries dw 184, 131, 131, 141, 141, 148, 148, 128, 15, 193, 0
_celcius dw 187, 130, 145, 187, 7, 128, 7, 134, 187, 0
_farad dw 186, 186, 132, 132, 14, 148, 132, 132, 15, 175, 187, 0
_cap dw 7, 195, 132, 132, 0, 199, 0, 132, 187, 129, 191, 132, 141,
187, 0
org PAGE3_ORG
jmp $
;******************************************************************************************
;
Main Program
; Program execution begins here on power-up or after a reset
;******************************************************************************************
org MAINPROGRAM_ORG
····
_resetEntry
;******************************************************************************************
;
Initialise all port configuration
;******************************************************************************************
_mode ST_W ;point MODE to write ST register
mov···· w,#RB_ST··········· ;Setup RB Schmitt Trigger, 0 = enabled,
1 = disabled
mov !rb,w
mov···· w,#RC_ST··········· ;Setup RC Schmitt Trigger, 0 = enabled,
1 = disabled
mov !rc,w
IFDEF SX48_52
mov···· w,#RD_ST··········· ;Setup RD Schmitt Trigger, 0 = enabled,
1 = disabled
mov !rd,w
mov···· w,#RE_ST··········· ;Setup RE Schmitt Trigger, 0 = enabled,
1 = disabled
mov !re,w
ENDIF
_mode LVL_W ;point MODE to write LVL register
mov···· w,#RA_LVL··········· ;Setup RA CMOS or TTL levels, 1 = TTL,
0 = CMOS
mov !ra,w
mov···· w,#RB_LVL··········· ;Setup RB CMOS or TTL levels, 1 = TTL,
0 = CMOS
mov !rb,w
mov···· w,#RC_LVL··········· ;Setup RC CMOS or TTL levels, 1 = TTL,
0 = CMOS
mov !rc,w
IFDEF SX48_52
mov···· w,#RD_LVL··········· ;Setup RD CMOS or TTL levels, 1 = TTL,
0 = CMOS
mov !rd,w
mov···· w,#RE_LVL··········· ;Setup RE CMOS or TTL levels, 1 = TTL,
0 = CMOS
mov !re,w
ENDIF
_mode PLP_W ;point MODE to write PLP register
mov···· w,#RA_PLP··········· ;Setup RA Weak Pull-up, 0 = enabled, 1
= disabled
mov !ra,w
mov···· w,#RB_PLP··········· ;Setup RB Weak Pull-up, 0 = enabled, 1
= disabled
mov !rb,w
mov···· w,#RC_PLP··········· ;Setup RC Weak Pull-up, 0 = enabled, 1
= disabled
mov !rc,w
IFDEF SX48_52
mov···· w,#RD_PLP··········· ;Setup RD Weak Pull-up, 0 = enabled, 1
= disabled
mov !rd,w
mov···· w,#RE_PLP··········· ;Setup RE Weak Pull-up, 0 = enabled, 1
= disabled
mov !re,w
ENDIF
_mode DDIR_W ;point MODE to write DDIR register
mov w,#RA_DDIR ;Setup RA Direction register, 0 = output, 1 = input
mov !ra,w
mov w,#RB_DDIR ;Setup RB Direction register, 0 = output, 1 = input
mov !rb,w
mov w,#RC_DDIR ;Setup RC Direction register, 0 = output, 1 = input
mov !rc,w
IFDEF SX48_52
mov w,#RD_DDIR ;Setup RD Direction register, 0 = output, 1 = input
mov !rd,w
mov w,#RE_DDIR ;Setup RE Direction register, 0 = output, 1 = input
mov !re,w
ENDIF
mov···· w,#RA_latch········· ;Initialize RA data latch
mov···· ra,w
mov···· w,#RB_latch········ ;Initialize RB data latch
mov···· rb,w
mov···· w,#RC_latch········· ;Initialize RC data latch
mov···· rc,w
IFDEF SX48_52
mov···· w,#RD_latch········ ;Initialize RD data latch
mov···· rd,w
mov···· w,#RE_latch········ ;Initialize RE data latch
mov···· re,w
ENDIF
;*********************************************************************************************************
;
Clear all Data RAM
locations
;**********************************************************************************************************
IFDEF SX48_52·· ;SX48/52 RAM clear routine
mov w,#$0a ;reset all ram starting at $0A
mov fsr,w
:zeroRam clr ind ;clear using indirect addressing
incsz fsr ;repeat until done
jmp :zeroRam
_bank bank0 ;clear bank 0 registers
clr $10
clr $11
clr $12
clr $13
clr $14
clr $15
clr $16
clr $17
clr $18
clr $19
clr $1a
clr $1b
clr $1c
clr $1d
clr $1e
clr $1f
ELSE···· ;SX18/20/28 RAM clear routine
clr fsr ;reset all ram banks
:zeroRam sb fsr.4 ;are we on low half of bank?
setb fsr.3 ; To clear from 08 - Global Registers
clr ind ;clear using indirect addressing
incsz fsr ;repeat until done
jmp :zeroRam
ENDIF
;*********************************************************************************
; Initialize program/VP registers
;*********************************************************************************
_bank rs232TxBank ;select rs232 bank
mov w,#UARTDivide1 ;load rs232Tx1Divide with UART1 baud rate
mov rs232Tx1Divide,w
mov w,#UARTDivide2 ;load rs232Tx1Divide with UART2 baud rate
mov rs232Tx1Divide,w
;*********************************************************************************
; Setup and enable RTCC interrupt, WREG register, RTCC/WDT prescaler
;*********************************************************************************
RTCC_ON = %10000000 ;Enables RTCC at address $01 (RTW hi)
;*WREG at address $01 (RTW lo) by default
RTCC_ID = %01000000 ;Disables RTCC edge interrupt (RTE_IE hi)
;*RTCC edge interrupt (RTE_IE lo) enabled by default
RTCC_INC_EXT = %00100000 ;Sets RTCC increment on RTCC pin transition
(RTS hi)
;*RTCC increment on internal instruction (RTS lo) is default
RTCC_FE = %00010000 ;Sets RTCC to increment on falling edge (RTE_ES
hi)
;*RTCC to increment on rising edge (RTE_ES lo) is default
RTCC_PS_ON = %00000000 ;Assigns prescaler to RTCC (PSA lo)
RTCC_PS_OFF = %00001000 ;Assigns prescaler to WDT (PSA hi)
PS_000 = %00000000 ;RTCC = 1:2, WDT = 1:1
PS_001 = %00000001 ;RTCC = 1:4, WDT = 1:2
PS_010 = %00000010 ;RTCC = 1:8, WDT = 1:4
PS_011 = %00000011 ;RTCC = 1:16, WDT = 1:8
PS_100 = %00000100 ;RTCC = 1:32, WDT = 1:16
PS_101 = %00000101 ;RTCC = 1:64, WDT = 1:32
PS_110 = %00000110 ;RTCC = 1:128, WDT = 1:64
PS_111 = %00000111 ;RTCC = 1:256, WDT = 1:128
OPTIONSETUP equ RTCC_PS_OFF|PS_111 ; the default option setup for this
program.
mov w,#OPTIONSETUP ; setup option register for RTCC interrupts
enabled
mov !option,w ; and prescaler assigned to WDT.
jmp @mainLoop
;*****************************************************************************************
;
MAIN PROGRAM CODE
;*****************************************************************************************
mainLoop
IFDEF TEST1
mov w, #_welcome
setb rs232Tx1Flag
call @sendstring2
jmp mainloop1
mainloop1
call getbyte1 ; Get a Byte
_bank rs232RxBank
cje rs232Byte1,#'D',:desee
cje rs232Byte1,#'A',:asee
cje rs232Byte1,#'-',:negative
cje rs232Byte1,#'1',[noparse]:o[/noparse]ne
cje rs232Byte1,#'2',:two
cje rs232Byte1,#'3',:three
cje rs232Byte1,#'4',:four
cje rs232Byte1,#'5',:five
cje rs232Byte1,#'6',:six
cje rs232Byte1,#'7',:seven
cje rs232Byte1,#'8',:eight
cje rs232Byte1,#'9',:nine
cje rs232Byte1,#'.',[noparse]:p[/noparse]oint
cje rs232Byte1,#'0',:zero
cje rs232Byte1,#'n',:nano
cje rs232Byte1,#'u',:micro
cje rs232Byte1,#'m',:milli
cje rs232Byte1,#'M',:mega
cje rs232Byte1,#'k',:kilo
cje rs232Byte1,#'V',:volts
cje rs232Byte1,#'A',:amps
cje rs232Byte1,#'T',:temper
cje rs232Byte1,#'H',:hertz
cje rs232Byte1,#'C',:compare
cje rs232Byte1,#'F',:farad
:asee
mov w,#_asee
call @sendstring2
:desee
mov w,#_desee
call @sendstring2
:compare
call getbyte1
cje rs232Byte1,#'a',:cap
mov w,#_celcius
call @sendstring2
:cap
mov w,#_cap
call @sendstring2
:temper
mov w,#_temper
call @sendstring2
[noparse]:o[/noparse]ne
mov w,#_one
call @sendstring2
:two
mov w,#_two
call @sendstring2
:three
mov w,#_three
call @sendstring2
:four
mov w,#_four
call @sendstring2
:five
mov w,#_five
call @sendstring2
:six
mov w,#_six
call @sendstring2
:seven
mov w,#_seven
call @sendstring2
:eight
mov w,#_eight
call @sendstring2
:nine
mov w,#_nine
call @sendstring2
:zero
mov w,#_zero
call @sendstring2
[noparse]:p[/noparse]oint
mov w,#_point
call @sendstring2
:kilo
mov w,#_kilo
call @sendstring2
:nano
mov w,#_nano
call @sendstring2
:mega
mov w,#_mega
call @sendstring2
:milli
mov w,#_milli
call @sendstring2
:micro
mov w,#_micro
call @sendstring2
:amps
mov w,#_amps
call @sendstring2
:negative
mov w,#_negative
call @sendstring2
:farad
mov w,#_farad
call @sendstring2
:volts
mov w,#_volts
call @sendstring2
:hertz
mov w,#_hertz
call @sendstring2
:henries
mov w,#_henries
call @sendstring2
clr rs232Byte1
jmp mainloop1
ENDIF
jmp $ ; If program get stuck here, then you have not
; selected TEST1 or TEST2 at the beginning of
; the source code.
;*****************************************************************************************
END ;End of program code
;*****************************************************************************************
Warning 237 - pass 2:· Literal truncated to 8 bits.
My question is:
We need to be able to pass a 16 bit number into a subroutine.· What is the best method for accomplishing this?
Program Code:
SX28AC
TEST1
················································································
SX_Key
; ** Baud Rates for UART 1 **
U1B1200 ;baud rate of 1.2 Kbps
; ** Baud Rates for UART 2· **
U2B9600 ;baud rate of 9.6 kbps
IFDEF SX_Key ;SX-Key Directives
· IFDEF SX28AC ;SX28AC device directives for SX-Key
device SX28,oschs2,turbo,stackx,optionx
· ENDIF
· IFDEF SX48_52 ;SX48/52/BD device directives for SX-Key
device oschs2
· ENDIF
freq 50_000_000
ELSE · ;SASM Directives
·
· IFDEF SX28AC ;SX28AC device directives for SASM
device SX28,oschs2,turbo,stackx,optionx
· ENDIF
·
· IFDEF SX48_52 ;SX48BD or SX52BD device directives for SASM
device SX52,oschs2·
· ENDIF
ENDIF
id '2UART VP' ;
reset resetEntry ; set reset vector
IRC_CAL IRC_FAST
;*********************************************************************************************
;
Macro's
; Macro: _bank
; Sets the bank appropriately for all revisions of SX.
;
; This is required since the bank instruction has only a 3-bit
operand, it cannot be used to
; access all 16 banks of the SX48/52.· FSR.7 (SX48/52bd production
release) needs to be set
; appropriately, depending on the bank address being accessed. This
macro fixes this.
;
; So, instead of using the bank instruction to switch between banks,
use _bank instead.
;*********************************************************************************************
_bank macro 1
· noexpand
bank \1
IFDEF SX48_52
·· IF \1 & %10000000 ;SX48BD and SX52BD (production release) bank
instruction
· expand
setb fsr.7 ;modifies FSR bits 4,5 and 6. FSR.7 needs to be set by
software.
· noexpand
··· ·· ELSE
· expand
clrb fsr.7
· noexpand
········· ENDIF
ENDIF
endm
;*********************************************************************************************
; Macro: _mode
; Sets the MODE register appropriately for all revisions of SX.
;
; This is required since the MODE (or MOV M,#) instruction has only a
4-bit operand.
; The SX28AC use only 4 bits of the MODE register, however the
SX48/52BD have
; the added ability of reading or writing some of the MODE registers,
and therefore use
; 5-bits of the MODE register. The· MOV M,W instruction modifies all
8-bits of the
; MODE register, so this instruction must be used on the SX48/52BD to
make sure the MODE
; register is written with the correct value. This macro fixes this.
;
; So, instead of using the MODE or MOV M,# instructions to load the M
register, use
;· _mode instead.
;*********************************************************************************************
_mode macro 1
· noexpand
IFDEF SX48_52
· expand
mov w,#\1·········· ;loads the M register correctly for the SX48BD
and SX52BD
mov m,w
· noexpand
ELSE
· expand
mov m,#\1··· ;loads the M register correctly for the SX18AC, SX20AC
;and SX28AC
· noexpand
ENDIF
endm
;*********************************************************************************************
······· ; INCP/DECP macros for incrementing/decrementing pointers to
RAM
······· ; used to compensate for incompatibilities between SX28AC and
SX52BD
;*********************************************************************************************
INCP macro 1 ; Increments a pointer to RAM
inc··· \1
IFNDEF SX48_52
setb· \1.4 ; If SX18 or SX28AC,keep bit 4 of the pointer = 1
ENDIF ; to jump from $1f to $30,etc
endm
DECP macro 1 ; Decrements a pointer to RAM
IFDEF SX48_52
dec··· \1
ELSE
clrb·· \1.4 ; If SX18 or SX28AC, forces rollover to next bank
dec··· \1 ; if it rolls over. (skips banks with bit 4 = 0)
setb·· \1.4············ ; Eg: $30 ---> $20 ---> $1f ---> $1f
ENDIF·························· ; AND: $31 ---> $21 ---> $20 ---> $30
endm
;*********************************************************************************************
······· ; Error generating macros
······· ; Used to generate an error message if the label is
intentionally moved into the second page.
······· ; Use for lookup tables.
;*********************************************************************************************
tablestart macro 0 ; Generates an error message if code that MUST be
in
; the first half of a page is moved into the second half
if $ & $100
ERROR····· 'Must be located in the first half of a page.'
endif
endm
tableEnd macro 0 ; Generates an error message if code that MUST be in
; the first half of a page is moved into the second half
if $ & $100
ERROR····· 'Must be located in the first half of a page.'
endif
endm
;*********************************************************************************************
;
Memory Organization
;*********************************************************************************************
;*********************************************************************************************
;
Data Memory address
definitions
; These definitions ensure the proper address is used for banks 0 - 7
for 2K SX devices
; (SX28) and 4K SX devices (SX48/52).
;*********************************************************************************************
IFDEF SX48_52
global_org = $0A
bank0_org = $00
bank1_org = $10
bank2_org = $20
bank3_org = $30
bank4_org = $40
bank5_org = $50
bank6_org = $60
bank7_org = $70
ELSE
global_org = $08
bank0_org = $10
bank1_org = $30
bank2_org = $50
bank3_org = $70
bank4_org = $90
bank5_org = $B0
bank6_org = $D0
bank7_org = $F0
ENDIF
;*********************************************************************************************
;
Global Register
definitions
; NOTE: Global data memory starts at $0A on SX48/52 and $08 on
SX18/20/28.
;*********************************************************************************************
org···· global_org
flags0 equ global_org + 0 ; stores bit-wise operators like flags
; and function-enabling bits (semaphores)
;
VP: RS232
Receive
rs232Tx1Flag equ flags0.0 ;indicates that UART1 is transmitting if set
or not transmitting if reset
rs232Tx2Flag equ flags0.1 ;indicates that UART2 is transmitting if set
or not transmitting if reset
rs232Rx1Flag equ flags0.2 ;indicates that UART1 has received a byte if
set
rs232Rx2Flag equ flags0.3 ;indicates that UART2 has received a byte if
set
isrTemp0 equ global_org + 1 ; Interrupt Service Routine's temp
register.·
; Don't use this register in the mainline.
localTemp0 equ global_org + 2 ; temporary storage register
; Used by first level of nesting
; Never guaranteed to maintain data
localTemp1 equ global_org + 3 ; temporary storage register
; Used by second level of nesting
; or when a routine needs more than one
; temporary global register.
localTemp2 equ global_org + 4 ; temporary storage register
; Used by third level of nesting or by
; main loop routines that need a loop
; counter, etc.
;*********************************************************************************************
;
RAM Bank Register
definitions
;*********************************************************************************************
;*********************************************************************************
; Bank 0
;*********************************************************************************
org···· bank0_org
bank0 = $
;*********************************************************************************
; Bank 1
;*********************************************************************************
org···· bank1_org
bank1 = $
rs232TxBank =······ $ ;UART Transmit bank
rs232Tx1High ds····· 1 ;High Byte to be· transmitted
rs232Tx1Low ds····· 1 ;Low· Byte to be transmitted
rs232Tx1Count ds····· 1 ;counter to keep track of the bits sent
rs232Tx1Divide ds····· 1 ;xmit timing counter
rs232Tx1Byte ds 1 ;store the byte to be sent in this buffer
rs232Tx2High ds····· 1 ;High Byte to be· transmitted
rs232Tx2Low ds····· 1 ;Low· Byte to be transmitted
rs232Tx2Count ds····· 1 ;counter to keep track of the bits sent
rs232Tx2Divide ds····· 1 ;xmit timing counter
rs232Tx2Byte ds 1 ;store the byte to be sent in this buffer
MultiplexBank = $ ;Multipler Bank
isrMultiplex · ds····· 1· ;Used to jump between the ISR Threads when
; an Interrupt occurs
;*********************************************************************************
; Bank 2
;*********************************************************************************
org···· bank2_org
bank2 = $
rs232RxBank = $
rs232Rx1Count ds····· 1 ;counter to keep track of the number of bits
received
rs232Rx1Divide ds····· 1 ;receive timing counter
rs232Rx1Byte ds····· 1 ;buffer for incoming byte
rs232Byte1 ds 1 ;Used by serial routines
rs232Rx2Count ds····· 1 ;counter to keep track of the number of bits
received
rs232Rx2Divide ds····· 1 ;receive timing counter
rs232Rx2Byte ds····· 1 ;buffer for incoming byte
rs232Byte2 ds 1 ;used by serial routines
;*********************************************************************************
; Bank 3
;*********************************************************************************
org···· bank3_org
bank3 = $
;*********************************************************************************
; Bank 4
;*********************************************************************************
org···· bank4_org
bank4 = $
;*********************************************************************************
; Bank 5
;*********************************************************************************
org···· bank5_org
bank5 = $
;*********************************************************************************
; Bank 6
;*********************************************************************************
org···· bank6_org
bank6 = $
;*********************************************************************************
; Bank 7
;*********************************************************************************
org···· bank7_org
bank7 = $
IFDEF SX48_52
;*********************************************************************************
; Bank 8
;*********************************************************************************
org $80 ;bank 8 address on SX52
bank8 = $
;*********************************************************************************
; Bank 9
;*********************************************************************************
org $90 ;bank 9 address on SX52
bank9 = $
;*********************************************************************************
; Bank A
;*********************************************************************************
org $A0 ;bank A address on SX52
bankA = $
;*********************************************************************************
; Bank B
;*********************************************************************************
org $B0 ;bank B address on SX52
bankB = $
;*********************************************************************************
; Bank C
;*********************************************************************************
org $C0 ;bank C address on SX52
bankC = $
;*********************************************************************************
; Bank D
;*********************************************************************************
org $D0 ;bank D address on SX52
bankD = $
;*********************************************************************************
; Bank E
;*********************************************************************************
org $E0 ;bank E address on SX52
bankE = $
;*********************************************************************************
; Bank F
;*********************************************************************************
org $F0 ;bank F address on SX52
bankF = $
ENDIF
;*****************************************************************************************
;
Port Assignment
;*****************************************************************************************
RA_latch equ %00000000 ;SX28/48/52 port A latch init ;intial value
after reset
RA_DDIR equ %11111111 ;SX28/48/52 port A DDIR value ;0=Output,1=Input
RA_LVL equ %00000000 ;SX28/48/52 port A LVL value ;0=CMOS,1=TTL
RA_PLP equ %00000000 ;SX28/48/52 port A PLP value ;0=Enable,1=Disable
RB_latch equ %10001000 ;SX28/48/52 port B latch init ;intial value
after reset
RB_DDIR equ %01110111 ;SX28/48/52 port B DDIR value ;0=Output,1=Input
RB_ST equ %11111111 ;SX28/48/52 port B ST value ;0=Enable,1=Disable
RB_LVL equ %00000000 ;SX28/48/52 port B LVL value ;0=CMOS,1=TTL
RB_PLP equ %11001100 ;SX28/48/52 port B PLP value ;0=Enable,1=Disable
RC_latch equ %00000000 ;SX28/48/52 port C latch init ;intial value
after reset
RC_DDIR equ %11111111 ;SX28/48/52 port C DDIR value ;0=Output,1=Input
RC_ST equ %11111111 ;SX28/48/52 port C ST value ;0=Enable,1=Disable
RC_LVL equ %00000000 ;SX28/48/52 port C LVL value ;0=CMOS,1=TTL
RC_PLP equ %00000000 ;SX28/48/52 port C PLP value ;0=Enable,1=Disable
IFDEF SX48_52
RD_latch equ %00000000 ;SX48/52 port D latch init ;intial value after
reset
RD_DDIR equ %11111111 ;SX48/52 port D DDIR value ;0=Output,1=Input
RD_ST equ %11111111 ;SX48/52 port D ST value ;0=Enable,1=Disable
RD_LVL equ %00000000 ;SX48/52 port D LVL value ;0=CMOS,1=TTL
RD_PLP equ %00000000 ;SX48/52 port D PLP value ;0=Enable,1=Disable
RE_latch equ %00000000 ;SX48/52 port E latch init ;intial value after
reset
RE_DDIR equ %11111111 ;SX48/52 port E DDIR value ;0=Output,1=Input
RE_ST equ %11111111 ;SX48/52 port E ST value ;0=Enable,1=Disable
RE_LVL equ %00000000 ;SX48/52 port E LVL value ;0=CMOS,1=TTL
RE_PLP equ %00000000 ;SX48/52 port E PLP value ;0=Enable,1=Disable
ENDIF
;*********************************************************************************************
;
Pin Definitions
;*********************************************************************************************
rs232Rxpin1····· equ···· rb.6 ;UART1 receive input
rs232Txpin1····· equ···· rb.7 ;UART1 transmit output
rs232Rxpin2····· equ···· rb.2 ;UART2 receive input
rs232Txpin2····· equ···· rb.3 ;UART2 transmit output
;*********************************************************************************************
;
Program constants
;*********************************************************************************************
;*********************************************************************************************
; UART Constants values
;*********************************************************************************************
intPeriod = 217
UARTfs = 230400
Num = 4 ; Number of times ISR thread1 is called in the
; ISRMultiplexer
IFDEF· U1B1200
UARTBaud1 = 1200
ENDIF
IFDEF· U1B2400
UARTBaud1 = 2400
ENDIF
IFDEF· U1B4800
UARTBaud1 = 4800
ENDIF
IFDEF· U1B9600
UARTBaud1 = 9600
ENDIF
IFDEF· U1B1920
UARTBaud1 = 19200
ENDIF
IFDEF· U1B5760
UARTBaud1 = 57600
ENDIF
UARTDivide1 = (UARTfs/(UARTBaud1*Num)) ;48
UARTStDelay1 = UARTDivide1 +(UARTDivide1/2)+1
IFDEF· U2B1200
UARTBaud2 = 1200
ENDIF
IFDEF· U2B2400
UARTBaud2 = 2400
ENDIF
IFDEF· U2B4800
UARTBaud2 = 4800
ENDIF
IFDEF· U2B9600
UARTBaud2 = 9600
ENDIF
IFDEF· U2B1920
UARTBaud2 = 19200
ENDIF
IFDEF· U2B5760
UARTBaud2 = 57600
ENDIF
UARTDivide2 = (UARTfs/(UARTBaud2*Num)) ;6
UARTStDelay2 = UARTDivide2 +(UARTDivide2/2)+1
IFDEF SX48_52
;*********************************************************************************************
; SX48BD/52BD Mode addresses
; *On SX48BD/52BD, most registers addressed via mode are read and
write, with the
; exception of CMP and WKPND which do an exchange with W.
;*********************************************************************************************
;
Timer (read) addresses
TCPL_R equ $00 ;Read Timer Capture register low byte
TCPH_R equ $01 ;Read Timer Capture register high byte
TR2CML_R equ $02 ;Read Timer R2 low byte
TR2CMH_R equ $03 ;Read Timer R2 high byte
TR1CML_R equ $04 ;Read Timer R1 low byte
TR1CMH_R equ $05 ;Read Timer R1 high byte
TCNTB_R equ $06 ;Read Timer control register B
TCNTA_R equ $07 ;Read Timer control register A
;
Exchange addresses
CMP equ $08 ;Exchange Comparator enable/status register with W
WKPND equ $09 ;Exchange MIWU/RB Interrupts pending with W
;
Port setup (read)
addresses
WKED_R equ $0A ;Read MIWU/RB Interrupt edge setup, 1 = falling, 0 =
rising
WKEN_R equ $0B ;Read MIWU/RB Interrupt edge setup, 0 = enabled, 1 =
disabled
ST_R equ $0C ;Read Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
LVL_R equ $0D ;Read Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
PLP_R equ $0E ;Read Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
DDIR_R equ $0F ;Read Port Direction
;
Timer (write)
addresses
CLR_TMR equ $10 ;Resets 16-bit Timer
TR2CML_W equ $12 ;Write Timer R2 low byte
TR2CMH_W equ $13 ;Write Timer R2 high byte
TR1CML_W equ $14 ;Write Timer R1 low byte
TR1CMH_W equ $15 ;Write Timer R1 high byte
TCNTB_W equ $16 ;Write Timer control register B
TCNTA_W equ $17 ;Write Timer control register A
;
Port setup (write)
addresses
WKED_W equ $1A ;Write MIWU/RB Interrupt edge setup, 1 = falling, 0 =
rising
WKEN_W equ $1B ;Write MIWU/RB Interrupt edge setup, 0 = enabled, 1 =
disabled
ST_W equ $1C ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
LVL_W equ $1D ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
PLP_W equ $1E ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
DDIR_W equ $1F ;Write Port Direction
ELSE
;*********************************************************************************************
; SX28AC Mode addresses
; *On SX28, all registers addressed via mode are write only, with the
exception of
; CMP and WKPND which do an exchange with W.
;*********************************************************************************************
;
Exchange
addresses
CMP equ $08 ;Exchange Comparator enable/status register with W
WKPND equ $09 ;Exchange MIWU/RB Interrupts pending with W
;
Port setup (read)
addresses
WKED_W equ $0A ;Write MIWU/RB Interrupt edge setup, 1 = falling, 0 =
rising
WKEN_W equ $0B ;Write MIWU/RB Interrupt edge setup, 0 = enabled, 1 =
disabled
ST_W equ $0C ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
LVL_W equ $0D ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
PLP_W equ $0E ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
DDIR_W equ $0F ;Write Port Direction
ENDIF
;*********************************************************************************************
;
Program memory ORG defines
;*********************************************************************************************
INTERRUPT_ORG equ $0 ; Interrupt must always start at location zero
RESETENTRY_ORG equ $1FB ; The program will jump here on reset
SUBROUTINES_ORG equ $200 ; The subroutines are in this location
STRINGS_ORG equ $300 ; The strings are in the location $300
PAGE3_ORG equ $400 ; Page 3 is empty
MAINPROGRAM_ORG equ $600 ; The main program is in the lastpage of
program memory
;*********************************************************************************************
org INTERRUPT_ORG······· ; First location in program memory.
;*********************************************************************************************
;*********************************************************************************************
;
Interrupt Service Routine
; Note 1: The interrupt code must always originate at address $0.
; · Interrupt Frequency = (Cycle Frequency / -(retiw value))·
; · For example: With a retiw value of -217 and an oscillator frequency
; · of 50MHz, this code runs every 4.32us.
; Note 2: Mode Register 'M' is not saved in SX 28 but saved in SX 52
when an Interrupt
; · occurs. If the code is to run on a SX 28 and 'M' register is used
in the ISR,
; · then the 'M' register has to be saved at the Start of ISR and
restored at the
; · End of ISR.
;*********************************************************************************************
org···· $0
interrupt ;3
;*********************************************************************************************
; Interrupt
; Interrupt Frequency = (Cycle Frequency / -(retiw value))· For
example:
; With a retiw value of -217 and an oscillator frequency of 50MHz, this
code runs
; every 4.32us.
;*********************************************************************************************
;*********************************************************************************************
;
VP:VP
Multitasker
; Virtual Peripheral Multitasker : up to 16 individual threads, each
running at the
; (interrupt rate/16). Change them below:
;Input variable(s): isrmultiplex: variable used to choose threads
;Output variable(s): None,executes the next thread
;Variable(s) affected: isrmultiplex
;Flag(s) affected: None
;Program Cycles: 9 cycles (turbo mode)
;*********************************************************************************************
··············· _bank········· Multiplexbank······· ;
··············· inc··········· isrMultiplex········ ; toggle interrupt
rate
··············· mov··········· w,isrMultiplex······ ;
;*********************************************************************************************
; The code between the tableStart and tableEnd statements MUST be
completely within the first
; half of a page. The routines it is jumping to must be in the same
page as this table.
;*********************************************************************************************
········ tableStart································ ; Start all tables
with this macro
··············· jmp··········· pc+w················ ;
··············· jmp··········· isrThread1·········· ;
··············· jmp··········· isrThread2·········· ;
··············· jmp··········· isrThread3·········· ;·
··············· jmp··········· isrThread4·········· ;
··············· jmp··········· isrThread1·········· ;
··············· jmp··········· isrThread5·········· ;
··············· jmp··········· isrThread6·········· ;·
··············· jmp··········· isrThread7·········· ;
··············· jmp··········· isrThread1·········· ;
··············· jmp··········· isrThread8·········· ;
··············· jmp··········· isrThread9·········· ;
··············· jmp··········· isrThread10········· ;·
··············· jmp··········· isrThread1·········· ;
··············· jmp··········· isrThread11········· ;
··············· jmp··········· isrThread12········· ;
··············· jmp··········· isrThread13········· ;
········ tableEnd·································· ; End all tables
with this macro.··
;*********************************************************************************************
;VP: VP Multitasker
; ISR TASKS
;*********************************************************************************************
isrThread1········································· ; Serviced at ISR
rate/4
;*********************************************************************************************
; Virtual Peripheral: Universal Asynchronous Receiver Transmitter
(UART) These routines send
; and receive RS232 serial data, and are currently configured (though
modifications can be
; made) for the popular "No parity-checking, 8 data bit, 1 stop bit"
(N,8,1) data format.
;
; The VP below has 2 UARTS implemented - UART1 & UART2. Both the UARTs
can work at independent
; Baud Rates.
;
; RECEIVING: The rs232Rx1flag & rs232Rx2flag are set high whenever a
valid byte of data has
; been received and it is the calling routine's responsibility to reset
this flag once the
; incoming data has been collected.
;
; TRANSMITTING: The transmit routine requires the data to be inverted
and loaded
; (rs232Txhigh+rs232Txlow) register pair (with the inverted 8 data bits
stored in
; rs232Txhigh and rs232Txlow bit 7 set high to act as a start bit).
Then the number of bits
; ready for transmission (10=1 start + 8 data + 1 stop) must be loaded
into the rs232Txcount
; register. As soon as this latter is done, the transmit routine
immediately begins sending
; the data. This routine has a varying execution rate and therefore
should always be
; placed after any timing-critical virtual peripherals such as timers,
; adcs, pwms, etc.
; Note: The transmit and receive routines are independent and either
may be removed for each
; of the UARTs. The initial "_bank rs232TxBank" & "_bank rs232RxBank"
(common)
; instruction is kept for Transmit & Receive routines.
;······ Input variable(s) : rs232Tx1Low (only high bit used),
rs232Tx1High, rs232Tx1Count
; If rs232Tx1Flag SET, then transmit on UART1
; rs232Tx2Low (only high bit used), rs232Tx2High, rs232Tx2Count
; If rs232Tx2Flag SET, then transmit on UART2
;······ Output variable(s) : rs232Rx1Flag, rs232Rx1Byte
; rs232Rx2Flag, rs232Rx2Byte
;······ Variable(s) affected : rs232Tx1Divide, rs232Rx1Divide,
rs232Rx1Count
; rs232Tx2Divide, rs232Rx2Divide, rs232Rx2Count
;······ Flag(s) affected : rs232Tx1Flag, rs232Tx2Flag
; rs232Rx1Flag, rs232Rx1Flag
; Program cycles: 22 worst case for Tx, 23 worst case for Rx
; Variable Length?· Yes.
;*********************************************************************************************
UART1
rs232Transmit
_bank rs232TxBank ;2 switch to serial register bank
sb rs232Tx1FLag ;1
jmp rs232Receive1 ;1
decsz rs232Tx1Divide ;1 only execute the transmit routine
jmp rs232Receive1 ;1
mov w,#UARTDivide1 ;1 load UART1 baud rate (50MHz)
mov rs232Tx1Divide,w ;1·
test··· rs232Tx1Count ;1 are we sending?
snz ;1·
jmp rs232Receive1 ;1
:txbit clc···························· ;1 yes, ready stop bit
rr····· rs232Tx1High ;1· and shift to next bit
rr····· rs232Tx1Low ;1·
dec···· rs232Tx1Count ;1 decrement bit counter
snb rs232Tx1Low.6 ;1 output next bit
clrb rs232TxPin1 ;1·
sb rs232Tx1Low.6 ;1·
setb rs232TxPin1 ;1·
test··· rs232Tx1Count ;1 are we sending?
snz ;1·
clrb rs232Tx1Flag ;1,22
rs232Receive1
_bank rs232RxBank ;2
······· sb rs232RxPin1 ;1 get current rx bit
······· clc ;1·
······· snb rs232RxPin1 ;1·
······· stc ;1·
test··· rs232Rx1Count·········· ;1 currently receiving byte?
sz ;1·
jmp :rxbit················· ;1 if so, jump ahead
mov···· w,#9··················· ;1 in case start, ready 9 bits
mov···· rs232Rx1Count,w ;1 it is, so renew bit count
mov···· w,#UARTStDelay1 ;1 ready 1.5 bit periods (50MHz)
mov···· rs232Rx1Divide,w ;1·
:rxbit········· decsz rs232Rx1Divide ;1 middle of next bit?
········· jmp :rs232RxOut1 ;1
mov w,#UARTDivide1 ;1 yes, ready 1 bit period (50MHz)
mov rs232Rx1Divide,w ;1·
dec···· rs232Rx1Count·········· ;1 last bit?
sz····························· ;1 if not
rr····· rs232Rx1Byte··········· ;1· then save bit
snz···························· ;1 if so,
setb··· rs232Rx1Flag·········· ;1,23· then set flag
:rs232RxOut1
UART2
_bank rs232TxBank ;2 switch to serial register bank
sb rs232Tx2flag ;1
jmp rs232Receive2 ;1
decsz rs232Tx2Divide ;1 only execute the transmit routine
jmp rs232Receive2 ;1
mov w,#UARTDivide2 ;1 load UART2 baud rate (50MHz)
mov rs232Tx2Divide,w ;1·
test··· rs232Tx2Count ;1 are we sending?
snz ;1
jmp rs232Receive2 ;1
:txbit stc···························· ;1 yes, ready stop bit
rr····· rs232Tx2High ;1· and shift to next bit
rr····· rs232Tx2Low ;1·
dec···· rs232Tx2Count ;1 decrement bit counter
snb rs232Tx2Low.6 ;1 output next bit
clrb rs232TxPin2 ;1·
sb rs232Tx2Low.6 ;1·
setb rs232TxPin2 ;1·
test··· rs232Tx2Count ;1 are we sending?
snz ;1·
clrb rs232Tx2Flag ;1,22
rs232Receive2
_bank rs232RxBank ;2
······· sb rs232RxPin2 ;1 get current rx bit
······· clc ;1·
······· snb rs232RxPin2 ;1·
······· stc ;1·
test··· rs232Rx2Count·········· ;1 currently receiving byte?
sz ;1·
jmp :rxbit················· ;1 if so, jump ahead
mov···· w,#9··················· ;1 in case start, ready 9 bits
sc ;1 skip ahead if not start bit
mov···· rs232Rx2Count,w ;1 it is, so renew bit count
mov···· w,#UARTStDelay2 ;1 ready 1.5 bit periods (50MHz)
mov···· rs232Rx2Divide,w ;1·
:rxbit········· decsz rs232Rx2Divide ;1 middle of next bit?
········· jmp :rs232RxOut2 ;1
mov w,#UARTDivide2 ;1 yes, ready 1 bit period (50MHz)
mov rs232Rx2Divide,w ;1·
dec···· rs232Rx2Count·········· ;1 last bit?
sz····························· ;1 if not
rr····· rs232Rx2Byte··········· ;1· then save bit
snz···························· ;1 if so,
setb··· rs232Rx2Flag·········· ;1,23· then set flag
:rs232RxOut2
UARTOut
;*********************************************************************************************
;===================================== PUT YOUR OWN VPs
HERE==================================
; Virtual Peripheral:
;
; Input variable(s):
; Output variable(s):
; Variable(s) affected:
; Flag(s) affected:
;*********************************************************************************************
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread2 ; Serviced at ISR rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread3····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread4····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread5····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread6····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread7····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread8····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread9····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread10···································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread11···································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread12···································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread13···································· ; Serviced at ISR
rate/16
·············································· ; This thread must
reload the isrMultiplex register
·············· _bank Multiplexbank
··············· mov isrMultiplex,#255 ;reload isrMultiplex so
isrThread1 will be run on the
··············································· ; next interrupt.
··············· jmp isrOut·········· ; 7 cycles until mainline program
resumes execution
; This thread must reload the isrMultiplex register
··············································· ; since it is the last
one to run in a rotation.
;
isrOut
;*********************************************************************************
; Set Interrupt Rate
;*********************************************************************************
isr_end
mov w,#intPeriod ;refresh RTCC on return
;(RTCC = 217, no. of instructions executed in the ISR)
retiw ;return from the interrupt
;*****************************************************************************************
; End of the Interrupt Service Routine
;*****************************************************************************************
;*****************************************************************************************
; RESET VECTOR
;*****************************************************************************************
;*****************************************************************************************
;
Reset
Entry
;*****************************************************************************************
org RESETENTRY_ORG
resetEntry ; Program starts here on power-up
·· page _resetEntry
jmp _resetEntry
;*****************************************************************************************
;
UART
Subroutines
;*****************************************************************************************
org SUBROUTINES_ORG
;*****************************************************************************************
; Function : getbyte
; INPUTS : rs232RX1Flag,rs232Rx2Flag
; OUTPUTS : Received byte in rs232Rx1Byte or rs232Rx2Byte
; Get byte via serial port and echo it back to the serial port
;*****************************************************************************************
getbyte
getbyte1
_bank rs232RxBank ; switch to rs232 bank
sb rs232RX1Flag ; check if byte has been received by UART1
jmp getbyte2
clrb··· rs232Rx1Flag ; reset the receive flag
mov···· w,rs232Rx1Byte ; store byte (copy using W)
mov rs232Byte1,w
getbyte2 sb rs232Rx2Flag ; check if byte has been received by UART2
jmp [noparse]:o[/noparse]ut
clrb··· rs232Rx2Flag
mov w,rs232Rx2Byte
mov rs232Byte2,w
[noparse]:o[/noparse]ut retp
;****************************************************************************************
; Function : sendbyte
; INPUTS : rs232Tx1Flag set, rs232Tx1Byte - the byte to be sent via
UART1
; · rs232Tx2Flag set, rs232Tx2Byte- the byte to be sent via UART2
; OUTPUTS : Outputs The byte via RS-232 UART1/UART2
; Send byte via serial port
;
; Note: Before calling a sendbyte in Main, it should be ensured that
respective
; ····· flag of the UART rs232Tx1Flag/rs232Tx2Flag is CLEAR, and if
clear then a
; ····· byte can be sent, then the respective UART flag must be SET.
;****************************************************************************************
sendbyte···
sendbyte1
_bank··· rs232TxBank
test rs232Tx1Count
sz
jmp sendbyte2
sb rs232Tx1Flag
jmp sendbyte2
···· mov w,rs232Tx1Byte
not···· w ; ready bits (inverse logic)
mov···· rs232Tx1High,w········· ; store data byte
setb··· rs232Tx1Low.7·········· ; set up start bit
mov···· w,#10 ; 1 start + 8 data + 1 stop bit
mov···· rs232Tx1Count,w
sendbyte2 test rs232Tx2Count
sz
jmp sendbyte1
sb rs232Tx2Flag
jmp [noparse]:o[/noparse]ut
mov w,rs232Tx2Byte
not w
mov···· rs232Tx2High,w········· ; store data byte
setb··· rs232Tx2Low.7·········· ; set up start bit
mov···· w,#10 ; 1 start + 8 data + 1 stop bit
mov···· rs232Tx2Count,w
[noparse]:o[/noparse]ut retp··························· ; leave and fix page bits
;*********************************************************************************
; Function : sendstring1
; · Care should be taken that the srings are located within program
; · memory locations $300-$3ff as the area
; INPUTS : 'w', The address of a null-terminated string in program
memory
; OUTPUTS : outputs the string via RS-232 UART1
; Send string pointed to by address in W register
; Note: This routine is a locking routine in the sense that the
function returns
; to 'main' (the calling function) only after all the bytes of the
string
; are transmitted (until 00H is encountered).
;*********************************************************************************
sendstring1 _bank rs232TxBank
mov···· localTemp1,w··········· ; store string address
:string test rs232Tx1Count
sz
jmp :string
setb rs232Tx1Flag ; SET flag for UART1
mov w,#STRINGS_ORG>>8 ; with indirect addressing
mov m,w
mov···· w,localTemp1··········· ; read next string character
iread·························· ; using the mode register
test··· w······················ ; are we at the last char?
snz···························· ; if not=0, skip ahead
jmp [noparse]:o[/noparse]ut··················· ; yes, leave & fix page bits
_bank rs232TxBank
mov rs232Tx1Byte,w
call··· sendByte1············· ; not 0, so send character
_bank rs232TxBank
inc···· localTemp1············· ; point to next character
jmp···· :string············ ; loop until done
[noparse]:o[/noparse]ut clrb rs232Tx1Flag
mov w,#$1F ; reset the mode register
mov m,w
retp
;*********************************************************************************
; Function : sendstring2
; · Care should be taken that the srings are located within program
; · memory locations $300-$3ff as the area
; INPUTS : 'w', The address of a null-terminated string in program
memory
; OUTPUTS : outputs the string via RS-232 UART2
; Send string pointed to by address in W register
; Note: This routine is a locking routine in the sense that the
function returns
; to 'main' (the calling function) only after all the bytes of the
string
; are transmitted (until 00H is encountered).
;*********************************************************************************
sendstring2 _bank rs232TxBank
mov···· localTemp1,w·········· ; store string address
:string test rs232Tx2Count
sz
jmp :string
setb rs232Tx2Flag ; SET flag for UART2
mov w,#STRINGS_ORG>>8 ; with indirect addressing
mov m,w
mov···· w,localTemp1··········· ; read next string character
iread·························· ; using the mode register
test··· w······················ ; are we at the last char?
snz···························· ; if not=0, skip ahead
jmp [noparse]:o[/noparse]ut··················· ; yes, leave & fix page bits
_bank rs232TxBank
mov rs232Tx2Byte,w
call··· sendByte2·············· ; not 0, so send character
_bank rs232TxBank
inc···· localTemp1············· ; point to next character
jmp···· :string············ ; loop until done
[noparse]:o[/noparse]ut clrb rs232Tx2Flag
mov w,#$1F ; reset the mode register
mov m,w
retp
;******************************************************************************************
org··· STRINGS_ORG···· ; This label defines where strings are kept in
program space.
;******************************************************************************************
;******************************************************************************************
;
String Data
;******************************************************************************************
;VP: RS232 Transmit
_welcome dw 191, 7, 131, 140, 7, 198, 7, 148, 7, 134, 8, 191, 139, 148,
0
_zero dw 167, 7, 128, 7, 149, 164, 0
_one dw 147, 14, 136, 8, 141, 0
_two dw 8, 191, 162, 0
_three dw 8, 190, 148, 8, 128, 0
_four dw 186, 7, 137, 153, 0
_five dw 186, 157, 166, 0
_six dw 8, 187, 129, 14, 194, 7, 187, 0
_seven dw 8, 187, 7, 131, 166, 131, 141, 0
_eight dw 154, 4, 191, 0
_nine dw 141, 14, 157, 141, 0
_point dw 7, 199, 7, 156, 15, 141, 15, 191, 0
_desee dw 8, 174, 128, 128, 5, 6, 8, 187, 128, 128, 0
_asee dw 8, 154, 1, 6, 8, 187, 26, 2, 128, 128, 0
_volts dw 166, 26, 1, 164, 26, 1, 146, 193, 0
_amps dw 133, 133, 140, 140, 199, 199, 8, 193, 0
_temper dw 191, 7, 131, 140, 7, 0, 198, 7, 148, 7, 134, 8, 191, 139,
148,0
_milli dw 140, 129, 145, 145, 128, 128, 0
_micro dw 140, 140, 157, 196, 196, 7, 148, 136, 8, 137, 0
_kilo dw 194, 7, 128, 14, 146, 137, 0
_mega dw 22, 88, 23, 5,0
_nano dw 14, 141, 7, 131, 0, 141, 141, 164,0
_hertz dw 183, 14, 148, 191, 193, 0
_negative dw 141, 130, 178, 133, 191, 129, 166, 0
_henries dw 184, 131, 131, 141, 141, 148, 148, 128, 15, 193, 0
_celcius dw 187, 130, 145, 187, 7, 128, 7, 134, 187, 0
_farad dw 186, 186, 132, 132, 14, 148, 132, 132, 15, 175, 187, 0
_cap dw 7, 195, 132, 132, 0, 199, 0, 132, 187, 129, 191, 132, 141,
187, 0
org PAGE3_ORG
jmp $
;******************************************************************************************
;
Main Program
; Program execution begins here on power-up or after a reset
;******************************************************************************************
org MAINPROGRAM_ORG
····
_resetEntry
;******************************************************************************************
;
Initialise all port configuration
;******************************************************************************************
_mode ST_W ;point MODE to write ST register
mov···· w,#RB_ST··········· ;Setup RB Schmitt Trigger, 0 = enabled,
1 = disabled
mov !rb,w
mov···· w,#RC_ST··········· ;Setup RC Schmitt Trigger, 0 = enabled,
1 = disabled
mov !rc,w
IFDEF SX48_52
mov···· w,#RD_ST··········· ;Setup RD Schmitt Trigger, 0 = enabled,
1 = disabled
mov !rd,w
mov···· w,#RE_ST··········· ;Setup RE Schmitt Trigger, 0 = enabled,
1 = disabled
mov !re,w
ENDIF
_mode LVL_W ;point MODE to write LVL register
mov···· w,#RA_LVL··········· ;Setup RA CMOS or TTL levels, 1 = TTL,
0 = CMOS
mov !ra,w
mov···· w,#RB_LVL··········· ;Setup RB CMOS or TTL levels, 1 = TTL,
0 = CMOS
mov !rb,w
mov···· w,#RC_LVL··········· ;Setup RC CMOS or TTL levels, 1 = TTL,
0 = CMOS
mov !rc,w
IFDEF SX48_52
mov···· w,#RD_LVL··········· ;Setup RD CMOS or TTL levels, 1 = TTL,
0 = CMOS
mov !rd,w
mov···· w,#RE_LVL··········· ;Setup RE CMOS or TTL levels, 1 = TTL,
0 = CMOS
mov !re,w
ENDIF
_mode PLP_W ;point MODE to write PLP register
mov···· w,#RA_PLP··········· ;Setup RA Weak Pull-up, 0 = enabled, 1
= disabled
mov !ra,w
mov···· w,#RB_PLP··········· ;Setup RB Weak Pull-up, 0 = enabled, 1
= disabled
mov !rb,w
mov···· w,#RC_PLP··········· ;Setup RC Weak Pull-up, 0 = enabled, 1
= disabled
mov !rc,w
IFDEF SX48_52
mov···· w,#RD_PLP··········· ;Setup RD Weak Pull-up, 0 = enabled, 1
= disabled
mov !rd,w
mov···· w,#RE_PLP··········· ;Setup RE Weak Pull-up, 0 = enabled, 1
= disabled
mov !re,w
ENDIF
_mode DDIR_W ;point MODE to write DDIR register
mov w,#RA_DDIR ;Setup RA Direction register, 0 = output, 1 = input
mov !ra,w
mov w,#RB_DDIR ;Setup RB Direction register, 0 = output, 1 = input
mov !rb,w
mov w,#RC_DDIR ;Setup RC Direction register, 0 = output, 1 = input
mov !rc,w
IFDEF SX48_52
mov w,#RD_DDIR ;Setup RD Direction register, 0 = output, 1 = input
mov !rd,w
mov w,#RE_DDIR ;Setup RE Direction register, 0 = output, 1 = input
mov !re,w
ENDIF
mov···· w,#RA_latch········· ;Initialize RA data latch
mov···· ra,w
mov···· w,#RB_latch········ ;Initialize RB data latch
mov···· rb,w
mov···· w,#RC_latch········· ;Initialize RC data latch
mov···· rc,w
IFDEF SX48_52
mov···· w,#RD_latch········ ;Initialize RD data latch
mov···· rd,w
mov···· w,#RE_latch········ ;Initialize RE data latch
mov···· re,w
ENDIF
;*********************************************************************************************************
;
Clear all Data RAM
locations
;**********************************************************************************************************
IFDEF SX48_52·· ;SX48/52 RAM clear routine
mov w,#$0a ;reset all ram starting at $0A
mov fsr,w
:zeroRam clr ind ;clear using indirect addressing
incsz fsr ;repeat until done
jmp :zeroRam
_bank bank0 ;clear bank 0 registers
clr $10
clr $11
clr $12
clr $13
clr $14
clr $15
clr $16
clr $17
clr $18
clr $19
clr $1a
clr $1b
clr $1c
clr $1d
clr $1e
clr $1f
ELSE···· ;SX18/20/28 RAM clear routine
clr fsr ;reset all ram banks
:zeroRam sb fsr.4 ;are we on low half of bank?
setb fsr.3 ; To clear from 08 - Global Registers
clr ind ;clear using indirect addressing
incsz fsr ;repeat until done
jmp :zeroRam
ENDIF
;*********************************************************************************
; Initialize program/VP registers
;*********************************************************************************
_bank rs232TxBank ;select rs232 bank
mov w,#UARTDivide1 ;load rs232Tx1Divide with UART1 baud rate
mov rs232Tx1Divide,w
mov w,#UARTDivide2 ;load rs232Tx1Divide with UART2 baud rate
mov rs232Tx1Divide,w
;*********************************************************************************
; Setup and enable RTCC interrupt, WREG register, RTCC/WDT prescaler
;*********************************************************************************
RTCC_ON = %10000000 ;Enables RTCC at address $01 (RTW hi)
;*WREG at address $01 (RTW lo) by default
RTCC_ID = %01000000 ;Disables RTCC edge interrupt (RTE_IE hi)
;*RTCC edge interrupt (RTE_IE lo) enabled by default
RTCC_INC_EXT = %00100000 ;Sets RTCC increment on RTCC pin transition
(RTS hi)
;*RTCC increment on internal instruction (RTS lo) is default
RTCC_FE = %00010000 ;Sets RTCC to increment on falling edge (RTE_ES
hi)
;*RTCC to increment on rising edge (RTE_ES lo) is default
RTCC_PS_ON = %00000000 ;Assigns prescaler to RTCC (PSA lo)
RTCC_PS_OFF = %00001000 ;Assigns prescaler to WDT (PSA hi)
PS_000 = %00000000 ;RTCC = 1:2, WDT = 1:1
PS_001 = %00000001 ;RTCC = 1:4, WDT = 1:2
PS_010 = %00000010 ;RTCC = 1:8, WDT = 1:4
PS_011 = %00000011 ;RTCC = 1:16, WDT = 1:8
PS_100 = %00000100 ;RTCC = 1:32, WDT = 1:16
PS_101 = %00000101 ;RTCC = 1:64, WDT = 1:32
PS_110 = %00000110 ;RTCC = 1:128, WDT = 1:64
PS_111 = %00000111 ;RTCC = 1:256, WDT = 1:128
OPTIONSETUP equ RTCC_PS_OFF|PS_111 ; the default option setup for this
program.
mov w,#OPTIONSETUP ; setup option register for RTCC interrupts
enabled
mov !option,w ; and prescaler assigned to WDT.
jmp @mainLoop
;*****************************************************************************************
;
MAIN PROGRAM CODE
;*****************************************************************************************
mainLoop
IFDEF TEST1
mov w, #_welcome
setb rs232Tx1Flag
call @sendstring2
jmp mainloop1
mainloop1
call getbyte1 ; Get a Byte
_bank rs232RxBank
cje rs232Byte1,#'D',:desee
cje rs232Byte1,#'A',:asee
cje rs232Byte1,#'-',:negative
cje rs232Byte1,#'1',[noparse]:o[/noparse]ne
cje rs232Byte1,#'2',:two
cje rs232Byte1,#'3',:three
cje rs232Byte1,#'4',:four
cje rs232Byte1,#'5',:five
cje rs232Byte1,#'6',:six
cje rs232Byte1,#'7',:seven
cje rs232Byte1,#'8',:eight
cje rs232Byte1,#'9',:nine
cje rs232Byte1,#'.',[noparse]:p[/noparse]oint
cje rs232Byte1,#'0',:zero
cje rs232Byte1,#'n',:nano
cje rs232Byte1,#'u',:micro
cje rs232Byte1,#'m',:milli
cje rs232Byte1,#'M',:mega
cje rs232Byte1,#'k',:kilo
cje rs232Byte1,#'V',:volts
cje rs232Byte1,#'A',:amps
cje rs232Byte1,#'T',:temper
cje rs232Byte1,#'H',:hertz
cje rs232Byte1,#'C',:compare
cje rs232Byte1,#'F',:farad
:asee
mov w,#_asee
call @sendstring2
:desee
mov w,#_desee
call @sendstring2
:compare
call getbyte1
cje rs232Byte1,#'a',:cap
mov w,#_celcius
call @sendstring2
:cap
mov w,#_cap
call @sendstring2
:temper
mov w,#_temper
call @sendstring2
[noparse]:o[/noparse]ne
mov w,#_one
call @sendstring2
:two
mov w,#_two
call @sendstring2
:three
mov w,#_three
call @sendstring2
:four
mov w,#_four
call @sendstring2
:five
mov w,#_five
call @sendstring2
:six
mov w,#_six
call @sendstring2
:seven
mov w,#_seven
call @sendstring2
:eight
mov w,#_eight
call @sendstring2
:nine
mov w,#_nine
call @sendstring2
:zero
mov w,#_zero
call @sendstring2
[noparse]:p[/noparse]oint
mov w,#_point
call @sendstring2
:kilo
mov w,#_kilo
call @sendstring2
:nano
mov w,#_nano
call @sendstring2
:mega
mov w,#_mega
call @sendstring2
:milli
mov w,#_milli
call @sendstring2
:micro
mov w,#_micro
call @sendstring2
:amps
mov w,#_amps
call @sendstring2
:negative
mov w,#_negative
call @sendstring2
:farad
mov w,#_farad
call @sendstring2
:volts
mov w,#_volts
call @sendstring2
:hertz
mov w,#_hertz
call @sendstring2
:henries
mov w,#_henries
call @sendstring2
clr rs232Byte1
jmp mainloop1
ENDIF
jmp $ ; If program get stuck here, then you have not
; selected TEST1 or TEST2 at the beginning of
; the source code.
;*****************************************************************************************
END ;End of program code
;*****************************************************************************************
Comments
mov w, #-200
add this line to the code to disable this warning.
LIST Q = 37 ;Truncated Literals
Another Question:
When I run the debugger, it gets stuck at:· ·reset···· resetEntry
Any ideas as to what might be causing this?
Here are issues that I am concerned about:
The program is written to receive·input from a multimeter·through RS232,·translate the received data, and send the final output to a Speakjet Chip.· The multimeter uses 7 data bits and 2 stop bits, while the Speakjet uses 8 bits with no parity/one stop bit/noninverted.· Instead of the output being the programmed set of words, the output consists of a somewhat predictable set of beeps, chirps, random words not programmed, etc...··I have tried changing the intPeriod, which alters the output, but am still having no luck.· I initially tried programming in BASIC, but had problems with the SX compiler when using IF statements.· I resorted to assembly instead.· I am brand new to assembly and therefore am at a loss as to what my problem may be.· If anyone can enlighten me in any way, I would greatly appreciate it.
I assume you're refering to the source code at the top of this thread? If so, the first problem I see is that in your function "SendByte", you have two UARTS that are both set to 1 start-8 data-1 stop when you say that the multimeter uses 1 start-7data-2 stop. Whenever you're trying to debug a tricky program like this, you need to start breaking this thing into blocks that you can test and prove.
I would start taking all the external hardware (such as the multimeter and the Speakjet) out of the equation and subsitute a good terminal program instead. Check out "RealTerm". It runs under Windows and can talk in both formats you described. Before you write any code, use RealTerm to verify that your understanding of the various communications protocols are correct. You can then use it as a dummy device to stand-in for the actual external hardware. That way you can use it to send some known data and see if it is being received properly by your code.
It sounds like you're trying to write and debug the entire program all at once. Break this thing up into smaller, more manageable chunks. For example, I would start with trying to write a simple program that sends a small string to the Speakjet chip at 1-8-1 and see if you can get the expected response. This should be a totally separate program so it will be as small as possible. Once you get that working, create another program to talk to the multimeter, only you'll have to modify the UART code to speak 1-7-2 instead. Once you've got the separate pieces working, then you can work on merging them together.
This about this as a step by step process and start knocking off the things you assume to be true by proving them first.
Thanks, PeterM