Shop OBEX P1 Docs P2 Docs Learn Events
Serial Output Error — Parallax Forums

Serial Output Error

beardcmbeardcm Posts: 12
edited 2005-04-14 00:47 in General Discussion
When running RealTerm, the output·of the code produces strings of decimal numbers of the correct length.· However, the output strings to not match·the string of decimal numbers specified inside the code for a given word.·

What could be causing this to·happen?

Comments

  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2005-04-08 20:13
    Is it inverted?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe - Mask Designer III

    National Semiconductor Corporation
    Latest Company News
    (Communication Interface Division)
    500 Pinnacle Court, Suite 525
    Mail Stop GA1
    Norcross,GA 30071
  • beardcmbeardcm Posts: 12
    edited 2005-04-08 20:17
    The strings stored in the string memory locations are exactly what we need to be sent out of the chip. There seems to be no correlation between the output inverted (using realTerm inverted viewing) or otherwise.
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2005-04-08 20:22
    I'm not sure about the "realTerm inverted viewing".... what I meant was are you transmitting the data from the SX as "inverted" or "non-inverted".

    You asked what could be causing this to happen. This was the first thing that I thought of that might be a culprit.




    A quick look at "realTerm" and the option to invert the data is NOT the same as inverting the RS232 serial data leaving the SX / entering the PC

    realterm.sourceforge.net/

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe - Mask Designer III

    National Semiconductor Corporation
    Latest Company News
    (Communication Interface Division)
    500 Pinnacle Court, Suite 525
    Mail Stop GA1
    Norcross,GA 30071

    Post Edited (Beau Schwabe) : 4/8/2005 8:30:12 PM GMT
  • beardcmbeardcm Posts: 12
    edited 2005-04-08 20:40
    In the sendbyte subroutine, I have tried removing the not w command and while the output it gives is different, but it is still not the same as the numerical values stored in the string. With or without the inverted setting in realterm. I thought maybe it was an issue of timing, due to the fact there are two different baud rates involved in the programming. Trying various values for intperiod variable alters the output, yet it still isn't the output we are looking for, which is why I was wondering if there might be something else about the program that may be causing the problem.
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2005-04-08 20:56
    The "not w command" only inverts the data.....

    Ok... A serial BYTE is actually 10-bits. You have 8-Data bits that compose a Byte, and you have a START and a STOP bit
    that make up the other 2-bits totaling 10-bits.

    The inversion that I am suggesting is in the "BaudMode" setting as part of the SEROUT routine. When this is set, not only are the DATA
    bits inverted (same as the 'not w command' or flipping this in the realTerm) BUT, the STOP and START bits are also inverted.

    Now, you mention that you have different baud speeds. This needs to be corrected first! you should have the same Baud setting for
    everything within the SX and within realTerm.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe - Mask Designer III

    National Semiconductor Corporation
    Latest Company News
    (Communication Interface Division)
    500 Pinnacle Court, Suite 525
    Mail Stop GA1
    Norcross,GA 30071
  • beardcmbeardcm Posts: 12
    edited 2005-04-08 22:00
    As to the problem of the baud rates being different, the two devices that I need to connect together run at two different baud rates. If it were up to me I would not be attempting to do this, but as this is my senior project and the parts were recommended by the sponsors, I am kind of stuck.
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2005-04-08 22:09
    What about using a different pin for the different bauds? ....At least for debugging?
    I still think you are going to have problems mixing different baud modes.
    It is important to work out a common denominator that you can transmit and receive data with.

    Also, I assume you are programming on an SX.. Are you using SX/Basic or SX/Assembly for your programming?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe - Mask Designer III

    National Semiconductor Corporation
    Latest Company News
    (Communication Interface Division)
    500 Pinnacle Court, Suite 525
    Mail Stop GA1
    Norcross,GA 30071
  • beardcmbeardcm Posts: 12
    edited 2005-04-10 00:54
    I am using assembly language.
  • Jim PalmerJim Palmer Posts: 23
    edited 2005-04-11 16:57
    What was the output for the welcome string you are sending when you generate it with the program you attached to your original message?

    Jim
  • beardcmbeardcm Posts: 12
    edited 2005-04-11 22:03
    I figured out what the problem with the output speed, it was probably a typo in the original program.
    But, now we get extra numbers before the output that is supposed to correspond to the values for welcome.

    Intended output: 84,147,131,145,195,136,140,255,0
    Actual output: 0 140 140 112 124 31 0 12 28 31 56 130 168 77 131 145 195 136 140 255

    Here is the new code, with the problem fixed.

    LIST Q = 37 ;disables truncation errors

    device SX28,oschs2,turbo,stackx,optionx

    freq 50_000_000

    IRC_CAL IRC_FAST

    ; ** Baud Rates for UART 1 **
    U1B1200 ;baud rate of 1.2 Kbps

    ; ** Baud Rates for UART 2 **
    U2B9600 ;baud rate of 9.6 kbps

    id '2UART VP' ;
    reset resetEntry ; set reset vector



    ;*********************************************************************************************
    ;
    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

    expand
    clrb fsr.7
    noexpand

    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

    expand
    mov m,#\1 ;loads the M register correctly for the SX18AC, SX20AC
    ;and SX28AC
    noexpand

    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

    setb \1.4 ; If SX18 or SX28AC,keep bit 4 of the pointer = 1
    ; to jump from $1f to $30,etc
    endm

    DECP macro 1 ; Decrements a pointer to RAM

    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
    ; 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).
    ;*********************************************************************************************

    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


    ;*********************************************************************************************
    ;
    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 = $



    ;*****************************************************************************************
    ;
    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


    ;*********************************************************************************************
    ;
    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

    UARTDivide1 = (UARTfs/(UARTBaud1*Num)) ;48
    UARTStDelay1 = UARTDivide1 +(UARTDivide1/2)+1

    IFDEF U2B9600
    UARTBaud2 = 9600

    UARTDivide2 = (UARTfs/(UARTBaud2*Num)) ;6
    UARTStDelay2 = UARTDivide2 +(UARTDivide2/2)+1


    ;*********************************************************************************************
    ; 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
    clrb 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 84,147,131,145,195,136,140,255,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
    _ohms dw 164, 140, 15, 193
    _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

    _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

    _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

    _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

    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


    ;*********************************************************************************************************
    ;
    Clear all Data RAM locations
    ;**********************************************************************************************************

    ;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


    ;*********************************************************************************
    ; 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 rs232Tx2Divide,w ;I changed to rs232Tx2Divide

    ;*********************************************************************************
    ; 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
    mov w, #_welcome
    setb rs232Tx1Flag
    call @sendstring2

    jmp mainloop1
    mainloop1

    jmp mainloop1

    ;*****************************************************************************************
    END ;End of program code
    ;*****************************************************************************************
  • edited 2005-04-14 00:47
    I noticed that when you are calculating the clock dividers for the UART's you indicate that the UART's will only get 1/4 of the ISR slots. However, looking at the code, it indicates 1/16 in most places but with the way that the code is written, it actually looks like it would be 1/13.

    It also appears that a little too much code has been trimmed down in the UART's. UART 1 is missing a "sc" instruction for the receiver to properly wait for the start bit before it starts sampling the bits for the next byte.

    If I were you, I would simplify this code down to one UART (just comment out the second one), and remove all of the multiplexing code that you don't even appear to be using. Later, you can slowly add in more complexity.
Sign In or Register to comment.